robustcheckout: resolve symbolic revisions from remote (
bug 1287506); r?Callek
Previously, if we were checkout out a symbolic revision, we would
always pull from the remote then resolve that name locally. This
is not ideal because the local repo may have other references to
that name not on the remote and the local references may be checked
out.
We change the code to resolve the name on the remote then use the
resolved value locally. As part of this, we refactor the code to
avoid pulling if the remotely resolved name is locally available.
In theory, we may not pull things like phases and obsolescence
markers that could have been updated on the remote. However, this
is an existing deficiency in the robustcheckout extension. If we
want to ensure all remote state is present locally, we should add
an --always-pull flag or something. But that's for another bug.
MozReview-Commit-ID: 4dSEZITAL2D
--- a/hgext/robustcheckout/__init__.py
+++ b/hgext/robustcheckout/__init__.py
@@ -13,16 +13,17 @@ from __future__ import absolute_import
import contextlib
import errno
import functools
import os
import re
from mercurial.i18n import _
+from mercurial.node import hex
from mercurial import (
commands,
error,
exchange,
extensions,
cmdutil,
hg,
scmutil,
@@ -254,27 +255,37 @@ def _docheckout(ui, url, dest, upstream,
if revision and revision in repo:
ctx = repo[revision]
if not ctx.hex().startswith(revision):
raise error.Abort('--revision argument is ambiguous',
hint='must be the first 12+ characters of a '
'SHA-1 fragment')
+ checkoutrevision = ctx.hex()
havewantedrev = True
if not havewantedrev:
ui.write('(pulling to obtain %s)\n' % (revision or branch,))
try:
remote = hg.peer(repo, {}, url)
pullrevs = [remote.lookup(revision or branch)]
- pullop = exchange.pull(repo, remote, heads=pullrevs)
- if not pullop.rheads:
- raise error.Abort('unable to pull requested revision')
+ checkoutrevision = hex(pullrevs[0])
+ if branch:
+ ui.warn('(remote resolved %s to %s; '
+ 'result is not deterministic)\n' %
+ (branch, checkoutrevision))
+
+ if checkoutrevision in repo:
+ ui.warn('(revision already present locally; not pulling)\n')
+ else:
+ pullop = exchange.pull(repo, remote, heads=pullrevs)
+ if not pullop.rheads:
+ raise error.Abort('unable to pull requested revision')
except error.Abort as e:
if e.message == _('repository is unrelated'):
ui.warn('(repository is unrelated; deleting)\n')
destvfs.rmtree(forcibly=True)
return callself()
raise
except error.RepoError as e:
@@ -298,21 +309,20 @@ def _docheckout(ui, url, dest, upstream,
if purgeext.purge(ui, repo, all=True, abort_on_err=True,
# The function expects all arguments to be
# defined.
**{'print': None, 'print0': None, 'dirs': None,
'files': None}):
raise error.Abort('error purging')
# Update the working directory.
- if commands.update(ui, repo, rev=revision or branch, clean=True):
+ if commands.update(ui, repo, rev=checkoutrevision, clean=True):
raise error.Abort('error updating')
- ctx = repo[revision or branch]
- ui.write('updated to %s\n' % ctx.hex())
+ ui.write('updated to %s\n' % checkoutrevision)
return None
def extsetup(ui):
# Ensure required extensions are loaded.
for ext in ('purge', 'share'):
try:
extensions.find(ext)
--- a/hgext/robustcheckout/tests/test-revision-branch.t
+++ b/hgext/robustcheckout/tests/test-revision-branch.t
@@ -38,37 +38,40 @@ Specifying branch argument will checkout
requesting all changes
adding changesets
adding manifests
adding file changes
added 3 changesets with 3 changes to 1 files (+1 heads)
searching for changes
no changes found
(pulling to obtain default)
- no changes found
+ (remote resolved default to 5d6cdc75a09bcccf76f9339a28e1d89360c59dce; result is not deterministic)
+ (revision already present locally; not pulling)
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
updated to 5d6cdc75a09bcccf76f9339a28e1d89360c59dce
Specifying branch argument will always attempt to pull because branch revisions can change
$ hg robustcheckout http://localhost:$HGPORT/repo0 dest --branch default
ensuring http://localhost:$HGPORT/repo0@default is available at dest
(existing repository shared store: $TESTTMP/share/b8b78f0253d822e33ba652fd3d80a5c0837cfdf3/.hg)
(pulling to obtain default)
- no changes found
+ (remote resolved default to 5d6cdc75a09bcccf76f9339a28e1d89360c59dce; result is not deterministic)
+ (revision already present locally; not pulling)
0 files updated, 0 files merged, 0 files removed, 0 files unresolved
updated to 5d6cdc75a09bcccf76f9339a28e1d89360c59dce
Updating to another branch works
$ hg robustcheckout http://localhost:$HGPORT/repo0 dest --branch branch1
ensuring http://localhost:$HGPORT/repo0@branch1 is available at dest
(existing repository shared store: $TESTTMP/share/b8b78f0253d822e33ba652fd3d80a5c0837cfdf3/.hg)
(pulling to obtain branch1)
- no changes found
+ (remote resolved branch1 to aada1b3e573f7272bb2ef93b34acbf0f77c69d44; result is not deterministic)
+ (revision already present locally; not pulling)
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
updated to aada1b3e573f7272bb2ef93b34acbf0f77c69d44
Specifying revision will switch away from branch
$ hg robustcheckout http://localhost:$HGPORT/repo0 dest --revision 5d6cdc75a09b
ensuring http://localhost:$HGPORT/repo0@5d6cdc75a09b is available at dest
(existing repository shared store: $TESTTMP/share/b8b78f0253d822e33ba652fd3d80a5c0837cfdf3/.hg)
@@ -101,17 +104,16 @@ revision
$ hg -q commit -A -m 'default head 2'
$ cd ..
$ hg -R server/repo0 log -r default -T '{node}\n'
5d6cdc75a09bcccf76f9339a28e1d89360c59dce
$ hg -R dest log -r default -T '{node}\n'
6f89935a511842d2a7393cad33ef93bf793b1db2
-FIXME
-
$ hg robustcheckout http://localhost:$HGPORT/repo0 dest --branch default
ensuring http://localhost:$HGPORT/repo0@default is available at dest
(existing repository shared store: $TESTTMP/share/b8b78f0253d822e33ba652fd3d80a5c0837cfdf3/.hg)
(pulling to obtain default)
- no changes found
- 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
- updated to 6f89935a511842d2a7393cad33ef93bf793b1db2
+ (remote resolved default to 5d6cdc75a09bcccf76f9339a28e1d89360c59dce; result is not deterministic)
+ (revision already present locally; not pulling)
+ 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ updated to 5d6cdc75a09bcccf76f9339a28e1d89360c59dce