Patchwork [09,of,19] commit: refactor subrepo state building into working context

login
register
mail settings
Submitter David Schleimer
Date Feb. 10, 2013, 11:29 p.m.
Message ID <84e89fe78426b02aeb09.1360538999@dev010.prn1.facebook.com>
Download mbox | patch
Permalink /patch/951/
State Changes Requested
Headers show

Comments

David Schleimer - Feb. 10, 2013, 11:29 p.m.
# HG changeset patch
# User David Schleimer <dschleimer@fb.com>
# Date 1360330572 28800
# Node ID 84e89fe78426b02aeb09add9a63a04e1e7459ec0
# Parent  62d93c48151c79f5e08c3e22b79e52052283ce66
commit: refactor subrepo state building into working context

This moves the logic for building a new substate into the working
context.  In particular, this is the logic that decides which subrepos
need to be committed before the main commit can proceed, validates
that we aren't about to commit without including a modified subrepo,
figures out whether we need to write out a new substate, and builds
said new substate.

This is part of a larger refactoring effort that moves logic into the
working context.  The long-term goal of that refactoring is to unify
how we commit from the working copy and from memory.  Among other
things, this will support optimizations in graft, rebase, and similar
commands.

Patch

diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -1162,6 +1162,44 @@ 
             finally:
                 wlock.release()
 
+    def commitablesubstate(self, match, force):
+        subs = []
+        commitsubs = set()
+        newstate = self.substate.copy()
+        oldstate = self.p1().substate
+
+        # compare current state to last committed state
+        # build new substate based on last committed state
+        for s in sorted(newstate.keys()):
+            if not match(s):
+                # ignore working copy, use old state if present
+                if s in oldstate:
+                    newstate[s] = oldstate[s]
+                    continue
+                if not force:
+                    raise util.Abort(
+                        _("commit with new subrepo %s excluded") % s)
+            if self.sub(s).dirty(True):
+                if not self._repo.ui.configbool('ui', 'commitsubrepos'):
+                    raise util.Abort(
+                        _("uncommitted changes in subrepo %s") % s,
+                        hint=_("use --subrepos for recursive commit"))
+                subs.append(s)
+                commitsubs.add(s)
+            else:
+                bs = self.sub(s).basestate()
+                newstate[s] = (newstate[s][0], bs, newstate[s][2])
+                if oldstate.get(s, (None, None, None))[1] != bs:
+                    subs.append(s)
+
+        # check for removed subrepos
+        for p in self.parents():
+            r = [s for s in p.substate if s not in newstate]
+            subs += [s for s in r if match(s)]
+
+        return subs, commitsubs, newstate
+
+
     def markcommitted(self, node):
         """Perform post-commit cleanup necessary after commiting this workingctx
 
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -1155,10 +1155,8 @@ 
             if force:
                 changes[0].extend(changes[6]) # mq may commit unchanged files
 
+            subs = []
             # check subrepos
-            subs = []
-            commitsubs = set()
-            newstate = wctx.substate.copy()
             # only manage subrepos and .hgsubstate if .hgsub is present
             if '.hgsub' in wctx:
                 # we'll decide whether to track this ourselves, thanks
@@ -1167,35 +1165,9 @@ 
                 if '.hgsubstate' in changes[2]:
                     changes[2].remove('.hgsubstate')
 
-                # compare current state to last committed state
-                # build new substate based on last committed state
-                oldstate = wctx.p1().substate
-                for s in sorted(newstate.keys()):
-                    if not match(s):
-                        # ignore working copy, use old state if present
-                        if s in oldstate:
-                            newstate[s] = oldstate[s]
-                            continue
-                        if not force:
-                            raise util.Abort(
-                                _("commit with new subrepo %s excluded") % s)
-                    if wctx.sub(s).dirty(True):
-                        if not self.ui.configbool('ui', 'commitsubrepos'):
-                            raise util.Abort(
-                                _("uncommitted changes in subrepo %s") % s,
-                                hint=_("use --subrepos for recursive commit"))
-                        subs.append(s)
-                        commitsubs.add(s)
-                    else:
-                        bs = wctx.sub(s).basestate()
-                        newstate[s] = (newstate[s][0], bs, newstate[s][2])
-                        if oldstate.get(s, (None, None, None))[1] != bs:
-                            subs.append(s)
+                subs, commitsubs, newstate = wctx.commitablesubstate(match,
+                                                                     force)
 
-                # check for removed subrepos
-                for p in wctx.parents():
-                    r = [s for s in p.substate if s not in newstate]
-                    subs += [s for s in r if match(s)]
                 if subs:
                     if (not match('.hgsub') and
                         '.hgsub' in (wctx.modified() + wctx.added())):