[PATCH 3 of 3 DEFAULT] forget: fix subrepo recursion for explicit path handling

David M. Carr david at carrclan.us
Tue Jan 17 18:36:28 CST 2012


# HG changeset patch
# User David M. Carr  <david at carrclan.us>
# Date 1326845459 18000
# Node ID ea8b3ed46daa0cb692c60edf01acbcc10f3d4846
# Parent  5a7d51d6a5c1284a9cdceace36d181db5a5dd078
forget: fix subrepo recursion for explicit path handling

When support for handling explicit paths in subrepos was added to the forget
command (95174c381525), subrepo recursion wasn't taken into account.  This
change fixes that by pulling the majority of the logic of commands.forget into
cmdutil.forget, which can then be called from both there and subrepo.forget.

diff -r 5a7d51d6a5c1 -r ea8b3ed46daa mercurial/cmdutil.py
--- a/mercurial/cmdutil.py	Tue Jan 17 19:10:58 2012 -0500
+++ b/mercurial/cmdutil.py	Tue Jan 17 19:10:59 2012 -0500
@@ -1198,6 +1198,48 @@
         bad.extend(f for f in rejected if f in match.files())
     return bad
 
+def forget(ui, repo, match, prefix, explicitonly):
+    join = lambda f: os.path.join(prefix, f)
+    bad = []
+    oldbad = match.bad
+    match.bad = lambda x, y: bad.append(x) or oldbad(x, y)
+    wctx = repo[None]
+    forgot = []
+    s = repo.status(match=match, clean=True)
+    forget = sorted(s[0] + s[1] + s[3] + s[6])
+    if explicitonly:
+        forget = [f for f in forget if match.exact(f)]
+
+    for subpath in wctx.substate:
+        sub = wctx.sub(subpath)
+        try:
+            submatch = matchmod.narrowmatcher(subpath, match)
+            subbad, subforgot = sub.forget(ui, submatch, prefix)
+            bad.extend([subpath + '/' + f for f in subbad])
+            forgot.extend([subpath + '/' + f for f in subforgot])
+        except error.LookupError:
+            ui.status(_("skipping missing subrepository: %s\n")
+                           % join(subpath))
+
+    for f in match.files():
+        if match.exact(f) or not explicitonly:
+            if f not in repo.dirstate and not os.path.isdir(match.rel(join(f))):
+                if f not in forgot:
+                    if os.path.exists(match.rel(join(f))):
+                        ui.warn(_('not removing %s: '
+                                  'file is already untracked\n')
+                                % match.rel(join(f)))
+                    bad.append(f)
+
+    for f in forget:
+        if ui.verbose or not match.exact(f):
+            ui.status(_('removing %s\n') % match.rel(join(f)))
+
+    rejected = wctx.forget(forget, prefix)
+    bad.extend(f for f in rejected if f in match.files())
+    forgot.extend(forget)
+    return bad, forgot
+
 def duplicatecopies(repo, rev, p1):
     "Reproduce copies found in the source revision in the dirstate for grafts"
     for dst, src in copies.pathcopies(repo[p1], repo[rev]).iteritems():
diff -r 5a7d51d6a5c1 -r ea8b3ed46daa mercurial/commands.py
--- a/mercurial/commands.py	Tue Jan 17 19:10:58 2012 -0500
+++ b/mercurial/commands.py	Tue Jan 17 19:10:59 2012 -0500
@@ -2449,46 +2449,9 @@
     if not pats:
         raise util.Abort(_('no files specified'))
 
-    wctx = repo[None]
-    m = scmutil.match(wctx, pats, opts)
-    s = repo.status(match=m, clean=True)
-    forget = sorted(s[0] + s[1] + s[3] + s[6])
-    subforget = {}
-    errs = 0
-
-    for subpath in wctx.substate:
-        sub = wctx.sub(subpath)
-        try:
-            submatch = matchmod.narrowmatcher(subpath, m)
-            for fsub in sub.walk(submatch):
-                if submatch.exact(fsub):
-                    subforget[subpath + '/' + fsub] = (fsub, sub)
-        except error.LookupError:
-            ui.status(_("skipping missing subrepository: %s\n") % subpath)
-
-    for f in m.files():
-        if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
-            if f not in subforget:
-                if os.path.exists(m.rel(f)):
-                    ui.warn(_('not removing %s: file is already untracked\n')
-                            % m.rel(f))
-                errs = 1
-
-    for f in forget:
-        if ui.verbose or not m.exact(f):
-            ui.status(_('removing %s\n') % m.rel(f))
-
-    if ui.verbose:
-        for f in sorted(subforget.keys()):
-            ui.status(_('removing %s\n') % m.rel(f))
-
-    wctx.forget(forget)
-
-    for f in sorted(subforget.keys()):
-        fsub, sub = subforget[f]
-        sub.forget([fsub])
-
-    return errs
+    m = scmutil.match(repo[None], pats, opts)
+    rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
+    return rejected and 1 or 0
 
 @command(
     'graft',
diff -r 5a7d51d6a5c1 -r ea8b3ed46daa mercurial/context.py
--- a/mercurial/context.py	Tue Jan 17 19:10:58 2012 -0500
+++ b/mercurial/context.py	Tue Jan 17 19:10:59 2012 -0500
@@ -900,16 +900,20 @@
         finally:
             wlock.release()
 
-    def forget(self, files):
+    def forget(self, files, prefix=""):
+        join = lambda f: os.path.join(prefix, f)
         wlock = self._repo.wlock()
         try:
+            rejected = []
             for f in files:
                 if self._repo.dirstate[f] != 'a':
                     self._repo.dirstate.remove(f)
                 elif f not in self._repo.dirstate:
-                    self._repo.ui.warn(_("%s not tracked!\n") % f)
+                    self._repo.ui.warn(_("%s not tracked!\n") % join(f))
+                    rejected.append(f)
                 else:
                     self._repo.dirstate.drop(f)
+            return rejected
         finally:
             wlock.release()
 
diff -r 5a7d51d6a5c1 -r ea8b3ed46daa mercurial/subrepo.py
--- a/mercurial/subrepo.py	Tue Jan 17 19:10:58 2012 -0500
+++ b/mercurial/subrepo.py	Tue Jan 17 19:10:59 2012 -0500
@@ -360,8 +360,8 @@
         '''
         pass
 
-    def forget(self, files):
-        pass
+    def forget(self, ui, match, prefix):
+        return []
 
 class hgsubrepo(abstractsubrepo):
     def __init__(self, ctx, path, state):
@@ -561,9 +561,9 @@
         ctx = self._repo[None]
         return ctx.walk(match)
 
-    def forget(self, files):
-        ctx = self._repo[None]
-        ctx.forget(files)
+    def forget(self, ui, match, prefix):
+        return cmdutil.forget(ui, self._repo, match,
+                              os.path.join(prefix, self._path), True)
 
 class svnsubrepo(abstractsubrepo):
     def __init__(self, ctx, path, state):
diff -r 5a7d51d6a5c1 -r ea8b3ed46daa tests/test-subrepo-recursion.t
--- a/tests/test-subrepo-recursion.t	Tue Jan 17 19:10:58 2012 -0500
+++ b/tests/test-subrepo-recursion.t	Tue Jan 17 19:10:59 2012 -0500
@@ -197,12 +197,6 @@
   A foo/bar/z2.txt
 This is expected to forget the file, but is currently broken
   $ hg forget foo/bar/z2.txt
-  not removing foo/bar/z2.txt: file is already untracked
-  [1]
-  $ hg status -S
-  A foo/bar/z2.txt
-When fixed, remove the next two commands
-  $ hg forget -R foo/bar foo/bar/z2.txt
   $ hg status -S
   ? foo/bar/z2.txt
   $ rm foo/bar/z2.txt


More information about the Mercurial-devel mailing list