[PATCH 2 of 2 RFC] extdiff: use -S to archive the full repo
Matt Harbison
mharbison72 at gmail.com
Fri Feb 13 03:45:21 UTC 2015
On Wed, 11 Feb 2015 07:13:17 -0500, Mathias De Maré
<mathias.demare at gmail.com> wrote:
> On Wed, Feb 11, 2015 at 4:23 AM, Matt Harbison <mharbison72 at gmail.com>
> wrote:
>
> On Tue, 10 Feb 2015 14:36:42 -0500, Mathias De Maré <
>> mathias.demare at gmail.com> wrote:
>>
>> Adding a single file in the working directory worked fine (since it only
>>> does the snapshot for the old (non-working dir) context).
>>> When I add a file and remove another, I get 'abort: no files match the
>>> archive pattern' when the snapshot of the working directory is done. I
>>> had
>>> a further look, and it seems (archive.py:307-310) like for the
>>> subrepositories, the revision is always extracted by checking the
>>> substate.
>>> As a result, the last revision is used (instead of the working
>>> directory).
>>> Specifically for Git, I have the impression there's additionally the
>>> problem that 'git archive' does not support archiving the working
>>> directory.
>>>
>>
>> After some digging, I think that makes sense. hg doesn't support
>> archiving the working copy from the command line either. Maybe what you
>> can try is in subrepo:1550, put a print statement before returning from
>> the
>> 'if not revision' check. The working copy is represented by None, so 0
>> files is returned, and if the parent didn't have anything to archive,
>> archive() complains. (I also bet that if the delta is only file
>> removes,
>> it will also archive 0 files and abort. Maybe we need to pass some
>> sort of
>> flag from extdiff to archive to control whether it aborts.)
>>
>
> No, I think the issue is simply that when you select the subrepo version
> through substate (like is done in archive.py:307-310), you will get the
> latest version of the substate file, and as a result you will get the
> latest committed revision, instead of None.
> I just tried this (with 1 added file and 1 removed file), and the output
> when adding on subrepo:1550 is (this is with your 2 RFC patches and the
> one
> you presented in this mail):
>
>> revision: aa307b592e8a579e599c79665d9f1c4ec19af59f
>> revision: aa307b592e8a579e599c79665d9f1c4ec19af59f
>>
>
> Since the only file that is passed to the subrepo archive is exactly the
> file that was added (and so is not in the revision specified), the
> archive
> will indeed say that no files can be archived.
> So archive should actually return 'None' to the subrepo, so we can handle
> it correctly in the subrepo.
Sorry for the delayed response. I had to reboot last night, and Windows
decided to install 11 updates... and it still wasn't done 12 hours later
when I left for work this morning.
I put together some tests to see if I could figure out the differences
between what I was seeing and what you were. I had assumed that adding a
file to a subrepo and modifying one in a subrepo wouldn't cause a
difference in how the recursion is handled- but that doesn't appear to be
the case. This can be applied on top of the 3rd patch in this chain.
There's either a subtle subrepo bug, or (more likely), I'm missing
something.
# HG changeset patch
# User Matt Harbison <matt_harbison at yahoo.com>
# Date 1423795917 18000
# Thu Feb 12 21:51:57 2015 -0500
# Node ID 2a257d5dafbb12c498e47a8c5d0a5c29495f1ea2
# Parent 57c3177c05122a6655ac27ed71f07276ef5c8375
extdiff: basic hg subrepo testing
What extdiff sees when a subrepo has a modified file, and when it has an
added
file is different for reasons unknown. A modified file in a git subrepo
also
works as we would like (i.e. the modified file is archived), but
apparently it
doesn't archive an added file either.
diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py
--- a/mercurial/subrepo.py
+++ b/mercurial/subrepo.py
@@ -658,6 +658,8 @@
def diff(self, ui, diffopts, node2, match, prefix, **opts):
try:
node1 = node.bin(self._state[1])
+# print('hgsub diff: "%s"' % self._state[1])
+
# We currently expect node2 to come from substate and be
# in hex format
if node2 is not None:
@@ -676,6 +678,7 @@
total = abstractsubrepo.archive(self, archiver, prefix, match)
rev = self._state[1]
ctx = self._repo[rev]
+# print('hgsub archive: "%s, ctx type is %s"' % (rev, type(ctx)))
for subpath in ctx.substate:
s = subrepo(ctx, subpath)
submatch = matchmod.narrowmatcher(subpath, match)
diff --git a/tests/test-subrepo-extdiff.t b/tests/test-subrepo-extdiff.t
new file mode 100644
--- /dev/null
+++ b/tests/test-subrepo-extdiff.t
@@ -0,0 +1,93 @@
+ $ cat >> $HGRCPATH <<EOF
+ > [extensions]
+ > extdiff=
+ > EOF
+
+ $ hg init root
+ $ echo "hgsub = hgsub" > root/.hgsub
+ $ cd root
+ $ hg init hgsub
+ $ hg add .hgsub
+ $ echo test > hgsub/modified.txt
+ $ hg -R hgsub add hgsub/modified.txt
+
+-------------------------------------------------------------------------------
+For hg subrepos that have not been locked in, changes are visible to
diff, but
+NOT extdiff. self._state[1] is ''
+
+ $ hg status -S
+ A .hgsub
+ A hgsub/modified.txt
+
+ $ hg diff -S
+ diff -r 000000000000 .hgsub
+ --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+ +++ b/.hgsub * (glob)
+ @@ -0,0 +1,1 @@
+ +hgsub = hgsub
+ diff -r 000000000000 hgsub/modified.txt
+ --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+ +++ b/hgsub/modified.txt * (glob)
+ @@ -0,0 +1,1 @@
+ +test
+
+ $ hg extdiff -S
+ diff -Npru root.000000000000/.hgsub root/.hgsub
+ --- root.000000000000/.hgsub 1970-01-01 00:00:00 +0000
+ +++ root/.hgsub * (glob)
+ @@ -0,0 +1 @@
+ +hgsub = hgsub
+ [1]
+
+ $ hg ci -qm "modified.txt -> test" -S
+
+-------------------------------------------------------------------------------
+For hg subrepos that *have* been locked in, changes are visible to diff
+AND extdiff. self._state[1] is 50a11ebc6587
+
+ $ echo 'second mod' > hgsub/modified.txt
+
+ $ hg status -S
+ M hgsub/modified.txt
+ $ hg diff -S
+ diff -r 50a11ebc6587 hgsub/modified.txt
+ --- a/hgsub/modified.txt Thu Jan 01 00:00:00 1970 +0000
+ +++ b/hgsub/modified.txt * (glob)
+ @@ -1,1 +1,1 @@
+ -test
+ +second mod
+ $ hg extdiff -S
+ ---
c:/users/matt/appdata/local/temp/extdiff.*/root.*/hgsub/modified.txt *
(glob)
+ +++ $TESTTMP/root/hgsub/modified.txt * (glob)
+ @@ -1 +1 @@
+ -test
+ +second mod
+ [1]
+
+-------------------------------------------------------------------------------
+But adding a file to hgsubrepo causes extdiff to see *nothing*.
self_state[1]
+is still 50a11ebc6587, as it was when we had better results in the last
test.
+
+ $ echo 'added' > hgsub/added.txt
+# $ hg -R hgsub add hgsub/added.txt
+ $ hg add hgsub/added.txt
+
+ $ hg status -S
+ M hgsub/modified.txt
+ A hgsub/added.txt
+
+ $ hg diff -S
+ diff -r 50a11ebc6587 hgsub/added.txt
+ --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+ +++ b/hgsub/added.txt * (glob)
+ @@ -0,0 +1,1 @@
+ +added
+ diff -r 50a11ebc6587 hgsub/modified.txt
+ --- a/hgsub/modified.txt Thu Jan 01 00:00:00 1970 +0000
+ +++ b/hgsub/modified.txt * (glob)
+ @@ -1,1 +1,1 @@
+ -test
+ +second mod
+
+ $ hg extdiff -S
+ [1]
diff --git a/tests/test-subrepo-git.t b/tests/test-subrepo-git.t
--- a/tests/test-subrepo-git.t
+++ b/tests/test-subrepo-git.t
@@ -698,6 +698,16 @@
+foo
+bar
+ $ hg extdiff -S --config extensions.extdiff=
+ --- nul 1970-01-01 00:00:00 +0000
+ +++ $TESTTMP/tc/s/foobar * (glob)
+ @@ -0,0 +1,4 @@
+ +woopwoop
+ +
+ +foo
+ +bar
+ [1]
+
$ hg commit --subrepos -m "Added foobar"
committing subrepository s
created new head
>>
>> I think you may need to manually copy from the filesystem to the archive
>> for this conditional. Since the status call was previously done, every
>> file you need to archive is listed in the matcher.
>>
> That is indeed correct, I'll have a look if I can create a patch to
> handle
> that case for git and for svn. However, we don't even get into that case
> yet, because of the issue above.
After further digging, the only time I've seen this case triggered is if
the subrepo hasn't been committed to the parent repo yet. I was hoping
this would be used as 'give me the wctx of this subrepo', but it's not. I
can see how it gets there in subrepo:145.
I wonder if context.substate() should be overridden in workingctx to set
the state to None, so that repo[None].substate always yields subrepo
working directories. We would need it for a revset symbol that indicates
the working directory too. It's different from repo['.'].substate, so I
don't think it will break anything. I'll try it and see what happens, but
maybe a subrepo expert can chime in.
>>
>> Whatever you implement should work for svn too, since it is just
>> filesystem access. (But svn seems to use the base class implementation,
>> which doesn't check the revision. Not sure what is going on there.)
>>
>>
>>> If I then commit the added and removed file and run extdiff on those,
>>> it
>>> works fine.
>>>
>>> So to get the working directory working, we'll also need to modify the
>>> support for archiving subrepos in general and git subrepos in
>>> particular.
>>>
>>
>> Here's a demo that working directory archiving for hgsubrepos works.
>> The
>> thing that surprised me is it seems to ignore uncommitted adds. But so
>> does 'hg diff' apparently. This should apply on top of this series.
>> Ignore the tests at the very bottom around line 518- it uses largefiles,
>> and is probably wonky.
>>
>> # HG changeset patch
>> # User Matt Harbison <matt_harbison at yahoo.com>
>> # Date 1423621101 18000
>> # Tue Feb 10 21:18:21 2015 -0500
>> # Node ID 57c3177c05122a6655ac27ed71f07276ef5c8375
>> # Parent 9c4f27e5c804662d2d25581ad3856ef6da3729ec
>> extdiff: quick and dirty working copy snapshot via archive
[snip]
More information about the Mercurial-devel
mailing list