[PATCH 5 of 6 DEFAULT] remove: support removing explicit paths in subrepos

David M. Carr david at carrclan.us
Sat Jan 14 09:00:20 CST 2012


# HG changeset patch
# User David M. Carr  <david at carrclan.us>
# Date 1326514745 18000
# Node ID 471cea2010939c4186b269e0bf47db1f445ad516
# Parent  97f8b28771e6ad077e58b6536d207e79516b61ac
remove: support removing explicit paths in subrepos

Change the behavior of the remove command such that explicit paths in
subrepos are handled by removing the file in the subrepo.  This eliminates
the previous behavior where if you called "hg remove" for an explicit
path in a subrepo, it would warn and skip removing the file.  After
this change, calling "hg remove" with explicit paths in subrepos
should now have the same behavior as explicitly named paths in the
same repository, including Warn/Remove/Delete behavior as modified
by the --after and --force options.

diff -r 97f8b28771e6 -r 471cea201093 mercurial/commands.py
--- a/mercurial/commands.py	Fri Jan 13 22:21:23 2012 -0500
+++ b/mercurial/commands.py	Fri Jan 13 23:19:05 2012 -0500
@@ -4526,11 +4526,21 @@
     m = scmutil.match(wctx, pats, opts)
     s = repo.status(match=m, clean=True)
     modified, added, deleted, clean = s[0], s[1], s[3], s[6]
+    substatus = {}
     subremove = []
 
     for subpath in wctx.substate:
+        sub = wctx.sub(subpath)
         try:
             submatch = matchmod.narrowmatcher(subpath, m)
+            ss = sub.status(None, match=submatch, clean=True)
+            def exactmatch(x): return submatch.exact(x)
+            submodified, subadded, subdeleted, subclean = \
+                    filter(exactmatch, ss[0]), filter(exactmatch, ss[1]),\
+                    filter(exactmatch, ss[3]), filter(exactmatch, ss[6])
+            substatus[sub] = {'path': subpath, 'matcher': submatch,
+                              'modified': submodified, 'added': subadded,
+                              'deleted': subdeleted, 'clean': subclean}
             for fsub in submatch.files():
                 subremove.append(subpath + '/' + fsub)
         except error.LookupError:
@@ -4538,25 +4548,51 @@
 
     for f in m.files():
         if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
-            if os.path.exists(m.rel(f)):
-                if f not in subremove:
+            if f not in subremove:
+                if os.path.exists(m.rel(f)):
                     ui.warn(_('not removing %s: '
                               'file is untracked\n') % m.rel(f))
-                else:
-                    ui.warn(_('not removing %s: '
-                              'file is in a subrepo\n') % m.rel(f))
-            ret = 1
+                ret = 1
 
     if force:
         list = modified + deleted + clean + added
+        for sub, cursubstatus in substatus.iteritems():
+            cursubstatus['list'] = cursubstatus['modified'] +\
+                    cursubstatus['deleted'] + cursubstatus['clean'] +\
+                    cursubstatus['added']
     elif after:
         list = deleted
+        for sub, cursubstatus in substatus.iteritems():
+            cursubstatus['list'] = cursubstatus['deleted']
+            submatch = cursubstatus['matcher']
+            subpath = cursubstatus['path']
+            for f in cursubstatus['modified'] + cursubstatus['added'] +\
+                    cursubstatus['clean']:
+                ui.warn(_('not removing %s: file still exists (use -f'
+                          ' to force removal)\n'
+                          ) % (subpath + '/' + submatch.rel(f)))
+            ret = 1
         for f in modified + added + clean:
             ui.warn(_('not removing %s: file still exists (use -f'
                       ' to force removal)\n') % m.rel(f))
             ret = 1
     else:
         list = deleted + clean
+        for sub, cursubstatus in substatus.iteritems():
+            cursubstatus['list'] = cursubstatus['deleted'] +\
+                    cursubstatus['clean']
+            subpath = cursubstatus['path']
+            submatch = cursubstatus['matcher']
+            for f in cursubstatus['modified']:
+                ui.warn(_('not removing %s: file is modified (use -f'
+                          ' to force removal)\n'
+                          ) % (subpath + '/' + submatch.rel(f)))
+                ret = 1
+            for f in cursubstatus['added']:
+                ui.warn(_('not removing %s: file has been marked for add'
+                          ' (use forget to undo)\n'
+                          ) % (subpath + '/' + submatch.rel(f)))
+                ret = 1
         for f in modified:
             ui.warn(_('not removing %s: file is modified (use -f'
                       ' to force removal)\n') % m.rel(f))
@@ -4570,6 +4606,10 @@
         if ui.verbose or not m.exact(f):
             ui.status(_('removing %s\n') % m.rel(f))
 
+    if ui.verbose:
+        for f in sorted(subremove):
+            ui.status(_('removing %s\n') % m.rel(f))
+
     wlock = repo.wlock()
     try:
         if not after:
@@ -4585,6 +4625,24 @@
     finally:
         wlock.release()
 
+    for sub, cursubstatus in substatus.iteritems():
+        wlock = sub.wlock()
+        try:
+            if not after:
+                for f in cursubstatus['list']:
+                    if f in cursubstatus['added']:
+                        continue # we never unlink added files on remove
+                    try:
+                        util.unlinkpath(repo.wjoin(
+                                            cursubstatus['path'] + '/' + f))
+                    except OSError, inst:
+                        if inst.errno != errno.ENOENT:
+                            raise
+            sub.forget(cursubstatus['list'])
+        finally:
+            if wlock is not None:
+                wlock.release()
+
     return ret
 
 @command('rename|move|mv',
diff -r 97f8b28771e6 -r 471cea201093 tests/test-subrepo.t
--- a/tests/test-subrepo.t	Fri Jan 13 22:21:23 2012 -0500
+++ b/tests/test-subrepo.t	Fri Jan 13 23:19:05 2012 -0500
@@ -1054,20 +1054,19 @@
   committing subrepository s
 Attempt to remove clean file with after
   $ remove -A s/f1
-  not removing s/f1: file is in a subrepo
+  not removing s/f1: file still exists (use -f to force removal)
   exit code: 1
   ./s/f1
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
 Attempt to remove clean file with no opts
   $ remove s/f1
-  not removing s/f1: file is in a subrepo
-  exit code: 1
-  ./s/f1
-  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  exit code: 0
+  R s/f1
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 Attempt to remove modified file with no opts
   $ echo c1 >> s/f1
   $ remove s/f1
-  not removing s/f1: file is in a subrepo
+  not removing s/f1: file is modified (use -f to force removal)
   exit code: 1
   M s/f1
   ./s/f1
@@ -1075,7 +1074,7 @@
 Attempt to remove modified file with after
   $ echo c1 >> s/f1
   $ remove -A s/f1
-  not removing s/f1: file is in a subrepo
+  not removing s/f1: file still exists (use -f to force removal)
   exit code: 1
   M s/f1
   ./s/f1
@@ -1083,23 +1082,20 @@
 Attempt to remove modified file with force
   $ echo c1 >> s/f1
   $ remove -f s/f1
-  not removing s/f1: file is in a subrepo
-  exit code: 1
-  M s/f1
-  ./s/f1
+  exit code: 0
+  R s/f1
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 Attempt to remove missing file with no opts
   $ rm s/f1
   $ remove s/f1
-  exit code: 1
-  ! s/f1
-  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg revert -R s s/f1
+  exit code: 0
+  R s/f1
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 Attempt to remove added file with no opts
   $ echo c2 > s/f2
   $ hg add s/f2
   $ remove s/f2
-  not removing s/f2: file is in a subrepo
+  not removing s/f2: file has been marked for add (use forget to undo)
   exit code: 1
   A s/f2
   ./s/f1
@@ -1108,7 +1104,7 @@
 Attempt to remove added file with after
   $ hg add s/f2
   $ remove -A s/f2
-  not removing s/f2: file is in a subrepo
+  not removing s/f2: file still exists (use -f to force removal)
   exit code: 1
   A s/f2
   ./s/f1
@@ -1117,9 +1113,9 @@
 Attempt to remove added file with force
   $ hg add s/f2
   $ remove -f s/f2
-  not removing s/f2: file is in a subrepo
-  exit code: 1
-  A s/f2
+  exit code: 0
+  ? s/f2
   ./s/f1
   ./s/f2
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ rm s/f2


More information about the Mercurial-devel mailing list