[PATCH 4 of 4] revert: add support for reverting added subrepos

Angel Ezquerra angel.ezquerra at gmail.com
Wed Mar 28 16:31:33 CDT 2012


# HG changeset patch
# User Angel Ezquerra <angel.ezquerra at gmail.com>
# Date 1332927737 -7200
# Node ID 012faafa7816588896ce7e885b66e72b80975b1a
# Parent  4ac4d56de5ab18913f7cf8d78bb6458149be27a1
revert: add support for reverting added subrepos

Detect subrepos that are found on the working directory but not on the parent
revision. This means that they have been added to the .hgsub file (and possibly
to the .hgsubstate file).

To "remove them", parse the .hgsub and .hgsubstate files and remove any lines
that refert to the added subrepo.

NOTES / ISSUES:

* The "cmdutil.removesub" function could be folded into the remove command.
* Is modifying the .hgsub and .hgsubstate files automatically OK?
* This may change the line endings on the .hgsub and .hgsubstate files

diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -1349,12 +1349,15 @@
         m.bad = lambda x, y: False
         for abs in repo.walk(m):
             names[abs] = m.rel(abs), m.exact(abs)
+        wdsubs = [s for s in repo[None].substate if m(s)]
 
         # walk target manifest.
 
         def badfn(path, msg):
             if path in names:
                 return
+            if path in wdsubs:
+                return
             if path in repo[node].substate:
                 return
             path_ = path + '/'
@@ -1500,13 +1503,80 @@
                 checkout(f)
                 normal(f)
 
-            if targetsubs:
+            if targetsubs or wdsubs:
                 # Revert the subrepos on the revert list
                 for sname in targetsubs:
                     ctx.sub(sname).revert(
-                        ui, ctx.substate[sname], *pats, **opts)
+                        ui, ctx.substate[sname], *pats, **opts)
+                # Revert the subrepos that have been added to the working directory
+                for sname in wdsubs:
+                    if sname not in targetsubs:
+                        removesub(ui, repo, sname)
     finally:
         wlock.release()
+
+def removesub(ui, repo, spath):
+    # remove the corresponding lines from the .hgsub and .hgsubstate files
+    ui.status(_('removing subrepo %s\n') % spath)
+
+    spath = os.path.normcase(spath)
+    hgsubpath = repo.wjoin('.hgsub')
+    hgsubstatepath = repo.wjoin('.hgsubstate')
+
+    try:
+        h = open(hgsubpath, 'r')
+        hgsub = h.readlines()
+        h.close()
+    except:
+        ui.warn(_('could not open .hgsub file for reading'))
+        return
+
+    try:
+        h = open(hgsubstatepath, 'r')
+        hgsubstate = h.readlines()
+        h.close()
+    except:
+        ui.warn(_('could not open .hgsubstate file for reading'))
+        return
+
+    # filter any lines that refer to the selected subrepo
+    def filterlines(lines, filterfunc):
+        filteredlines = []
+        for line in lines:
+            if filterfunc(line):
+                continue
+            filteredlines.append(line)
+        return filteredlines
+
+    def hgsubmatch(line):
+        subpath = os.path.normcase(line.split('=')[0].strip())
+        return subpath == spath
+
+    def hgsubstatematch(line):
+        subpath = line.split()[1].strip()
+        return subpath == spath
+
+    newhgsub = filterlines(hgsub, hgsubmatch)
+    if len(newhgsub) == len(hgsub):
+        ui.warn(_('repository %s is not present on .hgsub file') % spath)
+        return
+
+    # it does not matter if the subrepo is not found on the .hgsubsate file
+    newhgsubstate = filterlines(hgsubstate, hgsubstatematch)
+
+    # Update the .hgsub and .hgsubstate files
+    outdata = [(hgsubpath, newhgsub)]
+    if len(newhgsubstate) != len(hgsubstate):
+        outdata.append((hgsubstatepath, newhgsubstate))
+
+    for fname, lines in outdata:
+        try:
+            h = open(fname, 'w')
+            h.writelines(lines)
+            h.close()
+        except:
+            ui.warn(_('could not open %s file for writing') % fname)
+            return
 
 def command(table):
     '''returns a function object bound to table which can be used as


More information about the Mercurial-devel mailing list