[PATCH 5 of 6] status: recurse into subrepositories with --subrepos/-S flag

Martin Geisler mg at lazybytes.net
Mon Aug 30 17:01:37 CDT 2010


# HG changeset patch
# User Martin Geisler <mg at lazybytes.net>
# Date 1283205545 -7200
# Node ID 63bb43d8d1fbd7650d8b428632136f3763c29fa4
# Parent  d84f8da539f995c47437933d8161c6664736dd01
status: recurse into subrepositories with --subrepos/-S flag

diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -3457,7 +3457,8 @@
         show = ui.quiet and states[:4] or states[:5]
 
     stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
-                       'ignored' in show, 'clean' in show, 'unknown' in show)
+                       'ignored' in show, 'clean' in show, 'unknown' in show,
+                       opts.get('subrepos'))
     changestates = zip(states, 'MAR!?IC', stat)
 
     if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
@@ -4429,6 +4430,7 @@
           ('C', 'copies', None, _('show source of copied files')),
           ('0', 'print0', None,
            _('end filenames with NUL, for use with xargs')),
+          ('S', 'subrepos', None, _('recurse into subrepositories')),
           ('', 'rev', [],
            _('show difference from revision'), _('REV')),
           ('', 'change', '',
diff --git a/mercurial/localrepo.py b/mercurial/localrepo.py
--- a/mercurial/localrepo.py
+++ b/mercurial/localrepo.py
@@ -1023,7 +1023,8 @@
         return self[node].walk(match)
 
     def status(self, node1='.', node2=None, match=None,
-               ignored=False, clean=False, unknown=False):
+               ignored=False, clean=False, unknown=False,
+               listsubrepos=False):
         """return status of files between two nodes or node and working directory
 
         If node1 is None, use the first dirstate parent instead.
@@ -1129,6 +1130,23 @@
             removed = mf1.keys()
 
         r = modified, added, removed, deleted, unknown, ignored, clean
+
+        if listsubrepos:
+            for subpath in ctx1.substate:
+                sub = ctx1.sub(subpath)
+                if working:
+                    rev2 = None
+                else:
+                    rev2 = ctx2.substate[subpath][1]
+                try:
+                    submatch = matchmod.subrepomatcher(subpath, match)
+                    s = sub.status(rev2, match=submatch, ignored=listignored,
+                                   clean=listclean, unknown=listunknown)
+                    for rfiles, sfiles in zip(r, s):
+                        rfiles.extend("%s/%s" % (subpath, f) for f in sfiles)
+                except error.LookupError:
+                    self.ui.status(_("skipping missing subrepo: %s\n") % subpath)
+
         [l.sort() for l in r]
         return r
 
diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py
--- a/mercurial/subrepo.py
+++ b/mercurial/subrepo.py
@@ -241,6 +241,9 @@
         """
         raise NotImplementedError
 
+    def status(self, rev2, **opts):
+        raise NotImplementedError
+
 
 class hgsubrepo(abstractsubrepo):
     def __init__(self, ctx, path, state):
@@ -271,6 +274,12 @@
                 addpathconfig('default-push', defpushpath)
             fp.close()
 
+    def status(self, rev2, **opts):
+        rev1 = self._state[1]
+        ctx1 = self._repo[rev1]
+        ctx2 = self._repo[rev2]
+        return self._repo.status(ctx1, ctx2, **opts)
+
     def dirty(self):
         r = self._state[1]
         if r == '':
@@ -441,6 +450,10 @@
         # push is a no-op for SVN
         return True
 
+    def status(self, rev2, **opts):
+        # TODO: implement this.
+        return []
+
 types = {
     'hg': hgsubrepo,
     'svn': svnsubrepo,
diff --git a/tests/test-debugcomplete.t b/tests/test-debugcomplete.t
--- a/tests/test-debugcomplete.t
+++ b/tests/test-debugcomplete.t
@@ -190,7 +190,7 @@
   push: force, rev, branch, new-branch, ssh, remotecmd
   remove: after, force, include, exclude
   serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, templates, style, ipv6, certificate
-  status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude
+  status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, subrepos, rev, change, include, exclude
   summary: remote
   update: clean, check, date, rev
   addremove: similarity, include, exclude, dry-run
diff --git a/tests/test-help.t b/tests/test-help.t
--- a/tests/test-help.t
+++ b/tests/test-help.t
@@ -528,6 +528,7 @@
    -n --no-status            hide status prefix
    -C --copies               show source of copied files
    -0 --print0               end filenames with NUL, for use with xargs
+   -S --subrepos             recurse into subrepositories
       --rev REV [+]          show difference from revision
       --change REV           list the changed files of a revision
    -I --include PATTERN [+]  include names matching the given patterns
diff --git a/tests/test-subrepo-recursion.t b/tests/test-subrepo-recursion.t
new file mode 100644
--- /dev/null
+++ b/tests/test-subrepo-recursion.t
@@ -0,0 +1,66 @@
+Make status look into subrepositories by default:
+
+  $ echo '[defaults]' >> $HGRCPATH
+  $ echo 'status = -S' >> $HGRCPATH
+
+Create test repository:
+
+  $ hg init outer
+  $ cd outer
+  $ hg init inner
+  $ cd inner
+  $ echo x1 > x.txt
+  $ hg add x.txt
+  $ hg commit -m x1
+  $ cd ..
+  $ echo 'inner = inner' > .hgsub
+  $ hg add .hgsub
+  $ hg commit -m 'add inner'
+  committing subrepository inner
+
+  $ echo a1 > a.txt
+  $ hg add a.txt
+  $ hg commit -m a1
+  $ echo a2 >> a.txt
+  $ hg commit -m a2
+
+Changed working directory:
+
+  $ echo x2 >> inner/x.txt
+  $ hg status
+  M inner/x.txt
+
+Status call crossing repository boundaries:
+
+  $ hg status inner/x.txt
+  M inner/x.txt
+  $ hg status -I 'inner/?.txt'
+  M inner/x.txt
+  $ hg status -I '**/?.txt'
+  M inner/x.txt
+
+Status from within a subdirectory:
+
+  $ mkdir dir
+  $ cd dir
+  $ echo b1 > b.txt
+  $ hg status
+  M inner/x.txt
+  ? dir/b.txt
+
+Status with relative path:
+
+  $ hg status ..
+  M ../inner/x.txt
+  ? b.txt
+  $ cd ..
+
+Status between revisions:
+
+  $ rm -r dir
+  $ hg commit -m a3
+  committing subrepository inner
+  $ hg status
+  $ hg status --rev 2:3
+  M .hgsubstate
+  M inner/x.txt


More information about the Mercurial-devel mailing list