Git development
 help / color / mirror / Atom feed
* Re: TortoiseGit
From: Li Frank @ 2008-12-14  9:46 UTC (permalink / raw)
  To: Geoffrey Lee, git
In-Reply-To: <83d7aaa40812131828r2eebd309oaf8531b88d4c925c@mail.gmail.com>

Yes!
TSVNcache.exe has not started porting! TSVNCache is used for overlay icon.
TortoiseMerge have not started porting!

I think this release is just a begining.

best regards
Frank Li

2008/12/14 Geoffrey Lee <geoffreyj.lee@gmail.com>:
> Hi Frank,
> I was just about to start a TortoiseGit project until I saw your project
> today. Would you like any help?
> -Geoffrey Lee

^ permalink raw reply

* What's cooking in git.git (Dec 2008, #02; Sun, 14)
From: Junio C Hamano @ 2008-12-14  8:24 UTC (permalink / raw)
  To: git

Here are the topics that have been cooking.  Commits prefixed
with '-' are only in 'pu' while commits prefixed with '+' are
in 'next'.

The topics list the commits in reverse chronological order.  The topics
meant to be merged to the maintenance series have "maint-" in their names.

As we have already passed -rc2, things queued in 'next' let alone 'pu' are
unlikely to be merged to 'master' by the end of year unless otherwise
noted.

----------------------------------------------------------------
[New Topics]

* wp/add-p-goto (Thu Dec 4 10:22:40 2008 +0000) 2 commits
 + Add 'g' command to go to a hunk
 + Add subroutine to display one-line summary of hunks

* jn/gitweb-blame (Thu Dec 11 01:33:29 2008 +0100) 3 commits
 - gitweb: cache $parent_commit info in git_blame()
 - gitweb: A bit of code cleanup in git_blame()
 - gitweb: Move 'lineno' id from link to row element in git_blame

I've briefly looked at the resurrection of Ajaxy blame that comes on top
of this series and it looked promising.

* mv/um-pdf (Wed Dec 10 23:44:50 2008 +0100) 1 commit
 - Add support for a pdf version of the user manual

I do not have a new enough combination of dblatex and asciidoc myself but
this would help interested people.

* np/auto-thread (Sat Dec 13 15:06:40 2008 -0500) 2 commits
 + pack-objects: don't use too many threads with few objects
 + autodetect number of CPUs by default when using threads

* sc/gitweb-category (Fri Dec 12 00:45:12 2008 +0100) 3 commits
 - gitweb: Optional grouping of projects by category
 - gitweb: Split git_project_list_body in two functions
 - gitweb: Modularized git_get_project_description to be more generic

----------------------------------------------------------------
[Post 1.6.1 items]

* gb/gitweb-patch (Sat Dec 6 16:02:35 2008 +0100) 3 commits
 - gitweb: link to patch(es) view from commit and log views
 - gitweb: add patches view
 - gitweb: add patch view

Updated series.  Reviews and Acks?

* lt/reset-merge (Wed Dec 3 18:00:12 2008 -0800) 2 commits
 + Document "git-reset --merge"
 + Add 'merge' mode to 'git reset'

With updated documents.

* wp/add-patch-find (Thu Nov 27 04:08:03 2008 +0000) 3 commits
 . In add --patch, Handle K,k,J,j slightly more gracefully.
 . Add / command in add --patch
 . git-add -i/-p: Change prompt separater from slash to comma

I am still holding onto this earlier topic to add '/' subcommand to allow
finding a hunk with given text, but I'd rather not merge/rebase it on top
of wp/add-p-goto series myself.  Waiting for a reroll.

* cb/mergetool (Fri Dec 12 21:48:41 2008 +0000) 4 commits
 - mergetool: Don't keep temporary merge files unless told to
 - mergetool: Add prompt to continue after failing to merge a file
 - Add -y/--no-prompt option to mergetool
 - Fix some tab/space inconsistencies in git-mergetool.sh

Updated series.  Waiting for comments from the original author (Ted) and
other interested parties.

----------------------------------------------------------------
[Graduated to "master"]

* jc/rm-i-t-a (Fri Nov 28 19:56:34 2008 -0800) 5 commits
 + git add --intent-to-add: do not let an empty blob be committed by
   accident
 + git add --intent-to-add: fix removal of cached emptiness
 + builtin-rm.c: explain and clarify the "local change" logic
 + Merge branch 'nd/narrow' (early part) into jc/add-i-t-a
 + Extend index to save more flags

As intent-to-add index entry is a new feature for 1.6.1, it probably is a
good idea to merge this to 'master'.  Nitpicks and bugfixes are very much
appreciated.

* jn/gitweb-utf8 (Mon Dec 1 19:01:42 2008 +0100) 1 commit
 + gitweb: Fix handling of non-ASCII characters in inserted HTML
   files.

A bugfix.

----------------------------------------------------------------
[Will merge to "master" soon]

What are you looking for?  We are in -rc ;-)

----------------------------------------------------------------
[On Hold]

* jc/blame (Wed Jun 4 22:58:40 2008 -0700) 2 commits
 + blame: show "previous" information in --porcelain/--incremental
   format
 + git-blame: refactor code to emit "porcelain format" output

* ds/uintmax-config (Mon Nov 3 09:14:28 2008 -0900) 1 commit
 - autoconf: Enable threaded delta search when pthreads are supported

Rebased to 'master', that introduced NO_PTHREADS.

* cc/bisect-replace (Mon Nov 24 22:20:30 2008 +0100) 9 commits
 - bisect: add "--no-replace" option to bisect without using replace
   refs
 - rev-list: make it possible to disable replacing using "--no-
   bisect-replace"
 - bisect: use "--bisect-replace" options when checking merge bases
 - merge-base: add "--bisect-replace" option to use fixed up revs
 - commit: add "bisect_replace_all" prototype to "commit.h"
 - rev-list: add "--bisect-replace" to list revisions with fixed up
   history
 - Documentation: add "git bisect replace" documentation
 - bisect: add test cases for "git bisect replace"
 - bisect: add "git bisect replace" subcommand

I really hate the idea of introducing a potentially much more useful
replacement of the existing graft mechanism and tie it very tightly to
bisect, making it unusable from outside.

 (1) I do not think "bisect replace" workflow is a practical and usable
     one;

 (2) The underlying mechanism to express "this object replaces that other
     object" is much easier to work with than what the graft does which is
     "the parents of this commit are these", and idea to use the normal
     ref to point at them means this can potentially be used for
     transferring the graft information across repositories, which the
     current graft mechanism cannot do.

 (3) Because I like the aspect (2) of this series so much, it deeply
     disappoints and troubles me that this is implemented minimally near
     the surface, and that it is controlled by the "bisect" Porcelain
     alone, by explicitly passing command line arguments.

I think a mechanism like this should be added to replace grafts, but it
should always be enabled for normal revision traversal operation, while
always disabled for object enumeration and transfer operation (iow, fsck,
fetch and push should use the real ancestry information recorded in the
underlying objects, while rev-list, log, etc. should always use the
replaced objects).  I have a suspicion that even cat-file could honor it.

* nd/narrow (Sun Nov 30 17:54:38 2008 +0700) 17 commits
 - wt-status: show sparse checkout info
 - Introduce default sparse patterns (core.defaultsparse)
 - checkout: add new options to support sparse checkout
 - clone: support sparse checkout with --sparse-checkout option
 - unpack_trees(): add support for sparse checkout
 - unpack_trees(): keep track of unmerged entries
 - Introduce "sparse patterns"
 - Merge branch 'master' into nd/narrow
 + t2104: touch portability fix
 + grep: skip files outside sparse checkout area
 + checkout_entry(): CE_NO_CHECKOUT on checked out entries.
 + Prevent diff machinery from examining worktree outside sparse
   checkout
 + ls-files: Add tests for --sparse and friends
 + update-index: add --checkout/--no-checkout to update
   CE_NO_CHECKOUT bit
 + update-index: refactor mark_valid() in preparation for new options
 + ls-files: add options to support sparse checkout
 + Introduce CE_NO_CHECKOUT bit

Kicked back to 'on hold' until 1.6.1 final by popular demand; will be
dropped from 'next' (see recent discussion on the interaction between the
checkout area and commands such as "grep").

* jc/clone-symref-2 (Sat Nov 29 23:38:21 2008 -0800) 7 commits
 - clone: test the new HEAD detection logic
 - Merge commit 'HEAD@{2}' into HEAD
 - upload-pack: send the HEAD information
 - clone: find the current branch more explicitly
 - connect.c::read_extra_info(): find where HEAD points at
 - connect.c::read_extra_info(): prepare to receive more than server
   capabilities
 - get_remote_heads(): refactor code to read "server capabilities"

This is no way meant for 1.6.1, let alone next, yet.

* jc/send-pack-tell-me-more (Thu Mar 20 00:44:11 2008 -0700) 1 commit
 - "git push": tellme-more protocol extension

This seems to have a deadlock during communication between the peers.
Someone needs to pick up this topic and resolve the deadlock before it can
continue.

* jk/renamelimit (Sat May 3 13:58:42 2008 -0700) 1 commit
 - diff: enable "too large a rename" warning when -M/-C is explicitly
   asked for

This would be the right thing to do for command line use,
but gitk will be hit due to tcl/tk's limitation, so I am holding
this back for now.

* jc/stripspace (Sun Mar 9 00:30:35 2008 -0800) 6 commits
 - git-am --forge: add Signed-off-by: line for the author
 - git-am: clean-up Signed-off-by: lines
 - stripspace: add --log-clean option to clean up signed-off-by:
   lines
 - stripspace: use parse_options()
 - Add "git am -s" test
 - git-am: refactor code to add signed-off-by line for the committer

^ permalink raw reply

* What's in git.git (Dec 2008, #02; Sun, 14)
From: Junio C Hamano @ 2008-12-14  8:24 UTC (permalink / raw)
  To: git

There are a handful fixes since 1.6.1-rc2 on 'master' and I am hoping that
we can do -rc3 later today, and declare the 1.6.1 final on the 20th or
so.

----------------------------------------------------------------

* The 'maint' branch has these fixes since the last announcement.

Brandon Casey (11):
  t7700: demonstrate mishandling of objects in packs with a .keep file
  packed_git: convert pack_local flag into a bitfield and add pack_keep
  pack-objects: new option --honor-pack-keep
  repack: don't repack local objects in packs with .keep file
  repack: do not fall back to incremental repacking with [-a|-A]
  builtin-gc.c: use new pack_keep bitfield to detect .keep file existence
  t7700: demonstrate mishandling of loose objects in an alternate ODB
  sha1_file.c: split has_loose_object() into local and non-local
    counterparts
  pack-objects: extend --local to mean ignore non-local loose objects too
  t7700: test that 'repack -a' packs alternate packed objects
  repack: only unpack-unreachable if we are deleting redundant packs

Davide Libenzi (1):
  xdiff: give up scanning similar lines early

Deskin Miller (1):
  git-svn: Make following parents atomic

Jakub Narebski (1):
  gitweb: Make project specific override for 'grep' feature work

Jeff King (2):
  commit: Fix stripping of patch in verbose mode.
  tag: delete TAG_EDITMSG only on successful tag

Jim Meyering (1):
  git-config.txt: fix a typo

Johannes Sixt (1):
  compat/mingw.c: Teach mingw_rename() to replace read-only files

Junio C Hamano (2):
  GIT 1.6.0.5
  work around Python warnings from AsciiDoc

Linus Torvalds (1):
  fsck: reduce stack footprint

Matt McCutchen (1):
  "git diff <tree>{3,}": do not reverse order of arguments

Miklos Vajna (1):
  http.c: use 'git_config_string' to get 'curl_http_proxy'

Nicolas Pitre (1):
  make sure packs to be replaced are closed beforehand

Thomas Rast (1):
  fetch-pack: Avoid memcpy() with src==dst


* The 'master' branch has these since the last announcement
  in addition to the above.

Alex Riesen (3):
  Make some of fwrite/fclose/write/close failures visible
  Make chdir failures visible
  Report symlink failures in merge-recursive

Alexander Potashev (2):
  Fix typos in documentation
  Fix typo in comment in builtin-add.c

Alexey Borzenkov (1):
  Define linkgit macro in [macros] section

Brandon Casey (1):
  git-branch: display sha1 on branch deletion

Deskin Miller (1):
  git-svn: Make branch use correct svn-remote

Jakub Narebski (2):
  gitweb: Fix handling of non-ASCII characters in inserted HTML files
  gitweb: Fix bug in insert_file() subroutine

Jeff King (6):
  add stage to gitignore
  reorder ALLOW_TEXTCONV option setting
  diff: allow turning on textconv explicitly for plumbing
  diff: fix handling of binary rewrite diffs
  diff: respect textconv in rewrite diffs
  rebase: improve error messages about dirty state

Junio C Hamano (16):
  builtin-rm.c: explain and clarify the "local change" logic
  git add --intent-to-add: fix removal of cached emptiness
  git add --intent-to-add: do not let an empty blob be committed by
    accident
  Install git-stage in exec-path
  git-am --whitespace: do not lose the command line option
  git-am: propagate -C<n>, -p<n> options as well
  git-am: propagate --3way options as well
  Test that git-am does not lose -C/-p/--whitespace options
  git-am: rename apply_opt_extra file to apply-opt
  Update draft release notes to 1.6.1
  Update draft release notes for 1.6.1
  Revert "git-stash: use git rev-parse -q"
  Point "stale" 1.6.0.5 documentation from the main git documentation page
  builtin-checkout.c: check error return from read_cache()
  read-cache.c: typofix in comment
  Fix t4031

Markus Heidelberg (1):
  builtin-commit: remove unused message variable

Miklos Vajna (5):
  filter-branch: use git rev-parse -q
  lost-found: use git rev-parse -q
  pull: use git rev-parse -q
  rebase: use git rev-parse -q
  submodule: use git rev-parse -q

Nguyễn Thái Ngọc Duy (1):
  Extend index to save more flags

Ralf Wildenhues (1):
  Improve language in git-merge.txt and related docs

Tor Arvid Lund (2):
  git-p4: Fix bug in p4Where method.
  git-p4: Fix regression in p4Where method.

^ permalink raw reply

* Re: [PATCH] git-fast-import possible memory corruption problem
From: Junio C Hamano @ 2008-12-14  5:53 UTC (permalink / raw)
  To: YONETANI Tomokazu; +Cc: git, Shawn O. Pearce
In-Reply-To: <7vd4fv4e3u.fsf@gitster.siamese.dyndns.org>

Junio C Hamano <gitster@pobox.com> writes:

>> As the `round out' takes place AFTER it found the room in the mem_pool,
>> there's a small chance of p->next_free being set outside of the chosen
>> area, up to (sizeof(uintmax_t) - 1) bytes.  pool_strdup() is one of the
>> functions which can trigger the problem, when pool_alloc() finds a room
>> at the end of a pool entry and the requested length is not multiple of
>> size(uintmax_t).  I believe attached patch addresses this problem.
>
> Thanks -- do you mean your reproducible crash does not reproduce with the
> patch anymore?
>
> I think your change to move the "round up" logic up in the codepath makes
> perfect sense.  But your patch seems to conflate totally unrelated change
> to move memzero from the caller to callee into it, and I do not see the
> reason why it should be that way.  If the caller asked 10 bytes to calloc
> from the pool, and the underlying pool allocator gives you a 16-byte
> block, you only have to guarantee that the first 10 bytes are cleared, and
> can leave the trailing padding 6 bytes at the end untouched.

That is, something like this...

 fast-import.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git c/fast-import.c w/fast-import.c
index 3c035a5..3276d5d 100644
--- c/fast-import.c
+++ w/fast-import.c
@@ -554,6 +554,10 @@ static void *pool_alloc(size_t len)
 	struct mem_pool *p;
 	void *r;
 
+	/* round up to a 'uintmax_t' alignment */
+	if (len & (sizeof(uintmax_t) - 1))
+		len += sizeof(uintmax_t) - (len & (sizeof(uintmax_t) - 1));
+
 	for (p = mem_pool; p; p = p->next_pool)
 		if ((p->end - p->next_free >= len))
 			break;
@@ -572,9 +576,6 @@ static void *pool_alloc(size_t len)
 	}
 
 	r = p->next_free;
-	/* round out to a 'uintmax_t' alignment */
-	if (len & (sizeof(uintmax_t) - 1))
-		len += sizeof(uintmax_t) - (len & (sizeof(uintmax_t) - 1));
 	p->next_free += len;
 	return r;
 }

^ permalink raw reply related

* Re: is gitosis secure?
From: david @ 2008-12-14  5:40 UTC (permalink / raw)
  To: Sitaram Chamarty; +Cc: git
In-Reply-To: <gi1qsl$22p$1@ger.gmane.org>

this is really a reply to an earlier message that I deleted.

the question was asked 'what would the security people like instead of 
SSH'

as a security person who doesn't like how ssh is used for everything, let 
me list a couple of concerns.

ssh is default allow (it lets you run any commands), you can lock it down 
with effort.

ssh defaults to establishing a tunnel between machines that other network 
traffic can use to bypass your system. yes I know that with enough effort 
and control of both systems you can tunnel over anything, the point is 
that ssh is eager to do this for you (overly eager IMHO)

ssh depends primarily on certificates that reside on untrusted machines. 
it can be made to work with tokens or such, but it takes a fair bit of 
effort.

sshd runs as root on just about every system

people trust ssh too much. they tend to think that anything is acceptable 
if it's done over ssh (this isn't a technical issue, but it is a social 
issue)


what would I like to see in an ideal world?

something that runs as the git user, does not enable tunneling, and only 
does the data transfer functions needed for a push. it should use 
off-the-shelf libraries for certificate authentication and tie into PAM 
for additional authentication.

the authentication would not be any better than with SSH, but the rest 
would be better. I was very pleased to watch the git-daemon development, 
and the emphisis on it running with minimum privilages and provide just 
the functionality that was needed, and appropriately assuming that any 
connection from the outside is hostile until proven otherwise.


what would I do with current tools?

I would say that developers working from outside should VPN into the 
company network before doing the push with SSH rather than exposing the 
SSH daemon to the entire Internet.

in the medium term, if the git-over-http gets finished, I would like to 
see a seperate cgi created to allow push as well. http is overused as a 
tunneling protocol, but it's easy to setup a server that can't do anything 
except what you want, so this tunneling is generally not a threat to 
servers (it's a horrible threat to client systems)

David Lang

^ permalink raw reply

* Re: [PATCH v3] git-sh-setup: Fix scripts whose PWD is a symlink into a git work-dir
From: Junio C Hamano @ 2008-12-14  3:54 UTC (permalink / raw)
  To: Marcel M. Cary; +Cc: git, jnareb, ae, j.sixt
In-Reply-To: <1229201231-12586-1-git-send-email-marcel@oak.homeunix.org>

"Marcel M. Cary" <marcel@oak.homeunix.org> writes:

> I also removed the "pwd -P" from the unit test.

Hmm, really...?

>> > +# Prove that the remote end really is a repo, and other commands
>> > +# work fine in this context.
>> > +#
>> > +test_debug "
>> > +    test_expect_success 'pushing from symlinked subdir' '
>> > +
>> > +        git push
>> > +    '
>> > +"
>> 
>> Why should this be hidden inside test_debug?
>
> I'm not particularly trying to test "git push" or "git pull" in general
> here.  That's also why the other "git pull" was in a test_debug.  I
> thought it was really only useful to someone trying to understand the
> contents of the test file.  There are other files that cover push and
> pull.  Do you think these test cases should run all the time here?

I'd say so.  Your supporting argument could be "See, push works just fine
with this layout, but pull doesn't because it is a shell script that can
be fooled, and this change is to fix the inconsistencies between them."
Having these test enabled would be a good way to do so.  Then it becomes
irrelevant if "jump into the middle of a directory hierarchy sideways via
symlink" is worth supporting or not ;-)

But whether it is inside test_debug or not, the test should check not just
the exit status from 'git push' but also check what happened to the
receiving repository at least to make sure it is pushing to the location
you are expecting it to.

> diff --git a/t/t2300-cd-to-toplevel.sh b/t/t2300-cd-to-toplevel.sh
> new file mode 100755
> index 0000000..05854b4
> --- /dev/null
> +++ b/t/t2300-cd-to-toplevel.sh
> @@ -0,0 +1,37 @@
> +#!/bin/sh
> +
> +test_description='cd_to_toplevel'
> +
> +. ./test-lib.sh
> +
> +test_cd_to_toplevel () {
> +	test_expect_success "$2" '
> +		(
> +			cd '"'$1'"' &&
> +			. git-sh-setup &&
> +			cd_to_toplevel &&
> +			[ "$(pwd -P)" = "$TOPLEVEL" ]
> +		)
> +	'
> +}

The quoting of $1 here is a bit tricky, but I think it is good enough for
directory names used in tests that use this function.

^ permalink raw reply

* Re: [PATCH] git-fast-import possible memory corruption problem
From: Junio C Hamano @ 2008-12-14  3:42 UTC (permalink / raw)
  To: YONETANI Tomokazu; +Cc: git
In-Reply-To: <20081214020822.GB4121@les.ath.cx>

YONETANI Tomokazu <qhwt+git@les.ath.cx> writes:

> While trying to convert NetBSD CVS repository to Git, I've been
> experiencing 100% reproducible crash of git-fast-import.  After
> poking here and there and I noticed a dubious code fragment in
> pool_alloc():
> 	:
>
>         r = p->next_free;
>         /* round out to a 'uintmax_t' alignment */
>         if (len & (sizeof(uintmax_t) - 1))
>                 len += sizeof(uintmax_t) - (len & (sizeof(uintmax_t) - 1));
>         p->next_free += len;
>         return r;
>
> As the `round out' takes place AFTER it found the room in the mem_pool,
> there's a small chance of p->next_free being set outside of the chosen
> area, up to (sizeof(uintmax_t) - 1) bytes.  pool_strdup() is one of the
> functions which can trigger the problem, when pool_alloc() finds a room
> at the end of a pool entry and the requested length is not multiple of
> size(uintmax_t).  I believe attached patch addresses this problem.

Thanks -- do you mean your reproducible crash does not reproduce with the
patch anymore?

I think your change to move the "round up" logic up in the codepath makes
perfect sense.  But your patch seems to conflate totally unrelated change
to move memzero from the caller to callee into it, and I do not see the
reason why it should be that way.  If the caller asked 10 bytes to calloc
from the pool, and the underlying pool allocator gives you a 16-byte
block, you only have to guarantee that the first 10 bytes are cleared, and
can leave the trailing padding 6 bytes at the end untouched.

^ permalink raw reply

* Sending a threaded patch series with Evolution
From: Matt McCutchen @ 2008-12-14  2:34 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: git
In-Reply-To: <m3hc57g28b.fsf@localhost.localdomain>

On Sat, 2008-12-13 at 14:05 -0800, Jakub Narebski wrote: 
> By the way, your message [PATCH 2/2] should be threaded, i.e. be
> response to [PATCH 1/2] (or to cover letter [PATCH 0/2]), to not
> mistake it with other [PATCH 2/2] patches.

I'm using Evolution 2.24 as my mail client, and I have a wrapper script
"git draft-patch" that runs "git format-patch" and loads the patches
into my Evolution Drafts folder so I can look them over in the composer
and add non-commit-message text below the "---" if I wish before
sending.  I did pass --thread, but the composer changed the Message-Id,
breaking the threading.

I'll try to get this right in the future.  I can see two approaches to
doing so:

1. Check over / edit the patches in a text editor before loading them
into Drafts, and then send them by moving them directly to Outbox
(without using the composer) so that the Message-Id won't change.

2. Send the first patch, then manually edit the Message-Id Evolution
assigned it into the second patch, etc.

Neither of these approaches is particularly nice.  Does anyone have a
better idea?

-- 
Matt

^ permalink raw reply

* Re: is gitosis secure?
From: Sitaram Chamarty @ 2008-12-14  2:26 UTC (permalink / raw)
  To: git
In-Reply-To: <87hc58hwmi.fsf@hades.wkstn.nix>

On 2008-12-13, Nix <nix@esperi.org.uk> wrote:
> telnet. I do not jest, this is our sysadmins' stated reasons for not
> opening the git port and for tweaking their (mandatory) HTTP proxy to
> block HTTP traffic from git.

Wow -- my sympathies!

But on occasion, when real or imaginary issues prevented me
from making a live connection, I have used "git bundle" to
do the job.  Not as satisfactory as a real connection, but
when you have a proper, non-fast-forwarding, repo as the
"mother ship", git bundle with some custom procmail scripts
on both sides can work OK enough.

To do that with a public repo you'd have to mirror that on a
home machine and let your restricted environment work
against that.

> Do not underestimate the stupidity and hideboundedness of undertrained
> system administrators, for it is vast.

These same administrators also underestimate (i) the number
of well connected home machines and (ii) the idea that on
his own machine, everyone is root.

Most of these blocks are "default allow", and your home IP
is not on that list and they don't have the smarts to figure
out that you're getting around their blocks :-) Add dynamic
IP and a dyndns hostname (and dyndns has a hundred or so 2nd
level domains to choose your 3rd level hostname from!) and
clueless admins don't stand a chance.

[sorry this is so badly off-topic...]

^ permalink raw reply

* Re: [PATCH] pack-objects: don't use too many threads with few objects
From: Jeff King @ 2008-12-14  2:20 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: Junio C Hamano, git
In-Reply-To: <alpine.LFD.2.00.0812131456040.30035@xanadu.home>

On Sat, Dec 13, 2008 at 03:06:40PM -0500, Nicolas Pitre wrote:

> If there are few objects to deltify, they might be split amongst threads 
> so that there is simply no other objects left to delta against within 
> the same thread.  Let's use the same 2*window treshold as used for the 
> final load balancing to allow extra threads to be created.
>
> This fixes the benign t5300 test failure.
 
I can confirm this fixes my t5300 failure. Thanks.

Tested-by: Jeff King <peff@peff.net>

-Peff

^ permalink raw reply

* [PATCH] git-fast-import possible memory corruption problem
From: YONETANI Tomokazu @ 2008-12-14  2:08 UTC (permalink / raw)
  To: git

[-- Attachment #1: Type: text/plain, Size: 919 bytes --]

Hello.
While trying to convert NetBSD CVS repository to Git, I've been
experiencing 100% reproducible crash of git-fast-import.  After
poking here and there and I noticed a dubious code fragment in
pool_alloc():
	:

        r = p->next_free;
        /* round out to a 'uintmax_t' alignment */
        if (len & (sizeof(uintmax_t) - 1))
                len += sizeof(uintmax_t) - (len & (sizeof(uintmax_t) - 1));
        p->next_free += len;
        return r;

As the `round out' takes place AFTER it found the room in the mem_pool,
there's a small chance of p->next_free being set outside of the chosen
area, up to (sizeof(uintmax_t) - 1) bytes.  pool_strdup() is one of the
functions which can trigger the problem, when pool_alloc() finds a room
at the end of a pool entry and the requested length is not multiple of
size(uintmax_t).  I believe attached patch addresses this problem.

Best regards,
YONETANI Tomokazu.

[-- Attachment #2: git-fast-import.patch --]
[-- Type: text/plain, Size: 1489 bytes --]

diff --git a/fast-import.c b/fast-import.c
index 3c035a5..fb4367a 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -549,11 +549,15 @@ static unsigned int hc_str(const char *s, size_t len)
 	return r;
 }
 
-static void *pool_alloc(size_t len)
+static void *_pool_alloc(size_t len, int zero)
 {
 	struct mem_pool *p;
 	void *r;
 
+	/* round out to a 'uintmax_t' alignment */
+	if (len & (sizeof(uintmax_t) - 1))
+		len += sizeof(uintmax_t) - (len & (sizeof(uintmax_t) - 1));
+
 	for (p = mem_pool; p; p = p->next_pool)
 		if ((p->end - p->next_free >= len))
 			break;
@@ -561,7 +565,8 @@ static void *pool_alloc(size_t len)
 	if (!p) {
 		if (len >= (mem_pool_alloc/2)) {
 			total_allocd += len;
-			return xmalloc(len);
+			r = xmalloc(len);
+			goto out;
 		}
 		total_allocd += sizeof(struct mem_pool) + mem_pool_alloc;
 		p = xmalloc(sizeof(struct mem_pool) + mem_pool_alloc);
@@ -572,19 +577,22 @@ static void *pool_alloc(size_t len)
 	}
 
 	r = p->next_free;
-	/* round out to a 'uintmax_t' alignment */
-	if (len & (sizeof(uintmax_t) - 1))
-		len += sizeof(uintmax_t) - (len & (sizeof(uintmax_t) - 1));
 	p->next_free += len;
+out:
+	if (zero)
+		memset(r, 0, len);
 	return r;
 }
 
+static void *pool_alloc(size_t len)
+{
+	return _pool_alloc(len, 0);
+}
+
 static void *pool_calloc(size_t count, size_t size)
 {
 	size_t len = count * size;
-	void *r = pool_alloc(len);
-	memset(r, 0, len);
-	return r;
+	return _pool_alloc(len, 1);
 }
 
 static char *pool_strdup(const char *s)

^ permalink raw reply related

* Re: [PATCH 1/2] gitweb: allow access to forks with strict_export
From: Matt McCutchen @ 2008-12-14  2:06 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: Junio C Hamano, git, Petr Baudis
In-Reply-To: <200812132351.37420.jnareb@gmail.com>

On Sat, 2008-12-13 at 23:51 +0100, Jakub Narebski wrote:
> "no_hide" (currently "include_forks") allows us to _not_ passing this
> parameter in other places than project_in_list(); undef is falsy.

Right.  That's why I made the current parameter $for_strict_export (so
only project_in_list passes it) rather than the negation.

> By the way, doesn't git_project_index and perhaps git_opml also need
> this parameter passed to git_get_projects_list?

Yes, now that you mention it, I suppose they should show forks, though
not hidden repositories.  Then git_get_projects_list can be called in
three different modes: include everything (project_in_list), include
forks but not hidden (git_get_project_index and git_opml), or include
neither forks nor hidden (git_project_list).  Should we have two
separate parameters to git_get_projects_list or a single three-valued
one?

That raises another point.  I was going to change git_get_projects_list
so that forks of a hidden project that are not themselves hidden appear
on the parent project's page but not in the main project list.  This
way, users who know about the parent project can navigate to the fork,
but the fork does not give away the existence of the parent project by
appearing in the main list.  Then I guess git_project_index and git_opml
should omit forks of hidden projects, meaning that some fork-checking
still has to take place with "include forks" on but "include hidden"
off.  This will make git_get_projects_list somewhat more complex but not
unmanageably so, and I do think it's the behavior we want.

I will send an updated patch.

-- 
Matt

^ permalink raw reply

* Re: Git weekly news: 2008-50
From: Jeff Whiteside @ 2008-12-14  2:14 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: Felipe Contreras, git list
In-Reply-To: <3ab397d0812131813s5c84aa98kdd76bc646bfb82b0@mail.gmail.com>

You seemed to get a lot of flak lastweek, but I liked the content
(both weeks), especially "why git is > than x" and the github
screencast link.   Thanks mate.

On Sat, Dec 13, 2008 at 6:13 PM, Jeff Whiteside
<jeff.m.whiteside@gmail.com> wrote:
>
> You seemed to get a lot of flak lastweek, but I liked the content (both weeks), especially "why git is > than x" and the github screencast link.   Thanks mate.
>
> On Sat, Dec 13, 2008 at 2:18 PM, Jakub Narebski <jnareb@gmail.com> wrote:
>>
>> "Felipe Contreras" <felipe.contreras@gmail.com> writes:
>>
>> > This week I'm trying to address some of the issues mentioned here. I
>> > still would like people to request user accounts to this blog if they
>> > wish to make some git related posts.
>> >
>> > http://gitlog.wordpress.com/2008/12/13/git-weekly-links-2008-50/
>> >
>> > == Articles ==
>> >
>> > Why Subversion does not suck
>> > http://blog.assembla.com/assemblablog/tabid/12618/bid/7437/Why-Subversion-does-not-suck.aspx
>> [...]
>>
>> Thanks a lot. I quite like the new format, both HTML version on blog,
>> and the format used here in this email.
>>
>> P.S. Small nitpick: you have changed the title of blog post, but not
>> subject of email.
>>
>> --
>> Jakub Narebski
>> Poland
>> ShadeHawk on #git
>> --
>> To unsubscribe from this list: send the line "unsubscribe git" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply

* Re: [PATCH 1/2] gitweb: allow access to forks with strict_export
From: Matt McCutchen @ 2008-12-14  1:51 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jakub Narebski, git, Petr Baudis
In-Reply-To: <7vr64b4sib.fsf@gitster.siamese.dyndns.org>

On Sat, 2008-12-13 at 14:31 -0800, Junio C Hamano wrote:
> Jakub Narebski <jnareb@gmail.com> writes:
> 
> > Matt McCutchen <matt@mattmccutchen.net> writes:
> >
> > CC-ed Petr Baudis, author of forks support in gitweb.
> >
> >> git_get_projects_list excludes forks in order to unclutter the main
> >> project list, but this caused the strict_export check, which also relies
> >> on git_get_project_list, to incorrectly fail for forks.  This patch adds
> >> an argument so git_get_projects_list knows when it is being called for a
> >> strict_export check (as opposed to a user-visible project list) and
> >> doesn't exclude the forks.
> >>
> >> Signed-off-by: Matt McCutchen <matt@mattmccutchen.net>
> >
> > Looks good for me.
> 
> That sounds like a broken API to me.
> 
> At least, please have the decency to not call the extra parameter "for
> strict export".  I would understand it if the extra parameter is called
> "toplevel_only" (or its negation, "include_forks").
> 
> IOW, don't name a parameter after the name of one caller that happens to
> want an unspecified special semantics, without saying what that special
> semantics is.  Instead, name it after the special semantics that the
> argument triggers.

I disagree.  The parameter is really "include forks (if there is such a
concept under the current config)", and with my second patch, it becomes
"include hidden projects" too.  That's really unwieldy.

In my view, the parameter makes the distinction between generating a
filtered list for user consumption and a list of everything for a
strict_export check.  The particular semantics it activates may evolve
as gitweb does (case in point: my second patch).  The current semantics
can be described in a comment on git_get_projects_list.

Granted, there may be a better name for the parameter than
$for_strict_export.  How about $include_all?

-- 
Matt

^ permalink raw reply

* Re: [PATCH] Simplified GIT usage guide
From: Ping Yin @ 2008-12-14  1:45 UTC (permalink / raw)
  To: Nick Andrew
  Cc: David Howells, Johannes Schindelin, torvalds, git, linux-kernel,
	Miklos Vajna
In-Reply-To: <20081213230504.GA21912@mail.local.tull.net>

On Sun, Dec 14, 2008 at 7:05 AM, Nick Andrew <nick@nick-andrew.net> wrote:
> The way I did it was to start with the directed acyclic graph of
> commits, explaining how branches fork the graph and merges join
> it. This was presented to people who know subversion, and so they
> immediately became aware that there are other ways to manage source
> code than in a linear r1 r2 r3 r4 r5. I described tags and branch
> heads briefly.
>
> Next up I described the things you'd do with git: add new commits,
> create a branch, merge a branch, rebase, tag, push and fetch and
> showed what that does with the dag of commits.
>
> Finally I showed the actual commands used to perform those actions.
> I didn't get into the object database structure at all (that was
> prepared in case I had extra time).
>

I think this is the right way to start with the DAG. And i do the same.

^ permalink raw reply

* Re: [PATCH try 2] gitweb: Add option to put a trailing slash on pathinfo-style project URLs
From: Matt McCutchen @ 2008-12-14  1:43 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: git, Giuseppe Bilotta
In-Reply-To: <m3tz97g329.fsf@localhost.localdomain>

On Sat, 2008-12-13 at 13:47 -0800, Jakub Narebski wrote:
> Errr... I see that it adds trailing slash only for project-only
> path_info links, but the commit message was not entirely clear for me.

I will clarify the message.

> BTW. encoding data in position in array feels a bit hacky to me, but
> I guess that is the limitation of current %feature design, with
> 'default' having to be array (reference).
> 
> >  	# Note that you will need to change the default location of CSS,
> >  	# favicon, logo and possibly other files to an absolute URL. Also,
> >  	# if gitweb.cgi serves as your indexfile, you will need to force
> > @@ -829,8 +834,8 @@ sub href (%) {
> >  		}
> >  	}
> >  
> > -	my $use_pathinfo = gitweb_check_feature('pathinfo');
> > -	if ($use_pathinfo) {
> > +	my @use_pathinfo = gitweb_get_feature('pathinfo');
> 
> Why not name those variables for better readability?
> 
> +       my ($use_pathinfo, $trailing_slash) = gitweb_get_feature('pathinfo');

I'll do that.

> > +	if ($use_pathinfo[0]) {
> >  		# try to put as many parameters as possible in PATH_INFO:
> >  		#   - project name
> >  		#   - action
> > @@ -845,7 +850,12 @@ sub href (%) {
> >  		$href =~ s,/$,,;
> >  
> >  		# Then add the project name, if present
> > -		$href .= "/".esc_url($params{'project'}) if defined $params{'project'};
> > +		my $proj_href = undef;
> > +		if (defined $params{'project'}) {
> > +			$href .= "/".esc_url($params{'project'});
> > +			# Save for trailing-slash check below.
> > +			$proj_href = $href;
> > +		}
> >  		delete $params{'project'};
> >  
> >  		# since we destructively absorb parameters, we keep this
> > @@ -903,6 +913,10 @@ sub href (%) {
> >  			$href .= $known_snapshot_formats{$fmt}{'suffix'};
> >  			delete $params{'snapshot_format'};
> >  		}
> > +
> > +		# If requested in the configuration, add a trailing slash to a URL that
> > +		# has nothing appended after the project path.
> > +		$href .= '/' if ($use_pathinfo[1] && defined $proj_href && $href eq $proj_href);
> >  	}
> 
> The check _feels_ inefficient.  I think (but feel free to disagree) that
> it would be better to use something like $project_pathinfo, set it
> when adding project as pathinfo, and unset if we add anything else as
> pathinfo.

I considered doing that, but I decided that not having to litter the
preceding code with manipulation of $project_pathinfo outweighed
whatever negligible performance difference there might be.

> > +		if ($use_pathinfo[0]) {
> >  			$action .= "/".esc_url($project);
> > +			# Add a trailing slash if requested in the configuration.
> > +			$action .= '/' if ($use_pathinfo[1]);
> 
> Hmmm... let me check something... you rely on the fact that $project
> doesn't end with slash, while I think (but please check it) that it
> can end with slash if it is provided by CGI query.

You are right; in fact, this is already a problem for the strict_export
check.  Gitweb should probably strip trailing slashes when it reads the
"p" parameter.  I will submit a separate patch for that.

-- 
Matt

^ permalink raw reply

* Re: [PATCH try 2] gitweb: Add option to put a trailing slash on pathinfo-style project URLs
From: Matt McCutchen @ 2008-12-14  1:13 UTC (permalink / raw)
  To: Giuseppe Bilotta; +Cc: Jakub Narebski, git
In-Reply-To: <cb7bb73a0812131423h1f629ec1n9e8eacd657a4901@mail.gmail.com>

On Sat, 2008-12-13 at 23:23 +0100, Giuseppe Bilotta wrote:
> On Sat, Dec 13, 2008 at 10:47 PM, Jakub Narebski <jnareb@gmail.com> wrote:
> > Matt McCutchen <matt@mattmccutchen.net> writes:
> >
> >> My Web site uses pathinfo mode and some rewrite magic to show the gitweb
> >> interface at the URL of the real repository directory (which users also
> >> pull from).  In this case, it's desirable to end generated links to the
> >> project in a trailing slash so the Web server doesn't have to redirect
> >> the client to add the slash.  This patch adds a second element to the
> >> "pathinfo" feature configuration to control the trailing slash.
> >>
> >> Signed-off-by: Matt McCutchen <matt@mattmccutchen.net>
> >
> > Did you check that it does not confuse gitweb if filename parameter is
> > passed using pathinfo?  Gitweb used to rely on final '/' to
> > distinguish directory pathnames from ordinary pathnames, but I think
> > currently thanks to the fact that gitweb now embeds action in pathinfo
> > URL, and does not need to guess type, it is not an issue.
> >
> > Or only project URLs (i.e. only with project parameter, i.e. only
> > "http://git.example.com/project.git/" but not other path_info links)
> > have trailing slash added?
> >
> > Errr... I see that it adds trailing slash only for project-only
> > path_info links, but the commit message was not entirely clear for me.
> 
> If indeed the additional / is only asked for in summary view, I think
> there's no need for a feature toggle, we can always put it there. If
> not, I'm really curious about seeing the rewrite rules (they might
> also be worth adding to the gitweb documentation as examples of 'power
> usage').

The trailing slash is used only when the URL refers to a project with no
appended parameters (i.e., summary view), because the URL refers to the
real git dir on disk (hence, pulling from the same URL) and it plays
nicer with the Web server configuration to have the trailing slash.

I was wary about changing the default behavior, but if you and Jakub
both think it's OK, that's great.

I was thinking of proposing the addition of some info about my setup,
including the rewrite rules, to the documentation.  Maybe we could do
that after dealing with the patches.

-- 
Matt

^ permalink raw reply

* [RFC/PATCH v2] gitweb: Incremental blame (proof of concept)
From: Jakub Narebski @ 2008-12-14  0:17 UTC (permalink / raw)
  To: git
  Cc: Luben Tuikov, Nanako Shiraishi, Petr Baudis, Fredrik Kuivinen,
	Jakub Narebski
In-Reply-To: <20081210200908.16899.36727.stgit@localhost.localdomain>

This is tweaked up version of Petr Baudis <pasky@suse.cz> patch, which
in turn was tweaked up version of Fredrik Kuivinen <frekui@gmail.com>'s
proof of concept patch.  It adds 'blame_incremental' view, which
incrementally displays line data in blame view using JavaScript (AJAX).

The original patch by Fredrik Kuivinen has been lightly tested in a
couple of browsers (Firefox, Mozilla, Konqueror, Galeon, Opera and IE6).
The next patch by Petr Baudis has been tested in Firefox and Epiphany.
This patch has been lightly tested in Mozilla 1.17.2 and Konqueror
3.5.3.

This patch does not (contrary to the one by Petr Baudis) enable this
view in gitweb: there are no links leading to 'blame_incremental'
action.  You would have to generate URL 'by hand' (e.g. changing 'blame'
or 'blob' in gitweb URL to 'blame_incremental').  Having links in gitweb
lead to this new action (e.g. by rewriting them like in previous patch),
if JavaScript is enabled in browser, is left for later.

Like earlier patch by Per Baudis it avoids code duplication, but it goes
one step further and use git_blame_common for ordinary blame view, for
incremental blame, and (which is change from previous patch) for
incremental blame data.

How the 'blame_incremental' view works:
* gitweb generates initial info by putting file contents (from
  git-cat-file) together with line numbers in blame table
* then gitweb makes web browser JavaScript engine call startBlame()
  function from blame.js
* startBlame() opens connection to 'blame_data' view, which in turn
  calls "git blame --incremental" for a file, and streams output of
  git-blame to JavaScript (blame.js)
* blame.js updates line info in blame view, coloring it, and updating
  progress info; note that it has to use 3 colors to ensure that
  different neighbour groups have different styles
* when 'blame_data' ends, and blame.js finishes updating line info,
  it fixes colors to match (as far as possible) ordinary 'blame' view,
  and updates generating time info.

This code uses http://ajaxpatterns.org/HTTP_Streaming pattern.

It deals with streamed 'blame_data' server error by notifying about them
in the progress info area (just in case).

This patch adds GITWEB_BLAMEJS compile configuration option, and
modifies git-instaweb.sh to take blame.js into account, but it does not
update gitweb/README file (as it is only proof of concept patch).  The
code for git-instaweb.sh was taken from Pasky's patch.

While at it, this patch uniquifies td.dark and td.dark2 style: they
differ only in that td.dark2 doesn't have style for :hover.


This patch also adds showing time (in seconds) it took to generate
a page in page footer (based on example code by Pasky), even though
it is independent change, to be able to evaluate incremental blame in
gitweb better.  In proper patch series it would be independent commit;
and it probably would provide fallback if Time::HiRes is not available
(by e.g. not showing generating time info), even though this is
unlikely.

Signed-off-by: Fredrik Kuivinen <frekui@gmail.com>
Signed-off-by: Petr Baudis <pasky@suse.cz>
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
Differences from previous version of patch:
 * Fixed copying git-instaweb related changes from Petr Baudis patch;
   git-instaweb should not work with 'blame_incremental' view
 * Fixed links in blame table in 'blame_incremental' view, and add
   support for href(..., -partial_query=>1)
 * The title attribute for "Commit" column ("sha1" cells) agrees with
   the one used for 'blame' view, meaning using localtime e.g. 
     'Kay Sievers, 2005-08-07 21:49:46 +0200'
   There was a bug in Pasky and Frederik patch here...
 * Incremental blame data generation can lead to neighbour groups
   blaming the same commit; such groups are now concatenated when
   fixing colors to zebra pattern. This mean that 'blame_incremental'
   output should match 'blame' view.
 * New feature adding author initials below shortened sha1 of commit
   was dropped; it was not present in 'blame' view, and it would make
   fixing of line grouping mentioned in previous point much more
   difficult.

 * Use more robust createRequestObject(), using try ... catch,
   taken from AJAX article at WikiPedia.
 * Better error handling: show big warning with link to 'blame'
   view if scripts are disabled, show error if XMLHttpRequest object
   cannot be started, show statusText on server returning status != 200
 * use deleteCell (DOM HTML) rather than removeChild (DOM Core)
   to delete cell(s) below cell spanning multiple rows
 * Set 'commits' to empty associative array to mark memory to be freed
 * A few improvements to findColorNo and its helper functions
 * Remember about Internet Explorer quirk when setting class attr
 * Added many comments, changed names of few variables to be more
   readable, rename few functions, split off functions, etc.
 * A bit of style cleanup: always use block with if, in continued
   (broken) lines put operator at the end of line, use literal object
   notation "{}" to initialize empty associative array rather than
   cryptic "new Object()", use === and !=== instead of == and !=,
   always use radix parameter to parseInt (i.e. parseInt(str, 10))  
   All those changes were recommended by JSLint.

 Makefile           |    6 +-
 git-instaweb.sh    |    7 +
 gitweb/blame.js    |  470 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 gitweb/gitweb.css  |   27 +++-
 gitweb/gitweb.perl |  263 ++++++++++++++++++++---------
 5 files changed, 683 insertions(+), 90 deletions(-)
 create mode 100644 gitweb/blame.js

diff --git a/Makefile b/Makefile
index 5158197..d2d3fff 100644
--- a/Makefile
+++ b/Makefile
@@ -218,6 +218,7 @@ GITWEB_HOMETEXT = indextext.html
 GITWEB_CSS = gitweb.css
 GITWEB_LOGO = git-logo.png
 GITWEB_FAVICON = git-favicon.png
+GITWEB_BLAMEJS = blame.js
 GITWEB_SITE_HEADER =
 GITWEB_SITE_FOOTER =
 
@@ -1209,13 +1210,14 @@ gitweb/gitweb.cgi: gitweb/gitweb.perl
 	    -e 's|++GITWEB_CSS++|$(GITWEB_CSS)|g' \
 	    -e 's|++GITWEB_LOGO++|$(GITWEB_LOGO)|g' \
 	    -e 's|++GITWEB_FAVICON++|$(GITWEB_FAVICON)|g' \
+	    -e 's|++GITWEB_BLAMEJS++|$(GITWEB_BLAMEJS)|g' \
 	    -e 's|++GITWEB_SITE_HEADER++|$(GITWEB_SITE_HEADER)|g' \
 	    -e 's|++GITWEB_SITE_FOOTER++|$(GITWEB_SITE_FOOTER)|g' \
 	    $< >$@+ && \
 	chmod +x $@+ && \
 	mv $@+ $@
 
-git-instaweb: git-instaweb.sh gitweb/gitweb.cgi gitweb/gitweb.css
+git-instaweb: git-instaweb.sh gitweb/gitweb.cgi gitweb/gitweb.css gitweb/blame.js
 	$(QUIET_GEN)$(RM) $@ $@+ && \
 	sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
 	    -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
@@ -1224,6 +1226,8 @@ git-instaweb: git-instaweb.sh gitweb/gitweb.cgi gitweb/gitweb.css
 	    -e '/@@GITWEB_CGI@@/d' \
 	    -e '/@@GITWEB_CSS@@/r gitweb/gitweb.css' \
 	    -e '/@@GITWEB_CSS@@/d' \
+	    -e '/@@GITWEB_BLAMEJS@@/r gitweb/blame.js' \
+	    -e '/@@GITWEB_BLAMEJS@@/d' \
 	    -e 's|@@PERL@@|$(PERL_PATH_SQ)|g' \
 	    $@.sh > $@+ && \
 	chmod +x $@+ && \
diff --git a/git-instaweb.sh b/git-instaweb.sh
index 0843372..510789f 100755
--- a/git-instaweb.sh
+++ b/git-instaweb.sh
@@ -268,8 +268,15 @@ gitweb_css () {
 EOFGITWEB
 }
 
+gitweb_blamejs () {
+	cat > "$1" <<\EOFGITWEB
+@@GITWEB_BLAMEJS@@
+EOFGITWEB
+}
+
 gitweb_cgi "$GIT_DIR/gitweb/gitweb.cgi"
 gitweb_css "$GIT_DIR/gitweb/gitweb.css"
+gitweb_blamejs "$GIT_DIR/gitweb/blame.js"
 
 case "$httpd" in
 *lighttpd*)
diff --git a/gitweb/blame.js b/gitweb/blame.js
new file mode 100644
index 0000000..6288bd1
--- /dev/null
+++ b/gitweb/blame.js
@@ -0,0 +1,470 @@
+// Copyright (C) 2007, Fredrik Kuivinen <frekui@gmail.com>
+
+var DEBUG = 0;
+function debug(str) {
+	if (DEBUG) {
+		alert(str);
+	}
+}
+
+function createRequestObject() {
+	try {
+		return new XMLHttpRequest();
+	} catch(e) {}
+	try {
+		return new ActiveXObject("Msxml2.XMLHTTP");
+	} catch (e) {}
+	try {
+		return new ActiveXObject("Microsoft.XMLHTTP");
+	} catch (e) {}
+
+	debug("XMLHttpRequest not supported");
+	return null;
+}
+
+var http; // XMLHttpRequest object
+var projectUrl; // partial query
+
+// 'commits' is an associative map. It maps SHA1s to Commit objects.
+var commits = {};
+
+function Commit(sha1) {
+	this.sha1 = sha1;
+}
+
+// convert month or day of the month to string, padding it with
+// '0' (zero) to two characters width if necessary, e.g. 2 -> '02'
+function zeroPad(n) {
+	if (n < 10) {
+		return '0' + n;
+	} else {
+		return n.toString();
+	}
+}
+
+// pad number N with nonbreakable spaces on the right, to WIDTH characters
+// example: spacePad(12, 3) == '&nbsp;12' ('&nbsp;' is nonbreakable space)
+function spacePad(n,width) {
+	var scale = 1;
+	var str = '';
+
+	while (width > 1) {
+		scale *= 10;
+		if (n < scale) {
+			str += '&nbsp;';
+		}
+		width--;
+	}
+	return str + n;
+}
+
+var blamedLines = 0;
+var totalLines  = '???';
+var div_progress_bar;
+var div_progress_info;
+
+// how many lines does a file have, used in progress info
+function countLines() {
+	var table =
+		document.getElementById('blame_table') ||
+		document.getElementsByTagName('table')[0];
+
+	if (table) {
+		return table.getElementsByTagName('tr').length - 1; // for header
+	} else {
+		return '...';
+	}
+}
+
+// update progress info and length (width) of progress bar
+function updateProgressInfo() {
+	if (!div_progress_info) {
+		div_progress_info = document.getElementById('progress_info');
+	}
+	if (!div_progress_bar) {
+		div_progress_bar = document.getElementById('progress_bar');
+	}
+	if (!div_progress_info && !div_progress_bar) {
+		return;
+	}
+
+	var percentage = Math.floor(100.0*blamedLines/totalLines);
+
+	if (div_progress_info) {
+		div_progress_info.innerHTML  = blamedLines + ' / ' + totalLines +
+			' ('+spacePad(percentage,3)+'%)';
+	}
+
+	if (div_progress_bar) {
+		div_progress_bar.setAttribute('style', 'width: '+percentage+'%;');
+	}
+}
+
+// used to extract N from colorN, where N is a number,
+var colorRe = new RegExp('color([0-9]*)');
+
+// return N if <tr class="colorN">, otherwise return null
+// (some browsers require CSS class names to begin with letter)
+function getColorNo(tr) {
+	if (!tr) {
+		return null;
+	}
+	var className = tr.getAttribute('class');
+	if (className) {
+		match = colorRe.exec(className);
+		if (match) {
+			return parseInt(match[1],10);
+		}
+	}
+	return null;
+}
+
+// return one of given possible colors
+// example: chooseColorNoFrom(2, 3) might be 2 or 3
+function chooseColorNoFrom() {
+	// simplest version
+	return arguments[0];
+}
+
+// given two neigbour <tr> elements, find color which would be different
+// from color of both of neighbours; used to 3-color blame table
+function findColorNo(tr_prev, tr_next) {
+	var color_prev = getColorNo(tr_prev);
+	var color_next = getColorNo(tr_next);
+
+
+	// neither of neighbours has color set
+	if (!color_prev && !color_next) {
+		return chooseColorNoFrom(1,2,3);
+	}
+
+	// either both neighbours have the same color,
+	// or only one of neighbours have color set
+	var color;
+	if (color_prev == color_next) {
+		color = color_prev; // = color_next;
+	} else if (!color_prev) {
+		color = color_next;
+	} else if (!color_next) {
+		color = color_prev;
+	}
+	if (color) {
+		return chooseColorNoFrom((color % 3) + 1, ((color+1) % 3) + 1);
+	}
+
+	// neighbours have different colors
+	return (3 - ((color_prev + color_next) % 3));
+}
+
+// used to extract hours and minutes from timezone info, e.g '-0900'
+var tzRe = new RegExp('^([+-][0-9][0-9])([0-9][0-9])$');
+
+// called for each blame entry, as soon as it finishes
+function handleLine(commit) {
+	/* 
+	   This is the structure of the HTML fragment we are working
+	   with:
+	   
+	   <tr id="l123" class="">
+	     <td class="sha1" title=""><a href=""></a></td>
+	     <td class="linenr"><a class="linenr" href="">123</a></td>
+	     <td class="pre"># times (my ext3 doesn&#39;t).</td>
+	   </tr>
+	*/
+
+	var resline = commit.resline;
+
+	// format date and time string only once per commit
+	if (!commit.info) {
+		var localDate = new Date(); // date corrected by timezone
+		var match = tzRe.exec(commit.authorTimezone);
+		localDate.setTime(1000 * (commit.authorTime +
+			(parseInt(match[1],10)*3600 + parseInt(match[2],10)*60)));
+		var localDateStr = // e.g. '2005-08-07'
+			localDate.getUTCFullYear()         + '-' +
+			zeroPad(localDate.getUTCMonth()+1) + '-' +
+			zeroPad(localDate.getUTCDate());
+		var localTimeStr = // e.g. '21:49:46'
+			zeroPad(localDate.getUTCHours())   + ':' +
+			zeroPad(localDate.getUTCMinutes()) + ':' +
+			zeroPad(localDate.getUTCSeconds());
+
+		/* e.g. 'Kay Sievers, 2005-08-07 21:49:46 +0200' */
+		commit.info = commit.author + ', ' + localDateStr + ' ' +
+			localTimeStr + ' ' + commit.authorTimezone;
+	}
+
+	// color depends on group of lines, not only on blamed commit
+	var colorNo = findColorNo(
+		document.getElementById('l'+(resline-1)),
+		document.getElementById('l'+(resline+commit.numlines))
+	);
+
+
+	for (var i = 0; i < commit.numlines; i++) {
+		var tr = document.getElementById('l'+resline);
+		if (!tr) {
+			debug('tr is null! resline: ' + resline);
+			break;
+		}
+		/*
+			<tr id="l123" class="">
+			  <td class="sha1" title=""><a href=""></a></td>
+			  <td class="linenr"><a class="linenr" href="">123</a></td>
+			  <td class="pre"># times (my ext3 doesn&#39;t).</td>
+			</tr>
+		*/
+		var td_sha1  = tr.firstChild;
+		var a_sha1   = td_sha1.firstChild;
+		var a_linenr = td_sha1.nextSibling.firstChild;
+
+		/* <tr id="l123" class=""> */
+		if (colorNo !== null) {
+			tr.setAttribute('class', 'color'+colorNo);
+			// Internet Explorer needs this
+			tr.setAttribute('className', 'color'+colorNo);
+		}
+		/* <td class="sha1" title="?" rowspan="?"><a href="?">?</a></td> */
+		if (i === 0) {
+			td_sha1.title = commit.info;
+			td_sha1.setAttribute('rowspan', commit.numlines);
+
+			a_sha1.href = projectUrl + ';a=commit;h=' + commit.sha1;
+			a_sha1.innerHTML = commit.sha1.substr(0, 8);
+
+		} else {
+			//tr.removeChild(td_sha1); // DOM2 Core way
+			tr.deleteCell(0); // DOM2 HTML way
+		}
+
+		/* <td class="linenr"><a class="linenr" href="?">123</a></td> */
+		a_linenr.href = projectUrl + ';a=blame;hb=' + commit.sha1 +
+			';f=' + commit.filename + '#l' + (commit.srcline + i);
+
+		resline++;
+		blamedLines++;
+
+		//updateProgressInfo();
+	}
+}
+
+function startOfGroup(tr) {
+	return tr.firstChild.getAttribute('class') == 'sha1';
+}
+
+function fixColorsAndGroups() {
+	var colorClasses = ['light2', 'dark2'];
+	var linenum = 1;
+	var tr, prev_group;
+	var colorClass = 0;
+
+	while ((tr = document.getElementById('l'+linenum))) {
+		if (startOfGroup(tr, linenum, document)) {
+			if (prev_group &&
+			    prev_group.firstChild.firstChild.href ==
+			            tr.firstChild.firstChild.href) {
+				// we have to concatenate groups
+				var rows = prev_group.firstChild.getAttribute('rowspan');
+				// assume that we have rowspan even for rowspan="1"
+				prev_group.firstChild.setAttribute('rowspan',
+					(rows + tr.firstChild.getAttribute('rowspan')));
+				tr.removeChild(tr.firstChild);
+			} else {
+				colorClass = (colorClass + 1) % 2;
+				prev_group = tr;
+			}
+		}
+		tr.setAttribute('class', colorClasses[colorClass]);
+		// Internet Explorer needs this
+		tr.setAttribute('className', colorClasses[colorClass]);
+		linenum++;
+	}
+}
+
+var t_interval_server = '';
+var t0 = new Date();
+
+// write how much it took to generate data, and to run script
+function writeTimeInterval() {
+	var info = document.getElementById('generate_time');
+	if (!info) {
+		return;
+	}
+	var t1 = new Date();
+
+	info.innerHTML += ' + ' +
+		t_interval_server+'s server (blame_data) / ' +
+		(t1.getTime() - t0.getTime())/1000 + 's client (JavaScript)';
+}
+
+// ----------------------------------------------------------------------
+
+var prevDataLength = -1;
+var nextLine = 0;
+var inProgress = false;
+
+var sha1Re = new RegExp('([0-9a-f]{40}) ([0-9]+) ([0-9]+) ([0-9]+)');
+var infoRe = new RegExp('([a-z-]+) ?(.*)');
+var endRe = new RegExp('END ?(.*)');
+var curCommit = new Commit();
+
+var pollTimer = null;
+
+function handleResponse() {
+	debug('handleResp ready: ' + http.readyState +
+	      ' respText null?: ' + (http.responseText === null) +
+	      ' progress: ' + inProgress);
+
+	if (http.readyState != 4 && http.readyState != 3) {
+		return;
+	}
+
+	// the server returned error
+	if (http.readyState == 3 && http.status != 200) {
+		return;
+	}
+	if (http.readyState == 4 && http.status != 200) {
+		if (!div_progress_info) {
+			div_progress_info = document.getElementById('progress_info');
+		}
+
+		if (div_progress_info) {
+			div_progress_info.setAttribute('class', 'error');
+			// Internet Explorer needs this
+			div_progress_info.setAttribute('className', 'error');
+			div_progress_info.innerHTML = 'Server error: ' +
+				http.status+' - '+(http.statusText || 'Error contacting server');
+		}
+
+		clearInterval(pollTimer);
+		inProgress = false;
+	}
+
+	// In konqueror http.responseText is sometimes null here...
+	if (http.responseText === null) {
+		return;
+	}
+
+	// in case we were called before finished processing
+	if (inProgress) {
+		return;
+	} else {
+		inProgress = true;
+	}
+
+	while (prevDataLength != http.responseText.length) {
+		if (http.readyState == 4 &&
+		    prevDataLength == http.responseText.length) {
+			break;
+		}
+
+		prevDataLength = http.responseText.length;
+		var response = http.responseText.substring(nextLine);
+		var lines = response.split('\n');
+		nextLine = nextLine + response.lastIndexOf('\n') + 1;
+		if (response[response.length-1] != '\n') {
+			lines.pop();
+		}
+
+		for (var i = 0; i < lines.length; i++) {
+			var match = sha1Re.exec(lines[i]);
+			if (match) {
+				var sha1 = match[1];
+				var srcline = parseInt(match[2],10);
+				var resline = parseInt(match[3],10);
+				var numlines = parseInt(match[4],10);
+				var c = commits[sha1];
+				if (!c) {
+					c = new Commit(sha1);
+					commits[sha1] = c;
+				}
+
+				c.srcline = srcline;
+				c.resline = resline;
+				c.numlines = numlines;
+				curCommit = c;
+			} else if ((match = infoRe.exec(lines[i]))) {
+				var info = match[1];
+				var data = match[2];
+				if (info == 'filename') {
+					curCommit.filename = data;
+					handleLine(curCommit);
+					updateProgressInfo();
+				} else if (info == 'author') {
+					curCommit.author = data;
+				} else if (info == 'author-time') {
+					curCommit.authorTime = parseInt(data,10);
+				} else if (info == 'author-tz') {
+					curCommit.authorTimezone = data;
+				}
+			} else if ((match = endRe.exec(lines[i]))) {
+				t_interval_server = match[1];
+				debug('END: '+lines[i]);
+			} else if (lines[i] !== '') {
+				debug('malformed line: ' + lines[i]);
+			}
+		}
+	}
+
+	// did we finish work?
+	if (http.readyState == 4 &&
+	    prevDataLength == http.responseText.length) {
+		clearInterval(pollTimer);
+
+		fixColorsAndGroups();
+		writeTimeInterval();
+		commits = {}; // free memory
+	}
+
+	inProgress = false;
+}
+
+// ============================================================
+// ------------------------------------------------------------
+
+/*
+	Function: startBlame
+
+	Incrementally update line data in blame_incremental view in gitweb.
+
+	Parameters:
+
+		blamedataUrl - URL to server script generating blame data.
+		bUrl -partial URL to project, used to generate links in blame.
+
+	Comments:
+
+	Called from 'blame_incremental' view after loading table with
+	file contents, a base for blame view.
+*/
+function startBlame(blamedataUrl, bUrl) {
+	debug('startBlame('+blamedataUrl+', '+bUrl+')');
+
+	http = createRequestObject();
+	if (!http) {
+		div_progress_info = document.getElementById('progress_info');
+
+		if (div_progress_info) {
+			div_progress_info.setAttribute('class', 'error');
+			// Internet Explorer needs this
+			div_progress_info.setAttribute('className', 'error');
+			div_progress_info.innerHTML = 'XMLHttpRequest not supported';
+		}
+
+		return;
+	}
+
+	t0 = new Date();
+	projectUrl = bUrl;
+	totalLines = countLines();
+	updateProgressInfo();
+
+	http.open('get', blamedataUrl);
+	http.onreadystatechange = handleResponse;
+	http.send(null);
+
+	// not all browsers call onreadystatechange event on each server flush
+	pollTimer = setInterval(handleResponse, 2000);
+}
+
+// end of blame.js
diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css
index a01eac8..e359618 100644
--- a/gitweb/gitweb.css
+++ b/gitweb/gitweb.css
@@ -223,11 +223,7 @@ tr.light:hover {
 	background-color: #edece6;
 }
 
-tr.dark {
-	background-color: #f6f6f0;
-}
-
-tr.dark2 {
+tr.dark, tr.dark2 {
 	background-color: #f6f6f0;
 }
 
@@ -235,6 +231,14 @@ tr.dark:hover {
 	background-color: #edece6;
 }
 
+tr.color1:hover { background-color: #e6ede6; }
+tr.color2:hover { background-color: #e6e6ed; }
+tr.color3:hover { background-color: #ede6e6; }
+
+tr.color1 { background-color: #f6fff6; }
+tr.color2 { background-color: #f6f6ff; }
+tr.color3 { background-color: #fff6f6; }
+
 td {
 	padding: 2px 5px;
 	font-size: 100%;
@@ -255,7 +259,7 @@ td.sha1 {
 	font-family: monospace;
 }
 
-td.error {
+.error {
 	color: red;
 	background-color: yellow;
 }
@@ -326,6 +330,17 @@ td.mode {
 	font-family: monospace;
 }
 
+/* progress of blame_interactive */
+div#progress_bar {
+	height: 2px;
+	margin-bottom: -2px;
+	background-color: #d8d9d0;
+}
+div#progress_info {
+	float: right;
+	text-align: right;
+}
+
 /* styling of diffs (patchsets): commitdiff and blobdiff views */
 div.diff.header,
 div.diff.extended_header {
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 4987fdc..93a4e82 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -18,6 +18,9 @@ use File::Find qw();
 use File::Basename qw(basename);
 binmode STDOUT, ':utf8';
 
+use Time::HiRes qw(gettimeofday tv_interval);
+our $t0 = [gettimeofday];
+
 BEGIN {
 	CGI->compile() if $ENV{'MOD_PERL'};
 }
@@ -74,6 +77,8 @@ our $stylesheet = undef;
 our $logo = "++GITWEB_LOGO++";
 # URI of GIT favicon, assumed to be image/png type
 our $favicon = "++GITWEB_FAVICON++";
+# URI of blame.js
+our $blamejs = "++GITWEB_BLAMEJS++";
 
 # URI and label (title) of GIT logo link
 #our $logo_url = "http://www.kernel.org/pub/software/scm/git/docs/";
@@ -493,6 +498,8 @@ our %cgi_param_mapping = @cgi_param_mapping;
 # we will also need to know the possible actions, for validation
 our %actions = (
 	"blame" => \&git_blame,
+	"blame_incremental" => \&git_blame_incremental,
+	"blame_data" => \&git_blame_data,
 	"blobdiff" => \&git_blobdiff,
 	"blobdiff_plain" => \&git_blobdiff_plain,
 	"blob" => \&git_blob,
@@ -919,7 +926,8 @@ sub href (%) {
 			}
 		}
 	}
-	$href .= "?" . join(';', @result) if scalar @result;
+	$href .= "?" . join(';', @result)
+		if ($params{-partial_query} or scalar @result);
 
 	return $href;
 }
@@ -1272,7 +1280,7 @@ use constant {
 };
 
 # submodule/subproject, a commit object reference
-sub S_ISGITLINK($) {
+sub S_ISGITLINK {
 	my $mode = shift;
 
 	return (($mode & S_IFMT) == S_IFGITLINK)
@@ -1558,7 +1566,7 @@ sub format_diff_from_to_header {
 	# no extra formatting for "^--- /dev/null"
 	if (! $diffinfo->{'nparents'}) {
 		# ordinary (single parent) diff
-		if ($line =~ m!^--- "?a/!) {
+		if ($line =~ m!^--- "?a/!) {#"
 			if ($from->{'href'}) {
 				$line = '--- a/' .
 				        $cgi->a({-href=>$from->{'href'}, -class=>"path"},
@@ -1816,7 +1824,7 @@ sub git_cmd {
 # Try to avoid using this function wherever possible.
 sub quote_command {
 	return join(' ',
-		    map( { my $a = $_; $a =~ s/(['!])/'\\$1'/g; "'$a'" } @_ ));
+		    map( { my $a = $_; $a =~ s/(['!])/'\\$1'/g; "'$a'" } @_ ));#'
 }
 
 # get HEAD ref of given project as hash
@@ -2874,13 +2882,13 @@ sub git_header_html {
 	# 'application/xhtml+xml', otherwise send it as plain old 'text/html'.
 	# we have to do this because MSIE sometimes globs '*/*', pretending to
 	# support xhtml+xml but choking when it gets what it asked for.
-	if (defined $cgi->http('HTTP_ACCEPT') &&
-	    $cgi->http('HTTP_ACCEPT') =~ m/(,|;|\s|^)application\/xhtml\+xml(,|;|\s|$)/ &&
-	    $cgi->Accept('application/xhtml+xml') != 0) {
-		$content_type = 'application/xhtml+xml';
-	} else {
+	#if (defined $cgi->http('HTTP_ACCEPT') &&
+	#    $cgi->http('HTTP_ACCEPT') =~ m/(,|;|\s|^)application\/xhtml\+xml(,|;|\s|$)/ &&
+	#    $cgi->Accept('application/xhtml+xml') != 0) {
+	#	$content_type = 'application/xhtml+xml';
+	#} else {
 		$content_type = 'text/html';
-	}
+	#}
 	print $cgi->header(-type=>$content_type, -charset => 'utf-8',
 	                   -status=> $status, -expires => $expires);
 	my $mod_perl_version = $ENV{'MOD_PERL'} ? " $ENV{'MOD_PERL'}" : '';
@@ -3042,6 +3050,14 @@ sub git_footer_html {
 	}
 	print "</div>\n"; # class="page_footer"
 
+	print "<div class=\"page_footer\">\n";
+	print 'This page took '.
+	      '<span id="generate_time" class="time_span">'.
+	      tv_interval($t0, [gettimeofday]).'s'.
+	      '</span>'.
+	      " to generate.\n";
+	print "</div>\n"; # class="page_footer"
+
 	if (-f $site_footer) {
 		insert_file($site_footer);
 	}
@@ -3803,7 +3819,7 @@ sub git_patchset_body {
 	while ($patch_line) {
 
 		# parse "git diff" header line
-		if ($patch_line =~ m/^diff --git (\"(?:[^\\\"]*(?:\\.[^\\\"]*)*)\"|[^ "]*) (.*)$/) {
+		if ($patch_line =~ m/^diff --git (\"(?:[^\\\"]*(?:\\.[^\\\"]*)*)\"|[^ "]*) (.*)$/) {#"
 			# $1 is from_name, which we do not use
 			$to_name = unquote($2);
 			$to_name =~ s!^b/!!;
@@ -4574,7 +4590,9 @@ sub git_tag {
 	git_footer_html();
 }
 
-sub git_blame {
+sub git_blame_common {
+	my $format = shift || 'porcelain';
+
 	# permissions
 	gitweb_check_feature('blame')
 		or die_error(403, "Blame view not allowed");
@@ -4596,10 +4614,36 @@ sub git_blame {
 		}
 	}
 
-	# run git-blame --porcelain
-	open my $fd, "-|", git_cmd(), "blame", '-p',
-		$hash_base, '--', $file_name
-		or die_error(500, "Open git-blame failed");
+	my $fd;
+	if ($format eq 'incremental') {
+		# get file contents (as base)
+		open $fd, "-|", git_cmd(), 'cat-file', 'blob', $hash
+			or die_error(500, "Open git-cat-file failed");
+	} elsif ($format eq 'data') {
+		# run git-blame --incremental
+		open $fd, "-|", git_cmd(), "blame", "--incremental",
+			$hash_base, "--", $file_name
+			or die_error(500, "Open git-blame --incremental failed");
+	} else {
+		# run git-blame --porcelain
+		open $fd, "-|", git_cmd(), "blame", '-p',
+			$hash_base, '--', $file_name
+			or die_error(500, "Open git-blame --porcelain failed");
+	}
+
+	# incremental blame data returns early
+	if ($format eq 'data') {
+		print $cgi->header(
+			-type=>"text/plain", -charset => "utf-8",
+			-status=> "200 OK");
+		local $| = 1; # output autoflush
+		print while <$fd>;
+		close $fd
+			or print "ERROR $!\n";
+		print "END ".tv_interval($t0, [gettimeofday])."\n";
+
+		return;
+	}
 
 	# page header
 	git_header_html();
@@ -4610,93 +4654,146 @@ sub git_blame {
 		$cgi->a({-href => href(action=>"history", -replay=>1)},
 		        "history") .
 		" | " .
-		$cgi->a({-href => href(action=>"blame", file_name=>$file_name)},
+		$cgi->a({-href => href(action=>$action, file_name=>$file_name)},
 		        "HEAD");
 	git_print_page_nav('','', $hash_base,$co{'tree'},$hash_base, $formats_nav);
 	git_print_header_div('commit', esc_html($co{'title'}), $hash_base);
 	git_print_page_path($file_name, $ftype, $hash_base);
 
 	# page body
+	if ($format eq 'incremental') {
+		print "<noscript>\n<div class=\"error\"><center><b>\n".
+		      "This page requires JavaScript to run\nUse ".
+		      $cgi->a({-href => href(action=>'blame',-replay=>1)}, 'this page').
+		      " instead.\n".
+		      "</b></center></div>\n</noscript>\n";
+
+		print qq!<div id="progress_bar" style="width: 100%; background-color: yellow"></div>\n!;
+	}
+
+	print qq!<div class="page_body">\n!;
+	print qq!<div id="progress_info">... / ...</div>\n!
+		if ($format eq 'incremental');
+	print qq!<table id="blame_table" class="blame" width="100%">\n!.
+	      #qq!<col width="5.5em" /><col width="2.5em" /><col width="*" />\n!.
+	      qq!<thead>\n!.
+	      qq!<tr><th>Commit</th><th>Line</th><th>Data</th></tr>\n!.
+	      qq!</thead>\n!.
+	      qq!<tbody>\n!;
+
 	my @rev_color = qw(light2 dark2);
 	my $num_colors = scalar(@rev_color);
 	my $current_color = 0;
-	my %metainfo = ();
 
-	print <<HTML;
-<div class="page_body">
-<table class="blame">
-<tr><th>Commit</th><th>Line</th><th>Data</th></tr>
-HTML
- LINE:
-	while (my $line = <$fd>) {
-		chomp $line;
-		# the header: <SHA-1> <src lineno> <dst lineno> [<lines in group>]
-		# no <lines in group> for subsequent lines in group of lines
-		my ($full_rev, $orig_lineno, $lineno, $group_size) =
-		   ($line =~ /^([0-9a-f]{40}) (\d+) (\d+)(?: (\d+))?$/);
-		if (!exists $metainfo{$full_rev}) {
-			$metainfo{$full_rev} = {};
-		}
-		my $meta = $metainfo{$full_rev};
-		my $data; # last line is used later
-		while ($data = <$fd>) {
-			chomp $data;
-			last if ($data =~ s/^\t//); # contents of line
-			if ($data =~ /^(\S+) (.*)$/) {
-				$meta->{$1} = $2;
-			}
-		}
-		my $short_rev = substr($full_rev, 0, 8);
-		my $author = $meta->{'author'};
-		my %date =
-			parse_date($meta->{'author-time'}, $meta->{'author-tz'});
-		my $date = $date{'iso-tz'};
-		if ($group_size) {
-			$current_color = ($current_color + 1) % $num_colors;
-		}
-		print "<tr id=\"l$lineno\" class=\"$rev_color[$current_color]\">\n";
-		if ($group_size) {
-			print "<td class=\"sha1\"";
-			print " title=\"". esc_html($author) . ", $date\"";
-			print " rowspan=\"$group_size\"" if ($group_size > 1);
-			print ">";
-			print $cgi->a({-href => href(action=>"commit",
-			                             hash=>$full_rev,
-			                             file_name=>$file_name)},
-			              esc_html($short_rev));
-			print "</td>\n";
+	if ($format eq 'incremental') {
+		my $color_class = $rev_color[$current_color];
+
+		#contents of a file
+		my $linenr = 0;
+	LINE:
+		while (my $line = <$fd>) {
+			chomp $line;
+			$linenr++;
+
+			print qq!<tr id="l$linenr" class="$color_class">!.
+			      qq!<td class="sha1"><a href=""></a></td>!.
+			      qq!<td class="linenr">!.
+			      qq!<a class="linenr" href="">$linenr</a></td>!;
+			print qq!<td class="pre">! . esc_html($line) . "</td>\n";
+			print qq!</tr>\n!;
 		}
-		my $parent_commit;
-		if (!exists $meta->{'parent'}) {
-			open (my $dd, "-|", git_cmd(), "rev-parse", "$full_rev^")
-				or die_error(500, "Open git-rev-parse failed");
-			$parent_commit = <$dd>;
-			close $dd;
-			chomp($parent_commit);
-			$meta->{'parent'} = $parent_commit;
-		} else {
-			$parent_commit = $meta->{'parent'};
-		}
-		my $blamed = href(action => 'blame',
-		                  file_name => $meta->{'filename'},
-		                  hash_base => $parent_commit);
-		print "<td class=\"linenr\">";
-		print $cgi->a({ -href => "$blamed#l$orig_lineno",
-		                -class => "linenr" },
-		              esc_html($lineno));
-		print "</td>";
-		print "<td class=\"pre\">" . esc_html($data) . "</td>\n";
-		print "</tr>\n";
-	}
-	print "</table>\n";
-	print "</div>";
+
+	} else { # porcelain, i.e. ordinary blame
+		my %metainfo = (); # saves information about commits
+
+		# blame data
+	LINE:
+		while (my $line = <$fd>) {
+			chomp $line;
+			# the header: <SHA-1> <src lineno> <dst lineno> [<lines in group>]
+			# no <lines in group> for subsequent lines in group of lines
+			my ($full_rev, $orig_lineno, $lineno, $group_size) =
+				($line =~ /^([0-9a-f]{40}) (\d+) (\d+)(?: (\d+))?$/);
+			$metainfo{$full_rev} ||= {};
+			my $meta = $metainfo{$full_rev};
+			my $data; # last line is used later
+			while ($data = <$fd>) {
+				chomp $data;
+				last if ($data =~ s/^\t//); # contents of line
+				if ($data =~ /^(\S+) (.*)$/) {
+					$meta->{$1} = $2;
+				}
+			}
+			my $short_rev = substr($full_rev, 0, 8);
+			my $author = $meta->{'author'};
+			my %date =
+				parse_date($meta->{'author-time'}, $meta->{'author-tz'});
+			my $date = $date{'iso-tz'};
+			if ($group_size) {
+				$current_color = ($current_color + 1) % $num_colors;
+			}
+			print qq!<tr id="l$lineno" class="$rev_color[$current_color]">\n!;
+			if ($group_size) {
+				print qq!<td class="sha1"!.
+				      qq! title="!. esc_html($author) . qq!, $date"!;
+				print qq! rowspan="$group_size"! if ($group_size > 1);
+				print qq!>!;
+				print $cgi->a({-href => href(action=>"commit",
+				                             hash=>$full_rev,
+				                             file_name=>$file_name)},
+				              esc_html($short_rev));
+				print qq!</td>\n!;
+			}
+			if (!exists $meta->{'parent'}) {
+				open my $dd, "-|", git_cmd(), "rev-parse", "$full_rev^"
+					or die_error(500, "Open git-rev-parse failed");
+				$meta->{'parent'} = <$dd>;
+				close $dd;
+				chomp $meta->{'parent'};
+			}
+			my $blamed = href(action => 'blame',
+			                  file_name => $meta->{'filename'},
+			                  hash_base => $meta->{'parent'});
+			print qq!<td class="linenr">!.
+			       $cgi->a({ -href => "$blamed#l$orig_lineno",
+			                -class => "linenr" },
+			               esc_html($lineno)).
+			      qq!</td>!;
+			print qq!<td class="pre">! . esc_html($data) . "</td>\n";
+			print qq!</tr>\n!;
+		}
+	}
+
+	# footer
+	print "</tbody>\n".
+	      "</table>\n"; # class="blame"
+	print "</div>\n";   # class="blame_body"
 	close $fd
 		or print "Reading blob failed\n";
 
-	# page footer
+	if ($format eq 'incremental') {
+		print qq!<script type="text/javascript" src="$blamejs"></script>\n!.
+		      qq!<script type="text/javascript">\n!.
+		      qq!startBlame("!. href(action=>"blame_data", -replay=>1) .qq!",\n!.
+		      qq!           "!. href(-partial_query=>1) .qq!");\n!.
+		      qq!</script>\n!;
+	}
+
 	git_footer_html();
 }
 
+sub git_blame {
+	git_blame_common();
+}
+
+sub git_blame_incremental {
+	git_blame_common('incremental');
+}
+
+sub git_blame_data {
+	git_blame_common('data');
+}
+
 sub git_tags {
 	my $head = git_get_head_hash($project);
 	git_header_html();
-- 
1.6.0.4

^ permalink raw reply related

* Re: [PATCH] Simplified GIT usage guide
From: Nick Andrew @ 2008-12-13 23:12 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: David Howells, torvalds, git, linux-kernel
In-Reply-To: <4942C2D1.4090309@garzik.org>

On Fri, Dec 12, 2008 at 03:00:17PM -0500, Jeff Garzik wrote:
> David Howells wrote:
>> Add a guide to using GIT's simpler features.
>>
>> Signed-off-by: David Howells <dhowells@redhat.com>
>> ---
>>
>>  Documentation/git-haters-guide.txt | 1283 ++++++++++++++++++++++++++++++++++++
>>  1 files changed, 1283 insertions(+), 0 deletions(-)
>>  create mode 100644 Documentation/git-haters-guide.txt
>
> What do you feel is missing from the Kernel Hackers' Guide to Git?  :)
>
> http://linux.yyz.us/git-howto.html

Better advertising, for one :-)

And how to work with different trees in the same local repo.

Nick.

^ permalink raw reply

* Re: [PATCH] Simplified GIT usage guide
From: Nick Andrew @ 2008-12-13 23:05 UTC (permalink / raw)
  To: David Howells
  Cc: Johannes Schindelin, torvalds, git, linux-kernel, Miklos Vajna
In-Reply-To: <29095.1229109133@redhat.com>

On Fri, Dec 12, 2008 at 07:12:13PM +0000, David Howells wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:

> > So I think that your document might do a good job scaring people away from 
> > Git.  But I do not believe that your document, especially in the tone it 
> > is written, does a good job of helping Git newbies.
> 
> Hmmm.  So what would you suggest is a good way to write for GIT newbies?  Is
> it just that the overview should be canned or drastically simplified?

The way I did it was to start with the directed acyclic graph of
commits, explaining how branches fork the graph and merges join
it. This was presented to people who know subversion, and so they
immediately became aware that there are other ways to manage source
code than in a linear r1 r2 r3 r4 r5. I described tags and branch
heads briefly.

Next up I described the things you'd do with git: add new commits,
create a branch, merge a branch, rebase, tag, push and fetch and
showed what that does with the dag of commits.

Finally I showed the actual commands used to perform those actions.
I didn't get into the object database structure at all (that was
prepared in case I had extra time).

I think a tutorial shouldn't be written in a way that polarises
peoples' opinions or they come to regard git as a "necessary evil".
If the audience is a person who knows nothing about git, that's
hardly a "git hater" and I think the document starts off on the
wrong foot as a result.

Nick.

^ permalink raw reply

* Re: [PATCH 1/2] gitweb: allow access to forks with strict_export
From: Jakub Narebski @ 2008-12-13 22:51 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Matt McCutchen, git, Petr Baudis
In-Reply-To: <7vr64b4sib.fsf@gitster.siamese.dyndns.org>

Junio C Hamano wrote:
> Jakub Narebski <jnareb@gmail.com> writes:
> > Matt McCutchen <matt@mattmccutchen.net> writes:
>>
>> CC-ed Petr Baudis, author of forks support in gitweb.
>>
>>> git_get_projects_list excludes forks in order to unclutter the main
>>> project list, but this caused the strict_export check, which also relies
>>> on git_get_project_list, to incorrectly fail for forks.  This patch adds
>>> an argument so git_get_projects_list knows when it is being called for a
>>> strict_export check (as opposed to a user-visible project list) and
>>> doesn't exclude the forks.
>>>
>>> Signed-off-by: Matt McCutchen <matt@mattmccutchen.net>
>>
>> Looks good for me.
> 
> That sounds like a broken API to me.
> 
> At least, please have the decency to not call the extra parameter "for
> strict export".  I would understand it if the extra parameter is called
> "toplevel_only" (or its negation, "include_forks").
> 
> IOW, don't name a parameter after the name of one caller that happens to
> want an unspecified special semantics, without saying what that special
> semantics is.  Instead, name it after the special semantics that the
> argument triggers.
 
Ahhh... true. 

"no_hide" (currently "include_forks") allows us to _not_ passing this
parameter in other places than project_in_list(); undef is falsy.

By the way, doesn't git_project_index and perhaps git_opml also need
this parameter passed to git_get_projects_list?

Then patch subject would change...
-- 
Jakub Narebski
Poland

^ permalink raw reply

* TortoiseGit
From: Alcides Fonseca @ 2008-12-13 22:47 UTC (permalink / raw)
  To: git



^ permalink raw reply

* Re: [PATCH try 2] gitweb: Add option to put a trailing slash on pathinfo-style project URLs
From: Junio C Hamano @ 2008-12-13 22:37 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: Matt McCutchen, git, Giuseppe Bilotta
In-Reply-To: <m3tz97g329.fsf@localhost.localdomain>

Jakub Narebski <jnareb@gmail.com> writes:

>> +	# If you want a trailing slash on the project path (because, for
>> +	# example, you have a real directory at that URL and are using
>> +	# some rewrite magic to invoke gitweb), then set:
>> +	# $feature{'pathinfo'}{'default'} = [1, 1];
>> +
>
> Are any disadvantages to having it always enabled?

Good question.

>> +	my @use_pathinfo = gitweb_get_feature('pathinfo');
>
> Why not name those variables for better readability?
>
> +       my ($use_pathinfo, $trailing_slash) = gitweb_get_feature('pathinfo');

Good suggestion.

^ permalink raw reply

* Re: [PATCH 1/2] gitweb: allow access to forks with strict_export
From: Junio C Hamano @ 2008-12-13 22:31 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: Matt McCutchen, git, Petr Baudis
In-Reply-To: <m3prjvg2st.fsf@localhost.localdomain>

Jakub Narebski <jnareb@gmail.com> writes:

> Matt McCutchen <matt@mattmccutchen.net> writes:
>
> CC-ed Petr Baudis, author of forks support in gitweb.
>
>> git_get_projects_list excludes forks in order to unclutter the main
>> project list, but this caused the strict_export check, which also relies
>> on git_get_project_list, to incorrectly fail for forks.  This patch adds
>> an argument so git_get_projects_list knows when it is being called for a
>> strict_export check (as opposed to a user-visible project list) and
>> doesn't exclude the forks.
>>
>> Signed-off-by: Matt McCutchen <matt@mattmccutchen.net>
>
> Looks good for me.

That sounds like a broken API to me.

At least, please have the decency to not call the extra parameter "for
strict export".  I would understand it if the extra parameter is called
"toplevel_only" (or its negation, "include_forks").

IOW, don't name a parameter after the name of one caller that happens to
want an unspecified special semantics, without saying what that special
semantics is.  Instead, name it after the special semantics that the
argument triggers.

^ permalink raw reply

* Re: [PATCH try 2] gitweb: Add option to put a trailing slash on pathinfo-style project URLs
From: Giuseppe Bilotta @ 2008-12-13 22:23 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: Matt McCutchen, git
In-Reply-To: <m3tz97g329.fsf@localhost.localdomain>

On Sat, Dec 13, 2008 at 10:47 PM, Jakub Narebski <jnareb@gmail.com> wrote:
> Matt McCutchen <matt@mattmccutchen.net> writes:
>
>> My Web site uses pathinfo mode and some rewrite magic to show the gitweb
>> interface at the URL of the real repository directory (which users also
>> pull from).  In this case, it's desirable to end generated links to the
>> project in a trailing slash so the Web server doesn't have to redirect
>> the client to add the slash.  This patch adds a second element to the
>> "pathinfo" feature configuration to control the trailing slash.
>>
>> Signed-off-by: Matt McCutchen <matt@mattmccutchen.net>
>
> Did you check that it does not confuse gitweb if filename parameter is
> passed using pathinfo?  Gitweb used to rely on final '/' to
> distinguish directory pathnames from ordinary pathnames, but I think
> currently thanks to the fact that gitweb now embeds action in pathinfo
> URL, and does not need to guess type, it is not an issue.
>
> Or only project URLs (i.e. only with project parameter, i.e. only
> "http://git.example.com/project.git/" but not other path_info links)
> have trailing slash added?
>
> Errr... I see that it adds trailing slash only for project-only
> path_info links, but the commit message was not entirely clear for me.

If indeed the additional / is only asked for in summary view, I think
there's no need for a feature toggle, we can always put it there. If
not, I'm really curious about seeing the rewrite rules (they might
also be worth adding to the gitweb documentation as examples of 'power
usage').

-- 
Giuseppe "Oblomov" Bilotta

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox