[PATCH 1 of 2 RFC] extdiff: use archiver to take snapshots of committed revisions

Matt Harbison mharbison72 at gmail.com
Mon Feb 9 04:01:36 UTC 2015


# HG changeset patch
# User Matt Harbison <matt_harbison at yahoo.com>
# Date 1342054131 14400
#      Wed Jul 11 20:48:51 2012 -0400
# Node ID 6abceaa1a49f82cebd3a4f141f69558e2bb3cec4
# Parent  ff5caa8dfd993680d9602ca6ebb14da9de10d5f4
extdiff: use archiver to take snapshots of committed revisions

[This is the proof of concept that Mathias asked for.  The fix for file
archiving from the internal API maybe should be a separate commit.]

There should be no visible functional differences, other than the largefile
standins are no longer included in the non working copy snapshots.  That's
probably not a big deal, and proper largefile support can still be added.  This
is the first step to make -S work.  The full (deep) working copy snapshot needs
to be handled prior to that.  This could probably be improved in the future by
excluding .hgsub and .hgsubstate from status, since that is really just private
bookkeeping info.

diff --git a/hgext/extdiff.py b/hgext/extdiff.py
--- a/hgext/extdiff.py
+++ b/hgext/extdiff.py
@@ -63,6 +63,7 @@
 from mercurial.i18n import _
 from mercurial.node import short, nullid
 from mercurial import cmdutil, scmutil, util, commands, encoding, filemerge
+from mercurial import archival
 import os, shlex, shutil, tempfile, re
 
 cmdtable = {}
@@ -80,31 +81,44 @@
         dirname = '%s.%s' % (dirname, short(node))
     base = os.path.join(tmproot, dirname)
     os.mkdir(base)
+    fns_and_mtime = []
+
     if node is not None:
         ui.note(_('making snapshot of %d files from rev %s\n') %
                 (len(files), short(node)))
+
+        # Use archive to build the snapshot for committed nodes.  (It aborts if
+        # the list is empty.)
+        if files:
+            repo.ui.setconfig("ui", "archivemeta", False)
+
+            archival.archive(repo, base, node, 'files',
+                             matchfn=scmutil.matchfiles(repo, files))
     else:
         ui.note(_('making snapshot of %d files from working directory\n') %
             (len(files)))
-    wopener = scmutil.opener(base)
-    fns_and_mtime = []
-    ctx = repo[node]
-    for fn in sorted(files):
-        wfn = util.pconvert(fn)
-        if wfn not in ctx:
-            # File doesn't exist; could be a bogus modify
-            continue
-        ui.note('  %s\n' % wfn)
-        dest = os.path.join(base, wfn)
-        fctx = ctx[wfn]
-        data = repo.wwritedata(wfn, fctx.data())
-        if 'l' in fctx.flags():
-            wopener.symlink(data, wfn)
-        else:
-            wopener.write(wfn, data)
-            if 'x' in fctx.flags():
-                util.setflags(dest, False, True)
-        if node is None:
+
+        # TODO: Use filesystem routines to duplicate the relevant parts of the
+        #       working directory instead of this (archive doesn't work for
+        #       wctx).  This will allow any subrepo type and largefiles to work
+        wopener = scmutil.opener(base)
+        ctx = repo[node]
+        for fn in sorted(files):
+            wfn = util.pconvert(fn)
+            if wfn not in ctx:
+                # File doesn't exist; could be a bogus modify
+                continue
+            ui.note('  %s\n' % wfn)
+            dest = os.path.join(base, wfn)
+            fctx = ctx[wfn]
+            data = repo.wwritedata(wfn, fctx.data())
+            if 'l' in fctx.flags():
+                wopener.symlink(data, wfn)
+            else:
+                wopener.write(wfn, data)
+                if 'x' in fctx.flags():
+                    util.setflags(dest, False, True)
+
             fns_and_mtime.append((dest, repo.wjoin(fn),
                                   os.lstat(dest).st_mtime))
     return dirname, fns_and_mtime
diff --git a/hgext/largefiles/overrides.py b/hgext/largefiles/overrides.py
--- a/hgext/largefiles/overrides.py
+++ b/hgext/largefiles/overrides.py
@@ -851,7 +851,7 @@
         repo._lfcommithooks.pop()
 
 def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None,
-            prefix=None, mtime=None, subrepos=None):
+            prefix='', mtime=None, subrepos=None):
     # No need to lock because we are only reading history and
     # largefile caches, neither of which are modified.
     lfcommands.cachelfiles(repo.ui, repo, node)
diff --git a/mercurial/archival.py b/mercurial/archival.py
--- a/mercurial/archival.py
+++ b/mercurial/archival.py
@@ -230,7 +230,7 @@
     }
 
 def archive(repo, dest, node, kind, decode=True, matchfn=None,
-            prefix=None, mtime=None, subrepos=False):
+            prefix='', mtime=None, subrepos=False):
     '''create archive of repo as it was at node.
 
     dest can be name of directory, name of archive file, or file
diff --git a/tests/test-subrepo-deep-nested-change.t b/tests/test-subrepo-deep-nested-change.t
--- a/tests/test-subrepo-deep-nested-change.t
+++ b/tests/test-subrepo-deep-nested-change.t
@@ -419,4 +419,47 @@
   A a.dat
   A a.txt
 
+  $ cat <<EOF >> $HGRCPATH
+  > [extdiff]
+  > cmd.falabala = echo
+  > opts.falabala = diffing
+  > EOF
+
+Interaction with extdiff, largefiles and subrepos
+
+  $ hg --config extensions.extdiff= extdiff
+  diff -Npru cloned.6e907bf12afc/.hglf/a.dat cloned/.hglf/a.dat
+  --- cloned.6e907bf12afc/.hglf/a.dat	1970-01-01 00:00:00 +0000
+  +++ cloned/.hglf/a.dat	* (glob)
+  @@ -0,0 +1 @@
+  +
+  [1]
+
+  $ hg --config extensions.extdiff= extdiff -r .^
+  diff -Npru cloned.1f79fbad5d0f/.hglf/a.dat cloned/.hglf/a.dat
+  --- cloned.1f79fbad5d0f/.hglf/a.dat	1970-01-01 00:00:00 +0000
+  +++ cloned/.hglf/a.dat	* (glob)
+  @@ -0,0 +1 @@
+  +
+  diff -Npru cloned.1f79fbad5d0f/.hglf/foo/bar/large.dat cloned/.hglf/foo/bar/large.dat
+  --- cloned.1f79fbad5d0f/.hglf/foo/bar/large.dat	1970-01-01 00:00:00 +0000
+  +++ cloned/.hglf/foo/bar/large.dat	* (glob)
+  @@ -0,0 +1 @@
+  +2f6933b5ee0f5fdd823d9717d8729f3c2523811b
+  diff -Npru cloned.1f79fbad5d0f/foo/bar/abc cloned/foo/bar/abc
+  --- cloned.1f79fbad5d0f/foo/bar/abc	* (glob)
+  +++ cloned/foo/bar/abc	* (glob)
+  @@ -0,0 +1 @@
+  +changed
+  [1]
+
+  $ hg --config extensions.extdiff= extdiff -r 0 -r .^
+  diff -Npru cloned.7f491f53a367/.hgsubstate cloned.1f79fbad5d0f/.hgsubstate
+  --- cloned.7f491f53a367/.hgsubstate	* (glob)
+  +++ cloned.1f79fbad5d0f/.hgsubstate	* (glob)
+  @@ -1 +1 @@
+  -fc3b4ce2696f7741438c79207583768f2ce6b0dd sub1
+  +7a36fa02b66e61f27f3d4a822809f159479b8ab2 sub1
+  [1]
+
   $ cd ..


More information about the Mercurial-devel mailing list