Jeb Wilkins

Coding and climbing in Cumbria.

How to Implement Annotate in a Bazaar Client

UPDATE: I seem to have done a far better job of explaining this here http://bazaar-vcs.org/Integrating_with_Bazaar

This is a brief explanation of how to implement Annotate support if software writing against the bzrlib library. Annotate support is useful because its a good demo of finding information held within the repositories history - for each line in a given file find out which commit it was added/last edited in, and then fetch the information for that commit.

First we grab a ‘handle’ to the file we’re interested in, and the working tree containing it.

tree, relpath = workingtree.WorkingTree.open_containing('/path/to/my/file.txt') fileid = tree.path2id(relpath)

we then need an annotation iterator which allows us to walk the lines of the file, finding information as we go

annotation = list(tree.annotate_iter(fileid))

we then need to retrieve all the revision ids within the file and their associate revisions

revision_ids = set(revision_id for revision_id, text in annotation) revisions = tree.branch.repository.get_revisions(revision_ids)

To avoid repeatedly reloading the same revision information over and over, we preload the revision information associated with the revisions we’ve already retrieved.

revision_map = dict(izip(revision_ids, revisions)) revno_map = tree.branch.get_revision_id_to_revno_map()

We can then walk over the lines of our file, using the annotation iterator we generated earlier

for revision_id, text in annotation : rev = revision_map[revision_id] revno = revno_map[revision_id] print "%s, %s: %s" % (revno[0], rev.committer, text)

One point to note is revno actually contains a tuple with a single value, hence the ‘revno[0]’. I’m not sure why this is tuple and if there are actually situations where it might return more than one value.