merge with stable
authorPierre-Yves David <pierre-yves.david@ens-lyon.org>
Sun, 16 Oct 2016 20:29:27 +0200
changeset 1743 299cdaa24fa5
parent 1738 cb5edd4b160c (current diff)
parent 1742 970a4c13ebc3 (diff)
child 1745 6c922448ccec
child 1767 f746f787f82c
merge with stable
README
hgext/evolve.py
tests/test-prev-next.t
--- a/README	Sat Oct 08 15:49:12 2016 +0200
+++ b/README	Sun Oct 16 20:29:27 2016 +0200
@@ -63,6 +63,9 @@
 5.4.2 --
 
  - Fix erroneous manifest computation when solving 'bumped' changeset.
+ - split: avoid crash on empty commit (issue5191),
+ - next: improve locking to avoid issue with working copy parent (issue5244)
+ - prev: improve locking to avoid issue with working copy parent (issue5244)
 
 5.4.1 -- 2016-08-01
 
--- a/hgext/evolve.py	Sat Oct 08 15:49:12 2016 +0200
+++ b/hgext/evolve.py	Sun Oct 16 20:29:27 2016 +0200
@@ -2213,57 +2213,63 @@
     """update to parent revision
 
     Displays the summary line of the destination for clarity."""
-    wkctx = repo[None]
-    wparents = wkctx.parents()
+    wlock = None
     dryrunopt = opts['dry_run']
-    if len(wparents) != 1:
-        raise error.Abort('merge in progress')
-    if not opts['merge']:
-        try:
-            cmdutil.bailifchanged(repo)
-        except error.Abort as exc:
-            exc.hint = _('do you want --merge?')
-            raise
-
-    parents = wparents[0].parents()
-    topic = getattr(repo, 'currenttopic', '')
-    if topic and not opts.get("no_topic", False):
-        parents = [ctx for ctx in parents if ctx.topic() == topic]
-    displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate})
-    if not parents:
-        ui.warn(_('no parent in topic "%s"\n') % topic)
-        ui.warn(_('(do you want --no-topic)\n'))
-    elif len(parents) == 1:
-        p = parents[0]
-        bm = bmactive(repo)
-        shouldmove = opts.get('move_bookmark') and bm is not None
-        if dryrunopt:
-            ui.write(('hg update %s;\n' % p.rev()))
-            if shouldmove:
-                ui.write(('hg bookmark %s -r %s;\n' % (bm, p.rev())))
+    if not dryrunopt:
+        wlock = repo.wlock()
+    try:
+        wkctx = repo[None]
+        wparents = wkctx.parents()
+        if len(wparents) != 1:
+            raise error.Abort('merge in progress')
+        if not opts['merge']:
+            try:
+                cmdutil.bailifchanged(repo)
+            except error.Abort as exc:
+                exc.hint = _('do you want --merge?')
+                raise
+
+        parents = wparents[0].parents()
+        topic = getattr(repo, 'currenttopic', '')
+        if topic and not opts.get("no_topic", False):
+            parents = [ctx for ctx in parents if ctx.topic() == topic]
+        displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate})
+        if not parents:
+            ui.warn(_('no parent in topic "%s"\n') % topic)
+            ui.warn(_('(do you want --no-topic)\n'))
+        elif len(parents) == 1:
+            p = parents[0]
+            bm = bmactive(repo)
+            shouldmove = opts.get('move_bookmark') and bm is not None
+            if dryrunopt:
+                ui.write(('hg update %s;\n' % p.rev()))
+                if shouldmove:
+                    ui.write(('hg bookmark %s -r %s;\n' % (bm, p.rev())))
+            else:
+                ret = hg.update(repo, p.rev())
+                if not ret:
+                    tr = lock = None
+                    try:
+                        lock = repo.lock()
+                        tr = repo.transaction('previous')
+                        if shouldmove:
+                            repo._bookmarks[bm] = p.node()
+                            repo._bookmarks.recordchange(tr)
+                        else:
+                            bmdeactivate(repo)
+                        tr.close()
+                    finally:
+                        lockmod.release(tr, lock)
+
+            displayer.show(p)
+            return 0
         else:
-            ret = hg.update(repo, p.rev())
-            if not ret:
-                tr = lock = None
-                wlock = repo.wlock()
-                try:
-                    lock = repo.lock()
-                    tr = repo.transaction('previous')
-                    if shouldmove:
-                        repo._bookmarks[bm] = p.node()
-                        repo._bookmarks.recordchange(tr)
-                    else:
-                        bmdeactivate(repo)
-                    tr.close()
-                finally:
-                    lockmod.release(tr, lock, wlock)
-        displayer.show(p)
-        return 0
-    else:
-        for p in parents:
-            displayer.show(p)
-        ui.warn(_('multiple parents, explicitly update to one\n'))
-        return 1
+            for p in parents:
+                displayer.show(p)
+            ui.warn(_('multiple parents, explicitly update to one\n'))
+            return 1
+    finally:
+        lockmod.release(wlock)
 
 @command('^next',
          [('B', 'move-bookmark', False,
@@ -2281,91 +2287,96 @@
 
     Displays the summary line of the destination for clarity.
     """
-    wkctx = repo[None]
-    wparents = wkctx.parents()
+    wlock = None
     dryrunopt = opts['dry_run']
-    if len(wparents) != 1:
-        raise error.Abort('merge in progress')
-    if not opts['merge']:
-        try:
-            cmdutil.bailifchanged(repo)
-        except error.Abort as exc:
-            exc.hint = _('do you want --merge?')
-            raise
-
-    children = [ctx for ctx in wparents[0].children() if not ctx.obsolete()]
-    topic = getattr(repo, 'currenttopic', '')
-    filtered = []
-    if topic and not opts.get("no_topic", False):
-        filtered = [ctx for ctx in children if ctx.topic() != topic]
-        # XXX N-square membership on children
-        children = [ctx for ctx in children if ctx not in filtered]
-    displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate})
-    if len(children) == 1:
-        c = children[0]
-        bm = bmactive(repo)
-        shouldmove = opts.get('move_bookmark') and bm is not None
-        if dryrunopt:
-            ui.write(('hg update %s;\n' % c.rev()))
-            if shouldmove:
-                ui.write(('hg bookmark %s -r %s;\n' % (bm, c.rev())))
+    if not dryrunopt:
+        wlock = repo.wlock()
+    try:
+        wkctx = repo[None]
+        wparents = wkctx.parents()
+        if len(wparents) != 1:
+            raise error.Abort('merge in progress')
+        if not opts['merge']:
+            try:
+                cmdutil.bailifchanged(repo)
+            except error.Abort as exc:
+                exc.hint = _('do you want --merge?')
+                raise
+
+        children = [ctx for ctx in wparents[0].children() if not ctx.obsolete()]
+        topic = getattr(repo, 'currenttopic', '')
+        filtered = []
+        if topic and not opts.get("no_topic", False):
+            filtered = [ctx for ctx in children if ctx.topic() != topic]
+            # XXX N-square membership on children
+            children = [ctx for ctx in children if ctx not in filtered]
+        displayer = cmdutil.show_changeset(ui, repo, {'template': shorttemplate})
+        if len(children) == 1:
+            c = children[0]
+            bm = bmactive(repo)
+            shouldmove = opts.get('move_bookmark') and bm is not None
+            if dryrunopt:
+                ui.write(('hg update %s;\n' % c.rev()))
+                if shouldmove:
+                    ui.write(('hg bookmark %s -r %s;\n' % (bm, c.rev())))
+            else:
+                ret = hg.update(repo, c.rev())
+                if not ret:
+                    lock = tr = None
+                    try:
+                        lock = repo.lock()
+                        tr = repo.transaction('next')
+                        if shouldmove:
+                            repo._bookmarks[bm] = c.node()
+                            repo._bookmarks.recordchange(tr)
+                        else:
+                            bmdeactivate(repo)
+                        tr.close()
+                    finally:
+                        lockmod.release(tr, lock)
+            displayer.show(c)
+            result = 0
+        elif children:
+            ui.warn(_("ambigious next changeset:\n"))
+            for c in children:
+                displayer.show(c)
+            ui.warn(_('explicitly update to one of them\n'))
+            result = 1
         else:
-            ret = hg.update(repo, c.rev())
-            if not ret:
-                lock = tr = None
-                wlock = repo.wlock()
-                try:
-                    lock = repo.lock()
-                    tr = repo.transaction('next')
-                    if shouldmove:
-                        repo._bookmarks[bm] = c.node()
-                        repo._bookmarks.recordchange(tr)
-                    else:
-                        bmdeactivate(repo)
-                    tr.close()
-                finally:
-                    lockmod.release(tr, lock, wlock)
-        displayer.show(c)
-        result = 0
-    elif children:
-        ui.warn(_("ambigious next changeset:\n"))
-        for c in children:
-            displayer.show(c)
-        ui.warn(_('explicitly update to one of them\n'))
-        result = 1
-    else:
-        aspchildren = _aspiringchildren(repo, [repo['.'].rev()])
-        if topic:
-            filtered.extend(repo[c] for c in children
-                            if repo[c].topic() != topic)
-            # XXX N-square membership on children
-            aspchildren = [ctx for ctx in aspchildren if ctx not in filtered]
-        if not opts['evolve'] or not aspchildren:
-            if filtered:
-                ui.warn(_('no children on topic "%s"\n') % topic)
-                ui.warn(_('do you want --no-topic\n'))
+            aspchildren = _aspiringchildren(repo, [repo['.'].rev()])
+            if topic:
+                filtered.extend(repo[c] for c in children
+                                if repo[c].topic() != topic)
+                # XXX N-square membership on children
+                aspchildren = [ctx for ctx in aspchildren if ctx not in filtered]
+            if not opts['evolve'] or not aspchildren:
+                if filtered:
+                    ui.warn(_('no children on topic "%s"\n') % topic)
+                    ui.warn(_('do you want --no-topic\n'))
+                else:
+                    ui.warn(_('no children\n'))
+                if aspchildren:
+                    msg = _('(%i unstable changesets to be evolved here, '
+                            'do you want --evolve?)\n')
+                    ui.warn(msg % len(aspchildren))
+                result = 1
+            elif 1 < len(aspchildren):
+                ui.warn(_("ambigious next (unstable) changeset:\n"))
+                for c in aspchildren:
+                    displayer.show(repo[c])
+                ui.warn(_('(run "hg evolve --rev REV" on one of them)\n'))
+                return 1
             else:
-                ui.warn(_('no children\n'))
-            if aspchildren:
-                msg = _('(%i unstable changesets to be evolved here, '
-                        'do you want --evolve?)\n')
-                ui.warn(msg % len(aspchildren))
-            result = 1
-        elif 1 < len(aspchildren):
-            ui.warn(_("ambigious next (unstable) changeset:\n"))
-            for c in aspchildren:
-                displayer.show(repo[c])
-            ui.warn(_('(run "hg evolve --rev REV" on one of them)\n'))
+                cmdutil.bailifchanged(repo)
+                result = _solveone(ui, repo, repo[aspchildren[0]], dryrunopt,
+                                   False, lambda:None, category='unstable')
+                if not result:
+                    ui.status(_('working directory now at %s\n') % repo['.'])
+                return result
             return 1
-        else:
-            cmdutil.bailifchanged(repo)
-            result = _solveone(ui, repo, repo[aspchildren[0]], dryrunopt,
-                               False, lambda:None, category='unstable')
-            if not result:
-                ui.status(_('working directory now at %s\n') % repo['.'])
-            return result
-        return 1
-    return result
+        return result
+    finally:
+        lockmod.release(wlock)
 
 def _reachablefrombookmark(repo, revs, bookmarks):
     """filter revisions and bookmarks reachable from the given bookmark
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/fake-editor.sh	Sun Oct 16 20:29:27 2016 +0200
@@ -0,0 +1,3 @@
+#!/bin/sh
+sleep 5
+echo "new desc" >> $1
--- a/tests/test-prev-next.t	Sat Oct 08 15:49:12 2016 +0200
+++ b/tests/test-prev-next.t	Sun Oct 16 20:29:27 2016 +0200
@@ -206,3 +206,34 @@
   move:[5] added d
   atop:[6] added b (3)
   working directory is now at 47ea25be8aea
+
+prev and next should lock properly against other commands
+
+  $ hg init repo
+  $ cd repo
+  $ HGEDITOR=${TESTDIR}/fake-editor.sh
+  $ echo hi > foo
+  $ hg ci -Am 'one'
+  adding foo
+  $ echo bye > foo
+  $ hg ci -Am 'two'
+
+  $ hg amend --edit &
+  $ sleep 1
+  $ hg prev
+  waiting for lock on working directory of $TESTTMP/repo held by process '*' on host '*' (glob)
+  got lock after [4-6] seconds (re)
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  [0] one
+  $ wait
+
+  $ hg amend --edit &
+  $ sleep 1
+  $ hg next --evolve
+  waiting for lock on working directory of $TESTTMP/repo held by process '*' on host '*' (glob)
+  1 new unstable changesets
+  got lock after [4-6] seconds (re)
+  move:[2] two
+  atop:[3] one
+  working directory now at a7d885c75614
+  $ wait