[PATCH] add: recurse into subrepositories with --subrepos/-S flag

Martin Geisler mg at lazybytes.net
Tue Sep 7 10:51:10 CDT 2010


# HG changeset patch
# User Martin Geisler <mg at lazybytes.net>
# Date 1283872204 -7200
# Node ID dd95f4a2649058b6ae9b37583471e6c12d5b5c7d
# Parent  d4f1591b9e84e489e55a5226c50017a6cf17d98f
add: recurse into subrepositories with --subrepos/-S flag

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -1237,19 +1237,32 @@
                 yield change(rev)
     return iterate()
 
-def add(ui, repo, match, dryrun):
+def add(ui, repo, match, dryrun, listsubrepos, prefix):
+    join = lambda f: os.path.join(prefix, f)
     bad = []
     oldbad = match.bad
     match.bad = lambda x, y: bad.append(x) or oldbad(x, y)
     names = []
+    wctx = repo[None]
     for f in repo.walk(match):
         exact = match.exact(f)
         if exact or f not in repo.dirstate:
             names.append(f)
             if ui.verbose or not exact:
-                ui.status(_('adding %s\n') % match.rel(f))
+                ui.status(_('adding %s\n') % match.rel(join(f)))
+
+    if listsubrepos:
+        for subpath in wctx.substate:
+            sub = wctx.sub(subpath)
+            try:
+                submatch = matchmod.narrowmatcher(subpath, match)
+                bad.extend(sub.add(ui, submatch, dryrun, prefix))
+            except error.LookupError:
+                self.ui.status(_("skipping missing subrepository: %s\n")
+                               % join(subpath))
+
     if not dryrun:
-        rejected = repo[None].add(names)
+        rejected = wctx.add(names, prefix)
         bad.extend(f for f in rejected if f in m.files())
     return bad
 
diff --git a/mercurial/commands.py b/mercurial/commands.py
--- a/mercurial/commands.py
+++ b/mercurial/commands.py
@@ -47,7 +47,8 @@
     """
 
     m = cmdutil.match(repo, pats, opts)
-    rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'))
+    rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
+                           opts.get('subrepos'), prefix="")
     return rejected and 1 or 0
 
 def addremove(ui, repo, *pats, **opts):
@@ -3987,7 +3988,8 @@
 ]
 
 table = {
-    "^add": (add, walkopts + dryrunopts, _('[OPTION]... [FILE]...')),
+    "^add": (add, walkopts + subrepoopts + dryrunopts,
+             _('[OPTION]... [FILE]...')),
     "addremove":
         (addremove, similarityopts + walkopts + dryrunopts,
          _('[OPTION]... [FILE]...')),
diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -769,7 +769,8 @@
                 self.modified() or self.added() or self.removed() or
                 (missing and self.deleted()))
 
-    def add(self, list):
+    def add(self, list, prefix=""):
+        join = lambda f: os.path.join(prefix, f)
         wlock = self._repo.wlock()
         ui, ds = self._repo.ui, self._repo.dirstate
         try:
@@ -779,7 +780,7 @@
                 try:
                     st = os.lstat(p)
                 except:
-                    ui.warn(_("%s does not exist!\n") % f)
+                    ui.warn(_("%s does not exist!\n") % join(f))
                     rejected.append(f)
                     continue
                 if st.st_size > 10000000:
@@ -787,13 +788,13 @@
                               "to manage this file\n"
                               "(use 'hg revert %s' to cancel the "
                               "pending addition)\n")
-                              % (f, 3 * st.st_size // 1000000, f))
+                              % (f, 3 * st.st_size // 1000000, join(f)))
                 if not (stat.S_ISREG(st.st_mode) or stat.S_ISLNK(st.st_mode)):
                     ui.warn(_("%s not added: only files and symlinks "
-                              "supported currently\n") % f)
+                              "supported currently\n") % join(f))
                     rejected.append(p)
                 elif ds[f] in 'amn':
-                    ui.warn(_("%s already tracked!\n") % f)
+                    ui.warn(_("%s already tracked!\n") % join(f))
                 elif ds[f] == 'r':
                     ds.normallookup(f)
                 else:
diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py
--- a/mercurial/subrepo.py
+++ b/mercurial/subrepo.py
@@ -255,6 +255,8 @@
         """
         raise NotImplementedError
 
+    def add(self, ui, match, dryrun, prefix):
+        return []
 
     def status(self, rev2, **opts):
         return [], [], [], [], [], [], []
@@ -291,6 +293,10 @@
                 addpathconfig('default-push', defpushpath)
             fp.close()
 
+    def add(self, ui, match, dryrun, prefix):
+        return cmdutil.add(ui, self._repo, match, dryrun, True,
+                           os.path.join(prefix, self._path))
+
     def status(self, rev2, **opts):
         try:
             rev1 = self._state[1]
diff --git a/tests/test-debugcomplete.t b/tests/test-debugcomplete.t
--- a/tests/test-debugcomplete.t
+++ b/tests/test-debugcomplete.t
@@ -176,7 +176,7 @@
 
 Show all commands + options
   $ hg debugcommands
-  add: include, exclude, dry-run
+  add: include, exclude, subrepos, dry-run
   annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, include, exclude
   clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd
   commit: addremove, close-branch, include, exclude, message, logfile, date, user
diff --git a/tests/test-help.t b/tests/test-help.t
--- a/tests/test-help.t
+++ b/tests/test-help.t
@@ -274,6 +274,7 @@
   
    -I --include PATTERN [+]  include names matching the given patterns
    -X --exclude PATTERN [+]  exclude names matching the given patterns
+   -S --subrepos             recurse into subrepositories
    -n --dry-run              do not perform actions, just print output
   
   [+] marked option can be specified multiple times
@@ -312,6 +313,7 @@
   
    -I --include PATTERN [+]  include names matching the given patterns
    -X --exclude PATTERN [+]  exclude names matching the given patterns
+   -S --subrepos             recurse into subrepositories
    -n --dry-run              do not perform actions, just print output
   
   global options:
@@ -364,6 +366,7 @@
   
    -I --include PATTERN [+]  include names matching the given patterns
    -X --exclude PATTERN [+]  exclude names matching the given patterns
+   -S --subrepos             recurse into subrepositories
    -n --dry-run              do not perform actions, just print output
   
   [+] marked option can be specified multiple times
@@ -391,6 +394,7 @@
   
    -I --include PATTERN [+]  include names matching the given patterns
    -X --exclude PATTERN [+]  exclude names matching the given patterns
+   -S --subrepos             recurse into subrepositories
    -n --dry-run              do not perform actions, just print output
   
   [+] marked option can be specified multiple times
diff --git a/tests/test-subrepo-recursion.t b/tests/test-subrepo-recursion.t
--- a/tests/test-subrepo-recursion.t
+++ b/tests/test-subrepo-recursion.t
@@ -8,25 +8,30 @@
 
   $ hg init
   $ echo x1 > x.txt
-  $ hg add x.txt
 
   $ hg init foo
   $ cd foo
   $ echo y1 > y.txt
-  $ hg add y.txt
 
   $ hg init bar
   $ cd bar
   $ echo z1 > z.txt
-  $ hg add z.txt
 
   $ cd ..
   $ echo 'bar = bar' > .hgsub
-  $ hg add .hgsub
 
   $ cd ..
   $ echo 'foo = foo' > .hgsub
-  $ hg add .hgsub
+
+Add files --- .hgsub files must go first to trigger subrepos:
+
+  $ hg add -S .hgsub
+  $ hg add -S foo/.hgsub
+  $ hg add -S foo/bar
+  adding foo/bar/z.txt
+  $ hg add -S
+  adding x.txt
+  adding foo/y.txt
 
 Test recursive status without committing anything:
 


More information about the Mercurial-devel mailing list