From: Jonas Fonseca To: Martin Langhoff Cc: Git Mailing List Subject: Re: [RFC] faking cvs annotate References: <46a038f90512151713i118e58acia466d0f65ff91383@mail.gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <46a038f90512151713i118e58acia466d0f65ff91383@mail.gmail.com> X-Mutt-References: <46a038f90512151713i118e58acia466d0f65ff91383@mail.gmail.com> X-Mutt-Fcc: =sent Status: RO Martin Langhoff wrote Fri, Dec 16, 2005: > I know, I know, use pickaxe :-) > > Any suggestions as to how to implement a not-too-slow annotate that > looks reasonable enough so as to fool real cvs clients? Let's assume > I'll have the "per-file-version numbers" to translate commit SHA1s > into cvs-ish version numbers in a magic hat, right next to the fluffy > bunnies. > > Suggestions of GIT machinery that would shortcut the trip from > > git-rev-list HEAD $path > > to a annotate-ish output. Did I dream it or is qgit showing something > annotate-ish in its screenshots? I've been working on some patch-based annotate, but it doesn't quite work yet. I could give it another try this weekend if you think it could be of any use. It is easy to cache the output of both git-rev-list HEAD $file and git-rev-list HEAD $file | while read rev; do git-diff-tree -p $rev $file done The former you might already know from the per-file-version numbers database and seems to be what takes the most time to generate. The latter is a patched-based file history and can be cached if needed. The idea is to add --annotate to git-apply and use its patch parser to load the patched-based file history. Iterating each fragment of each patch, added lines are blamed on the given revisions. Deleted lines are marked uninteresting so that when these lines are added in an older revision (we are iterating patches from newer to older) they can be ignored. You have the file source right there, so the only git queries needed are for expanding shortcut IDs and getting author info. (Things which could also be saved as git --diff headers). I don't think it will require more than 3-400 lines of C code. Compared to git-annotate.perl (if this comparison is even fair) posted in another thread here are some numbers: $ time ./git-annotate.perl src/protocol/http/http.c >/dev/null real 1m20.691s user 1m17.798s sys 0m0.651s $ time ./git-patch-annotate src/protocol/http/http.c >/dev/null real 0m12.395s user 0m10.889s sys 0m1.445s $ time git-rev-list HEAD src/protocol/http/http.c >/dev/null real 0m7.338s user 0m6.868s sys 0m0.040s $ time cat cached.revs | while read rev; do git-diff-tree -p $rev src/protocol/http/http.c done >/dev/null real 0m7.346s user 0m5.420s sys 0m1.672s The file used above has 452 revisions. And this is the git-patch-annotate stand-in script: #!/bin/sh file=$1 git-rev-list HEAD "$file" | while read rev; do git-diff-tree -p $rev "$file" done | git-apply --stat --summary -- Jonas Fonseca