[PATCH] subrepo: Update .hgsubstate in case of deleted subrepo

Saint Germain saintger at gmail.com
Mon Feb 22 18:45:25 CST 2010


I've discussed with tonfa on IRC and it seems that a flag
'clean-subrepo' or -CS is too specific.
He proposed a flag like '--subrepo' which could be used by other
commands as well (like 'status' ?). But for this kind of decision, we need mpm.

But what do you think about it ?

Anyway, here is the updated patch (on a newer revision than the
previous one)

To: mercurial-devel at selenic.com
Cc: 

Affichage de [PATCH] subrepo: Force updating subrepos if using overwrite option ...
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCH] subrepo: Force updating subrepos if using overwrite option
X-Mercurial-Node: 6f6c33d85a8daeb0c3402f7ab951ef390e49f7e6
Message-Id: <6f6c33d85a8daeb0c340.1266885679 at localhost.localdomain>
User-Agent: Mercurial-patchbomb/1.4.3+20-b9e44cc97355
Date: Tue, 23 Feb 2010 01:41:19 +0100
From: Saint Germain <saintger at gmail.com>
To: mercurial-devel at selenic.com

# HG changeset patch
# User Saint Germain <saintger at gmail.com>
# Date 1266885659 -3600
# Branch stable
# Node ID 6f6c33d85a8daeb0c3402f7ab951ef390e49f7e6
# Parent  b07d487009b2235f5d03cfa3b0f08be04a4b0a17
subrepo: Force updating subrepos if using overwrite option

Even if .hgsubstate doesn't need updating, subrepos may be 'dirty'. So if using -CS (overwrite)
option, add a check for 'dirty' subrepos and if found, force the update.

diff -r b07d487009b2 -r 6f6c33d85a8d mercurial/commands.py
--- a/mercurial/commands.py	Mon Feb 22 01:19:59 2010 +0100
+++ b/mercurial/commands.py	Tue Feb 23 01:40:59 2010 +0100
@@ -3241,7 +3241,8 @@
 
     return postincoming(ui, repo, modheads, opts.get('update'), None)
 
-def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
+def update(ui, repo, node=None, rev=None, clean=False, date=None,
+           check=False, clean_subrepos=False):
     """update working directory
 
     Update the repository's working directory to the specified
@@ -3297,7 +3298,7 @@
         rev = cmdutil.finddate(ui, repo, date)
 
     if clean or check:
-        return hg.clean(repo, rev)
+        return hg.clean(repo, rev, clean_subrepo=clean_subrepos)
     else:
         return hg.update(repo, rev)
 
@@ -3819,6 +3820,8 @@
     "^update|up|checkout|co":
         (update,
          [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
+          ('S', 'clean-subrepos', None,_('use with "clean" (-CS) to discard'
+                ' uncommitted changes (no backup) in subrepositories')),
           ('c', 'check', None, _('check for uncommitted changes')),
           ('d', 'date', '', _('tipmost revision matching date')),
           ('r', 'rev', '', _('revision'))],
diff -r b07d487009b2 -r 6f6c33d85a8d mercurial/hg.py
--- a/mercurial/hg.py	Mon Feb 22 01:19:59 2010 +0100
+++ b/mercurial/hg.py	Tue Feb 23 01:40:59 2010 +0100
@@ -367,9 +367,9 @@
 # naming conflict in clone()
 _update = update
 
-def clean(repo, node, show_stats=True):
+def clean(repo, node, show_stats=True, clean_subrepo=False):
     """forcibly switch the working directory to node, clobbering changes"""
-    stats = _merge.update(repo, node, False, True, None)
+    stats = _merge.update(repo, node, False, True, None, clean_subrepo)
     if show_stats:
         _showstats(repo, stats)
     return stats[3] > 0
diff -r b07d487009b2 -r 6f6c33d85a8d mercurial/merge.py
--- a/mercurial/merge.py	Mon Feb 22 01:19:59 2010 +0100
+++ b/mercurial/merge.py	Tue Feb 23 01:40:59 2010 +0100
@@ -117,7 +117,8 @@
 
     return action
 
-def manifestmerge(repo, p1, p2, pa, overwrite, partial):
+def manifestmerge(repo, p1, p2, pa, overwrite, partial,
+                  overwrite_subrepo=False):
     """
     Merge p1 and p2 with ancestor ma and generate merge action list
 
@@ -186,6 +187,16 @@
             if n == m2[f] or m2[f] == a: # same or local newer
                 if m1.flags(f) != rflags:
                     act("update permissions", "e", f, rflags)
+                # in case of subrepos, update if overwrite and subrepos is dirty
+                if f == '.hgsubstate':
+                    for s in p1.substate:
+                        if p1.sub(s).dirty(): # if dirty, force update
+                            if overwrite_subrepo:
+                                act("remote is newer", "g", f, rflags)
+                            elif overwrite:
+                                raise util.Abort("subrepos have uncommitted"
+                                " changes, use 'hg update -CS' to overwrite\n")
+                            break
             elif n == a: # remote newer
                 act("remote is newer", "g", f, rflags)
             else: # both changed
@@ -406,7 +417,7 @@
                 if f:
                     repo.dirstate.forget(f)
 
-def update(repo, node, branchmerge, force, partial):
+def update(repo, node, branchmerge, force, partial, clean_subrepos=False):
     """
     Perform a merge between the working directory and the given node
 
@@ -455,6 +466,7 @@
                 else:
                     raise util.Abort(_("branch %s not found") % wc.branch())
         overwrite = force and not branchmerge
+        overwrite_subrepo = overwrite and clean_subrepos
         pl = wc.parents()
         p1, p2 = pl[0], repo[node]
         pa = p1.ancestor(p2)
@@ -496,7 +508,8 @@
         if not util.checkcase(repo.path):
             _checkcollision(p2)
         action += _forgetremoved(wc, p2, branchmerge)
-        action += manifestmerge(repo, wc, p2, pa, overwrite, partial)
+        action += manifestmerge(repo, wc, p2, pa, overwrite, partial,
+                                overwrite_subrepo)
 
         ### apply phase
         if not branchmerge: # just jump to the new rev
diff -r b07d487009b2 -r 6f6c33d85a8d tests/test-subrepo
--- a/tests/test-subrepo	Mon Feb 22 01:19:59 2010 +0100
+++ b/tests/test-subrepo	Tue Feb 23 01:40:59 2010 +0100
@@ -207,4 +207,20 @@
     | "$TESTDIR/filtertmp.py"
 rm -rf mercurial mercurial2
 
+echo % test repositoy clean/overwrite updating
+hg init mercurial
+cd mercurial
+hg init nested
+echo test > nested/foo
+hg -R nested add nested/foo
+echo nested = nested > .hgsub
+hg add .hgsub
+hg ci -mtest
+echo modification > nested/foo
+hg -R nested commit -mmodif
+hg update -C
+hg update -CS
+cd ..
+rm -rf mercurial
+
 exit 0
diff -r b07d487009b2 -r 6f6c33d85a8d tests/test-subrepo.out
--- a/tests/test-subrepo.out	Mon Feb 22 01:19:59 2010 +0100
+++ b/tests/test-subrepo.out	Tue Feb 23 01:40:59 2010 +0100
@@ -266,3 +266,8 @@
 default = $HGTMP/test-subrepo/sub/mercurial/main/nested_absolute
 [paths]
 default = $HGTMP/test-subrepo/sub/mercurial/main/nested_relative
+% test repositoy clean/overwrite updating
+committing subrepository nested
+abort: subrepos have uncommitted changes, use 'hg update -CS' to overwrite
+
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved




On Thu, 18 Feb 2010 21:36:31 -0500, Steve Losh <steve at stevelosh.com>
wrote :

> Saint Germain and I have been talking about this patch on IRC.  I'm
> happy with this version of the patch, but I think we *might* be able
> to make it even better.
> 
> The main question I have is about deleting .hgsubstate automatically
> when the user manually deletes .hgsub entirely.
> 
> On the surface this seems like a good idea -- if you delete .hgsub
> that means there are no subrepos any more, so it seems
> like .hgsubstate should also be deleted.
> 
> The question I have is: "What happens when person A
> deletes .hgsubstate and .hgsub and then tried to merge with person B
> who has added a new subrepo to .hgsub (and therefore .hgsubstate)?"
> 
> Can Mercurial manage to merge the changes cleanly if we
> leave .hgsubstate blank (but not deleted), or are you going to get
> merge conflicts no matter what?
> 
> On Feb 18, 2010, at 7:20 PM, Saint Germain wrote:
> 
> > # HG changeset patch
> > # User Saint Germain <saintger at gmail.com>
> > # Date 1266538364 -3600
> > # Node ID 52bef2e2c25f10e806a0cdec03ed56e08f5a54c2
> > # Parent  b9e44cc97355ff27e05f6cd384061fc12731cec0
> > subrepo: Update .hgsubstate in case of deleted subrepo
> > 
> > When a subrepo is deleted from .hgsub, it also need to be removed
> > from .hgsubstate. When .hgsub is removed, .hgsubstate need at least
> > to be blanked out. Previous code was updating .hgsubstate only in
> > case of newly or modified subrepo.
> > 
> > diff -r b9e44cc97355 -r 52bef2e2c25f mercurial/localrepo.py
> > --- a/mercurial/localrepo.py	Wed Feb 03 16:09:19 2010 +0000
> > +++ b/mercurial/localrepo.py	Fri Feb 19 01:12:44 2010 +0100
> > @@ -833,8 +833,9 @@
> >                 cctx._text = editor(self, cctx, subs)
> >             edited = (text != cctx._text)
> > 
> > -            # commit subs
> > -            if subs:
> > +            # Update .hgsubstate if commited (added to .hgsub or
> > modified) subs
> > +            # or deleted subs (removed from .hgsub)
> > +            if subs or '.hgsub' in changes[0]+changes[2]:
> >                 state = wctx.substate.copy()
> >                 for s in subs:
> >                     self.ui.status(_('committing subrepository
> > %s\n') % s) diff -r b9e44cc97355 -r 52bef2e2c25f tests/test-subrepo
> > --- a/tests/test-subrepo	Wed Feb 03 16:09:19 2010 +0000
> > +++ b/tests/test-subrepo	Fri Feb 19 01:12:44 2010 +0100
> > @@ -160,5 +160,28 @@
> > 
> > hg up 5
> > hg merge 4    # try to merge default into br again
> > +cd ..
> > +rm -rf main
> > 
> > +echo % test subrepo delete from .hgsubstate
> > +hg init main
> > +mkdir main/nested main/nested2
> > +hg init main/nested
> > +hg init main/nested2
> > +echo test > main/nested/foo
> > +echo test > main/nested2/foo
> > +hg -R main/nested add
> > +hg -R main/nested2 add
> > +hg -R main/nested ci -m test
> > +hg -R main/nested2 ci -m test
> > +echo nested = nested > main/.hgsub
> > +echo nested2 = nested2 >> main/.hgsub
> > +hg -R main add
> > +hg -R main ci -m "nested 1 & 2 added"
> > +echo nested = nested > main/.hgsub
> > +hg -R main ci -m "nested 2 deleted"
> > +cat main/.hgsubstate | sed "s:.* ::"
> > +hg -R main remove main/.hgsub
> > +hg -R main ci -m ".hgsub deleted"
> > +cat main/.hgsubstate
> > exit 0
> > diff -r b9e44cc97355 -r 52bef2e2c25f tests/test-subrepo.out
> > --- a/tests/test-subrepo.out	Wed Feb 03 16:09:19 2010 +0000
> > +++ b/tests/test-subrepo.out	Fri Feb 19 01:12:44 2010 +0100
> > @@ -243,3 +243,10 @@
> > 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
> > 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
> > (branch merge, don't forget to commit)
> > +% test subrepo delete from .hgsubstate
> > +adding main/nested/foo
> > +adding main/nested2/foo
> > +adding main/.hgsub
> > +committing subrepository nested2
> > +committing subrepository nested
> > +nested
> > _______________________________________________
> > Mercurial-devel mailing list
> > Mercurial-devel at selenic.com
> > http://selenic.com/mailman/listinfo/mercurial-devel
> 


More information about the Mercurial-devel mailing list