[PATCH] subrepo: avoids empty commit when .hgsubstate is dirty (issue2403)

Erik Zielke ez at aragost.com
Fri Nov 26 09:54:14 CST 2010


# HG changeset patch
# User Erik Zielke <ez at aragost.com>
# Date 1290781536 -3600
# Node ID dbd15e50463af413519d18eca2b662d4a1583f05
# Parent  da69a1597285fe25eeedab1a45869487773b715b
subrepo: avoids empty commit when .hgsubstate is dirty (issue2403)

This patch avoids empty commit when .hgsubstate is dirty. Empty commit
was caused by .hgsubstate being updated back to the state of the
working copy parent when committing, if a user had changed it manually
and not made any changes in subrepositories.

The subrepository state from the working copies parent is compared
with the state calculated as a result of trying to commit the
subrepositories. If the two states are the same, then return None
otherwise the commit is just done.

The line: "committing subrepository x" will be written if there is
nothing committed, but .hgsubstate is dirty for x subrepository.

diff -r da69a1597285 -r dbd15e50463a mercurial/localrepo.py
--- a/mercurial/localrepo.py	Sun Nov 21 13:16:59 2010 +0100
+++ b/mercurial/localrepo.py	Fri Nov 26 15:25:36 2010 +0100
@@ -939,6 +939,7 @@
 
             # commit subs
             if subs or removedsubs:
+                pstate = subrepo.substate(self['.'])
                 state = wctx.substate.copy()
                 for s in sorted(subs):
                     sub = wctx.sub(s)
@@ -946,7 +947,18 @@
                         subrepo.subrelpath(sub))
                     sr = sub.commit(cctx._text, user, date)
                     state[s] = (state[s][0], sr)
-                subrepo.writestate(self, state)
+
+                changed = False
+                if len(pstate) != len(state):
+                    changed = True
+                if not changed:
+                    for newstate in state:
+                        if state[newstate][1] != pstate[newstate]:
+                            changed = True
+                if changed:
+                    subrepo.writestate(self, state)
+                else:
+                    return None
 
             # Save commit message in case this transaction gets rolled back
             # (e.g. by a pretxncommit hook).  Leave the content alone on
diff -r da69a1597285 -r dbd15e50463a mercurial/subrepo.py
--- a/mercurial/subrepo.py	Sun Nov 21 13:16:59 2010 +0100
+++ b/mercurial/subrepo.py	Fri Nov 26 15:25:36 2010 +0100
@@ -13,6 +13,19 @@
 
 nullstate = ('', '', 'empty')
 
+
+def substate(ctx):
+    rev = {}
+    if '.hgsubstate' in ctx:
+        try:
+            for l in ctx['.hgsubstate'].data().splitlines():
+                revision, path = l.split(" ", 1)
+                rev[path] = revision
+        except IOError as err:
+            if err.errno != errno.ENOENT:
+                raise
+    return rev
+
 def state(ctx, ui):
     """return a state dict, mapping subrepo paths configured in .hgsub
     to tuple: (source from .hgsub, revision from .hgsubstate, kind
@@ -39,15 +52,7 @@
     for path, src in ui.configitems('subpaths'):
         p.set('subpaths', path, src, ui.configsource('subpaths', path))
 
-    rev = {}
-    if '.hgsubstate' in ctx:
-        try:
-            for l in ctx['.hgsubstate'].data().splitlines():
-                revision, path = l.split(" ", 1)
-                rev[path] = revision
-        except IOError, err:
-            if err.errno != errno.ENOENT:
-                raise
+    rev = substate(ctx)
 
     state = {}
     for path, src in p[''].items():
diff -r da69a1597285 -r dbd15e50463a tests/test-subrepo-empty-commit.t
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-subrepo-empty-commit.t	Fri Nov 26 15:25:36 2010 +0100
@@ -0,0 +1,44 @@
+  $ hg init
+  $ hg init sub
+  $ echo 'sub = sub' > .hgsub
+  $ hg add .hgsub
+  $ echo c1 > f1
+  $ echo c2 > sub/f2
+  $ hg add -S
+  adding f1
+  adding sub/f2
+  $ hg commit -m0
+  committing subrepository sub
+
+Make .hgsubstate dirty:
+
+  $ echo '0000000000000000000000000000000000000000 sub' > .hgsubstate
+  $ hg diff --nodates
+  diff -r 853ea21970bb .hgsubstate
+  --- a/.hgsubstate
+  +++ b/.hgsubstate
+  @@ -1,1 +1,1 @@
+  -5bbc614a5b06ad7f3bf7c2463d74b005324f34c1 sub
+  +0000000000000000000000000000000000000000 sub
+
+trying to do an empty commit:
+
+  $ hg commit -m1
+  committing subrepository sub
+  nothing changed
+  [1]
+
+an okay update of .hgsubstate
+  $ cd sub
+  $ echo c3 > f2
+  $ hg commit -m "Sub commit"
+  $ cd ..
+  $ hg commit -m "Updated sub"
+  committing subrepository sub
+
+deleting again:
+  $ echo '' > .hgsub
+  $ hg commit -m2
+  $ cat .hgsub
+  
+  $ cat .hgsubstate


More information about the Mercurial-devel mailing list