[PATCH 1 of 1] subrepo: make update -C for svn and git subrepos clean the working directory
Erik Zielke
ez at aragost.com
Mon Jan 31 05:44:29 CST 2011
# HG changeset patch
# User Erik Zielke <ez at aragost.com>
# Date 1296472946 -3600
# Node ID 0a00428b75fc2aae53318c6eaad274fb70e7c16d
# Parent a94042c6fca18bb3ead93ac6f3a8d38867569de4
subrepo: make update -C for svn and git subrepos clean the working directory
makes update --clean behave the same way for all three kinds of
subrepositories [hg, svn, git]. Before svn and git did not take the
clean parameter into account, but just updated to the given revision
and merged uncommitted changes into that.
diff --git a/mercurial/merge.py b/mercurial/merge.py
--- a/mercurial/merge.py
+++ b/mercurial/merge.py
@@ -249,7 +249,7 @@
def actionkey(a):
return a[1] == 'r' and -1 or 0, a
-def applyupdates(repo, action, wctx, mctx, actx):
+def applyupdates(repo, action, wctx, mctx, actx, overwrite):
"""apply the merge action list to the working directory
wctx is the working copy context
@@ -310,7 +310,7 @@
repo.ui.note(_("removing %s\n") % f)
audit_path(f)
if f == '.hgsubstate': # subrepo states need updating
- subrepo.submerge(repo, wctx, mctx, wctx)
+ subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
try:
util.unlinkpath(repo.wjoin(f))
except OSError, inst:
@@ -320,7 +320,7 @@
removed += 1
elif m == "m": # merge
if f == '.hgsubstate': # subrepo states need updating
- subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx))
+ subrepo.submerge(repo, wctx, mctx, wctx.ancestor(mctx), overwrite)
continue
f2, fd, flags, move = a[2:]
r = ms.resolve(fd, wctx, mctx)
@@ -343,7 +343,7 @@
t = None
updated += 1
if f == '.hgsubstate': # subrepo states need updating
- subrepo.submerge(repo, wctx, mctx, wctx)
+ subrepo.submerge(repo, wctx, mctx, wctx, overwrite)
elif m == "d": # directory rename
f2, fd, flags = a[2:]
if f:
@@ -534,7 +534,7 @@
if not partial:
repo.hook('preupdate', throw=True, parent1=xp1, parent2=xp2)
- stats = applyupdates(repo, action, wc, p2, pa)
+ stats = applyupdates(repo, action, wc, p2, pa, overwrite)
if not partial:
repo.dirstate.setparents(fp1, fp2)
diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py
--- a/mercurial/subrepo.py
+++ b/mercurial/subrepo.py
@@ -82,7 +82,7 @@
''.join(['%s %s\n' % (state[s][1], s)
for s in sorted(state)]), '')
-def submerge(repo, wctx, mctx, actx):
+def submerge(repo, wctx, mctx, actx, overwrite):
"""delegated from merge.applyupdates: merging of .hgsubstate file
in working context, merging context and ancestor context"""
if mctx == actx: # backwards?
@@ -114,7 +114,7 @@
continue
elif ld == a: # other side changed
debug(s, "other changed, get", r)
- wctx.sub(s).get(r)
+ wctx.sub(s).get(r, overwrite)
sm[s] = r
elif ld[0] != r[0]: # sources differ
if repo.ui.promptchoice(
@@ -123,11 +123,11 @@
% (s, l[0], r[0]),
(_('&Local'), _('&Remote')), 0):
debug(s, "prompt changed, get", r)
- wctx.sub(s).get(r)
+ wctx.sub(s).get(r, overwrite)
sm[s] = r
elif ld[1] == a[1]: # local side is unchanged
debug(s, "other side changed, get", r)
- wctx.sub(s).get(r)
+ wctx.sub(s).get(r, overwrite)
sm[s] = r
else:
debug(s, "both sides changed, merge with", r)
@@ -263,13 +263,13 @@
"""
raise NotImplementedError
- def get(self, state):
+ def get(self, state, overwrite=False):
"""run whatever commands are needed to put the subrepo into
this state
"""
raise NotImplementedError
- def merge(self, state):
+ def merge(self, state, overwrite=False):
"""merge currently-saved state with the new state."""
raise NotImplementedError
@@ -431,7 +431,7 @@
other = hg.repository(self._repo.ui, srcurl)
self._repo.pull(other)
- def get(self, state):
+ def get(self, state, overwrite=False):
self._get(state)
source, revision, kind = state
self._repo.ui.debug("getting subrepo %s\n" % self._path)
@@ -599,7 +599,9 @@
except OSError:
pass
- def get(self, state):
+ def get(self, state, overwrite=False):
+ if overwrite:
+ self._svncommand(['revert', '--recursive', self._path])
status = self._svncommand(['checkout', state[0], '--revision', state[1]])
if not re.search('Checked out revision [0-9]+.', status):
raise util.Abort(status.splitlines()[-1])
@@ -749,9 +751,10 @@
out, code = self._gitdir(['diff-index', '--quiet', 'HEAD'])
return code == 1
- def get(self, state):
+ def get(self, state, overwrite=False):
source, revision, kind = state
self._fetch(source, revision)
+
# if the repo was set to be bare, unbare it
if self._gitcommand(['config', '--bool', 'core.bare']) == 'true':
self._gitcommand(['config', 'core.bare', 'false'])
@@ -759,16 +762,32 @@
self._gitcommand(['reset', '--hard', 'HEAD'])
return
elif self._gitstate() == revision:
+ if overwrite:
+ # first reset the index to unmark new files for commit, because
+ # reset --hard will otherwise throw away files added for commit,
+ # not just unmark them.
+ self._gitcommand(['reset', 'HEAD'])
+ self._gitcommand(['reset', '--hard', 'HEAD'])
return
branch2rev, rev2branch = self._gitbranchmap()
+ def checkout(args):
+ cmd = ['checkout']
+ if overwrite:
+ # first reset the index to unmark new files for commit, because
+ # the -f option will otherwise throw away files added for
+ # commit, not just unmark them.
+ self._gitcommand(['reset', 'HEAD'])
+ cmd.append('-f')
+ self._gitcommand(cmd + args)
+
def rawcheckout():
# no branch to checkout, check it out with no branch
self._ui.warn(_('checking out detached HEAD in subrepo %s\n') %
self._relpath)
self._ui.warn(_('check out a git branch if you intend '
'to make changes\n'))
- self._gitcommand(['checkout', '-q', revision])
+ checkout(['-q', revision])
if revision not in rev2branch:
rawcheckout()
@@ -778,12 +797,12 @@
for b in branches:
if b == 'refs/heads/master':
# master trumps all other branches
- self._gitcommand(['checkout', 'refs/heads/master'])
+ checkout(['refs/heads/master'])
return
if not firstlocalbranch and not b.startswith('refs/remotes/'):
firstlocalbranch = b
if firstlocalbranch:
- self._gitcommand(['checkout', firstlocalbranch])
+ checkout([firstlocalbranch])
return
tracking = self._gittracking(branch2rev.keys())
@@ -798,7 +817,7 @@
if remote not in tracking:
# create a new local tracking branch
local = remote.split('/', 2)[2]
- self._gitcommand(['checkout', '-b', local, remote])
+ checkout(['-b', local, remote])
elif self._gitisancestor(branch2rev[tracking[remote]], remote):
# When updating to a tracked remote branch,
# if the local tracking branch is downstream of it,
@@ -807,7 +826,7 @@
# Since we are only looking at branching at update, we need to
# detect this situation and perform this action lazily.
if tracking[remote] != self._gitcurrentbranch():
- self._gitcommand(['checkout', tracking[remote]])
+ checkout([tracking[remote]])
self._gitcommand(['merge', '--ff', remote])
else:
# a real merge would be required, just checkout the revision
diff --git a/tests/test-subrepo-git.t b/tests/test-subrepo-git.t
--- a/tests/test-subrepo-git.t
+++ b/tests/test-subrepo-git.t
@@ -304,3 +304,21 @@
$ ls ../narchive/inner/s | grep -v pax_global_header
f
g
+
+Check hg update --clean
+ $ cd $TESTTMP/t
+ $ echo > s/g
+ $ cd s
+ $ echo c1 > f1
+ $ echo c1 > f2
+ $ git add f1
+ $ git status --short
+ A f1
+ M g
+ ?? f2
+ $ cd ..
+ $ hg update -C > /dev/null 2>/dev/null
+ $ cd s
+ $ git status --short
+ ?? f1
+ ?? f2
diff --git a/tests/test-subrepo-svn.t b/tests/test-subrepo-svn.t
--- a/tests/test-subrepo-svn.t
+++ b/tests/test-subrepo-svn.t
@@ -264,3 +264,35 @@
$ hg up null
0 files updated, 0 files merged, 3 files removed, 0 files unresolved
$ ls
+
+Check hg update --clean
+ $ cd $TESTTMP/sub/t
+ $ cd s
+ $ echo c0 > alpha
+ $ echo c1 > f1
+ $ echo c1 > f2
+ $ svn add f1 -q
+ $ svn status
+ ? a
+ X externals
+ ? f2
+ M alpha
+ A f1
+
+ Performing status on external item at 'externals'
+ $ cd ..
+ $ hg update -C
+
+ Fetching external item into '$TESTTMP/sub/t/s/externals'
+ Checked out external at revision 1.
+
+ Checked out revision 3.
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ cd s
+ $ svn status
+ ? a
+ X externals
+ ? f1
+ ? f2
+
+ Performing status on external item at 'externals'
diff --git a/tests/test-subrepo.t b/tests/test-subrepo.t
--- a/tests/test-subrepo.t
+++ b/tests/test-subrepo.t
@@ -675,3 +675,31 @@
committing subrepository subrepo-1
committing subrepository subrepo-2
$ hg st subrepo-2/file
+
+Check hg update --clean
+ $ cd $TESTTMP/sub/t
+ $ rm -r t/t.orig
+ $ hg status -S --all
+ C .hgsub
+ C .hgsubstate
+ C a
+ C s/.hgsub
+ C s/.hgsubstate
+ C s/a
+ C s/ss/a
+ C t/t
+ $ echo c1 > s/a
+ $ cd s
+ $ echo c1 > b
+ $ echo c1 > c
+ $ hg add b
+ $ cd ..
+ $ hg status -S
+ M s/a
+ A s/b
+ ? s/c
+ $ hg update -C
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ hg status -S
+ ? s/b
+ ? s/c
More information about the Mercurial-devel
mailing list