changeset 266:0071322a0875

merge with Arne changes
author Pierre-Yves David <pierre-yves.david@logilab.fr>
date Mon, 18 Jun 2012 17:12:11 +0200
parents 24943df310d4 (diff) 240b37998806 (current diff)
children 34020ca0c451
files
diffstat 3 files changed, 152 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Mon Jun 18 14:35:49 2012 +0200
+++ b/.hgignore	Mon Jun 18 17:12:11 2012 +0200
@@ -3,4 +3,8 @@
 ^docs/build/
 ^docs/html/
 ^html/
-.pyc$
+\.pyc$
+~$
+\.orig$
+\.rej$
+\.err$
--- a/hgext/evolve.py	Mon Jun 18 14:35:49 2012 +0200
+++ b/hgext/evolve.py	Mon Jun 18 17:12:11 2012 +0200
@@ -57,6 +57,11 @@
 #############################
 
 def rewrite(repo, old, updates, head, newbases, commitopts):
+    """Return (nodeid, created) where nodeid is the identifier of the
+    changeset generated by the rewrite process, and created is True if
+    nodeid was actually created. If created is False, nodeid
+    references a changeset existing before the rewrite call.
+    """
     if len(old.parents()) > 1: #XXX remove this unecessary limitation.
         raise error.Abort(_('cannot amend merge changesets'))
     base = old.p1()
@@ -112,6 +117,8 @@
 
         user = commitopts.get('user') or old.user()
         date = commitopts.get('date') or None # old.date()
+        extra = dict(commitopts.get('extra', {}))
+        extra['branch'] = head.branch()
 
         new = context.memctx(repo,
                              parents=newbases,
@@ -120,33 +127,39 @@
                              filectxfn=filectxfn,
                              user=user,
                              date=date,
-                             extra=commitopts.get('extra') or None)
+                             extra=extra)
 
         if commitopts.get('edit'):
             new._text = cmdutil.commitforceeditor(repo, new, [])
+        revcount = len(repo)
         newid = repo.commitctx(new)
         new = repo[newid]
-
-        # update the bookmark
-        if bm:
-            repo._bookmarks[bm] = newid
-            bookmarks.write(repo)
+        created = len(repo) != revcount
+        if created:
+            # update the bookmark
+            if bm:
+                repo._bookmarks[bm] = newid
+                bookmarks.write(repo)
 
-        # add evolution metadata
-        repo.addobsolete(new.node(), old.node())
-        for u in updates:
-            repo.addobsolete(u.node(), old.node())
-            repo.addobsolete(new.node(), u.node())
-        oldbookmarks = repo.nodebookmarks(old.node())
-        for book in oldbookmarks:
-            repo._bookmarks[book] = new.node()
-        if oldbookmarks:
-            bookmarks.write(repo)
-
+            # add evolution metadata
+            repo.addobsolete(new.node(), old.node())
+            for u in updates:
+                repo.addobsolete(u.node(), old.node())
+                repo.addobsolete(new.node(), u.node())
+            oldbookmarks = repo.nodebookmarks(old.node())
+            for book in oldbookmarks:
+                repo._bookmarks[book] = new.node()
+            if oldbookmarks:
+                bookmarks.write(repo)
+        else:
+            # newid is an existing revision. It could make sense to
+            # replace revisions with existing ones but probably not by
+            # default.
+            pass
     finally:
         wlock.release()
 
-    return newid
+    return newid, created
 
 def relocate(repo, orig, dest):
     """rewrite <rev> on dest"""
@@ -352,8 +365,6 @@
      _('use text as commit message for this update')),
     ('c', 'change', '',
      _('specifies the changeset to amend'), _('REV')),
-    ('b', 'branch', '',
-     _('specifies a branch for the new.'), _('REV')),
     ('e', 'edit', False,
      _('edit commit message.'), _('')),
     ] + walkopts + commitopts + commitopts2,
@@ -385,16 +396,10 @@
     """
 
     # determine updates to subsume
-    change = opts.get('change')
+    change = opts.get('change', '.')
     if change == '.':
         change = 'p1(p1())'
     old = scmutil.revsingle(repo, change)
-    branch = opts.get('branch')
-    if branch:
-        opts.setdefault('extra', {})['branch'] = branch
-    else:
-        if old.branch() != 'default':
-            opts.setdefault('extra', {})['branch'] = old.branch()
 
     lock = repo.lock()
     try:
@@ -413,7 +418,11 @@
             def commitfunc(ui, repo, message, match, opts):
                 return repo.commit(message, opts.get('user'), opts.get('date'), match,
                                    editor=e)
-            cmdutil.commit(ui, repo, commitfunc, pats, ciopts)
+            revcount = len(repo)
+            tempid = cmdutil.commit(ui, repo, commitfunc, pats, ciopts)
+            if len(repo) == revcount:
+                # No revision created
+                tempid = None
 
             # find all changesets to be considered updates
             cl = repo.changelog
@@ -421,7 +430,7 @@
             updatenodes = set(cl.nodesbetween(roots=[old.node()],
                                               heads=[head.node()])[0])
             updatenodes.remove(old.node())
-            okoptions = ['message', 'logfile', 'edit', 'user', 'branch']
+            okoptions = ['message', 'logfile', 'edit', 'user']
             if not updatenodes:
                 for o in okoptions:
                     if opts.get(o):
@@ -435,13 +444,20 @@
             # perform amend
             if opts.get('edit'):
                 opts['force_editor'] = True
-            newid = rewrite(repo, old, updates, head,
-                            [old.p1().node(), old.p2().node()], opts)
-
-            # reroute the working copy parent to the new changeset
-            phases.retractboundary(repo, oldphase, [newid])
-            repo.dirstate.setparents(newid, node.nullid)
-
+            newid, created = rewrite(repo, old, updates, head,
+                                     [old.p1().node(), old.p2().node()], opts)
+            if created:
+                # reroute the working copy parent to the new changeset
+                phases.retractboundary(repo, oldphase, [newid])
+                repo.dirstate.setparents(newid, node.nullid)
+            else:
+                # rewrite() recreated an existing revision, discard
+                # the intermediate revision if any. No need to update
+                # phases or parents.
+                if tempid is not None:
+                    repo.addobsolete(node.nullid, tempid)
+                # XXX: need another message in collapse case.
+                raise error.Abort(_('no updates found'))
         finally:
             wlock.release()
     finally:
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-amend.t	Mon Jun 18 17:12:11 2012 +0200
@@ -0,0 +1,95 @@
+  $ cat >> $HGRCPATH <<EOF
+  > [defaults]
+  > amend=-d "0 0"
+  > [extensions]
+  > hgext.rebase=
+  > hgext.graphlog=
+  > EOF
+  $ echo "obsolete=$(echo $(dirname $TESTDIR))/hgext/obsolete.py" >> $HGRCPATH
+  $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext/evolve.py" >> $HGRCPATH
+
+  $ glog() {
+  >   hg glog --template '{rev}@{branch}({phase}) {desc|firstline}\n' "$@"
+  > }
+
+  $ hg init repo
+  $ cd repo
+  $ echo a > a
+  $ hg ci -Am adda
+  adding a
+
+Test amend captures branches
+
+  $ hg branch foo
+  marked working directory as branch foo
+  (branches are permanent and global, did you want a bookmark?)
+  $ hg amend
+  $ hg branch
+  foo
+  $ hg branches
+  foo                            2:a34b93d251e4
+  default                        0:07f494440405 (inactive)
+  $ glog
+  @  2@foo(draft) adda
+  
+Test no-op
+
+  $ hg amend
+  abort: no updates found
+  [255]
+  $ glog
+  @  2@foo(draft) adda
+  
+
+Test forcing the message to the same value, no intermediate revision.
+
+  $ hg amend -m 'adda'
+  abort: no updates found
+  [255]
+  $ glog
+  @  2@foo(draft) adda
+  
+
+Test collapsing into an existing revision, no intermediate revision.
+
+  $ echo a >> a
+  $ hg ci -m changea
+  $ echo a > a
+  $ hg ci -m reseta
+  $ hg amend --change 2
+  abort: no updates found
+  [255]
+  $ hg phase 2
+  2: draft
+  $ glog
+  @  4@foo(draft) reseta
+  |
+  o  3@foo(draft) changea
+  |
+  o  2@foo(draft) adda
+  
+
+Test collapsing into an existing rev, with an intermediate revision.
+
+  $ hg branch --force default
+  marked working directory as branch default
+  (branches are permanent and global, did you want a bookmark?)
+  $ hg ci -m resetbranch
+  created new head
+  $ hg branch --force foo
+  marked working directory as branch foo
+  (branches are permanent and global, did you want a bookmark?)
+  $ hg amend --change 2
+  abort: no updates found
+  [255]
+  $ glog
+  @  6@foo(secret) amends a34b93d251e49c93d5685ebacad785c73a7e8605
+  |
+  o  5@default(draft) resetbranch
+  |
+  o  4@foo(draft) reseta
+  |
+  o  3@foo(draft) changea
+  |
+  o  2@foo(draft) adda
+