Gregory Szorc <gregory.szorc@gmail.com> [Wed, 05 Sep 2018 12:44:25 -0700] rev 39782
narrow: remove custom filelog type
This functionality is now handled by core as of the previous commit.
I wanted this to be a standalone commit because the deleted code
makes a reference to remotefilelog's file type missing a node() method
and this may have implications to narrow+remotefilelog usage. The code
in core doesn't perform this check and therefore behavior may be subtly
different and buggy.
But I /think/ the check is merely a performance optimization and
nothing more. So I'm optimistic this will continue to "just work."
Differential Revision: https://phab.mercurial-scm.org/D4644
Gregory Szorc <gregory.szorc@gmail.com> [Thu, 13 Sep 2018 16:02:22 -0700] rev 39781
filelog: custom filelog to be used with narrow repos
Narrow repos may have file revisions whose copy/rename metadata
references files not in the store. This can pose problems when
consumers attempt to access a missing referenced file revision.
The narrow extension hacks around this problem by implementing a
derived filelog type that provides custom implementations of
renamed(), size(), and cmp() which handle renames against files not
in the narrow spec by silently removing the rename metadata.
While silently dropping metadata isn't the most robust solution,
it is the easiest to implement.
This commit ports the custom narrow filelog class to core.
When a narrow repo is constructed, its ifilestorage creation
function will automatically use the new filelog type. This means
the extra logic is 0 cost for non-narrow repos and shouldn't
interfere with their operation.
Differential Revision: https://phab.mercurial-scm.org/D4643
Gregory Szorc <gregory.szorc@gmail.com> [Tue, 18 Sep 2018 15:29:42 -0700] rev 39780
localrepo: iteratively derive local repository type
This commit implements the dynamic local repository type derivation
that was explained in the recent commit
bfeab472e3c0 "localrepo: create new function for instantiating a local
repo object."
Instead of a static localrepository class/type which must be customized
after construction, we now dynamically construct a type by building up
base classes/types to represent specific repository interfaces.
Conceptually, the end state is similar to what was happening when
various extensions would monkeypatch the __class__ of newly-constructed
repo instances. However, the approach is inverted. Instead of making
the instance then customizing it, we do the customization up front
by influencing the behavior of the type then we instantiate that
custom type.
This approach gives us much more flexibility. For example, we can
use completely separate classes for implementing different aspects
of the repository. For example, we could have one class representing
revlog-based file storage and another representing non-revlog based
file storage. When then choose which implementation to use based on
the presence of repo requirements.
A concern with this approach is that it creates a lot more types
and complexity and that complexity adds overhead. Yes, it is true that
this approach will result in more types being created. Yes, this is
more complicated than traditional "instantiate a static type." However,
I believe the alternatives to supporting alternate storage backends
are just as complicated. (Before I arrived at this solution, I had
patches storing factory functions on local repo instances for e.g.
constructing a file storage instance. We ended up having a handful
of these. And this was logically identical to assigning custom
methods. Since we were logically changing the type of the instance,
I figured it would be better to just use specialized types instead
of introducing levels of abstraction at run-time.)
On the performance front, I don't believe that having N base classes
has any significant performance overhead compared to just a single base
class. Intuition says that Python will need to iterate the base classes
to find an attribute. However, CPython caches method lookups: as long as
the __class__ or MRO isn't changing, method attribute lookup should be
constant time after first access. And non-method attributes are stored
in __dict__, of which there is only 1 per object, so the number of
base classes for __dict__ is irrelevant.
Anyway, this commit splits up the monolithic completelocalrepository
interface into sub-interfaces: 1 for file storage and 1 representing
everything else.
We've taught ``makelocalrepository()`` to call a series of factory
functions which will produce types implementing specific interfaces.
It then calls type() to create a new type from the built-up list of
base types.
This commit should be considered a start and not the end state. I
suspect we'll hit a number of problems as we start to implement
alternate storage backends:
* Passing custom arguments to __init__ and setting custom attributes
on __dict__.
* Customizing the set of interfaces that are needed. e.g. the
"readonly" intent could translate to not requesting an interface
providing methods related to writing.
* More ergonomic way for extensions to insert themselves so their
callbacks aren't unconditionally called.
* Wanting to modify vfs instances, other arguments passed to __init__.
That being said, this code is usable in its current state and I'm
convinced future commits will demonstrate the value in this approach.
Differential Revision: https://phab.mercurial-scm.org/D4642
Gregory Szorc <gregory.szorc@gmail.com> [Tue, 18 Sep 2018 15:15:24 -0700] rev 39779
localrepo: pass root manifest into manifestlog.__init__
Today, localrepository has a method that can be overloaded which
returns an instance of the root manifest storage object. When a
manifestlog is created, it calls this private method and stores
the root manifest object on it.
This "hook" on localrepository isn't part of the documented interface.
It isn't compatible with our desire to make repo storage determined
before the repo object is constructed.
This commit changes manifestlog.__init__ to accept the root
storage object instead of calling into the repo to construct it.
By doing things this way, the repo instance is responsible for
constructing the manifest storage object directly.
This does mean that other derived repo types need to overload
manifestlog(). But they should have been doing this already,
as manifestlog() is typically decorated in a storage-specific way.
e.g. localrepository.manifestlog() is decorated as
@storecache('00manifest.i'). And this assumes that a 00manifest.i
file exists in the store vfs. This condition may not hold for
repository types using non-revlog storage. So it is important
for special repo types to override manifestlog() to remove this
file association.
The code changed in perf is wrong because it isn't compatible with
older Mercurial versions. But I'm pretty sure the code was broken
on older versions before this commit. It only affects `hg perftags`.
I don't care enough to fix that at this time.
.. api::
``manifest.manifestlog.__init__()`` now receives the root manifest
storage instance instead of calling into a private method on
the repo object to obtain it.
Differential Revision: https://phab.mercurial-scm.org/D4641
Matt Harbison <matt_harbison@yahoo.com> [Fri, 21 Sep 2018 21:44:27 -0400] rev 39778
py3: create built in exceptions with str type messages in win32.py
I hit an IOError in unlink() in test-pathconflicts-basic.t, that then crashed as
it was handled:
File "mercurial\dispatch.py", line 359, in _runcatch
return _callcatch(ui, _runcatchfunc)
File "mercurial\dispatch.py", line 367, in _callcatch
return scmutil.callcatch(ui, func)
File "mercurial\scmutil.py", line 252, in callcatch
ui.error(_("abort: %s\n") % encoding.strtolocal(inst.strerror))
File "mercurial\encoding.py", line 205, in unitolocal
return tolocal(u.encode('utf-8'))
AttributeError: 'bytes' object has no attribute 'encode'
Matt Harbison <matt_harbison@yahoo.com> [Sat, 22 Sep 2018 12:11:48 -0400] rev 39777
tests: stabilize test-shelve.t#phasebased for #no-symlink and #no-execbit
The rev number ended up being 11 instead of 13 on Windows. If I ever get back
to issue2020, this will go away.
Martin von Zweigbergk <martinvonz@google.com> [Thu, 20 Sep 2018 21:35:01 -0700] rev 39776
debugdirstate: deprecate --nodates in favor of --no-dates
We have supported 'no-' prefixes for boolean flag for a few years now,
so I was expecting it to be --no-dates.
I noticed that we have --nodates options for a few more commands
(e.g. `hg diff`), but I'll leave that for another day.
Differential Revision: https://phab.mercurial-scm.org/D4693
Matt Harbison <matt_harbison@yahoo.com> [Fri, 21 Sep 2018 00:37:03 -0400] rev 39775
py3: fix a type error in hghave.has_hardlink
test-hghave.t was failing with:
feature hardlink failed: argument 1: <class 'TypeError'>: wrong type
Martin von Zweigbergk <martinvonz@google.com> [Fri, 21 Sep 2018 09:34:41 -0700] rev 39774
narrow: remove hack to read narowspec from shared .hg directory
This was another leftover from 576eef1ab43d (narrow: move
.hg/narrowspec to .hg/store/narrowspec (BC), 2018-08-02), in addition
to 623081f2abc2 (narrow: remove hack to write narrowspec to shared .hg
directory, 2018-09-12).
Differential Revision: https://phab.mercurial-scm.org/D4692
Augie Fackler <augie@google.com> [Fri, 21 Sep 2018 11:43:46 -0400] rev 39773
streamclone: reimplement nested context manager
It's gone in Python 3, and you can't *ctxs into a with statement. Sigh.
Differential Revision: https://phab.mercurial-scm.org/D4690