Help needed with implementing annotate

John Arbash Meinel john at arbash-meinel.com
Thu Nov 29 20:28:09 GMT 2007


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Jeremy Wilkins wrote:
> Hi All,
> 
> I've been doing some work on the TextMate integration with Bazaar.
> I've been trying to implement annotate support, the approach is to
> iterate over each line in the file and spit out a HTML table, which
> TextMate can render with an embedded webkit window.
> 
> The code I've got at the minute, only works if the file your trying to
> annotate had changes in the most recent commit, this is using
> annotate._annotate_file, eg
> 
> annotate_file =
> os.environ['TM_FILEPATH'].lstrip(os.environ['TM_PROJECT_DIRECTORY'])
> tree, relpath = workingtree.WorkingTree.open_containing(annotate_file)
> b = tree.branch
> revid = b.last_revision()
> fileid = tree.path2id(annotate_file)
> annotation = annotate._annotate_file(b, revid, fileid)
> 
> for (revno_str, author, date_str, line_rev_id, text) in annotation :
> 	print "%s: %s<br />" % ( revno_str, text )
> 
> the other approach I've been playing with is below, using
> workingtree.annotate_iter
> 
> tree, relpath = workingtree.WorkingTree.open_containing('filea.txt')
> fileid = tree.path2id('filea.txt')
> annotation = tree.annotate_iter(fileid)

"annotate_iter()" is the preferred api, as it will also show you which lines
have been modified from the last commit. (I believe annotate._annotate_file()
annotates the last committed version.)

> 
> for (revno_str, text) in annotation :
> 	print "%s: %s<br />" % ( revno_str, text )
> 
> 
> This seems more reliable but only gives a long string containing what
> I presume is a unique identified for the file. Is there anyway to get
> author and rev no information from this identifier? Or is there an
> alternative approach I should be using.
> 
> Thanks
> 
> jebw
> 
> 

I don't believe it is a 'revno_str' it is a 'revision_id'. Which you can pass into:
rev = tree.branch.repository.get_revision(revision_id)

Which will give you things like

rev.committer
rev.timestamp
rev.timezone
rev.message

etc.

However, it isn't a particularly cheap call, so you probably want to save them
in a cache, and maybe even pull them in ahead of time. For example:

tree, relpath = workingtree.WorkingTree.open_containing('filea.txt')
fileid = tree.path2id('filea.txt')
annotation = list(tree.annotate_iter(fileid))

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

revno_map = tree.branch.get_revision_id_to_revno_map()

for revision_id, text in annotation:
  rev = revision_map[revision_id]
  revno = revno_map[revision_id]
  # What would you like to do now?
  print "%s, %s: %s<br />" % (rev.committer, revno, text)


Also, you'll probably want to make sure you wrap the whole thing in a:

tree.lock_read()
try:
  ... # Do stuff
finally:
  tree.unlock()

We only cache data in memory for the length of a lock, so holding a lock will
allow us to not have to re-read indexes, etc.

John
=:->

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.7 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFHTyDZJdeBCYSNAAMRAm/pAKCnsR6ZxQJMdHINQNX9z5Sed2UnygCdEjDV
sDBz3Xw9oyodSyqQBAMUetA=
=Pi/I
-----END PGP SIGNATURE-----



More information about the bazaar mailing list