[issue1102] "hg tag" claims to succeed but fails

Tom Karzes mercurial-bugs at selenic.com
Sat Apr 26 02:11:32 CDT 2008


New submission from Tom Karzes <Tom.Karzes at magnumsemi.com>:

I've encountered some situations in which "hg tag" appears to have created
a tag (no error message, new revision created, 0 exit status), but the tag
remains effectively absent.  This should never happen.  If Mercurial cannot
add the tag for some reason, then the command must fail, even if the error
message is "Overly complex tagging history, please remove the tag from the
other heads and then try again".

See the attached file "tagfail.txt" for a detailed example of an easily
reproducible instance of this bug.

I believe this bug is due to the attempted fix for issue 498.  That fix is
clearly not a complete solution.  It can fail if a tag is removed in one
head, then re-added on another.  In general, it will fail if any kind of
cycle exists in the tagging sequence for a repository.  It also doesn't
provide any direct help for the case of a new head being created from an
earlier revision.

Here's a typical example of how this can fail: A revision is tagged.  Then
some changes are made (including the removal of the tag).  At some point,
that head is found to have problems and is abandoned.  A new head is now
created from an earlier revision that contains the old tag, which you want
to reinstate.

Thinking about the basic problem, it really seems to me that all that's
required is some help from Mercurial in keeping the .hgtags files in the
repository heads consistent.  This is an unavoidable problem (either with
or without the "issue 498" fix).  Without the fix, you need to make sure
that any tag definitions are consistent.  With the fix, you now have the
option (in some cases) of allowing one head to supersede another, but you
*still* need awareness of the other head to achieve this.  The only
advantage that the "issue 498" fix offers is this: In the cases in which it
works, it allows the conflict to be resolved without having to add a new
revision to the repository head that's being superseded.  Basically, it
allows you to change tags in a "frozen" head without having to create a new
revision that extends that head.  Ok, I suppose this is nice to have, but
I'm not convinced it warrants the added complexity seen in the .hgtags
files (which in general are much more unwieldy when you have multiple
entries for a given tag; obviously it's a lot cleaner if this can be
avoided).

In any case, the real issue here is keeping the repository heads
consistent.  If a revision appears in more than one head, then it must have
the same definition in those heads (or, with the "issue 498" approach, any
incompatible definitions must be overridden).

Regardless of which approach is taken, it seems to me that the real job
that needs to be done by Mercurial is to detect inconsistent heads, and
flag them as errors.  In the case of pushing or pulling, it needs to check
the resulting set of heads for compatibility.  If there is a conflict, then
it should require a resolution (or, at the very least, warn of the
conflict).  It might also be nice to have a command that explicitly checks
for tag conflicts.

In the case of creating a new head by extending an earlier revision, it
again needs to check for tag definitions and, if present, require that they
be compatible with the definitions in the other heads.  No matter what
mechanism is used, this needs to be done.

In terms of practical usage, the way I would like to use tags is as
follows: Each tag has an originating revision which first created it.  From
that point onward, I would only want that tag to appear in descendants of
that revision.  If the same tag name is introduced on an unrelated
repository head (not a descendant), then in fact I would regard it as a
different tag whose name happens to conflict with the original name.  In
that case, I would want one of the two tag names to change to avoid the
naming conflict.

In the case where I want to redefine (or remove) a tag, I would want to do
so consistently on all heads that define it in their .hgtags files.  These
would all be descendants of the originating revision.  In this case, all I
would want is a Mercurial command that would find them all and change them
consistently.  Simple.

There are obviously a huge number of advantages to this approach: It helps
detect genuine conflicts, it makes it easy to change tag definitions
consistently, and it avoids the complexity of having to have multiple
entries for a single tag in a single .hgtags file.  The only disadvantage I
can see to this approach is that, as mentioned, it does sometimes require
extending all heads that contain a particular tag in their .hgtags files,
even if some of those heads are considered "frozen".

If that problem really needs to be avoided, then the original fix for issue
498 *can* be made to work, but it requires keeping more (or at least,
different) information than is currently present.  It is not sufficient to
simply list the old tag definition followed by the definition that
supersedes it, since that information by itself is too ambiguous.  Instead,
when specifying a tag definition that is being superseded, what's needed is
the revision that introduced the definition being overridden, not the
revision that the tag refers to.

Additionally, for the actual tag definition, it would need to keep the
revision number that originally introduced the tag.  So a tag definition
would now include two revisions: (1) the revision that introduced it and
(2) the revision that the tag refers to.  (Alternatively, since the
originating revision should always be present, you could merely keep the
originating revision.)

All descendants of a revision that introduced a tag definition would carry
that revision as the originating revision in their .hgtags files.  At any
time, some other head could override that definition by specifying the
originating revision along with the tag name, overriding them all at once.
Later, if one of the overridden heads wants to redefine the tag, it could
become a new originator, and could override the other definitions
(overriding the other heads without having to extend them).

Personally, I think this might be overkill for this problem, and would be
content to back out the fix for issue 498, and instead add some tag
checking help to Mercurial.  But if this is really needed, then I think
something similar to what I outlined will be needed.

In any case, "hg tag" must either succeed, with the new tag definition
becoming available, or else fail, with an error message and non-zero exit
status (even if the error message is "Overly complex tagging history,
please remove the tag from the other heads and then try again").  It cannot
continue to do what it's doing now.

----------
files: tagfail.txt
messages: 5966
nosy: tkarzes
priority: urgent
status: unread
title: "hg tag" claims to succeed but fails

____________________________________________________
Mercurial issue tracker <mercurial-bugs at selenic.com>
<http://www.selenic.com/mercurial/bts/issue1102>
____________________________________________________
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: tagfail.txt
Url: http://selenic.com/pipermail/mercurial-devel/attachments/20080426/f76b09f4/attachment.txt 


More information about the Mercurial-devel mailing list