...
 
Commits (63)
......@@ -3,101 +3,9 @@
mercurial/cext/manifest.c
mercurial/cext/osutil.c
# Vendored code that we should never format:
contrib/python-zstandard/c-ext/bufferutil.c
contrib/python-zstandard/c-ext/compressionchunker.c
contrib/python-zstandard/c-ext/compressiondict.c
contrib/python-zstandard/c-ext/compressionparams.c
contrib/python-zstandard/c-ext/compressionreader.c
contrib/python-zstandard/c-ext/compressionwriter.c
contrib/python-zstandard/c-ext/compressobj.c
contrib/python-zstandard/c-ext/compressor.c
contrib/python-zstandard/c-ext/compressoriterator.c
contrib/python-zstandard/c-ext/constants.c
contrib/python-zstandard/c-ext/decompressionreader.c
contrib/python-zstandard/c-ext/decompressionwriter.c
contrib/python-zstandard/c-ext/decompressobj.c
contrib/python-zstandard/c-ext/decompressor.c
contrib/python-zstandard/c-ext/decompressoriterator.c
contrib/python-zstandard/c-ext/frameparams.c
contrib/python-zstandard/c-ext/python-zstandard.h
contrib/python-zstandard/zstd.c
contrib/python-zstandard/zstd/common/bitstream.h
contrib/python-zstandard/zstd/common/compiler.h
contrib/python-zstandard/zstd/common/cpu.h
contrib/python-zstandard/zstd/common/debug.c
contrib/python-zstandard/zstd/common/debug.h
contrib/python-zstandard/zstd/common/entropy_common.c
contrib/python-zstandard/zstd/common/error_private.c
contrib/python-zstandard/zstd/common/error_private.h
contrib/python-zstandard/zstd/common/fse_decompress.c
contrib/python-zstandard/zstd/common/fse.h
contrib/python-zstandard/zstd/common/huf.h
contrib/python-zstandard/zstd/common/mem.h
contrib/python-zstandard/zstd/common/pool.c
contrib/python-zstandard/zstd/common/pool.h
contrib/python-zstandard/zstd/common/threading.c
contrib/python-zstandard/zstd/common/threading.h
contrib/python-zstandard/zstd/common/xxhash.c
contrib/python-zstandard/zstd/common/xxhash.h
contrib/python-zstandard/zstd/common/zstd_common.c
contrib/python-zstandard/zstd/common/zstd_errors.h
contrib/python-zstandard/zstd/common/zstd_internal.h
contrib/python-zstandard/zstd/compress/fse_compress.c
contrib/python-zstandard/zstd/compress/hist.c
contrib/python-zstandard/zstd/compress/hist.h
contrib/python-zstandard/zstd/compress/huf_compress.c
contrib/python-zstandard/zstd/compress/zstd_compress.c
contrib/python-zstandard/zstd/compress/zstd_compress_internal.h
contrib/python-zstandard/zstd/compress/zstd_compress_literals.c
contrib/python-zstandard/zstd/compress/zstd_compress_literals.h
contrib/python-zstandard/zstd/compress/zstd_compress_sequences.c
contrib/python-zstandard/zstd/compress/zstd_compress_sequences.h
contrib/python-zstandard/zstd/compress/zstd_cwksp.h
contrib/python-zstandard/zstd/compress/zstd_double_fast.c
contrib/python-zstandard/zstd/compress/zstd_double_fast.h
contrib/python-zstandard/zstd/compress/zstd_fast.c
contrib/python-zstandard/zstd/compress/zstd_fast.h
contrib/python-zstandard/zstd/compress/zstd_lazy.c
contrib/python-zstandard/zstd/compress/zstd_lazy.h
contrib/python-zstandard/zstd/compress/zstd_ldm.c
contrib/python-zstandard/zstd/compress/zstd_ldm.h
contrib/python-zstandard/zstd/compress/zstdmt_compress.c
contrib/python-zstandard/zstd/compress/zstdmt_compress.h
contrib/python-zstandard/zstd/compress/zstd_opt.c
contrib/python-zstandard/zstd/compress/zstd_opt.h
contrib/python-zstandard/zstd/decompress/huf_decompress.c
contrib/python-zstandard/zstd/decompress/zstd_ddict.c
contrib/python-zstandard/zstd/decompress/zstd_ddict.h
contrib/python-zstandard/zstd/decompress/zstd_decompress_block.c
contrib/python-zstandard/zstd/decompress/zstd_decompress_block.h
contrib/python-zstandard/zstd/decompress/zstd_decompress_internal.h
contrib/python-zstandard/zstd/decompress/zstd_decompress.c
contrib/python-zstandard/zstd/deprecated/zbuff_common.c
contrib/python-zstandard/zstd/deprecated/zbuff_compress.c
contrib/python-zstandard/zstd/deprecated/zbuff_decompress.c
contrib/python-zstandard/zstd/deprecated/zbuff.h
contrib/python-zstandard/zstd/dictBuilder/cover.c
contrib/python-zstandard/zstd/dictBuilder/cover.h
contrib/python-zstandard/zstd/dictBuilder/divsufsort.c
contrib/python-zstandard/zstd/dictBuilder/divsufsort.h
contrib/python-zstandard/zstd/dictBuilder/fastcover.c
contrib/python-zstandard/zstd/dictBuilder/zdict.c
contrib/python-zstandard/zstd/dictBuilder/zdict.h
contrib/python-zstandard/zstd/zstd.h
hgext/fsmonitor/pywatchman/bser.c
mercurial/thirdparty/xdiff/xdiff.h
mercurial/thirdparty/xdiff/xdiffi.c
mercurial/thirdparty/xdiff/xdiffi.h
mercurial/thirdparty/xdiff/xemit.c
mercurial/thirdparty/xdiff/xemit.h
mercurial/thirdparty/xdiff/xhistogram.c
mercurial/thirdparty/xdiff/xinclude.h
mercurial/thirdparty/xdiff/xmacros.h
mercurial/thirdparty/xdiff/xmerge.c
mercurial/thirdparty/xdiff/xpatience.c
mercurial/thirdparty/xdiff/xprepare.c
mercurial/thirdparty/xdiff/xprepare.h
mercurial/thirdparty/xdiff/xtypes.h
mercurial/thirdparty/xdiff/xutils.c
mercurial/thirdparty/xdiff/xutils.h
mercurial/thirdparty/zope/interface/_zope_interface_coptimizations.c
syntax: glob
contrib/python-zstandard/**.c
contrib/python-zstandard/**.h
hgext/fsmonitor/pywatchman/**.c
mercurial/thirdparty/**.c
mercurial/thirdparty/**.h
[fix]
clang-format:command = clang-format --style file -i
clang-format:pattern = (**.c or **.cc or **.h) and not "listfile:contrib/clang-format-ignorelist"
clang-format:command = clang-format --style file
clang-format:pattern = set:(**.c or **.cc or **.h) and not "include:contrib/clang-format-ignorelist"
rustfmt:command = rustfmt
rustfmt:pattern = set:**.rs
......
......@@ -10,7 +10,8 @@ RUN apt-get update && apt-get install -y \
dh-python \
less \
python \
python-all-dev \
python-docutils \
python3-all \
python3-all-dev \
python3-docutils \
unzip \
zip
......@@ -68,79 +68,42 @@ begin
for d := 0 to GetArrayLength(pathdir)-1 do begin
updatepath := true;
// Modify WinNT path
if UsingWinNT() = true then begin
// Get current path, split into an array
RegQueryStringValue(regroot, regpath, 'Path', oldpath);
oldpath := oldpath + ';';
i := 0;
while (Pos(';', oldpath) > 0) do begin
SetArrayLength(pathArr, i+1);
pathArr[i] := Copy(oldpath, 0, Pos(';', oldpath)-1);
oldpath := Copy(oldpath, Pos(';', oldpath)+1, Length(oldpath));
i := i + 1;
// Check if current directory matches app dir
if pathdir[d] = pathArr[i-1] then begin
// if uninstalling, remove dir from path
if IsUninstaller() = true then begin
continue;
// if installing, flag that dir already exists in path
end else begin
updatepath := false;
end;
end;
// Get current path, split into an array
RegQueryStringValue(regroot, regpath, 'Path', oldpath);
oldpath := oldpath + ';';
i := 0;
while (Pos(';', oldpath) > 0) do begin
SetArrayLength(pathArr, i+1);
pathArr[i] := Copy(oldpath, 0, Pos(';', oldpath)-1);
oldpath := Copy(oldpath, Pos(';', oldpath)+1, Length(oldpath));
i := i + 1;
// Add current directory to new path
if i = 1 then begin
newpath := pathArr[i-1];
// Check if current directory matches app dir
if pathdir[d] = pathArr[i-1] then begin
// if uninstalling, remove dir from path
if IsUninstaller() = true then begin
continue;
// if installing, flag that dir already exists in path
end else begin
newpath := newpath + ';' + pathArr[i-1];
updatepath := false;
end;
end;
// Append app dir to path if not already included
if (IsUninstaller() = false) AND (updatepath = true) then
newpath := newpath + ';' + pathdir[d];
// Write new path
RegWriteStringValue(regroot, regpath, 'Path', newpath);
// Modify Win9x path
end else begin
// Convert to shortened dirname
pathdir[d] := GetShortName(pathdir[d]);
// If autoexec.bat exists, check if app dir already exists in path
aExecFile := 'C:\AUTOEXEC.BAT';
if FileExists(aExecFile) then begin
LoadStringsFromFile(aExecFile, aExecArr);
for i := 0 to GetArrayLength(aExecArr)-1 do begin
if IsUninstaller() = false then begin
// If app dir already exists while installing, skip add
if (Pos(pathdir[d], aExecArr[i]) > 0) then
updatepath := false;
break;
end else begin
// If app dir exists and = what we originally set, then delete at uninstall
if aExecArr[i] = 'SET PATH=%PATH%;' + pathdir[d] then
aExecArr[i] := '';
end;
end;
end;
// If app dir not found, or autoexec.bat didn't exist, then (create and) append to current path
if (IsUninstaller() = false) AND (updatepath = true) then begin
SaveStringToFile(aExecFile, #13#10 + 'SET PATH=%PATH%;' + pathdir[d], True);
// If uninstalling, write the full autoexec out
// Add current directory to new path
if i = 1 then begin
newpath := pathArr[i-1];
end else begin
SaveStringsToFile(aExecFile, aExecArr, False);
newpath := newpath + ';' + pathArr[i-1];
end;
end;
// Append app dir to path if not already included
if (IsUninstaller() = false) AND (updatepath = true) then
newpath := newpath + ';' + pathdir[d];
// Write new path
RegWriteStringValue(regroot, regpath, 'Path', newpath);
end;
end;
......@@ -207,13 +170,6 @@ begin
end;
function NeedRestart(): Boolean;
var
taskname: String;
begin
taskname := ModPathName;
if IsTaskSelected(taskname) and not UsingWinNT() then begin
Result := True;
end else begin
Result := False;
end;
Result := False;
end;
......@@ -331,9 +331,9 @@ class fileheredocmatcher(embeddedmatcher):
)
self._fileres = [
# "cat > NAME << LIMIT" case
re.compile(r' \$ \s*cat' + namepat + heredoclimitpat),
re.compile(r' {2}\$ \s*cat' + namepat + heredoclimitpat),
# "cat << LIMIT > NAME" case
re.compile(r' \$ \s*cat' + heredoclimitpat + namepat),
re.compile(r' {2}\$ \s*cat' + heredoclimitpat + namepat),
]
def startsat(self, line):
......@@ -426,7 +426,7 @@ class pydoctestmatcher(embeddedmatcher):
"""
_prefix = ' >>> '
_prefixre = re.compile(r' (>>>|\.\.\.) ')
_prefixre = re.compile(r' {2}(>>>|\.\.\.) ')
# If a line matches against not _prefixre but _outputre, that line
# is "an expected output line" (= not a part of code fragment).
......@@ -436,7 +436,7 @@ class pydoctestmatcher(embeddedmatcher):
# run-tests.py. But "directive line inside inline python code"
# should be rejected by Mercurial reviewers. Therefore, this
# regexp does not matche against such directive lines.
_outputre = re.compile(r' $| [^$]')
_outputre = re.compile(r' {2}$| {2}[^$]')
def __init__(self):
super(pydoctestmatcher, self).__init__("doctest style python code")
......@@ -509,7 +509,7 @@ class pyheredocmatcher(embeddedmatcher):
_prefix = ' > '
_startre = re.compile(
r' \$ (\$PYTHON|"\$PYTHON"|python).*' + heredoclimitpat
r' {2}\$ (\$PYTHON|"\$PYTHON"|python).*' + heredoclimitpat
)
def __init__(self):
......
......@@ -144,9 +144,7 @@ class convert_cvs(converter_source):
if root.startswith(b":pserver:"):
root = root[9:]
m = re.match(
r'(?:(.*?)(?::(.*?))?@)?([^:\/]*)(?::(\d*))?(.*)', root
)
m = re.match(r'(?:(.*?)(?::(.*?))?@)?([^:/]*)(?::(\d*))?(.*)', root)
if m:
conntype = b"pserver"
user, passw, serv, port, root = m.groups()
......
......@@ -239,7 +239,7 @@ class monotone_source(common.converter_source, common.commandline):
# key "test@selenic.com"
# mtn >= 0.45:
# key [ff58a7ffb771907c4ff68995eada1c4da068d328]
certlist = re.split(br'\n\n key ["\[]', certlist)
certlist = re.split(br'\n\n {6}key ["\[]', certlist)
for e in certlist:
m = self.cert_re.match(e)
if m:
......
......@@ -643,7 +643,7 @@ class svn_source(converter_source):
if not re.match(
r'svn:[0-9a-f]{8,8}-[0-9a-f]{4,4}-'
r'[0-9a-f]{4,4}-[0-9a-f]{4,4}-[0-9a-f]'
r'{12,12}(.*)\@[0-9]+$',
r'{12,12}(.*)@[0-9]+$',
revstr,
):
raise error.Abort(
......@@ -1303,7 +1303,7 @@ class svn_sink(converter_sink, commandline):
self.wc = os.path.realpath(path)
self.run0(b'update')
else:
if not re.search(br'^(file|http|https|svn|svn\+ssh)\://', path):
if not re.search(br'^(file|http|https|svn|svn\+ssh)://', path):
path = os.path.realpath(path)
if os.path.isdir(os.path.dirname(path)):
if not os.path.exists(
......
......@@ -52,7 +52,7 @@ def pygmentize(web, field, fctx, tmpl):
filenameonly = web.configbool(b'web', b'highlightonlymatchfilename', False)
ctx = fctx.changectx()
m = ctx.matchfileset(expr)
m = ctx.matchfileset(fctx.repo().root, expr)
if m(fctx.path()):
highlight.pygmentize(
field, fctx, style, tmpl, guessfilenameonly=filenameonly
......
......@@ -68,6 +68,7 @@ import errno
import os
import re
import shutil
import sys
from mercurial.i18n import _
from mercurial.node import (
bin,
......@@ -4277,8 +4278,9 @@ def extsetup(ui):
dotable(commands.table)
thismodule = sys.modules["hgext.mq"]
for extname, extmodule in extensions.extensions():
if extmodule.__file__ != __file__:
if extmodule != thismodule:
dotable(getattr(extmodule, 'cmdtable', {}))
......
......@@ -798,7 +798,7 @@ class rebaseruntime(object):
shouldupdate = repo[b'.'].rev() in updateifonnodes
# Update away from the rebase if necessary
if shouldupdate or needupdate(repo, self.state):
if shouldupdate:
mergemod.update(
repo, self.originalwd, branchmerge=False, force=True
)
......@@ -1056,10 +1056,9 @@ def rebase(ui, repo, **opts):
b'changesets'
),
)
if needupdate(repo, rbsrt.state):
# update to the current working revision
# to clear interrupted merge
hg.updaterepo(repo, rbsrt.originalwd, overwrite=True)
# update to the current working revision
# to clear interrupted merge
hg.updaterepo(repo, rbsrt.originalwd, overwrite=True)
rbsrt._finishrebase()
return 0
elif inmemory:
......@@ -1430,13 +1429,13 @@ def commitmemorynode(repo, p1, p2, wctx, editor, extra, user, date, commitmsg):
# By convention, ``extra['branch']`` (set by extrafn) clobbers
# ``branch`` (used when passing ``--keepbranches``).
branch = repo[p1].branch()
branch = None
if b'branch' in extra:
branch = extra[b'branch']
wctx.setparents(repo[p1].node(), repo[p2].node())
memctx = wctx.tomemctx(
commitmsg,
parents=(p1, p2),
date=date,
extra=extra,
user=user,
......@@ -1924,25 +1923,6 @@ def clearstatus(repo):
repo.vfs.unlinkpath(b"rebasestate", ignoremissing=True)
def needupdate(repo, state):
'''check whether we should `update --clean` away from a merge, or if
somehow the working dir got forcibly updated, e.g. by older hg'''
parents = [p.rev() for p in repo[None].parents()]
# Are we in a merge state at all?
if len(parents) < 2:
return False
# We should be standing on the first as-of-yet unrebased commit.
firstunrebased = min(
[old for old, new in pycompat.iteritems(state) if new == nullrev]
)
if firstunrebased in parents:
return True
return False
def sortsource(destmap):
"""yield source revisions in an order that we only rebase things once
......
......@@ -63,7 +63,7 @@ command = registrar.command(cmdtable)
# leave the attribute unspecified.
testedwith = b'ships-with-hg-core'
_partre = re.compile(br'\{(\d+)\}')
_partre = re.compile(br'{(\d+)\}')
class ShortRepository(object):
......
......@@ -39,6 +39,8 @@ typedef struct {
typedef struct {
int (*index_parents)(PyObject *, int, int *);
Py_ssize_t (*index_length)(const indexObject *);
const char *(*index_node)(indexObject *, Py_ssize_t);
} Revlog_CAPI;
/*
......
......@@ -167,10 +167,10 @@ class appender(object):
def _divertopener(opener, target):
"""build an opener that writes in 'target.a' instead of 'target'"""
def _divert(name, mode=b'r', checkambig=False):
def _divert(name, mode=b'r', checkambig=False, **kwargs):
if name != target:
return opener(name, mode)
return opener(name + b".a", mode)
return opener(name, mode, **kwargs)
return opener(name + b".a", mode, **kwargs)
return _divert
......@@ -178,9 +178,10 @@ def _divertopener(opener, target):
def _delayopener(opener, target, buf):
"""build an opener that stores chunks in 'buf' instead of 'target'"""
def _delay(name, mode=b'r', checkambig=False):
def _delay(name, mode=b'r', checkambig=False, **kwargs):
if name != target:
return opener(name, mode)
return opener(name, mode, **kwargs)
assert not kwargs
return appender(opener, name, mode, buf)
return _delay
......
......@@ -2429,12 +2429,16 @@ def walkchangerevs(repo, match, opts, prepare):
def fns_generator():
if allfiles:
fiter = iter(ctx)
else:
fiter = ctx.files()
for f in fiter:
if match(f):
def bad(f, msg):
pass
for f in ctx.matches(matchmod.badmatch(match, bad)):
yield f
else:
for f in ctx.files():
if match(f):
yield f
fns = fns_generator()
prepare(ctx, fns)
......
......@@ -2223,6 +2223,8 @@ def config(ui, repo, *values, **opts):
for t, f in rcutil.rccomponents():
if t == b'path':
ui.debug(b'read config from: %s\n' % f)
elif t == b'resource':
ui.debug(b'read config from: resource:%s.%s\n' % (f[0], f[1]))
elif t == b'items':
# Don't print anything for 'items'.
pass
......@@ -3077,17 +3079,12 @@ def _dograft(ui, repo, *revs, **opts):
# already, they'd have been in the graftstate.
if not (cont or opts.get(b'force')) and basectx is None:
# check for ancestors of dest branch
crev = repo[b'.'].rev()
ancestors = repo.changelog.ancestors([crev], inclusive=True)
# XXX make this lazy in the future
# don't mutate while iterating, create a copy
for rev in list(revs):
if rev in ancestors:
ui.warn(
_(b'skipping ancestor revision %d:%s\n') % (rev, repo[rev])
)
# XXX remove on list is slow
revs.remove(rev)
ancestors = repo.revs(b'%ld & (::.)', revs)
for rev in ancestors:
ui.warn(_(b'skipping ancestor revision %d:%s\n') % (rev, repo[rev]))
revs = [r for r in revs if r not in ancestors]
if not revs:
return -1
......@@ -3104,7 +3101,7 @@ def _dograft(ui, repo, *revs, **opts):
# The only changesets we can be sure doesn't contain grafts of any
# revs, are the ones that are common ancestors of *all* revs:
for rev in repo.revs(b'only(%d,ancestor(%ld))', crev, revs):
for rev in repo.revs(b'only(%d,ancestor(%ld))', repo[b'.'].rev(), revs):
ctx = repo[rev]
n = ctx.extra().get(b'source')
if n in ids:
......
......@@ -657,6 +657,9 @@ coreconfigitem(
b'experimental', b'revisions.disambiguatewithin', default=None,
)
coreconfigitem(
b'experimental', b'rust.index', default=False,
)
coreconfigitem(
b'experimental', b'server.filesdata.recommended-batch-size', default=50000,
)
coreconfigitem(
......
......@@ -200,8 +200,8 @@ class basectx(object):
def mutable(self):
return self.phase() > phases.public
def matchfileset(self, expr, badfn=None):
return fileset.match(self, expr, badfn=badfn)
def matchfileset(self, cwd, expr, badfn=None):
return fileset.match(self, cwd, expr, badfn=badfn)
def obsolete(self):
"""True if the changeset is obsolete"""
......@@ -328,11 +328,14 @@ class basectx(object):
default=b'glob',
listsubrepos=False,
badfn=None,
cwd=None,
):
r = self._repo
if not cwd:
cwd = r.getcwd()
return matchmod.match(
r.root,
r.getcwd(),
cwd,
pats,
include,
exclude,
......@@ -1525,6 +1528,23 @@ class workingctx(committablectx):
for n in p
]
def setparents(self, p1node, p2node=nullid):
dirstate = self._repo.dirstate
with dirstate.parentchange():
copies = dirstate.setparents(p1node, p2node)
pctx = self._repo[p1node]
if copies:
# Adjust copy records, the dirstate cannot do it, it
# requires access to parents manifests. Preserve them
# only for entries added to first parent.
for f in copies:
if f not in pctx and copies[f] in pctx:
dirstate.copy(copies[f], f)
if p2node == nullid:
for f, s in sorted(dirstate.copies().items()):
if f not in pctx and s not in pctx:
dirstate.copy(None, f)
def _fileinfo(self, path):
# populate __dict__['_manifest'] as workingctx has no _manifestdelta
self._manifest
......@@ -1694,15 +1714,18 @@ class workingctx(committablectx):
default=b'glob',
listsubrepos=False,
badfn=None,
cwd=None,
):
r = self._repo
if not cwd:
cwd = r.getcwd()
# Only a case insensitive filesystem needs magic to translate user input
# to actual case in the filesystem.
icasefs = not util.fscasesensitive(r.root)
return matchmod.match(
r.root,
r.getcwd(),
cwd,
pats,
include,
exclude,
......@@ -2155,6 +2178,10 @@ class overlayworkingctx(committablectx):
# ``overlayworkingctx`` (e.g. with --collapse).
util.clearcachedproperty(self, b'_manifest')
def setparents(self, p1node, p2node=nullid):
assert p1node == self._wrappedctx.node()
self._parents = [self._wrappedctx, self._repo.unfiltered()[p2node]]
def data(self, path):
if self.isdirty(path):
if self._cache[path][b'exists']:
......@@ -2218,7 +2245,7 @@ class overlayworkingctx(committablectx):
]
def p1copies(self):
copies = self._repo._wrappedctx.p1copies().copy()
copies = {}
narrowmatch = self._repo.narrowmatch()
for f in self._cache.keys():
if not narrowmatch(f):
......@@ -2230,7 +2257,7 @@ class overlayworkingctx(committablectx):
return copies
def p2copies(self):
copies = self._repo._wrappedctx.p2copies().copy()
copies = {}
narrowmatch = self._repo.narrowmatch()
for f in self._cache.keys():
if not narrowmatch(f):
......@@ -2409,9 +2436,9 @@ class overlayworkingctx(committablectx):
``text`` is the commit message.
``parents`` (optional) are rev numbers.
"""
# Default parents to the wrapped contexts' if not passed.
# Default parents to the wrapped context if not passed.
if parents is None:
parents = self._wrappedctx.parents()
parents = self.parents()
if len(parents) == 1:
parents = (parents[0], None)
......@@ -2439,6 +2466,9 @@ class overlayworkingctx(committablectx):
# necessary for memctx to register a deletion.
return None
if branch is None:
branch = self._wrappedctx.branch()
return memctx(
self._repo,
parents,
......@@ -2732,7 +2762,7 @@ class memctx(committablectx):
date=None,
extra=None,
branch=None,
editor=False,
editor=None,
):
super(memctx, self).__init__(
repo, text, user, date, extra, branch=branch
......@@ -2893,7 +2923,7 @@ class metadataonlyctx(committablectx):
user=None,
date=None,
extra=None,
editor=False,
editor=None,
):
if text is None:
text = originalctx.description()
......
......@@ -1171,7 +1171,7 @@ def debugfileset(ui, repo, expr, **opts):
files.update(ctx.files())
files.update(ctx.substate)
m = ctx.matchfileset(expr)
m = ctx.matchfileset(repo.getcwd(), expr)
if opts[b'show_matcher'] or (opts[b'show_matcher'] is None and ui.verbose):
ui.writenoi18n(b'* matcher:\n', stringutil.prettyrepr(m), b'\n')
for f in sorted(files):
......
......@@ -15,7 +15,6 @@ import pdb
import re
import signal
import sys
import time
import traceback
......@@ -1040,8 +1039,8 @@ def _dispatch(req):
def get_times():
t = os.times()
if t[4] == 0.0:
# Windows leaves this as zero, so use time.clock()
t = (t[0], t[1], t[2], t[3], time.clock())
# Windows leaves this as zero, so use time.perf_counter()
t = (t[0], t[1], t[2], t[3], util.timer())
return t
s = get_times()
......
......@@ -520,29 +520,30 @@ methods = {
class matchctx(object):
def __init__(self, basectx, ctx, badfn=None):
def __init__(self, basectx, ctx, cwd, badfn=None):
self._basectx = basectx
self.ctx = ctx
self._badfn = badfn
self._match = None
self._status = None
self.cwd = cwd
def narrowed(self, match):
"""Create matchctx for a sub-tree narrowed by the given matcher"""
mctx = matchctx(self._basectx, self.ctx, self._badfn)
mctx = matchctx(self._basectx, self.ctx, self.cwd, self._badfn)
mctx._match = match
# leave wider status which we don't have to care
mctx._status = self._status
return mctx
def switch(self, basectx, ctx):
mctx = matchctx(basectx, ctx, self._badfn)
mctx = matchctx(basectx, ctx, self.cwd, self._badfn)
mctx._match = self._match
return mctx
def withstatus(self, keys):
"""Create matchctx which has precomputed status specified by the keys"""
mctx = matchctx(self._basectx, self.ctx, self._badfn)
mctx = matchctx(self._basectx, self.ctx, self.cwd, self._badfn)
mctx._match = self._match
mctx._buildstatus(keys)
return mctx
......@@ -560,7 +561,7 @@ class matchctx(object):
return self._status
def matcher(self, patterns):
return self.ctx.match(patterns, badfn=self._badfn)
return self.ctx.match(patterns, badfn=self._badfn, cwd=self.cwd)
def predicate(self, predfn, predrepr=None, cache=False):
"""Create a matcher to select files by predfn(filename)"""
......@@ -617,12 +618,12 @@ class matchctx(object):
return matchmod.never(badfn=self._badfn)
def match(ctx, expr, badfn=None):
def match(ctx, cwd, expr, badfn=None):
"""Create a matcher for a single fileset expression"""
tree = filesetlang.parse(expr)
tree = filesetlang.analyze(tree)
tree = filesetlang.optimize(tree)
mctx = matchctx(ctx.p1(), ctx, badfn=badfn)
mctx = matchctx(ctx.p1(), ctx, cwd, badfn=badfn)
return getmatch(mctx, tree)
......
......@@ -313,9 +313,9 @@ def loaddoc(topic, subdir=None):
"""Return a delayed loader for help/topic.txt."""
def loader(ui):
package = b'helptext'
package = b'mercurial.helptext'
if subdir:
package = b'helptext' + b'.' + subdir
package += b'.' + subdir
with resourceutil.open_resource(package, topic + b'.txt') as fp:
doc = gettext(fp.read())
for rewriter in helphooks.get(topic, []):
......
......@@ -13,7 +13,7 @@ from __future__ import absolute_import, print_function
import re
tspecials = re.compile(br'[ \(\)<>@,;:\\"/\[\]\?=]')
tspecials = re.compile(br'[ ()<>@,;:\\"/\[\]?=]')
def _formatparam(param, value=None, quote=1):
......
......@@ -927,6 +927,9 @@ def resolverevlogstorevfsoptions(ui, requirements, features):
if repository.NARROW_REQUIREMENT in requirements:
options[b'enableellipsis'] = True
if ui.configbool(b'experimental', b'rust.index'):
options[b'rust.index'] = True
return options
......@@ -1883,20 +1886,7 @@ class localrepository(object):
return self.vfs.reljoin(self.root, f, *insidef)
def setparents(self, p1, p2=nullid):
with self.dirstate.parentchange():
copies = self.dirstate.setparents(p1, p2)
pctx = self[p1]
if copies:
# Adjust copy records, the dirstate cannot do it, it
# requires access to parents manifests. Preserve them
# only for entries added to first parent.
for f in copies:
if f not in pctx and copies[f] in pctx:
self.dirstate.copy(copies[f], f)
if p2 == nullid:
for f, s in sorted(self.dirstate.copies().items()):
if f not in pctx and s not in pctx:
self.dirstate.copy(None, f)
self[None].setparents(p1, p2)
def filectx(self, path, changeid=None, fileid=None, changectx=None):
"""changeid must be a changeset revision, if specified.
......@@ -2842,7 +2832,7 @@ class localrepository(object):
date=None,
match=None,
force=False,
editor=False,
editor=None,
extra=None,
):
"""Add a new revision to current repository.
......
......@@ -57,7 +57,7 @@ def _rematcher(regex):
return m.match
def _expandsets(kindpats, ctx=None, listsubrepos=False, badfn=None):
def _expandsets(cwd, kindpats, ctx=None, listsubrepos=False, badfn=None):
'''Returns the kindpats list with the 'set' patterns expanded to matchers'''
matchers = []
other = []
......@@ -68,11 +68,11 @@ def _expandsets(kindpats, ctx=None, listsubrepos=False, badfn=None):
raise error.ProgrammingError(
b"fileset expression with no context"
)
matchers.append(ctx.matchfileset(pat, badfn=badfn))
matchers.append(ctx.matchfileset(cwd, pat, badfn=badfn))
if listsubrepos:
for subpath in ctx.substate:
sm = ctx.sub(subpath).matchfileset(pat, badfn=badfn)
sm = ctx.sub(subpath).matchfileset(cwd, pat, badfn=badfn)
pm = prefixdirmatcher(subpath, sm, badfn=badfn)
matchers.append(pm)
......@@ -117,11 +117,11 @@ def _kindpatsalwaysmatch(kindpats):
def _buildkindpatsmatcher(
matchercls, root, kindpats, ctx=None, listsubrepos=False, badfn=None
matchercls, root, cwd, kindpats, ctx=None, listsubrepos=False, badfn=None,
):
matchers = []
fms, kindpats = _expandsets(
kindpats, ctx=ctx, listsubrepos=listsubrepos, badfn=badfn
cwd, kindpats, ctx=ctx, listsubrepos=listsubrepos, badfn=badfn,
)
if kindpats:
m = matchercls(root, kindpats, badfn=badfn)
......@@ -261,6 +261,7 @@ def match(
m = _buildkindpatsmatcher(
patternmatcher,
root,
cwd,
kindpats,
ctx=ctx,
listsubrepos=listsubrepos,
......@@ -276,6 +277,7 @@ def match(
im = _buildkindpatsmatcher(
includematcher,
root,
cwd,
kindpats,
ctx=ctx,
listsubrepos=listsubrepos,
......@@ -287,6 +289,7 @@ def match(
em = _buildkindpatsmatcher(
includematcher,
root,
cwd,
kindpats,
ctx=ctx,
listsubrepos=listsubrepos,
......
......@@ -13,10 +13,11 @@ import zlib
from ..node import nullid, nullrev
from .. import (
pycompat,
revlogutils,
util,
)
from ..revlogutils import nodemap as nodemaputil
stringio = pycompat.bytesio
......@@ -55,7 +56,7 @@ class BaseIndexObject(object):
@util.propertycache
def _nodemap(self):
nodemap = revlogutils.NodeMap({nullid: nullrev})
nodemap = nodemaputil.NodeMap({nullid: nullrev})
for r in range(0, len(self)):
n = self[r][7]
nodemap[n] = r
......
......@@ -61,10 +61,15 @@ def envrcitems(env=None):
return result
def defaultrcpath():
'''return rc paths in defaultrc'''
defaultpath = os.path.join(resourceutil.datapath, b'defaultrc')
return _expandrcpath(defaultpath)
def default_rc_resources():
"""return rc resource IDs in defaultrc"""
rsrcs = resourceutil.contents(b'mercurial.defaultrc')
return [
(b'mercurial.defaultrc', r)
for r in sorted(rsrcs)
if resourceutil.is_resource(b'mercurial.defaultrc', r)
and r.endswith(b'.rc')
]
def rccomponents():
......@@ -75,9 +80,10 @@ def rccomponents():
if a directory is provided, *.rc files under it will be used.
type could be either 'path' or 'items', if type is 'path', obj is a string,
and is the config file path. if type is 'items', obj is a list of (section,
name, value, source) that should fill the config directly.
type could be either 'path', 'items' or 'resource'. If type is 'path',
obj is a string, and is the config file path. if type is 'items', obj is a
list of (section, name, value, source) that should fill the config directly.
If type is 'resource', obj is a tuple of (package name, resource name).
'''
envrc = (b'items', envrcitems())
......@@ -90,10 +96,12 @@ def rccomponents():
continue
_rccomponents.extend((b'path', p) for p in _expandrcpath(p))
else:
_rccomponents = [(b'resource', r) for r in default_rc_resources()]
normpaths = lambda paths: [
(b'path', os.path.normpath(p)) for p in paths
]
_rccomponents = normpaths(defaultrcpath() + systemrcpath())
_rccomponents.extend(normpaths(systemrcpath()))
_rccomponents.append(envrc)
_rccomponents.extend(normpaths(userrcpath()))
return _rccomponents
......
......@@ -65,7 +65,6 @@ from . import (
mdiff,
policy,
pycompat,
revlogutils,
templatefilters,
util,
)
......@@ -76,6 +75,7 @@ from .interfaces import (
from .revlogutils import (
deltas as deltautil,
flagutil,
nodemap as nodemaputil,
sidedata as sidedatautil,
)
from .utils import (
......@@ -106,6 +106,7 @@ REVIDX_RAWTEXT_CHANGING_FLAGS
parsers = policy.importmod('parsers')
rustancestor = policy.importrust('ancestor')
rustdagop = policy.importrust('dagop')
rustrevlog = policy.importrust('revlog')
# Aliased for performance.
_zlibdecompress = zlib.decompress
......@@ -223,7 +224,7 @@ class revlogoldindex(list):
@util.propertycache
def _nodemap(self):
nodemap = revlogutils.NodeMap({nullid: nullrev})
nodemap = nodemaputil.NodeMap({nullid: nullrev})
for r in range(0, len(self)):
n = self[r][7]
nodemap[n] = r
......@@ -272,7 +273,7 @@ class revlogoldio(object):
def parseindex(self, data, inline):
s = self.size
index = []
nodemap = revlogutils.NodeMap({nullid: nullrev})
nodemap = nodemaputil.NodeMap({nullid: nullrev})
n = off = 0
l = len(data)
while off + s <= l:
......@@ -351,6 +352,12 @@ class revlogio(object):
return p
class rustrevlogio(revlogio):
def parseindex(self, data, inline):
index, cache = super(rustrevlogio, self).parseindex(data, inline)
return rustrevlog.MixedIndex(index), cache
class revlog(object):
"""
the underlying revision storage object
......@@ -587,6 +594,8 @@ class revlog(object):
self._io = revlogio()
if self.version == REVLOGV0:
self._io = revlogoldio()
elif rustrevlog is not None and self.opener.options.get(b'rust.index'):
self._io = rustrevlogio()
try:
d = self._io.parseindex(indexdata, self._inline)
except (ValueError, IndexError):
......
......@@ -6,9 +6,3 @@
# GNU General Public License version 2 or any later version.
from __future__ import absolute_import
from .. import error
class NodeMap(dict):
def __missing__(self, x):
raise error.RevlogError(b'unknown node: %s' % x)
# nodemap.py - nodemap related code and utilities
#
# Copyright 2019 Pierre-Yves David <pierre-yves.david@octobus.net>
# Copyright 2019 George Racinet <georges.racinet@octobus.net>
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
from __future__ import absolute_import
from .. import error
class NodeMap(dict):
def __missing__(self, x):
raise error.RevlogError(b'unknown node: %s' % x)
......@@ -58,6 +58,7 @@ else:
from . import scmposix as scmplatform
parsers = policy.importmod('parsers')
rustrevlog = policy.importrust('revlog')
termsize = scmplatform.termsize
......@@ -548,7 +549,11 @@ def shortesthexnodeidprefix(repo, node, minlength=1, cache=None):
if util.safehasattr(parsers, 'nodetree'):
# The CExt is the only implementation to provide a nodetree
# class so far.
nodetree = parsers.nodetree(cl.index, len(revs))
index = cl.index
if util.safehasattr(index, 'get_cindex'):
# the rust wrapped need to give access to its internal index
index = index.get_cindex()
nodetree = parsers.nodetree(index, len(revs))
for r in revs:
nodetree.insert(r)
if cache is not None:
......@@ -1426,8 +1431,8 @@ def movedirstate(repo, newctx, match=None):
"""
oldctx = repo[b'.']
ds = repo.dirstate
ds.setparents(newctx.node(), nullid)
copies = dict(ds.copies())
ds.setparents(newctx.node(), nullid)
s = newctx.status(oldctx, match=match)
for f in s.modified:
if ds[f] == b'r':
......
......@@ -355,7 +355,7 @@ class abstractsubrepo(object):
"""return file flags"""
return b''
def matchfileset(self, expr, badfn=None):
def matchfileset(self, cwd, expr, badfn=None):
"""Resolve the fileset expression for this repo"""
return matchmod.never(badfn=badfn)
......@@ -896,20 +896,20 @@ class hgsubrepo(abstractsubrepo):
return cmdutil.files(ui, ctx, m, uipathfn, fm, fmt, subrepos)
@annotatesubrepoerror
def matchfileset(self, expr, badfn=None):
def matchfileset(self, cwd, expr, badfn=None):
if self._ctx.rev() is None:
ctx = self._repo[None]
else:
rev = self._state[1]
ctx = self._repo[rev]
matchers = [ctx.matchfileset(expr, badfn=badfn)]
matchers = [ctx.matchfileset(cwd, expr, badfn=badfn)]
for subpath in ctx.substate:
sub = ctx.sub(subpath)
try:
sm = sub.matchfileset(expr, badfn=badfn)
sm = sub.matchfileset(cwd, expr, badfn=badfn)
pm = matchmod.prefixdirmatcher(subpath, sm, badfn=badfn)
matchers.append(pm)
except error.LookupError:
......
......@@ -964,7 +964,7 @@ class ifiledatatests(basetestcase):
with self.assertRaises(error.StorageError):
f.rawdata(node1)
def testbadnoderevisionraw(self):
def testbadnoderevision(self):
# Like above except we test read() first to isolate revision caching
# behavior.
f = self._makefilefn()
......
......@@ -456,6 +456,12 @@ class transaction(util.transactional):
return self._anypending
@active
def hasfinalize(self, category):
"""check is a callback already exist for a category
"""
return category in self._finalizecallback
@active
def addfinalize(self, category, callback):
"""add a callback to be called when the transaction is closed
......
......@@ -45,6 +45,7 @@ from . import (
from .utils import (
dateutil,
procutil,
resourceutil,
stringutil,
)
......@@ -307,6 +308,8 @@ class ui(object):
for t, f in rcutil.rccomponents():
if t == b'path':
u.readconfig(f, trust=True)
elif t == b'resource':
u.read_resource_config(f, trust=True)
elif t == b'items':
sections = set()
for section, name, value, source in f:
......@@ -424,6 +427,20 @@ class ui(object):
)
return False
def read_resource_config(
self, name, root=None, trust=False, sections=None, remap=None
):
try:
fp = resourceutil.open_resource(name[0], name[1])
except IOError:
if not sections: # ignore unless we were looking for something
return
raise
self._readconfig(
b'resource:%s.%s' % name, fp, root, trust, sections, remap
)
def readconfig(
self, filename, root=None, trust=False, sections=None, remap=None
):
......@@ -434,6 +451,11 @@ class ui(object):
return
raise
self._readconfig(filename, fp, root, trust, sections, remap)
def _readconfig(
self, filename, fp, root=None, trust=False, sections=None, remap=None
):
with fp:
cfg = config.config()
trusted = sections or trust or self._trusted(fp, filename)
......@@ -1626,7 +1648,7 @@ class ui(object):
# prompt to start parsing. Sadly, we also can't rely on
# choices containing spaces, ASCII, or basically anything
# except an ampersand followed by a character.
m = re.match(br'(?s)(.+?)\$\$([^\$]*&[^ \$].*)', prompt)
m = re.match(br'(?s)(.+?)\$\$([^$]*&[^ $].*)', prompt)
msg = m.group(1)
choices = [p.strip(b' ') for p in m.group(2).split(b'$$')]
......
......@@ -415,10 +415,16 @@ class bufferedinputpipe(object):
return data
def mmapread(fp):
def mmapread(fp, size=None):
if size == 0:
# size of 0 to mmap.mmap() means "all data"
# rather than "zero bytes", so special case that.
return b''
elif size is None:
size = 0
try:
fd = getattr(fp, 'fileno', lambda: fp)()
return mmap.mmap(fd, 0, access=mmap.ACCESS_READ)
return mmap.mmap(fd, size, access=mmap.ACCESS_READ)
except ValueError: