An interesting question has just been sent by Greg Ward on the Mercurial devel mailing-list (as a funny coincidence, it happened that I had to solve this problem a few days ago).
Let me quote his message:
here's my problem: imagine a customer is running software built from changeset A, and we want to upgrade them to a new version, built from changeset B. So I need to know what bugs are fixed in B that were not fixed in A. I have already implemented a changeset/bug mapping, so I can trivially lookup the bugs fixed by any changeset. (It even handles "ongoing" and "reverted" bugs in addition to "fixed".)
And he gives an example of situation where a tricky case may be found:
+--- 75 -- 78 -- 79 ------------+ / \ / +-- 77 -- 80 ---------- 84 -- 85 / / / 0 -- ... -- 74 -- 76 / \ / +-- 81 -- 82 -- 83 --+
So what is the problem?
Imagine the lastest distributed stable release is built on rev 81. Now, I need to publish a new bugfix release based on this latest stable version, including every changeset that is a bugfix, but that have not yet been applied at revision 81.
So the first problem we need to solve is answering: what are the revisions ancestors of revision 85 that are not ancestor of revision 81?
Command line solution
Using hg commands, the solution is proposed by Steve Losh:
hg log --template '{rev}\n' --rev 85:0 --follow --prune 81
or better, as suggested by Matt:
hg log -q --template '{rev}\n' --rev 85:0 --follow --prune 81
The second is better since it does only read the index, and thus is much faster. But on big repositories, this command remains quite slow (with Greg's situation, a repo of more than 100000 revisions, the command takes more than 2 minutes).
Python solution
Using Python, one may think about using revlog.nodesbetween(), but it won't work as wanted here, not listing revisions 75, 78 and 79.
On the mailing list, Matt gave the most simple and efficient solution:
cl = repo.changelog a = set(cl.ancestors(81)) b = set(cl.ancestors(85)) revs = b - a
Idea for a new extension
Using this simple python code, it should be easy to write a nice Mercurial extension (which could be named missingrevisions) to do this job.
Then, it should be interesting to also implement some filtering feature. For example, if there are simple conventions used in commit messages, eg. using something like "[fix #1245]" or "[close #1245]" in the commit message when the changeset is a fix for a bug listed in the bugtracker, then we may type commands like:
hg missingrevs REV -f bugfix
or:
hg missingrevs REV -h HEADREV -f bugfix
to find bugfix revisions ancestors of HEADREV that are not ancestors of REV.
With filters (bugfix here) may be configurables in hgrc using regexps.
Comments
Steve Losh blogged about this also :-)
Using commit messages as sensitive and long-term information seems to me a bad idea. Why not just use tags for that ? If the tag is present at a given revision, you're sure the bug was closed.