None of this function has been used in the past 5 years, so I think it is safe
to just kill them. All code accessing rich markers is using 'getmarkers(...)'
instead (or raw markers).
Extensions can have a 'configtable' mapping and use
'registrar.configitem(table)' to retrieve the registration function.
This behave in the same way as the other way for extensions to register new
items (commands, colors, etc).
We simplify the unstable computation code, skipping the expensive creation of
changectx object. We focus on efficient set operation and revnumber centric
functions.
In my mercurial development repository, this provides a 3x speedup to the
function:
before: 5.319 ms
after: 1.844 ms
repo details:
total changesets: 40886
obsolete changesets: 7756
mutable (not obsolete): 293
unstable: 30
There are cases in opts handling in debugcommands.py where we don't need to
convert opts keys back to bytes as there are some handful cases and no other
function using opts value. Using r'', we prevent the transformer to add
a b'' which will keep the value str.
Otherwise nested template formatter would not see the context objects.
It's just a boolean flag now. We might want to change it to 'ctxs -> items'
function so changectx attributes are populated automatically in JSON, but
I'm not sure.
It's now common that an old node gets replaced by zero or more new nodes,
that could happen with amend, rebase, histedit, etc. And it's a common
requirement to do bookmark movements, strip or obsolete nodes and even
moving working copy parent.
Previously, amend, rebase, history have their own logic doing the above.
This patch is an attempt to unify them and future code.
This enables new developers to be able to do "replace X with Y" thing
correctly, without any knowledge about bookmarks, strip or obsstore.
The next step will be migrating rebase to the new API, so it works inside a
transaction, and its code could be simplified.
For long, the fact that strip does not work inside a transaction and some
code has to work with both obsstore and fallback to strip lead to duplicated
code like:
with repo.transaction():
....
if obsstore:
obsstore.createmarkers(...)
if not obsstore:
repair.strip(...)
Things get more complex when you want to call something which may call strip
under the hood. Like you cannot simply write:
with repo.transaction():
....
rebasemod.rebase(...) # may call "strip", so this doesn't work
But you do want rebase to run inside a same transaction if possible, so the
code may look like:
with repo.transaction():
....
if obsstore:
rebasemod.rebase(...)
obsstore.createmarkers(...)
if not obsstore:
rebasemod.rebase(...)
repair.strip(...)
That's ugly and error-prone. Ideally it's possible to just write:
with repo.transaction():
rebasemod.rebase(...)
saferemovenodes(...)
This patch is the first step towards that. It adds a "delayedstrip" method
to repair.py which maintains a postclose callback in the transaction object.
This is necessary because some callers in merge.py pass backgroundclose=True
when writing.
As with previous changes in this series, this should be a no-op.
We would like to migrate direct calls of repo.wvfs/wwrite/wread/etc to a
call on the relevant workingfilectx, both as a cleanup (to reduce the number of
working copy functions on `repo`), and also to facilitate an in-memory merge
that doesn't write to the working copy.
In order to do that, the first step is to ensure we pass the target wctx around
and perform our writes and reads on it. Later, this object might become a
memctx.
This is naive implementation using two-pass scanning. Tracking descendants
isn't an easy problem if both start and stop depths are specified. It's
impractical to remember all possible depths of each node while scanning from
roots to descendants because the number of depths explodes. Instead, we could
cache (min, max) depths as a good approximation and track ancestors back when
needed, but that's likely to have off-by-one bug.
Since this implementation appears not significantly slower, and is quite
straightforward, I think it's good enough for practical use cases. The time
and space complexity is O(n) ish.
revisions:
0) 1-pass scanning with (min, max)-depth cache (worst-case quadratic)
1) 2-pass scanning (this version)
repository:
mozilla-central
# descendants(0) (for reference)
*) 0.430353
# descendants(0, depth=1000)
0) 0.264889
1) 0.398289
# descendants(limit(tip:0, 1, offset=10000), depth=1000)
0) 0.025478
1) 0.029099
# descendants(0, depth=2000, startdepth=1000)
0) painfully slow (due to quadratic backtracking of ancestors)
1) 1.531138
Prepares for adding depth support. I want to process depth=0 in
revdescendants() to make things simpler.
only() also calls dagop.revdescendants(), but it filters out root revisions
explicitly. So this should cause no problem.
# descendants(0) using hg repo
0) 0.052380
1) 0.051226
# only(tip) using hg repo
0) 0.001433
1) 0.001425