[PATCH 1 of 2 rfc] subrepo: make update -C for svn and git subrepos clean the working directory

Erik Zielke ez at aragost.com
Tue Jan 25 02:51:40 CST 2011


# HG changeset patch
# User Erik Zielke <ez at aragost.com>
# Date 1295943603 -3600
# Node ID 29633b15e5841f444bce6f6b33822d24e91d134f
# Parent  82d01ca87863e74dbf3ff1adc8c065620703a54a
subrepo: make update -C for svn and git subrepos clean the working directory

Makes the clean parameter work for svn and git sub repositories.

diff -r 82d01ca87863 -r 29633b15e584 mercurial/merge.py
--- a/mercurial/merge.py	Tue Jan 25 09:19:59 2011 +0100
+++ b/mercurial/merge.py	Tue Jan 25 09:20:03 2011 +0100
@@ -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 -r 82d01ca87863 -r 29633b15e584 mercurial/subrepo.py
--- a/mercurial/subrepo.py	Tue Jan 25 09:19:59 2011 +0100
+++ b/mercurial/subrepo.py	Tue Jan 25 09:20:03 2011 +0100
@@ -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,11 +599,13 @@
         except OSError:
             pass
 
-    def get(self, state):
+    def get(self, state, overwrite=False):
         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])
         self._ui.status(status)
+        if overwrite:
+            self._svncommand(['revert', '--recursive', self._path])
 
     def merge(self, state):
         old = int(self._state[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,26 @@
                 self._gitcommand(['reset', '--hard', 'HEAD'])
                 return
         elif self._gitstate() == revision:
+            if overwrite:
+#                self._gitcommand(['reset', 'HEAD', '.'])
+#                self._gitcommand(['reset', '--hard', 'HEAD'])
             return
         branch2rev, rev2branch = self._gitbranchmap()
 
+        def checkout(args):
+            cmd = ['checkout']
+            if overwrite:
+ #               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 +791,12 @@
         for b in branches:
             if b == 'refs/heads/master':
                 # master trumps all other branches
-                self._gitcommand(['checkout', 'refs/heads/master'])
+                checkout(['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 +811,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 +820,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 -r 82d01ca87863 -r 29633b15e584 tests/test-subrepo-update-clean.t
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-subrepo-update-clean.t	Tue Jan 25 09:20:03 2011 +0100
@@ -0,0 +1,181 @@
+Creating git repository
+  $ git init gitrepo -q
+  $ cd gitrepo
+  $ echo c > f0
+  $ git add f0
+  $ git commit -m0 -q
+  $ cd ..
+
+Creating svn repository
+  $ svnadmin create svnrepo
+  $ svn co -q file://$TESTTMP/svnrepo svnrepoco
+  $ cd svnrepoco
+  $ echo c > f1
+  $ svn add f1
+  A         f1
+  $ svn commit -m0 -q
+  $ cd ..
+
+Creating hg repository
+  $ hg init hgrepo
+  $ cd hgrepo
+  $ echo c > f2
+  $ hg add f2
+  $ hg commit -m1
+  $ cd ..
+
+Creating main hg repository
+  $ hg init main
+  $ cd main
+  $ git clone ../gitrepo gitrepo -q
+  $ svn co file://$TESTTMP/svnrepo svnrepo -q
+  $ hg clone ../hgrepo hgrepo
+  updating to branch default
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ echo gitrepo = [git]../gitrepo >> .hgsub
+  $ echo svnrepo = [svn]file://$TESTTMP/svnrepo  >> .hgsub
+  $ echo hgrepo  = ../hgrepo . >> .hgsub
+  $ hg add .hgsub
+  $ hg commit -m2
+  committing subrepository gitrepo
+  committing subrepository hgrepo
+  committing subrepository svnrepo
+
+Modifying file in each subrepo
+  $ echo c1 > gitrepo/f0
+  $ echo c1 > svnrepo/f1
+  $ echo c1 > hgrepo/f2
+
+Adding tracked file in each subrepo
+  $ echo c1 > gitrepo/f3
+  $ cd gitrepo
+  $ git add f3
+  $ cd ..
+  $ cd svnrepo
+  $ echo c1 > f4
+  $ svn add f4 -q
+  $ cd ..
+  $ cd hgrepo
+  $ echo c1 > f5
+  $ hg add f5
+  $ cd ..
+  $ cd svnrepo
+  $ svn status
+  M       f1
+  A       f4
+  $ cd ..
+  $ hg status -S
+  M gitrepo/f0
+  M hgrepo/f2
+  A gitrepo/f3
+  A hgrepo/f5
+
+Adding untracked file in each subrepo
+  $ cd gitrepo
+  $ echo c1 > f7
+  $ cd ..
+  $ cd svnrepo
+  $ echo c1 > f8
+  $ cd ..
+  $ cd hgrepo
+  $ echo c1 > f9
+  $ cd ..
+
+Checking status
+  $ cd svnrepo
+  $ svn status
+  ?       f8
+  M       f1
+  A       f4
+  $ cd ..
+  $ hg status -S
+  M gitrepo/f0
+  M hgrepo/f2
+  A gitrepo/f3
+  A hgrepo/f5
+  ? hgrepo/f9
+  $ cd gitrepo
+  $ ls
+  f0
+  f3
+  f7
+  $ cd ..
+
+Update clean
+  $ hg update -C
+  Checked out revision 1.
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg status -S -I gitrepo
+  $ cd gitrepo
+  $ ls
+  f0
+  f3
+  f7
+  $ cd ..
+  $ cd svnrepo
+  $ ls
+  f1
+  f4
+  f8
+  $ svn status
+  ?       f4
+  ?       f8
+  $ cd ..
+  $ hg status -S
+  ? hgrepo/f5
+  ? hgrepo/f9
+  $ cd hgrepo
+  $ ls
+  f2
+  f5
+  f9
+  $ cd ..
+
+Update clean 2
+  $ hg update -r 0 -C
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ echo c3 > gitrepo/f0
+  $ echo c3 > svnrepo/f1
+  $ echo c3 > hgrepo/f2
+  $ cd svnrepo
+  $ svn status
+  ?       f4
+  ?       f8
+  M       f1
+  $ cd ..
+  $ hg status -S
+  M gitrepo/f0
+  M hgrepo/f2
+  ? hgrepo/f5
+  ? hgrepo/f9
+  $ hg update tip -C
+  Checked out revision 1.
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ cd svnrepo
+  $ svn status
+  ?       f4
+  ?       f8
+  $ cd ..
+  $ hg status -S
+  ? hgrepo/f5
+  ? hgrepo/f9
+  $ echo c4 > gitrepo/f0
+  $ echo c4 > svnrepo/f1
+  $ echo c4 > hgrepo/f2
+  $ hg update -r 0 -C
+  Checked out revision 1.
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ cd svnrepo
+  $ svn status
+  ?       f4
+  ?       f8
+  $ cd ..
+  $ hg status -S
+  ? hgrepo/f5
+  ? hgrepo/f9
+  $ hg status -S -I gitrepo
+  $ cd gitrepo
+  $ ls
+  f0
+  f3
+  f7


More information about the Mercurial-devel mailing list