Search code examples
mercurialdvcs

ISO Mercurial "attributes" - tags that apply to more than one changeset, applied after the changeset


BRIEF

How do I tag multiple changesets in Mercurial with the same tag? Possibly on the same branch, possibly on different branches.

E.g. something like a tag that says whether the full QA test ran.

I can create multiple instances of a tag by editing the file, but the hg tools nearly always ignore all but the first.

DETAIL

I am looking for what I call changeset "attributes" - a concept that I have used in other CVS and DVCS, but which I cannot seem to find in Mercurial.

Basically, an attribute is very much like a tag, but where a tag is only supposed to refer to a single changeset, an attribute may apply to multiple changesets.

Q: does anyone know how to do this?

Similarly: is there a way to attach a description to a ChangeSet, after the changeset has been created. Note that i do not want to rewrite history: I do not want to delete or change or replace the original checkin message. I just want to add some more stuff - and have that more stuff appear in queries like hg log. E.g. "I forgot to add a file to commit df..a3 - look instead to commit 8f..77 where I checked in the missing files.

EXCRUCIATING DETAIL

I know - you can do hg tag -f to force a tag to apply to more than one changeset. But so many other hg tag related features really only work with a single changesrty per tag. Or at least only one changeset per line of descent - i.e. per head.

So you can leave a tag defined forever and ever. I like placing the date or other context in such a tag - e.g. tests-pass-2012-01-14.

Or you can have a "floating tag", that moves upwards - e.g. "most recent rev where all the slow tests pass", which I might call simply "tests-pass".

(By the way, you may apply such attributes or tags after the checkin - especially if you have a slow QA process, perhaps a quick smoke test, followed by a slower full set of tests that may take a week to complete. So you checkin, and then, later, go back and apply the attribute, the uniqified dated tag. And you may later need to go back and modify such a tag, e.g. if more tests are added, so that a changeset that used to pass all tests no longer does. E.g. all-tests-pass-2012-01-14 and all-tests-pass-2012-01-15 may apply to the same changeset.)

But it is onerous to have to uniqify such fixed tags. Hence what I call an attribute: a tag that applies to multiple changesets, Which is version controlled. So you might apply all-tests-pass to rev 105, and then later to 106 and 107. But then you realize that new tests fail on 106, so you repally.

Then the attribute history might look like

105:
    tagged all-tests-pass on 2012-01-14-10h00 (in changeset XXX)
    tagged all-tests-pass on 2012-01-15-10h00 (in changeset YYY)

106:
    tagged all-tests-pass on 2012-01-14-13h00 (in changeset XXX)
    tagged not-all-tests-pass on 2012-01-15-13h00 (in changeset YYY)

107:
    tagged all-tests-pass on 2012-01-14-14h00 (in changeset XXX)
    tagged all-tests-pass on 2012-01-15-10h00 (in changeset YYY)

and a revset query like

 105::107 and current_attribute_tag(all-tests-pass)

= returns 105 and 107 on the latest, at or after YYY is in the repo = but returns 105, 106, 107 if cloned so as not to include YYY

while

 105::107 and attribute_tag_at_any_time(all-tests-pass)

=returns 105 106 and 107 at any time if the repo holds XXX

===

I would like to be able to do things like

  • run hg bisect, but only on changesets tagged tests-pass.

  • exclude certain log messages from hg log and glog

etc.

===

By the way, I reject phases and bookmarks for this purpose because they are not version controlled. And I want these attribute tags to be VCed, so that I can follow something like to ebb and flow of all-tests-pass, as mentioned above.

branches are almost what I want, because Mercurial branches are really changeset attributes, not branches. But I don't think that the branch associated with a changeset can be changed after the commit.

(I really wish that you could switch changesets to a branch after you commit them. I call this wished for feature "retroactive branching".)

===

Here's a classic example of why I might want attributes: have you ever forgotten to add a file to the VCS? And then have a changeset that fails to build? Add the file in a subsequent changest? ...

I would like to be able to retroactively mark a changeset as will-not-build--missing-files. And then have bisect not even bother looking at such changesets.


Solution

  • Have a look at this: Custom revision properties in Mercurial?

    There's no native support for attributes. You could write an extension (there's a dictionary of extra properties that get saved with a changeset).

    Or you could hack it together with multiple changesets per tag (as you suggested).

    Or you could hack it together with a new all-tests-pass branch, and have your CI server merge to that branch when all tests pass (then bisects are being tip of default and tip of all-tests-pass).

    But the short answer remains that there's no existing native way to do it.