interfaces: convert the zope `Attribute` attrs to regular fields
At this point, we should have a useful protocol class.
The file syntax requires the type to be supplied for any fields that are
declared, but we'll leave the complex ones partially unspecified for now, for
simplicity. (Also, the things documented as `Callable` are really as future
type annotating worked showed- roll with it for now, but they're marked as TODO
for fixing later.) All of the fields and all of the attrs will need type
annotations, or the type rules say they are considered to be `Any`. That can be
done in a separate pass, possibly applying the `dirstate.pyi` file generated
from the concrete class.
The first cut of this turned the `interfaceutil.Attribute` fields into plain
fields, and thus the types on them. PyCharm flagged a few things as having
incompatible signatures when the concrete dirstate class subclassed this, when
the concrete class has them declared as `@property`. So they've been changed to
`@property` here in those cases. The remaining fields that are decorated in the
concrete class have comments noting the differences. We'll see if they need to
be changed going forward, but leave them for now. We'll be in trouble if the
`@util.propertycache` is needed, because we can't import that module here at
runtime, due to circular imports.
$ . "$TESTDIR/narrow-library.sh"
$ hg init master
$ cd master
$ mkdir inside
$ echo inside > inside/f1
$ mkdir outside
$ echo outside > outside/f2
$ mkdir patchdir
$ echo patch_this > patchdir/f3
$ hg ci -Aqm 'initial'
$ cd ..
$ hg clone --narrow ssh://user@dummy/master narrow --include inside
requesting all changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
new changesets dff6a2a6d433
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
$ cd narrow
$ mkdir outside
$ echo other_contents > outside/f2
$ hg tracked | grep outside
[1]
$ hg files | grep outside
[1]
$ hg status
`hg status` did not add outside.
$ hg tracked | grep outside
[1]
$ hg files | grep outside
[1]
Unfortunately this is not really a candidate for adding to narrowhg proper,
since it depends on some other source for providing the manifests (when using
treemanifests) and file contents. Something like a virtual filesystem and/or
remotefilelog. We want to be useful when not using those systems, so we do not
have this method available in narrowhg proper at the moment.
$ cat > "$TESTTMP/expand_extension.py" <<EOF
> import os
> import sys
>
> from mercurial import encoding
> from mercurial import extensions
> from mercurial import localrepo
> from mercurial import match as matchmod
> from mercurial import narrowspec
> from mercurial import patch
> from mercurial import util as hgutil
>
> narrowspecexpanded = False
> def expandnarrowspec(ui, repo, newincludes=None):
> if not newincludes:
> return
> if getattr(repo, '_narrowspecexpanded', False):
> return
> repo._narrowspecexpanded = True
> import sys
> newincludes = set([newincludes])
> includes, excludes = repo.narrowpats
> currentmatcher = narrowspec.match(repo.root, includes, excludes)
> includes = includes | newincludes
> if not repo.currenttransaction():
> ui.develwarn(b'expandnarrowspec called outside of transaction!')
> repo.setnarrowpats(includes, excludes)
> narrowspec.copytoworkingcopy(repo)
> newmatcher = narrowspec.match(repo.root, includes, excludes)
> added = matchmod.differencematcher(newmatcher, currentmatcher)
> with repo.dirstate.changing_parents(repo):
> for f in repo[b'.'].manifest().walk(added):
> repo.dirstate.update_file(
> f,
> p1_tracked=True,
> wc_tracked=True,
> possibly_dirty=True,
> )
>
> def reposetup(ui, repo):
> class expandingrepo(repo.__class__):
> def narrowmatch(self, *args, **kwargs):
> with repo.wlock(), repo.lock(), repo.transaction(
> b'expandnarrowspec'):
> expandnarrowspec(ui, repo,
> encoding.environ.get(b'DIRSTATEINCLUDES'))
> return super(expandingrepo, self).narrowmatch(*args, **kwargs)
> repo.__class__ = expandingrepo
>
> def extsetup(unused_ui):
> def overridepatch(orig, ui, repo, *args, **kwargs):
> with repo.wlock():
> expandnarrowspec(ui, repo, encoding.environ.get(b'PATCHINCLUDES'))
> return orig(ui, repo, *args, **kwargs)
>
> extensions.wrapfunction(patch, 'patch', overridepatch)
> EOF
$ cat >> ".hg/hgrc" <<EOF
> [extensions]
> expand_extension = $TESTTMP/expand_extension.py
> EOF
Since we do not have the ability to rely on a virtual filesystem or
remotefilelog in the test, we just fake it by copying the data from the 'master'
repo.
$ cp -a ../master/.hg/store/data/* .hg/store/data
Do that for patchdir as well.
$ cp -a ../master/patchdir .
`hg status` will now add outside, but not patchdir.
$ DIRSTATEINCLUDES=path:outside hg status
M outside/f2
$ hg tracked | grep outside
I path:outside
$ hg files | grep outside > /dev/null
$ hg tracked | grep patchdir
[1]
$ hg files | grep patchdir
[1]
Get rid of the modification to outside/f2.
$ hg update -C .
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
This patch will not apply cleanly at the moment, so `hg import` will break
$ cat > "$TESTTMP/foo.patch" <<EOF
> --- patchdir/f3
> +++ patchdir/f3
> @@ -1,1 +1,1 @@
> -this should be "patch_this", but its not, so patch fails
> +this text is irrelevant
> EOF
$ PATCHINCLUDES=path:patchdir hg import -p0 -e "$TESTTMP/foo.patch" -m ignored
applying $TESTTMP/foo.patch
patching file patchdir/f3
Hunk #1 FAILED at 0
1 out of 1 hunks FAILED -- saving rejects to file patchdir/f3.rej
abort: patch failed to apply
[20]
$ hg tracked | grep patchdir
[1]
$ hg files | grep patchdir > /dev/null
[1]
Let's make it apply cleanly and see that it *did* expand properly
$ cat > "$TESTTMP/foo.patch" <<EOF
> --- patchdir/f3
> +++ patchdir/f3
> @@ -1,1 +1,1 @@
> -patch_this
> +patched_this
> EOF
$ PATCHINCLUDES=path:patchdir hg import -p0 -e "$TESTTMP/foo.patch" -m message
applying $TESTTMP/foo.patch
$ cat patchdir/f3
patched_this
$ hg tracked | grep patchdir
I path:patchdir
$ hg files | grep patchdir > /dev/null