From: Junio C Hamano Date: Wed, 08 Feb 2006 21:45:11 GMT Subject: Re: [PATCH] Add git-annotate - a tool for annotating files with the revision and person that created each line in the file. Message-ID: <7vlkwlo788.fsf@assigned-by-dhcp.cox.net> In-Reply-To: <20060208210756.GA9490@mythryan2.michonline.com> Ryan Anderson writes: >> It's been a while since I looked at it the last time so it may >> not even work with the current git, but here it is.. > > I'll take a look through this in greater detail later, hopefully your > approach can be applied. Diff-analyzing is apparently tricky. Reading diff is tricky but I was lazy to match up the lines by hand, which is also a real work ;-). There are a few things I should add to that ancient code: - It wants old ls-tree behaviour. The command line used in the "sub find_file" needs to be updated to something like this: open $fh, '-|', 'git-ls-tree', '-z', '-r', $commit->{TREE}, $path or die "cannot read git-ls-tree $commit->{TREE}"; - It only cares about the line numbers and its output is meant to be postprocessed with the contents from the latest blob. - It predates the recent rev-list that skips commits that do not change the specified paths, and it literally follows each parent and optimizes not to diff with uninteresting parents by hand. I suspect if you go with the diff-reading approach, it might be easy to convert it to C (or even write the initial version in C) using the machinery similar to what is in combine-diff.c. The algorithm combine-diff.c uses keeps the lines discarded from each parent in lline structure linked to the sline structure (which keeps track of the lines in the final version), but for your annotate purposes what you care about is only what the child adds to the parent (IOW, we do not care about the lines that do not appear in the final version), so the logic and the data structure could be greatly simplified. You only need to keep "flag" element in the sline structure, and maybe bol and len that point at the contents of the resulting line from the final version. In addition, you would need to store "the current suspect commit" (starts from the final revision and updated as you pass the blame along) and another bool that says if "the current suspect" is known to be the guilty party or if the true culprit is one of its ancestors (capital vs lowercase difference in that explanatory note).