[PATCH 1 of 1 RESEND RFC] tag: abort if not at a branch head

Adrian Buehlmann adrian at cadifra.com
Tue Dec 7 05:09:03 CST 2010


On 2010-12-07 05:06, Kevin Bullock wrote:
> # HG changeset patch
> # User Kevin Bullock <kbullock at ringworld.org>
> # Date 1291694650 21600
> # Node ID d30fb522fd1ab9025f137d3fa40b84f171709bb8
> # Parent  c73745762f33cb19feb9dd6ddfc9962c459b9679
> tag: abort if not at a branch head

I'd suggest using V3 instead of RESEND next time for the flags.

And I think you can drop the "RFC", assuming you only send patches that
pass the testsuite.

> Since it's usually only desirable to make tag commits on top of branch
> heads, abort if the working dir parent is not a branch head. -f/--force
> may be passed to commit at a non-head anyway.
> 
> Does not abort if working dir parent is a named branch head but not a
> topological head.
> 
> diff --git a/mercurial/commands.py b/mercurial/commands.py
> --- a/mercurial/commands.py
> +++ b/mercurial/commands.py
> @@ -3665,16 +3665,23 @@
>  
>      Tags are used to name particular revisions of the repository and are
>      very useful to compare different revisions, to go back to significant
> -    earlier versions or to mark branch points as releases, etc.
> +    earlier versions or to mark branch points as releases, etc. Changing
> +    an existing tag is normally disallowed; use -f/--force to override.
>  
>      If no revision is given, the parent of the working directory is
>      used, or tip if no revision is checked out.
>  
>      To facilitate version control, distribution, and merging of tags,
> -    they are stored as a file named ".hgtags" which is managed
> -    similarly to other project files and can be hand-edited if
> -    necessary. The file '.hg/localtags' is used for local tags (not
> -    shared among repositories).
> +    they are stored as a file named ".hgtags" which is managed similarly
> +    to other project files and can be hand-edited if necessary. This
> +    also means that tagging creates a new commit. The file
> +    ".hg/localtags" is used for local tags (not shared among
> +    repositories).
> +
> +    Tag commits are usually made at the head of a branch. If the parent
> +    of the working directory is not a branch head, :hg:`tag` aborts; use
> +    -f/--force to force the tag commit to be based on a non-head
> +    changeset.
>  
>      See :hg:`help dates` for a list of formats valid for -d/--date.
>  
> @@ -3717,6 +3724,11 @@
>              if n in repo.tags():
>                  raise util.Abort(_('tag \'%s\' already exists '
>                                     '(use -f to force)') % n)
> +        wctx = repo[None]
> +        bheads = repo.branchheads()
> +        if not opts.get('local') and bheads \
> +                and not [x for x in wctx.parents() if x.node() in bheads]:
> +            raise util.Abort(_('not at a branch head (use -f to force)'))

I see. Apparently you do not agree with my merge comment :).

I've started fiddling with tagging merge changesets. I'll probably send some
patches myself then on that.

I currently have:

diff --git a/tests/test-tag.t b/tests/test-tag.t
--- a/tests/test-tag.t
+++ b/tests/test-tag.t
@@ -196,3 +196,33 @@ test custom commit messages
   $ hg log -l1 --template "{desc}\n"
   custom tag message
   second line
+
+  $ cd ..
+
+tagging a uncommitted merge
+
+  $ hg init r4
+  $ cd r4
+  $ echo c1 > f1 
+  $ hg add f1
+  $ hg ci -m0
+  $ echo foo >> f1
+  $ hg ci -m1
+  $ hg up -q 0
+  $ echo c2 > f2
+  $ hg add f2
+  $ hg ci -m2
+  created new head
+  $ hg heads -q
+  2:9adf12931dba
+  1:3ec40a953f20
+  $ hg merge
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+
+  $ hg tag t1
+  abort: cannot partially commit a merge (do not specify files or patterns)
+  [255]
+
+  $ cd ..
+

I intend to send a two patch bomb that changes that error message to:

   abort: uncommitted merge


>      if not rev_ and repo.dirstate.parents()[1] != nullid:
>          raise util.Abort(_('uncommitted merge - please provide a '
>                             'specific revision'))
> @@ -4481,7 +4493,7 @@
>           _('[OPTION]... [FILE]...')),
>      "tag":
>          (tag,
> -         [('f', 'force', None, _('replace existing tag')),
> +         [('f', 'force', None, _('force tag')),
>            ('l', 'local', None, _('make the tag local')),
>            ('r', 'rev', '',
>             _('revision to tag'), _('REV')),
> diff --git a/tests/test-tag.t b/tests/test-tag.t
> --- a/tests/test-tag.t
> +++ b/tests/test-tag.t
> @@ -78,13 +78,20 @@
>    $ cat .hg/localtags
>    d4f0d2909abc9290e2773c08837d70c1794e3f5a bleah1
>  
> +tagging on a non-head revision
> +
>    $ hg update 0
>    0 files updated, 0 files merged, 1 files removed, 0 files unresolved
> +  $ hg tag -l localblah
>    $ hg tag "foobar"
> +  abort: not at a branch head (use -f to force)
> +  [255]
> +  $ hg tag -f "foobar"

should we do

     $ hg tag -f "foobar"
     created new head

like on commit? (I forgot to ask that on the first round, sorry)

>    $ cat .hgtags
>    acb14030fe0a21b60322c440ad2d20cf7685a376 foobar
>    $ cat .hg/localtags
>    d4f0d2909abc9290e2773c08837d70c1794e3f5a bleah1
> +  acb14030fe0a21b60322c440ad2d20cf7685a376 localblah
>  
>    $ hg tag -l 'xx
>    > newline'
> @@ -102,6 +109,7 @@
>    tag:         bleah
>    tag:         bleah0
>    tag:         foobar
> +  tag:         localblah
>    user:        test
>    date:        Thu Jan 01 00:00:00 1970 +0000
>    summary:     test
> @@ -156,10 +164,10 @@
>    > f = file('.hg/localtags', 'w'); f.write(last); f.close()
>    > EOF
>    $ cat .hg/localtags; echo
> -  d4f0d2909abc9290e2773c08837d70c1794e3f5a bleah1
> +  acb14030fe0a21b60322c440ad2d20cf7685a376 localblah
>    $ hg tag -l localnewline
>    $ cat .hg/localtags; echo
> -  d4f0d2909abc9290e2773c08837d70c1794e3f5a bleah1
> +  acb14030fe0a21b60322c440ad2d20cf7685a376 localblah
>    c2899151f4e76890c602a2597a650a72666681bf localnewline
>    
>  
> @@ -196,3 +204,35 @@
>    $ hg log -l1 --template "{desc}\n"
>    custom tag message
>    second line
> +
> +
> +tagging when at named-branch-head that's not a topo-head
> +
> +  $ hg parents -q
> +  11:7d32ded1f932
> +  $ hg up default
> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  $ hg merge -t internal:local
> +  0 files updated, 1 files merged, 0 files removed, 0 files unresolved
> +  (branch merge, don't forget to commit)
> +  $ hg ci -m 'merge named branch'
> +  $ hg up 11
> +  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> +  $ hg tag new-topo-head
> +
> +
> +tagging on null rev
> +
> +  $ hg up null
> +  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
> +  $ hg tag nullrev
> +  abort: not at a branch head (use -f to force)
> +  [255]
> +
> +

...

> +tagging empty repo
> +
> +  $ cd ..
> +  $ hg init repo-tag-empty
> +  $ cd repo-tag-empty
> +  $ hg tag nullrev

I think this last test case could go into a separate, uncontroversial (? :),
unrelated patch.

Doing so would also emphasize that there is no code change needed to make
tagging an empty repo work (or that we don't want to crash or abort in
that boundary case).

Even if you apparently only care about making sure that this case still
passes *after* your code change for -f on for new heads...


More information about the Mercurial-devel mailing list