update: wlock the repo for the whole 'hg update' command
The update command is touching the repository and should lock it for
the length of its operations. Equally importantly, it should lock the
repository when it is writing bookmarks. It wasn't doing so until now,
leaving doors open for all kinds of drunk beaver parties.
This results in some minor tests changes, and the fixing of a couple
of bugs from race conditions.
Code does not receive any changes beside extra indentation.
--- a/mercurial/commands.py Thu Aug 13 11:09:36 2015 -0300
+++ b/mercurial/commands.py Tue Aug 11 16:26:12 2015 -0700
@@ -6451,51 +6451,55 @@
if rev is None or rev == '':
rev = node
- cmdutil.clearunfinished(repo)
-
- # with no argument, we also move the active bookmark, if any
- rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
-
- # if we defined a bookmark, we have to remember the original bookmark name
- brev = rev
- rev = scmutil.revsingle(repo, rev, rev).rev()
-
- if check and clean:
- raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
-
- if date:
- if rev is not None:
- raise util.Abort(_("you can't specify a revision and a date"))
- rev = cmdutil.finddate(ui, repo, date)
-
- if check:
- cmdutil.bailifchanged(repo, merge=False)
- if rev is None:
- rev = repo[repo[None].branch()].rev()
-
- repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
-
- if clean:
- ret = hg.clean(repo, rev)
- else:
- ret = hg.update(repo, rev)
-
- if not ret and movemarkfrom:
- if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
- ui.status(_("updating bookmark %s\n") % repo._activebookmark)
+ wlock = repo.wlock()
+ try:
+ cmdutil.clearunfinished(repo)
+
+ # with no argument, we also move the active bookmark, if any
+ rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
+
+ # if we defined a bookmark, we have to remember the original name
+ brev = rev
+ rev = scmutil.revsingle(repo, rev, rev).rev()
+
+ if check and clean:
+ raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
+
+ if date:
+ if rev is not None:
+ raise util.Abort(_("you can't specify a revision and a date"))
+ rev = cmdutil.finddate(ui, repo, date)
+
+ if check:
+ cmdutil.bailifchanged(repo, merge=False)
+ if rev is None:
+ rev = repo[repo[None].branch()].rev()
+
+ repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
+
+ if clean:
+ ret = hg.clean(repo, rev)
else:
- # this can happen with a non-linear update
- ui.status(_("(leaving bookmark %s)\n") %
- repo._activebookmark)
+ ret = hg.update(repo, rev)
+
+ if not ret and movemarkfrom:
+ if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
+ ui.status(_("updating bookmark %s\n") % repo._activebookmark)
+ else:
+ # this can happen with a non-linear update
+ ui.status(_("(leaving bookmark %s)\n") %
+ repo._activebookmark)
+ bookmarks.deactivate(repo)
+ elif brev in repo._bookmarks:
+ bookmarks.activate(repo, brev)
+ ui.status(_("(activating bookmark %s)\n") % brev)
+ elif brev:
+ if repo._activebookmark:
+ ui.status(_("(leaving bookmark %s)\n") %
+ repo._activebookmark)
bookmarks.deactivate(repo)
- elif brev in repo._bookmarks:
- bookmarks.activate(repo, brev)
- ui.status(_("(activating bookmark %s)\n") % brev)
- elif brev:
- if repo._activebookmark:
- ui.status(_("(leaving bookmark %s)\n") %
- repo._activebookmark)
- bookmarks.deactivate(repo)
+ finally:
+ wlock.release()
return ret
--- a/tests/test-blackbox.t Thu Aug 13 11:09:36 2015 -0300
+++ b/tests/test-blackbox.t Tue Aug 11 16:26:12 2015 -0700
@@ -119,8 +119,8 @@
$ echo '[hooks]' >> .hg/hgrc
$ echo 'update = echo hooked' >> .hg/hgrc
$ hg update
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
hooked
- 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ hg blackbox -l 5
1970/01/01 00:00:00 bob> update
1970/01/01 00:00:00 bob> writing .hg/cache/tags2-visible with 0 tags
--- a/tests/test-hook.t Thu Aug 13 11:09:36 2015 -0300
+++ b/tests/test-hook.t Tue Aug 11 16:26:12 2015 -0700
@@ -223,8 +223,8 @@
$ echo "update = printenv.py update" >> .hg/hgrc
$ hg update
preupdate hook: HG_PARENT1=539e4b31b6dc
+ 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
update hook: HG_ERROR=0 HG_PARENT1=539e4b31b6dc
- 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
pushkey hook
@@ -644,8 +644,8 @@
$ hg ci -ma
223eafe2750c tip
$ hg up 0 --config extensions.largefiles=
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
cb9a9f314b8b
- 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
make sure --verbose (and --quiet/--debug etc.) are propagated to the local ui
that is passed to pre/post hooks
--- a/tests/test-lock-badness.t Thu Aug 13 11:09:36 2015 -0300
+++ b/tests/test-lock-badness.t Tue Aug 11 16:26:12 2015 -0700
@@ -59,7 +59,6 @@
$ hg -R b up -q --config hooks.pre-update="python:`pwd`/hooks.py:sleephalf"
waiting for lock on working directory of b held by '*:*' (glob)
got lock after ? seconds (glob)
- warning: ignoring unknown working parent d2ae7f538514!
$ wait
$ cat stdout
adding b