Access the active bookmark name without parsing a command output?

363 views Asked by At

I'd like to automatically add the active bookmark name (if any) to the commit message.

I found this method to do something similar as a pre-commit hook. However it uses the branch name, which is redundant since named branches are part of metadata. I would like the active bookmark instead.

The internal API context used in this example does not seem to hold bookmark info (see MercurialApi). Using hglib I could get the result of hg bookmarks, then parse it, find the line with *, trim to the right column... that's ugly.

I understand that hg lacks the equivalent of git's "plumbing" commands, but I can't even find a python API that offers what I'm looking for.

Are bookmarks managed by the internal API (if so, where is the doc?) or how can I avoid the parsing solution?

4

There are 4 answers

0
Martin Geisler On BEST ANSWER

I believe you can use python-hglib:

import hglib
client = hglib.open('.')
bookmarks, active = client.bookmarks()
if active == -1:
    print 'no active bookmark'
else:
    print 'active bookmark:', bookmarks[active][0]

The confusion might be that the API documented on the MercurialAPI wiki page is the internal API. The API provided by python-hglib is apparently not really documented anywhere except in the code of the library. The bookmarks method is documented, for example.

1
Lazy Badger On

hg id -B in case of existing bookmark return bookmark-name only, nothing - if bookmark doesn't exist

0
Shadok On

Following Martin Geisler answer and this post, here is a hook that works on Windows:

in hgrc:

[hooks]
precommit.bookmark = python:/path/to/hg-hooks.py:prefix_commit_message   

and in hg-hooks.py:

import sys, mercurial

## to be accepted in TortoiseHg, see http://tortoisehg.bitbucket.io/manual/2.9/faq.html
sys.path.append(r'C:\Python27\Lib\site-packages')
import hglib

def _get_active_bookmark(path):
    '''Return the active bookmark or None.
    '''
    client = hglib.open(path)
    bookmarks, active = client.bookmarks()
    if active == -1:
        return None
    else:
        return bookmarks[active][0]


###
### Available hooks
###

def prefix_commit_message(ui, repo, **kwargs):
    '''Prepend [active bookmark name] to commit message.
    '''
    commitctx = repo.commitctx

    def rewrite_ctx(ctx, error):
        book = _get_active_bookmark(repo.root)
        if book:
            old_text = ctx._text
            if not old_text.lstrip().startswith("["):
                ctx._text = "[" + book + "] "+ old_text
        return commitctx(ctx, error)

    repo.commitctx = rewrite_ctx
0
Esteis On

For command-line usage / shell hooks, use this command, which prints either the active bookmark name or an empty string.

hg log -r . -T '{activebookmark}'

The active bookmark is always on the current commit (otherwise it would be inactive). The log template variable activebookmark prints the active bookmark (if associated with the changeset). You'll get exit code 0 (success) whether there is an active bookmark or not, but the printed string will differ. Example session:

$ hg bookmark myfeature
$ hg log -r . -T '{activebookmark}'
myfeature
$ hg bookmark --inactive
$ hg log -r . -T '{activebookmark}'

$ # We got an empty line.