subrepo: be more careful with deletions of .hgsub and .hgsubstate (issue2844)
authorMatt Mackall <mpm@selenic.com>
Mon, 06 Jun 2011 15:17:40 -0500
changeset 14536 52cbeb5a651b
parent 14535 e597ef52a7c2
child 14537 3c7907dc95ca
subrepo: be more careful with deletions of .hgsub and .hgsubstate (issue2844) We shouldn't try to process subrepos if .hgsub isn't present and we should remove .hgsubstate if .hgsub is marked for removal.
mercurial/localrepo.py
tests/test-subrepo.t
--- a/mercurial/localrepo.py	Sun Jun 05 22:26:01 2011 +0200
+++ b/mercurial/localrepo.py	Mon Jun 06 15:17:40 2011 -0500
@@ -944,18 +944,28 @@
             # check subrepos
             subs = []
             removedsubs = set()
-            for p in wctx.parents():
-                removedsubs.update(s for s in p.substate if match(s))
-            for s in wctx.substate:
-                removedsubs.discard(s)
-                if match(s) and wctx.sub(s).dirty():
-                    subs.append(s)
-            if (subs or removedsubs):
-                if (not match('.hgsub') and
-                    '.hgsub' in (wctx.modified() + wctx.added())):
-                    raise util.Abort(_("can't commit subrepos without .hgsub"))
-                if '.hgsubstate' not in changes[0]:
-                    changes[0].insert(0, '.hgsubstate')
+            if '.hgsub' in wctx:
+                # only manage subrepos and .hgsubstate if .hgsub is present
+                for p in wctx.parents():
+                    removedsubs.update(s for s in p.substate if match(s))
+                for s in wctx.substate:
+                    removedsubs.discard(s)
+                    if match(s) and wctx.sub(s).dirty():
+                        subs.append(s)
+                if (subs or removedsubs):
+                    if (not match('.hgsub') and
+                        '.hgsub' in (wctx.modified() + wctx.added())):
+                        raise util.Abort(
+                            _("can't commit subrepos without .hgsub"))
+                    if '.hgsubstate' not in changes[0]:
+                        changes[0].insert(0, '.hgsubstate')
+                        if '.hgsubstate' in changes[2]:
+                            changes[2].remove('.hgsubstate')
+            elif '.hgsub' in changes[2]:
+                # clean up .hgsubstate when .hgsub is removed
+                if ('.hgsubstate' in wctx and
+                    '.hgsubstate' not in changes[0] + changes[1] + changes[2]):
+                    changes[2].insert(0, '.hgsubstate')
 
             if subs and not self.ui.configbool('ui', 'commitsubrepos', True):
                 changedsubs = [s for s in subs if wctx.sub(s).dirty(True)]
--- a/tests/test-subrepo.t	Sun Jun 05 22:26:01 2011 +0200
+++ b/tests/test-subrepo.t	Mon Jun 06 15:17:40 2011 -0500
@@ -500,6 +500,7 @@
   $ hg -R testdelete remove testdelete/.hgsub
   $ hg -R testdelete ci -m ".hgsub deleted"
   $ cat testdelete/.hgsubstate
+  bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
 
 test repository cloning
 
@@ -823,3 +824,36 @@
   fc627a69481f
   $ hg -R t id 
   e95bcfa18a35
+
+Test that removing .hgsubstate doesn't break anything:
+
+  $ hg rm -f .hgsubstate
+  $ hg ci -mrm
+  committing subrepository s
+  committing subrepository t
+  created new head
+  $ hg log -vr tip
+  changeset:   14:3941e0aa5236
+  tag:         tip
+  parent:      11:365661e5936a
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  description:
+  rm
+  
+  
+
+Test that removing .hgsub removes .hgsubstate:
+
+  $ hg rm .hgsub
+  $ hg ci -mrm2
+  $ hg log -vr tip
+  changeset:   15:8b31de9d13d1
+  tag:         tip
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  files:       .hgsub .hgsubstate
+  description:
+  rm2
+  
+