[PATCH 3 of 3] archive: support 'wdir()'

Matt Harbison mharbison72 at gmail.com
Tue Jun 16 22:31:33 CDT 2015


On Tue, 16 Jun 2015 11:05:52 -0400, Yuya Nishihara <yuya at tcha.org> wrote:

> On Mon, 15 Jun 2015 21:59:22 -0400, Matt Harbison wrote:
>> On Mon, 15 Jun 2015 20:56:59 -0400, Matt Harbison  
>> <mharbison72 at gmail.com>
>> wrote:
>>
>> > On Mon, 15 Jun 2015 11:46:09 -0400, Yuya Nishihara <yuya at tcha.org>  
>> wrote:
>> >
>> >> On Mon, 15 Jun 2015 00:28:59 -0400, Matt Harbison wrote:
>> >>> # HG changeset patch
>> >>> # User Matt Harbison <matt_harbison at yahoo.com>
>> >>> # Date 1434328768 14400
>> >>> #      Sun Jun 14 20:39:28 2015 -0400
>> >>> # Node ID 18d376a661ffabe8121ab5d57b245f4f347f8cd1
>> >>> # Parent  f5f5e4ae488d9cae8111e9a212f647ed1430a019
>> >>> archive: support 'wdir()'
>> >>
>> >>> diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py
>> >>> --- a/mercurial/subrepo.py
>> >>> +++ b/mercurial/subrepo.py
>> >>> @@ -751,8 +751,8 @@
>> >>>      def archive(self, archiver, prefix, match=None):
>> >>>          self._get(self._state + ('hg',))
>> >>>          total = abstractsubrepo.archive(self, archiver, prefix,  
>> match)
>> >>> -        rev = self._state[1]
>> >>> -        ctx = self._repo[rev]
>> >>> +        ctx = self._getctx()
>> >>> +
>> >>>          for subpath in ctx.substate:
>> >>>              s = subrepo(ctx, subpath)
>> >>>              submatch = matchmod.narrowmatcher(subpath, match)
>> >>> @@ -918,18 +918,13 @@
>> >>>
>> >>>      @annotatesubrepoerror
>> >>>      def files(self):
>> >>> -        rev = self._state[1]
>> >>> -        ctx = self._repo[rev]
>> >>> -        return ctx.manifest().keys()
>> >>> +        return self._getctx().manifest().keys()
>> >>>
>> >>>      def filedata(self, name):
>> >>> -        rev = self._state[1]
>> >>> -        return self._repo[rev][name].data()
>> >>> +        return self._getctx()[name].data()
>> >>>
>> >>>      def fileflags(self, name):
>> >>> -        rev = self._state[1]
>> >>> -        ctx = self._repo[rev]
>> >>> -        return ctx.flags(name)
>> >>> +        return self._getctx().flags(name)
>> >>
>> >> Can't we switch to the hgsubrepo object representing wdir?
>> >
>> > We don't have such a thing- subrepo is always created based on the
>> > .hgsubstate file.  Do you mean do a hack like this, to patch state[1]  
>> to
>> > be None?
>> >
>> >     
>> https://www.selenic.com/pipermail/mercurial-devel/2015-June/070763.html
>> >
>> > I know previously when I tried getting subrepo.subrepo() to return a
>> > subrepo with state[1] == None if the calling context was wdir(),  
>> status
>> > and diff broke.  I can't seem to get it to fail the same way now, so
>> > I'll fiddle with that some more.
>>
>> A bit of followup:
>>
>> 1) sub._substate[1] must reflect what is written to .hgsubstate in p1(),
>> otherwise sub.dirty() is wrong.  Archive doesn't care about dirty, but
>> this detail precludes a general solution I think.
>
> True. subrepo shouldn't reflect the working directory changes in general.
> Perhaps "archive" is one of exceptional cases.
>
>> 2) If we were to create a local subrepo object in archive that is hacked
>> up to represent wdir(), I think we have to do it each time a subrepo is
>> entered into.  It isn't a matter of redirecting once at the top and
>> everything just works.  And since creating a subrepo involves  
>> pathauditor
>> (or if we call the constructor directly, creating a new repo object and
>> another path.exists()), it seems that the 'if rev is None' duplication
>> below is actually cheaper.
>
> Hmm, I thought something like the following. But I agree, it wasn't nice
> because sub.archive() had to know it want a wdir subrepo anyway.
>
> diff --git a/mercurial/archival.py b/mercurial/archival.py
> --- a/mercurial/archival.py
> +++ b/mercurial/archival.py
> @@ -315,7 +315,7 @@ def archive(repo, dest, node, kind, deco
>     if subrepos:
>          for subpath in sorted(ctx.substate):
> -            sub = ctx.sub(subpath)
> +            sub = ctx.workingsub(subpath)
>              submatch = matchmod.narrowmatcher(subpath, matchfn)
>              total += sub.archive(archiver, prefix, submatch)
> diff --git a/mercurial/context.py b/mercurial/context.py
> --- a/mercurial/context.py
> +++ b/mercurial/context.py
> @@ -254,6 +254,11 @@ class basectx(object):
>      def nullsub(self, path, pctx):
>          return subrepo.nullsubrepo(self, path, pctx)
> +    def workingsub(self, path):
> +        state = self.substate[path]
> +        state = (state[0], self.subrev(path), state[2])  # XXX hack
> +        return subrepo.subrepo(self, path, state)
> +
>      def match(self, pats=[], include=None, exclude=None, default='glob',
>                listsubrepos=False, badfn=None):
>          r = self._repo
> diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py
> --- a/mercurial/subrepo.py
> +++ b/mercurial/subrepo.py
> @@ -324,7 +324,7 @@ def _sanitize(ui, vfs, ignore):
>                            "in '%s'\n") % vfs.join(dirname))
>                  vfs.unlink(vfs.reljoin(dirname, f))
> -def subrepo(ctx, path):
> +def subrepo(ctx, path, state=None):
>      """return instance of the right subrepo class for subrepo in path"""
>      # subrepo inherently violates our import layering rules
>      # because it wants to make repo objects from deep inside the stack
> @@ -335,7 +335,8 @@ def subrepo(ctx, path):
>      hg = h
>     pathutil.pathauditor(ctx.repo().root)(path)
> -    state = ctx.substate[path]
> +    if not state:  # XXX hack
> +        state = ctx.substate[path]
>      if state[2] not in types:
>          raise util.Abort(_('unknown subrepo type %s') % state[2])
>      return types[state[2]](ctx, path, state[:2])
> @@ -754,7 +755,7 @@ class hgsubrepo(abstractsubrepo):
>          rev = self._state[1]
>          ctx = self._repo[rev]
>          for subpath in ctx.substate:
> -            s = subrepo(ctx, subpath)
> +            s = ctx.workingsub(subpath)  # XXX smells bad
>              submatch = matchmod.narrowmatcher(subpath, match)
>              total += s.archive(archiver, prefix + self._path + '/',  
> submatch)
>          return total

Works for me.  The funny thing is I did something almost identical a few  
months ago and rejected it as too hacky.


More information about the Mercurial-devel mailing list