##// END OF EJS Templates
branchmap-v3: introduce a "stop_rev" argument to `headsrevs`...
branchmap-v3: introduce a "stop_rev" argument to `headsrevs` The `headsrevs` method of the revlog already have a `revs` argument to compute the headrevs of a limited set of heads. However, it disable the use of the native compiled code to compute the heads, which slows down the branchmap v3 code a lot. The branchmap v3 usage is actually quite constrained as we will always only ignores a part at the top of the graph. So we could be significantly faster. We start by making small change to the python side to improve the situation and introduce the new API. More collaboration with the native code are coming later. This massively speedup operation and close most of the remaining gaps between branchmap-v3 and branchmap-v2. especially on repository with many revs like mozilla-try. A small overhead remains mostly because the `headrevs` logic currently has some inefficiently. We will look into them from there. ### benchmark.name = hg.command.unbundle # bin-env-vars.hg.py-re2-module = default # benchmark.variants.issue6528 = disabled # benchmark.variants.resource-usage = default # benchmark.variants.reuse-external-delta-parent = yes # benchmark.variants.revs = any-1-extra-rev # benchmark.variants.source = unbundle # benchmark.variants.validate = default # benchmark.variants.verbosity = quiet ## data-env-vars.name = netbeans-2018-08-01-zstd-sparse-revlog # bin-env-vars.hg.flavor = default branch-v2: 0.233711 ~~~~~ branch-v3 before: 0.368769 (+57.79%, +0.14) branch-v3 after: 0.239857 (+2.63%, +0.01) # bin-env-vars.hg.flavor = rust branch-v2: 0.235230 ~~~~~ branch-v3 before: 0.372460 (+58.34%, +0.14) branch-v3 after: 0.240972 (+2.44%, +0.01) ## data-env-vars.name = netbeans-2018-08-01-ds2-pnm # bin-env-vars.hg.flavor = rust branch-v2: 0.255586 ~~~~~ branch-v3 before: 0.318907 (+24.78%, +0.06) branch-v3 after: 0.268560 (+5.08%, +0.01) ## data-env-vars.name = mozilla-central-2024-03-22-zstd-sparse-revlog # bin-env-vars.hg.flavor = default branch-v2: 0.339010 ~~~~~ branch-v3 before: 0.349752 (+3.17%, +0.01) branch-v3 after: 0.349389 (+3.06%, +0.01) # bin-env-vars.hg.flavor = rust branch-v2: 0.346525 ~~~~~ branch-v3 before: 0.354300 (+2.24%, +0.01) branch-v3 after: 0.355661 (+2.64%, +0.01) ## data-env-vars.name = mozilla-central-2024-03-22-ds2-pnm # bin-env-vars.hg.flavor = rust branch-v2: 0.380202 ~~~~~ branch-v3 before: 0.396293 (+4.23%, +0.02) branch-v3 after: 0.408851 (+7.54%, +0.03) ## data-env-vars.name = mozilla-unified-2024-03-22-zstd-sparse-revlog # bin-env-vars.hg.flavor = default branch-v2: 0.412165 ~~~~~ branch-v3 before: 0.424769 (+3.06%, +0.01) branch-v3 after: 0.427782 (+3.79%, +0.02) # bin-env-vars.hg.flavor = rust branch-v2: 0.412397 ~~~~~ branch-v3 before: 0.421796 (+2.28%, +0.01) branch-v3 after: 0.422354 (+2.41%, +0.01) ## data-env-vars.name = mozilla-unified-2024-03-22-ds2-pnm # bin-env-vars.hg.flavor = rust branch-v2: 0.429501 ~~~~~ branch-v3 before: 0.443849 (+3.34%, +0.01) branch-v3 after: 0.443197 (+3.19%, +0.01) ## data-env-vars.name = mozilla-try-2024-03-26-zstd-sparse-revlog # bin-env-vars.hg.flavor = default branch-v2: 3.403171 ~~~~~ branch-v3 before: 6.234055 (+83.18%, +2.83) branch-v3 after: 3.819477 (+12.23%, +0.42) # bin-env-vars.hg.flavor = rust branch-v2: 3.454876 ~~~~~ branch-v3 before: 6.307813 (+82.58%, +2.85) branch-v3 after: 3.590284 (+3.92%, +0.14) ## data-env-vars.name = mozilla-try-2024-03-26-ds2-pnm # bin-env-vars.hg.flavor = rust branch-v2: 3.465435 ~~~~~ branch-v3 before: 5.176076 (+49.36%, +1.71) branch-v3 after: 3.633278 (+4.84%, +0.17)

File last commit:

r52756:f4733654 default
r52870:42a116f1 default
Show More
subrepoutil.py
545 lines | 17.8 KiB | text/x-python | PythonLexer
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 # subrepoutil.py - sub-repository operations and substate handling
#
Raphaël Gomès
contributor: change mentions of mpm to olivia...
r47575 # Copyright 2009-2010 Olivia Mackall <olivia@selenic.com>
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 #
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
Matt Harbison
typing: add `from __future__ import annotations` to most files...
r52756 from __future__ import annotations
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026
import os
import posixpath
import re
pytype: import typing directly...
r52178 import typing
from typing import (
Any,
Dict,
List,
Optional,
Set,
Tuple,
)
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026
from .i18n import _
from . import (
config,
error,
filemerge,
pathutil,
phases,
util,
)
urlutil: extract `url` related code from `util` into the new module...
r47669 from .utils import (
stringutil,
urlutil,
)
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026
pytype: import typing directly...
r52178 # keeps pyflakes happy
assert [
Any,
Dict,
List,
Optional,
Set,
Tuple,
]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 nullstate = (b'', b'', b'empty')
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026
pytype: import typing directly...
r52178 if typing.TYPE_CHECKING:
Matt Harbison
typing: add type annotations to the public methods of mercurial/subrepoutil.py...
r47389 from . import (
context,
localrepo,
match as matchmod,
scmutil,
subrepo,
ui as uimod,
)
pytype: import typing directly...
r52178 # keeps pyflakes happy
assert [
context,
localrepo,
matchmod,
scmutil,
subrepo,
uimod,
]
Substate = Dict[bytes, Tuple[bytes, bytes, bytes]]
Matt Harbison
typing: add type annotations to the public methods of mercurial/subrepoutil.py...
r47389
Augie Fackler
formatting: blacken the codebase...
r43346
pytype: move some type comment to proper annotation...
r52180 def state(ctx: "context.changectx", ui: "uimod.ui") -> Substate:
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 """return a state dict, mapping subrepo paths configured in .hgsub
to tuple: (source from .hgsub, revision from .hgsubstate, kind
(key in types dict))
"""
pytype: drop the last inline type comment...
r52182 p: config.config = config.config()
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 repo = ctx.repo()
Augie Fackler
formatting: blacken the codebase...
r43346
Martin von Zweigbergk
config: remove now-unused `abs` argument from `include` callback...
r45817 def read(f, sections=None, remap=None):
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 if f in ctx:
try:
data = ctx[f].data()
Manuel Jacob
py3: catch FileNotFoundError instead of checking errno == ENOENT
r50201 except FileNotFoundError:
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 # handle missing subrepo spec files as removed
Augie Fackler
formatting: blacken the codebase...
r43346 ui.warn(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"warning: subrepo spec file \'%s\' not found\n")
Augie Fackler
formatting: blacken the codebase...
r43346 % repo.pathto(f)
)
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 return
p.parse(f, data, sections, remap, read)
else:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"subrepo spec file \'%s\' not found") % repo.pathto(f)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'.hgsub' in ctx:
Martin von Zweigbergk
config: remove now-unused `abs` argument from `include` callback...
r45817 read(b'.hgsub')
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for path, src in ui.configitems(b'subpaths'):
p.set(b'subpaths', path, src, ui.configsource(b'subpaths', path))
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026
rev = {}
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'.hgsubstate' in ctx:
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for i, l in enumerate(ctx[b'.hgsubstate'].data().splitlines()):
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 l = l.lstrip()
if not l:
continue
try:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 revision, path = l.split(b" ", 1)
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 except ValueError:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"invalid subrepository revision "
b"specifier in \'%s\' line %d"
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 % (repo.pathto(b'.hgsubstate'), (i + 1))
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 rev[path] = revision
Manuel Jacob
py3: catch FileNotFoundError instead of checking errno == ENOENT
r50201 except FileNotFoundError:
pass
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026
pytype: move some type comment to proper annotation...
r52180 def remap(src: bytes) -> bytes:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 for pattern, repl in p.items(b'subpaths'):
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 # Turn r'C:\foo\bar' into r'C:\\foo\\bar' since re.sub
# does a string decode.
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 repl = stringutil.escapestr(repl)
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 # However, we still want to allow back references to go
# through unharmed, so we turn r'\\1' into r'\1'. Again,
# extra escapes are needed because re.sub string decodes.
repl = re.sub(br'\\\\([0-9]+)', br'\\\1', repl)
try:
Mads Kiilerich
subrepoutil: pass re.sub 'count' argument by name...
r52640 src = re.sub(pattern, repl, src, count=1)
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 except re.error as e:
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"bad subrepository pattern in %s: %s")
Augie Fackler
formatting: blacken the codebase...
r43346 % (
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 p.source(b'subpaths', pattern),
Augie Fackler
formatting: blacken the codebase...
r43346 stringutil.forcebytestr(e),
)
)
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 return src
state = {}
pytype: drop the last inline type comment...
r52182 for path, src in p.items(b''):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 kind = b'hg'
if src.startswith(b'['):
if b']' not in src:
raise error.Abort(_(b'missing ] in subrepository source'))
kind, src = src.split(b']', 1)
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 kind = kind[1:]
Augie Fackler
formatting: blacken the codebase...
r43346 src = src.lstrip() # strip any extra whitespace after ']'
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026
urlutil: extract `url` related code from `util` into the new module...
r47669 if not urlutil.url(src).isabs():
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 parent = _abssource(repo, abort=False)
if parent:
urlutil: extract `url` related code from `util` into the new module...
r47669 parent = urlutil.url(parent)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 parent.path = posixpath.join(parent.path or b'', src)
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 parent.path = posixpath.normpath(parent.path)
Pulkit Goyal
py3: use bytes() instead of str() on util.url()...
r37604 joined = bytes(parent)
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 # Remap the full joined path and use it if it changes,
# else remap the original source.
remapped = remap(joined)
if remapped == joined:
src = remap(src)
else:
src = remapped
src = remap(src)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 state[util.pconvert(path)] = (src.strip(), rev.get(path, b''), kind)
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026
return state
Augie Fackler
formatting: blacken the codebase...
r43346
pytype: move some type comment to proper annotation...
r52180 def writestate(repo: "localrepo.localrepository", state: Substate) -> None:
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 """rewrite .hgsubstate in (outer) repo with these subrepo states"""
Augie Fackler
formatting: blacken the codebase...
r43346 lines = [
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b'%s %s\n' % (state[s][1], s)
Augie Fackler
formatting: blacken the codebase...
r43346 for s in sorted(state)
if state[s][1] != nullstate[1]
]
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.wwrite(b'.hgsubstate', b''.join(lines), b'')
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026
Augie Fackler
formatting: blacken the codebase...
r43346
pytype: move some type comment to proper annotation...
r52180 def submerge(
repo: "localrepo.localrepository",
wctx: "context.workingctx",
mctx: "context.changectx",
actx: "context.changectx",
overwrite: bool,
labels: Optional[Any] = None,
) -> Substate:
Matt Harbison
typing: add type annotations to the public methods of mercurial/subrepoutil.py...
r47389 # TODO: type the `labels` arg
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 """delegated from merge.applyupdates: merging of .hgsubstate file
in working context, merging context and ancestor context"""
Augie Fackler
formatting: blacken the codebase...
r43346 if mctx == actx: # backwards?
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 actx = wctx.p1()
s1 = wctx.substate
s2 = mctx.substate
sa = actx.substate
sm = {}
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 repo.ui.debug(b"subrepo merge %s %s %s\n" % (wctx, mctx, actx))
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 def debug(s, msg, r=b""):
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 if r:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 r = b"%s:%s:%s" % r
repo.ui.debug(b" subrepo %s: %s %s\n" % (s, msg, r))
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026
promptssrc = filemerge.partextras(labels)
Gregory Szorc
global: bulk replace simple pycompat.iteritems(x) with x.items()...
r49768 for s, l in sorted(s1.items()):
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 a = sa.get(s, nullstate)
Augie Fackler
formatting: blacken the codebase...
r43346 ld = l # local state with possible dirty flag for compares
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 if wctx.sub(s).dirty():
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 ld = (l[0], l[1] + b"+")
Augie Fackler
formatting: blacken the codebase...
r43346 if wctx == actx: # overwrite
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 a = ld
prompts = promptssrc.copy()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 prompts[b's'] = s
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 if s in s2:
r = s2[s]
Augie Fackler
formatting: blacken the codebase...
r43346 if ld == r or r == a: # no change or local is newer
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 sm[s] = l
continue
Augie Fackler
formatting: blacken the codebase...
r43346 elif ld == a: # other side changed
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 debug(s, b"other changed, get", r)
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 wctx.sub(s).get(r, overwrite)
sm[s] = r
Augie Fackler
formatting: blacken the codebase...
r43346 elif ld[0] != r[0]: # sources differ
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 prompts[b'lo'] = l[0]
prompts[b'ro'] = r[0]
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 if repo.ui.promptchoice(
Augie Fackler
formatting: blacken the codebase...
r43346 _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b' subrepository sources for %(s)s differ\n'
b'you can use (l)ocal%(l)s source (%(lo)s)'
b' or (r)emote%(o)s source (%(ro)s).\n'
b'what do you want to do?'
b'$$ &Local $$ &Remote'
Augie Fackler
formatting: blacken the codebase...
r43346 )
% prompts,
0,
):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 debug(s, b"prompt changed, get", r)
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 wctx.sub(s).get(r, overwrite)
sm[s] = r
Augie Fackler
formatting: blacken the codebase...
r43346 elif ld[1] == a[1]: # local side is unchanged
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 debug(s, b"other side changed, get", r)
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 wctx.sub(s).get(r, overwrite)
sm[s] = r
else:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 debug(s, b"both sides changed")
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 srepo = wctx.sub(s)
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 prompts[b'sl'] = srepo.shortid(l[1])
prompts[b'sr'] = srepo.shortid(r[1])
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 option = repo.ui.promptchoice(
Augie Fackler
formatting: blacken the codebase...
r43346 _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b' subrepository %(s)s diverged (local revision: %(sl)s, '
b'remote revision: %(sr)s)\n'
b'you can (m)erge, keep (l)ocal%(l)s or keep '
b'(r)emote%(o)s.\n'
b'what do you want to do?'
b'$$ &Merge $$ &Local $$ &Remote'
Augie Fackler
formatting: blacken the codebase...
r43346 )
% prompts,
0,
)
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 if option == 0:
wctx.sub(s).merge(r)
sm[s] = l
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 debug(s, b"merge with", r)
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 elif option == 1:
sm[s] = l
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 debug(s, b"keep local subrepo revision", l)
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 else:
wctx.sub(s).get(r, overwrite)
sm[s] = r
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 debug(s, b"get remote subrepo revision", r)
Augie Fackler
formatting: blacken the codebase...
r43346 elif ld == a: # remote removed, local unchanged
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 debug(s, b"remote removed, remove")
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 wctx.sub(s).remove()
Augie Fackler
formatting: blacken the codebase...
r43346 elif a == nullstate: # not present in remote or ancestor
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 debug(s, b"local added, keep")
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 sm[s] = l
continue
else:
if repo.ui.promptchoice(
Augie Fackler
formatting: blacken the codebase...
r43346 _(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b' local%(l)s changed subrepository %(s)s'
b' which remote%(o)s removed\n'
b'use (c)hanged version or (d)elete?'
b'$$ &Changed $$ &Delete'
Augie Fackler
formatting: blacken the codebase...
r43346 )
% prompts,
0,
):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 debug(s, b"prompt remove")
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 wctx.sub(s).remove()
for s, r in sorted(s2.items()):
if s in s1:
continue
elif s not in sa:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 debug(s, b"remote added, get", r)
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 mctx.sub(s).get(r)
sm[s] = r
elif r != sa[s]:
prompts = promptssrc.copy()
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 prompts[b's'] = s
Augie Fackler
formatting: blacken the codebase...
r43346 if (
repo.ui.promptchoice(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b' remote%(o)s changed subrepository %(s)s'
b' which local%(l)s removed\n'
b'use (c)hanged version or (d)elete?'
b'$$ &Changed $$ &Delete'
Augie Fackler
formatting: blacken the codebase...
r43346 )
% prompts,
0,
)
== 0
):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 debug(s, b"prompt recreate", r)
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 mctx.sub(s).get(r)
sm[s] = r
# record merged .hgsubstate
writestate(repo, sm)
return sm
Augie Fackler
formatting: blacken the codebase...
r43346
pytype: move some type comment to proper annotation...
r52180 def precommit(
ui: "uimod.ui",
wctx: "context.workingcommitctx",
status: "scmutil.status",
match: "matchmod.basematcher",
force: bool = False,
) -> Tuple[List[bytes], Set[bytes], Substate]:
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 """Calculate .hgsubstate changes that should be applied before committing
Returns (subs, commitsubs, newstate) where
- subs: changed subrepos (including dirty ones)
- commitsubs: dirty subrepos which the caller needs to commit recursively
- newstate: new state dict which the caller must write to .hgsubstate
This also updates the given status argument.
"""
subs = []
commitsubs = set()
newstate = wctx.substate.copy()
# only manage subrepos and .hgsubstate if .hgsub is present
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'.hgsub' in wctx:
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 # we'll decide whether to track this ourselves, thanks
for c in status.modified, status.added, status.removed:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'.hgsubstate' in c:
c.remove(b'.hgsubstate')
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026
# compare current state to last committed state
# build new substate based on last committed state
oldstate = wctx.p1().substate
for s in sorted(newstate.keys()):
if not match(s):
# ignore working copy, use old state if present
if s in oldstate:
newstate[s] = oldstate[s]
continue
if not force:
raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b"commit with new subrepo %s excluded") % s
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 dirtyreason = wctx.sub(s).dirtyreason(True)
if dirtyreason:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not ui.configbool(b'ui', b'commitsubrepos'):
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
dirtyreason,
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 hint=_(b"use --subrepos for recursive commit"),
Augie Fackler
formatting: blacken the codebase...
r43346 )
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 subs.append(s)
commitsubs.add(s)
else:
bs = wctx.sub(s).basestate()
newstate[s] = (newstate[s][0], bs, newstate[s][2])
if oldstate.get(s, (None, None, None))[1] != bs:
subs.append(s)
# check for removed subrepos
for p in wctx.parents():
r = [s for s in p.substate if s not in newstate]
subs += [s for s in r if match(s)]
if subs:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if not match(b'.hgsub') and b'.hgsub' in (
Augie Fackler
formatting: blacken the codebase...
r43346 wctx.modified() + wctx.added()
):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b"can't commit subrepos without .hgsub"))
status.modified.insert(0, b'.hgsubstate')
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif b'.hgsub' in status.removed:
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 # clean up .hgsubstate when .hgsub is removed
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if b'.hgsubstate' in wctx and b'.hgsubstate' not in (
Augie Fackler
formatting: blacken the codebase...
r43346 status.modified + status.added + status.removed
):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 status.removed.insert(0, b'.hgsubstate')
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026
return subs, commitsubs, newstate
Augie Fackler
formatting: blacken the codebase...
r43346
subrepo: introduce a `repo_rel_or_abs_source` function...
r47691 def repo_rel_or_abs_source(repo):
"""return the source of this repo
Either absolute or relative the outermost repo"""
parent = repo
chunks = []
safehasattr: drop usage in favor of hasattr...
r51821 while hasattr(parent, '_subparent'):
subrepo: introduce a `repo_rel_or_abs_source` function...
r47691 source = urlutil.url(parent._subsource)
chunks.append(bytes(source))
if source.isabs():
break
parent = parent._subparent
chunks.reverse()
path = posixpath.join(*chunks)
Felipe Resende
subrepo: fix normalizing paths with scheme...
r52404 matchscheme = re.compile(b'^[a-zA-Z0-9+.\\-]+:').match
if matchscheme(path):
scheme, path = path.split(b':', 1)
if path.startswith(b'//'):
path = path[2:]
sep = b'//'
else:
sep = b''
normalized_path = scheme + b':' + sep + posixpath.normpath(path)
else:
normalized_path = posixpath.normpath(path)
return normalized_path
subrepo: introduce a `repo_rel_or_abs_source` function...
r47691
pytype: move some type comment to proper annotation...
r52180 def reporelpath(repo: "localrepo.localrepository") -> bytes:
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 """return path to this (sub)repo as seen from outermost repo"""
parent = repo
safehasattr: drop usage in favor of hasattr...
r51821 while hasattr(parent, '_subparent'):
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 parent = parent._subparent
Augie Fackler
formatting: blacken the codebase...
r43346 return repo.root[len(pathutil.normasprefix(parent.root)) :]
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026
pytype: move some type comment to proper annotation...
r52180 def subrelpath(sub: "subrepo.abstractsubrepo") -> bytes:
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 """return path to this subrepo as seen from outermost repo"""
return sub._relpath
Augie Fackler
formatting: blacken the codebase...
r43346
pytype: move some type comment to proper annotation...
r52180 def _abssource(
repo: "localrepo.localrepository",
push: bool = False,
abort: bool = True,
) -> Optional[bytes]:
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 """return pull/push path of repo - either based on parent repo .hgsub info
or on the top repo config. Abort or return None if no source found."""
safehasattr: drop usage in favor of hasattr...
r51821 if hasattr(repo, '_subparent'):
urlutil: extract `url` related code from `util` into the new module...
r47669 source = urlutil.url(repo._subsource)
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 if source.isabs():
return bytes(source)
source.path = posixpath.normpath(source.path)
parent = _abssource(repo._subparent, push, abort=False)
if parent:
urlutil: extract `url` related code from `util` into the new module...
r47669 parent = urlutil.url(util.pconvert(parent))
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 parent.path = posixpath.join(parent.path or b'', source.path)
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 parent.path = posixpath.normpath(parent.path)
return bytes(parent)
Augie Fackler
formatting: blacken the codebase...
r43346 else: # recursion reached top repo
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 path = None
safehasattr: drop usage in favor of hasattr...
r51821 if hasattr(repo, '_subtoppath'):
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 path = repo._subtoppath
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 elif push and repo.ui.config(b'paths', b'default-push'):
path = repo.ui.config(b'paths', b'default-push')
elif repo.ui.config(b'paths', b'default'):
path = repo.ui.config(b'paths', b'default')
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 elif repo.shared():
# chop off the .hg component to get the default path form. This has
# already run through vfsmod.vfs(..., realpath=True), so it doesn't
# have problems with 'C:'
return os.path.dirname(repo.sharedpath)
if path:
# issue5770: 'C:\' and 'C:' are not equivalent paths. The former is
# as expected: an absolute path to the root of the C: drive. The
# latter is a relative path, and works like so:
#
# C:\>cd C:\some\path
# C:\>D:
# D:\>python -c "import os; print os.path.abspath('C:')"
# C:\some\path
#
# D:\>python -c "import os; print os.path.abspath('C:relative')"
# C:\some\path\relative
urlutil: extract `url` related code from `util` into the new module...
r47669 if urlutil.hasdriveletter(path):
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 if len(path) == 2 or path[2:3] not in br'\/':
windows: use abspath in subrepoutil...
r48429 path = util.abspath(path)
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 return path
if abort:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise error.Abort(_(b"default path for subrepository not found"))
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026
Augie Fackler
formatting: blacken the codebase...
r43346
pytype: move some type comment to proper annotation...
r52180 def newcommitphase(ui: "uimod.ui", ctx: "context.changectx") -> int:
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 commitphase = phases.newcommitphase(ui)
substate = getattr(ctx, "substate", None)
if not substate:
return commitphase
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 check = ui.config(b'phases', b'checksubrepos')
if check not in (b'ignore', b'follow', b'abort'):
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 _(b'invalid phases.checksubrepos configuration: %s') % check
Augie Fackler
formatting: blacken the codebase...
r43346 )
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if check == b'ignore':
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 return commitphase
maxphase = phases.public
maxsub = None
for s in sorted(substate):
sub = ctx.sub(s)
subphase = sub.phase(substate[s][1])
if maxphase < subphase:
maxphase = subphase
maxsub = s
if commitphase < maxphase:
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if check == b'abort':
Augie Fackler
formatting: blacken the codebase...
r43346 raise error.Abort(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"can't commit in %s phase"
b" conflicting %s from subrepository %s"
Augie Fackler
formatting: blacken the codebase...
r43346 )
% (
phases.phasenames[commitphase],
phases.phasenames[maxphase],
maxsub,
)
)
ui.warn(
_(
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 b"warning: changes are committed in"
b" %s phase from subrepository %s\n"
Augie Fackler
formatting: blacken the codebase...
r43346 )
% (phases.phasenames[maxphase], maxsub)
)
Yuya Nishihara
subrepo: split non-core functions to new module...
r36026 return maxphase
return commitphase