Matt Harbison <matt_harbison@yahoo.com> [Sat, 17 Aug 2024 18:43:23 -0400] rev 51811
typing: create an @overload of `phasecache` ctor to handle the copy case
In `phasecache.copy()`, it calls `self.__class__(None, None, _load=False)`, but
the constuctor is typed to take a non-None repository. For the `_load=False`
case, all args are ignored (and the copy function itself populates the attrs on
the new object), so this isn't an error. For the default `_load=True` case, it
needs a non-None repository. This is the simplest way to handle that duality.
The reason this wasn't being detected is because pytype is confused by the
interface decorators on the `localrepository` class, and is inferring the whole
class as `Any`. (See
3e9a660b074a or
c1d7ac70980b) Therefore, the type hint of
`localrepo.localrepository` here was also effectively `Any`, which disabled the
type checking entirely.
This is the first foray into using `typing_extensions` to unlock future typing
features. I think this is safe and reasonable because 1) it is only imported in
the type checking phase (so no need to vendor our own copy), and 2) pytype has
its own copy of `typing_extensions` bundled with it, so no need to alter the
test environment. When run with a version of python that supports the symbol(s)
natively, `typing_extensions` simply re-exports from `typing`, so there
shouldn't be any future headaches with this.
Matt Harbison <matt_harbison@yahoo.com> [Sat, 17 Aug 2024 17:38:35 -0400] rev 51810
typing: declare the `_phasesets` member of `phasecache` to be `Optional`
Something in this area got flagged while making the repository class visible to
pytype (instead of being typed as `Any`). A None assignment to something not
optional is wrong, and when I tried setting it to `{}` to keep it non-Optional,
some tests failed. There are checks for the attr being None elsewhere, so this
seems to have just been an oversight.
Matt Harbison <matt_harbison@yahoo.com> [Fri, 16 Aug 2024 18:11:52 -0400] rev 51809
typing: hide the interface version of `dirstate` during type checking
As noted in the previous commit, the `dirstate` type is still inferred as `Any`
by pytype, including where it is used as a base class for the largefiles
dirstate. That effectively disables most type checking. The problems fixed two
commits ago were flagged by this change.
I'm not at all clear what the benefit of the original type is, but that was what
was used at runtime, so I don't want to change the largefiles base class to the
raw class. Having both a lowercase and camelcase name for the same thing isn't
great, but given that this trivially finds problems without worrying about which
symbol clients may be using, and the non-raw type is useless to pytype anyway,
I'm not going to worry about it.
Matt Harbison <matt_harbison@yahoo.com> [Fri, 16 Aug 2024 18:02:32 -0400] rev 51808
dirstate: remove the interface decorator to help pytype
This is the same change that was made for some of the manifest classes in
3e9a660b074a. Note that `dirstate` is still inferred as `Any`, but at least we
have `DirState` with all of the expected attributes.
Matt Harbison <matt_harbison@yahoo.com> [Fri, 16 Aug 2024 17:58:17 -0400] rev 51807
largefiles: sync up `largefilesdirstate` methods with `dirstate` base class
As it currently stands, pytype infers the `dirstate` class (and anything else
decorated with `@interfaceutil.implementer`) as `Any`. When that is worked
around, it suddenly noticed that most of these methods don't exist in the
`dirstate` class anymore. Since they only called into the missing methods and
there's no test failures, we can assume these are never called, and they can be
dropped.
In addition, PyCharm flagged `set_tracked()` and `_ignore()` as not overriding
a superclass method with the same arguments. The missing default parameter for
the former was the obvious issue. I'm guessing that the latter was named wrong
because while there is `_ignore()` in the base class, it takes no arguments and
returns a matcher. The `_ignorefiles()` superclass method also takes no args,
and returns a list of bytes. The `_ignorefileandline()` superclass method DOES
take a file, but returns a tuple. Therefore, the closest match is `_dirignore()`,
which takes a file AND returns a bool. No idea why this needs to be overridden
though.
Arseniy Alekseyev <aalekseyev@janestreet.com> [Fri, 16 Aug 2024 11:12:19 +0100] rev 51806
sparse: reliably avoid writing to store without a lock
With the code as written before this patch we can still end up writing to
store in `debugsparse`. Obviously we'll write to it if by accident a store
requirement is modified, but more importantly we write to it if another
concurrent transaction modifies the requirements file on disk.
We can't rule this out since we're not holding the store lock,
so it's better to explicitly pass a permission to write instead
of inferring it based on file contents.
Arseniy Alekseyev <aalekseyev@janestreet.com> [Thu, 15 Aug 2024 13:52:14 +0100] rev 51805
debugsparse: stop taking the store lock
debugsparse is a workspace-only opperation, or it better be workspace-only.
Let's make it to stop taking the store lock.
Arseniy Alekseyev <aalekseyev@janestreet.com> [Thu, 15 Aug 2024 14:54:22 +0100] rev 51804
scmutils: read the requires file before writing to avoid unnecessary rewrite
This lets us get away without the repo lock in situations where we need
to write requirements, but we know we're not changing the store requirements.
Arseniy Alekseyev <aalekseyev@janestreet.com> [Thu, 15 Aug 2024 14:56:50 +0100] rev 51803
localrepo: remove _readrequires function in favor of scmutil.readrequires
Arseniy Alekseyev <aalekseyev@janestreet.com> [Thu, 15 Aug 2024 14:53:17 +0100] rev 51802
scmutil: add `readrequires` next to `writerequires`
The code is copied from localrepo.py.