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

Augie Fackler raf at durin42.com
Mon Feb 9 17:01:12 CST 2015


On Sun, Feb 08, 2015 at 11:01:36PM -0500, Matt Harbison wrote:
> # 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 seems like a decent approach.

>
> [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.]

Yes, I think it should.

>
> 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.
>

I don't speak largefiles. Does this mean that the phony files won't be
included, but the actual largefile content will? For extdiff, that's
arguably the right behavior?

> 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.

It probably makes sense to keep extdiff and 'hg diff' output at least
somewhat related?

>
> 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 ..
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel


More information about the Mercurial-devel mailing list