[PATCH 2 of 2] revert: add support for reverting subrepos without --no-backup and/or --all

Angel Ezquerra angel.ezquerra at gmail.com
Sat Apr 14 17:49:23 CDT 2012


# HG changeset patch
# User Angel Ezquerra <angel.ezquerra at gmail.com>
# Date 1332927737 -7200
# Node ID 150a688482564127ee97b7c424af735ec06aa77b
# Parent  6952d4ae3b3d1af884ef8f98dbd78ed5db3abd3b
revert: add support for reverting subrepos without --no-backup and/or --all

When a subrepo is reverted but --no-backup is not set, call revert on the
subrepo that is being reverted prior to updating it to the revision specified
in the parent repo's .hgsubstate file.

The --all flag is passed down to the subrepo when it is being reverted. If the
--all flag is not set, all files that are modified on the subrepo will be
reverted.

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -1369,12 +1369,8 @@
             if abs not in names:
                 names[abs] = m.rel(abs), m.exact(abs)
 
+        # get the list of subrepos that must be reverted
         targetsubs = [s for s in repo[node].substate if m(s)]
-        if targetsubs and not opts.get('no_backup'):
-            msg = _("cannot revert subrepos unless the no-backup flag is set")
-            hint = _("there are subrepos on the revert list, "
-                     "use --no-backup to revert them")
-            raise util.Abort(msg, hint=hint)
 
         m = scmutil.matchfiles(repo, names)
         changes = repo.status(match=m)[:4]
@@ -1507,7 +1503,8 @@
             if targetsubs:
                 # Revert the subrepos on the revert list
                 for sname in targetsubs:
-                    ctx.sub(sname).revert(ui, ctx.substate[sname], *pats, **opts)
+                    ctx.sub(sname).revert(
+                        ui, ctx.substate[sname], *pats, **opts)
     finally:
         wlock.release()
 
diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py
--- a/mercurial/subrepo.py
+++ b/mercurial/subrepo.py
@@ -577,13 +577,36 @@
                               os.path.join(prefix, self._path), True)
 
     def revert(self, ui, substate, *pats, **opts):
-        # reverting a subrepo is done by updating it to the revision
-        # specified in the corresponding substate dictionary
+        # reverting a subrepo is a 2 step process:
+        # 1. if the no_backup is not set, revert all modified
+        #    files inside the subrepo
+        # 2. update the subrepo to the revision specified in
+        #    the corresponding substate dictionary
         ui.status(_('reverting subrepo %s\n') % substate[0])
+        if not opts.get('no_backup'):
+            # Revert all files on the subrepo, creating backups
+            # Note that this will not recursively revert subrepos
+            # We could do it if there was a set:subrepos() predicate
+            opts = opts.copy()
+            opts['date'] = None
+            opts['rev'] = substate[1]
+
+            pats = []
+            if not opts['all']:
+                pats = ['set:modified()']
+            self.filerevert(ui, *pats, **opts)
 
         # Update the repo to the revision specified in the given substate
         self.get(substate, overwrite=True)
 
+    def filerevert(self, ui, *pats, **opts):
+        ctx = self._repo[opts['rev']]
+        parents = self._repo.dirstate.parents()
+        if opts['all']:
+            cmdutil.revert(ui, self._repo, ctx, parents, **opts)
+        else:
+            cmdutil.revert(ui, self._repo, ctx, parents, 'set:modified()', **opts)
+
 class svnsubrepo(abstractsubrepo):
     def __init__(self, ctx, path, state):
         self._path = path


More information about the Mercurial-devel mailing list