--- a/.hgsigs Thu Mar 09 13:02:13 2023 -0600
+++ b/.hgsigs Mon Mar 20 23:16:14 2023 +0100
@@ -239,3 +239,4 @@
c890d8b8bc59b18e5febf60caada629df5356ee2 0 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
--- a/.hgtags Thu Mar 09 13:02:13 2023 -0600
+++ b/.hgtags Mon Mar 20 23:16:14 2023 +0100
@@ -255,3 +255,4 @@
c890d8b8bc59b18e5febf60caada629df5356ee2 6.3.1
59466b13a3ae0e29a5d4f485393e516cfbb057d0 6.3.2
8830004967ad865ead89c28a410405a6e71e0796 6.3.3
+05de4896508e8ec387b33eb30d8aab78d1c8e9e4 6.4rc0
--- a/contrib/import-checker.py Thu Mar 09 13:02:13 2023 -0600
+++ b/contrib/import-checker.py Mon Mar 20 23:16:14 2023 +0100
@@ -232,6 +232,7 @@
yield 'importlib.abc' # python3 only
yield 'importlib.machinery' # python3 only
yield 'importlib.util' # python3 only
+ yield 'packaging.version'
for m in 'fcntl', 'grp', 'pwd', 'termios': # Unix only
yield m
for m in 'cPickle', 'datetime': # in Python (not C) on PyPy
--- a/hgext/histedit.py Thu Mar 09 13:02:13 2023 -0600
+++ b/hgext/histedit.py Mon Mar 20 23:16:14 2023 +0100
@@ -1427,11 +1427,11 @@
for y in range(0, length):
line = output[y]
if diffcolors:
- if line and line[0] == b'+':
+ if line.startswith(b'+'):
win.addstr(
y, 0, line, curses.color_pair(COLOR_DIFF_ADD_LINE)
)
- elif line and line[0] == b'-':
+ elif line.startswith(b'-'):
win.addstr(
y, 0, line, curses.color_pair(COLOR_DIFF_DEL_LINE)
)
--- a/hgext/narrow/narrowbundle2.py Thu Mar 09 13:02:13 2023 -0600
+++ b/hgext/narrow/narrowbundle2.py Mon Mar 20 23:16:14 2023 +0100
@@ -6,7 +6,6 @@
# GNU General Public License version 2 or any later version.
-import errno
import struct
from mercurial.i18n import _
@@ -20,10 +19,10 @@
repair,
requirements,
scmutil,
+ transaction,
util,
wireprototypes,
)
-from mercurial.utils import stringutil
_NARROWACL_SECTION = b'narrowacl'
_CHANGESPECPART = b'narrow:changespec'
@@ -295,16 +294,7 @@
finally:
f.close()
- # remove undo files
- for undovfs, undofile in repo.undofiles():
- try:
- undovfs.unlink(undofile)
- except OSError as e:
- if e.errno != errno.ENOENT:
- ui.warn(
- _(b'error removing %s: %s\n')
- % (undovfs.join(undofile), stringutil.forcebytestr(e))
- )
+ transaction.cleanup_undo_files(repo.ui.warn, repo.vfs_map)
# Remove partial backup only if there were no exceptions
op._widen_uninterr.__exit__(None, None, None)
--- a/mercurial/cext/dirs.c Thu Mar 09 13:02:13 2023 -0600
+++ b/mercurial/cext/dirs.c Mon Mar 20 23:16:14 2023 +0100
@@ -13,7 +13,11 @@
#include "util.h"
+#if PY_VERSION_HEX >= 0x030C00A5
+#define PYLONG_VALUE(o) ((PyLongObject *)o)->long_value.ob_digit[0]
+#else
#define PYLONG_VALUE(o) ((PyLongObject *)o)->ob_digit[0]
+#endif
/*
* This is a multiset of directory names, built from the files that
--- a/mercurial/commands.py Thu Mar 09 13:02:13 2023 -0600
+++ b/mercurial/commands.py Mon Mar 20 23:16:14 2023 +0100
@@ -2507,7 +2507,7 @@
"""
opts = pycompat.byteskwargs(opts)
- context = repo.dirstate.changing_files
+ context = lambda repo: repo.dirstate.changing_files(repo)
rev = opts.get(b'at_rev')
ctx = None
if rev:
@@ -6019,7 +6019,7 @@
Returns 0 on success, 1 if errors are encountered.
"""
opts = pycompat.byteskwargs(opts)
- context = repo.dirstate.changing_files
+ context = lambda repo: repo.dirstate.changing_files(repo)
rev = opts.get(b'at_rev')
ctx = None
if rev:
--- a/mercurial/dirstate.py Thu Mar 09 13:02:13 2023 -0600
+++ b/mercurial/dirstate.py Mon Mar 20 23:16:14 2023 +0100
@@ -200,6 +200,12 @@
self._cwd
def refresh(self):
+ # XXX if this happens, you likely did not enter the `changing_xxx`
+ # using `repo.dirstate`, so a later `repo.dirstate` accesss might call
+ # `refresh`.
+ if self.is_changing_any:
+ msg = "refreshing the dirstate in the middle of a change"
+ raise error.ProgrammingError(msg)
if '_branch' in vars(self):
del self._branch
if '_map' in vars(self) and self._map.may_need_refresh():
--- a/mercurial/interfaces/repository.py Thu Mar 09 13:02:13 2023 -0600
+++ b/mercurial/interfaces/repository.py Mon Mar 20 23:16:14 2023 +0100
@@ -1524,6 +1524,10 @@
"""Name of the repoview that is active on this repo."""
)
+ vfs_map = interfaceutil.Attribute(
+ """a bytes-key → vfs mapping used by transaction and others"""
+ )
+
wvfs = interfaceutil.Attribute(
"""VFS used to access the working directory."""
)
--- a/mercurial/localrepo.py Thu Mar 09 13:02:13 2023 -0600
+++ b/mercurial/localrepo.py Mon Mar 20 23:16:14 2023 +0100
@@ -1565,6 +1565,14 @@
return checksvfs
+ @property
+ def vfs_map(self):
+ return {
+ b'': self.svfs,
+ b'plain': self.vfs,
+ b'store': self.svfs,
+ }
+
def close(self):
self._writecaches()
@@ -2410,12 +2418,11 @@
self.hook(b'pretxnopen', throw=True, txnname=desc, txnid=txnid)
self._writejournal(desc)
- renames = [(vfs, x, undoname(x)) for vfs, x in self._journalfiles()]
if report:
rp = report
else:
rp = self.ui.warn
- vfsmap = {b'plain': self.vfs, b'store': self.svfs} # root of .hg/
+ vfsmap = self.vfs_map
# we must avoid cyclic reference between repo and transaction.
reporef = weakref.ref(self)
# Code to track tag movement
@@ -2568,13 +2575,15 @@
vfsmap,
b"journal",
b"undo",
- aftertrans(renames),
+ lambda: None,
self.store.createmode,
validator=validate,
releasefn=releasefn,
checkambigfiles=_cachedfiles,
name=desc,
)
+ for vfs_id, path in self._journalfiles():
+ tr.add_journal(vfs_id, path)
tr.changes[b'origrepolen'] = len(self)
tr.changes[b'obsmarkers'] = set()
tr.changes[b'phases'] = []
@@ -2704,10 +2713,7 @@
with self.lock():
if self.svfs.exists(b"journal"):
self.ui.status(_(b"rolling back interrupted transaction\n"))
- vfsmap = {
- b'': self.svfs,
- b'plain': self.vfs,
- }
+ vfsmap = self.vfs_map
transaction.rollback(
self.svfs,
vfsmap,
@@ -2775,7 +2781,7 @@
return 0
self.destroying()
- vfsmap = {b'plain': self.vfs, b'': self.svfs}
+ vfsmap = self.vfs_map
skip_journal_pattern = None
if not parentgone:
skip_journal_pattern = RE_SKIP_DIRSTATE_ROLLBACK
@@ -2945,6 +2951,7 @@
known good state)."""
unfi = self.unfiltered()
if 'dirstate' in unfi.__dict__:
+ assert not self.dirstate.is_changing_any
del unfi.__dict__['dirstate']
def invalidate(self, clearfilecache=False):
@@ -3542,24 +3549,6 @@
self._sidedata_computers[kind][category] = (keys, computer, flags)
-# used to avoid circular references so destructors work
-def aftertrans(files):
- renamefiles = [tuple(t) for t in files]
-
- def a():
- for vfs, src, dest in renamefiles:
- # if src and dest refer to a same file, vfs.rename is a no-op,
- # leaving both src and dest on disk. delete dest to make sure
- # the rename couldn't be such a no-op.
- vfs.tryunlink(dest)
- try:
- vfs.rename(src, dest)
- except FileNotFoundError: # journal file does not yet exist
- pass
-
- return a
-
-
def undoname(fn: bytes) -> bytes:
base, name = os.path.split(fn)
assert name.startswith(b'journal')
--- a/mercurial/match.py Thu Mar 09 13:02:13 2023 -0600
+++ b/mercurial/match.py Mon Mar 20 23:16:14 2023 +0100
@@ -196,14 +196,14 @@
... return match(util.localpath(root), *args, **kwargs)
Usually a patternmatcher is returned:
- >>> _match(b'/foo', b'.', [b're:.*\.c$', b'path:foo/a', b'*.py'])
+ >>> _match(b'/foo', b'.', [br're:.*\.c$', b'path:foo/a', b'*.py'])
<patternmatcher patterns='.*\\.c$|foo/a(?:/|$)|[^/]*\\.py$'>
Combining 'patterns' with 'include' (resp. 'exclude') gives an
intersectionmatcher (resp. a differencematcher):
- >>> type(_match(b'/foo', b'.', [b're:.*\.c$'], include=[b'path:lib']))
+ >>> type(_match(b'/foo', b'.', [br're:.*\.c$'], include=[b'path:lib']))
<class 'mercurial.match.intersectionmatcher'>
- >>> type(_match(b'/foo', b'.', [b're:.*\.c$'], exclude=[b'path:build']))
+ >>> type(_match(b'/foo', b'.', [br're:.*\.c$'], exclude=[b'path:build']))
<class 'mercurial.match.differencematcher'>
Notice that, if 'patterns' is empty, an alwaysmatcher is returned:
@@ -212,7 +212,7 @@
The 'default' argument determines which kind of pattern is assumed if a
pattern has no prefix:
- >>> _match(b'/foo', b'.', [b'.*\.c$'], default=b're')
+ >>> _match(b'/foo', b'.', [br'.*\.c$'], default=b're')
<patternmatcher patterns='.*\\.c$'>
>>> _match(b'/foo', b'.', [b'main.py'], default=b'relpath')
<patternmatcher patterns='main\\.py(?:/|$)'>
@@ -223,7 +223,7 @@
name) matches againset one of the patterns given at initialization. There
are two ways of doing this check.
- >>> m = _match(b'/foo', b'', [b're:.*\.c$', b'relpath:a'])
+ >>> m = _match(b'/foo', b'', [br're:.*\.c$', b'relpath:a'])
1. Calling the matcher with a file name returns True if any pattern
matches that file name:
--- a/mercurial/repair.py Thu Mar 09 13:02:13 2023 -0600
+++ b/mercurial/repair.py Mon Mar 20 23:16:14 2023 +0100
@@ -7,8 +7,6 @@
# GNU General Public License version 2 or any later version.
-import errno
-
from .i18n import _
from .node import (
hex,
@@ -26,11 +24,11 @@
phases,
requirements,
scmutil,
+ transaction,
util,
)
from .utils import (
hashutil,
- stringutil,
urlutil,
)
@@ -270,19 +268,7 @@
bmchanges = [(m, repo[newbmtarget].node()) for m in updatebm]
repo._bookmarks.applychanges(repo, tr, bmchanges)
- # remove undo files
- for undovfs, undofile in repo.undofiles():
- try:
- undovfs.unlink(undofile)
- except OSError as e:
- if e.errno != errno.ENOENT:
- ui.warn(
- _(b'error removing %s: %s\n')
- % (
- undovfs.join(undofile),
- stringutil.forcebytestr(e),
- )
- )
+ transaction.cleanup_undo_files(repo.ui.warn, repo.vfs_map)
except: # re-raises
if backupfile:
--- a/mercurial/statprof.py Thu Mar 09 13:02:13 2023 -0600
+++ b/mercurial/statprof.py Mon Mar 20 23:16:14 2023 +0100
@@ -540,7 +540,11 @@
for stat in stats:
site = stat.site
- sitelabel = b'%s:%d:%s' % (site.filename(), site.lineno, site.function)
+ sitelabel = b'%s:%d:%s' % (
+ site.filename(),
+ site.lineno or -1,
+ site.function,
+ )
fp.write(
b'%6.2f %9.2f %9.2f %s\n'
% (
@@ -613,7 +617,7 @@
stattuple = (
stat.selfpercent(),
stat.selfseconds(),
- stat.site.lineno,
+ stat.site.lineno or -1,
source,
)
--- a/mercurial/streamclone.py Thu Mar 09 13:02:13 2023 -0600
+++ b/mercurial/streamclone.py Mon Mar 20 23:16:14 2023 +0100
@@ -7,7 +7,6 @@
import contextlib
-import errno
import os
import struct
@@ -24,14 +23,12 @@
requirements as requirementsmod,
scmutil,
store,
+ transaction,
util,
)
from .revlogutils import (
nodemap,
)
-from .utils import (
- stringutil,
-)
def new_stream_clone_requirements(default_requirements, streamed_requirements):
@@ -935,15 +932,4 @@
dest_repo.store.write(tr)
# clean up transaction file as they do not make sense
- undo_files = [(dest_repo.svfs, b'undo.backupfiles')]
- undo_files.extend(dest_repo.undofiles())
- for undovfs, undofile in undo_files:
- try:
- undovfs.unlink(undofile)
- except OSError as e:
- if e.errno != errno.ENOENT:
- msg = _(b'error removing %s: %s\n')
- path = undovfs.join(undofile)
- e_msg = stringutil.forcebytestr(e)
- msg %= (path, e_msg)
- dest_repo.ui.warn(msg)
+ transaction.cleanup_undo_files(dest_repo.ui.warn, dest_repo.vfs_map)
--- a/mercurial/transaction.py Thu Mar 09 13:02:13 2023 -0600
+++ b/mercurial/transaction.py Mon Mar 20 23:16:14 2023 +0100
@@ -11,6 +11,8 @@
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
+import errno
+import os
from .i18n import _
from . import (
@@ -38,6 +40,61 @@
return _active
+UNDO_BACKUP = b'%s.backupfiles'
+
+UNDO_FILES_MAY_NEED_CLEANUP = [
+ # legacy entries that might exists on disk from previous version:
+ (b'store', b'%s.narrowspec'),
+ (b'plain', b'%s.narrowspec.dirstate'),
+ (b'plain', b'%s.branch'),
+ (b'plain', b'%s.bookmarks'),
+ (b'store', b'%s.phaseroots'),
+ (b'plain', b'%s.dirstate'),
+ # files actually in uses today:
+ (b'plain', b'%s.desc'),
+ # Always delete undo last to make sure we detect that a clean up is needed if
+ # the process is interrupted.
+ (b'store', b'%s'),
+]
+
+
+def cleanup_undo_files(report, vfsmap, undo_prefix=b'undo'):
+ """remove "undo" files used by the rollback logic
+
+ This is useful to prevent rollback running in situation were it does not
+ make sense. For example after a strip.
+ """
+ backup_listing = UNDO_BACKUP % undo_prefix
+
+ backup_entries = []
+ undo_files = []
+ svfs = vfsmap[b'store']
+ try:
+ with svfs(backup_listing) as f:
+ backup_entries = read_backup_files(report, f)
+ except OSError as e:
+ if e.errno != errno.ENOENT:
+ msg = _(b'could not read %s: %s\n')
+ msg %= (svfs.join(backup_listing), stringutil.forcebytestr(e))
+ report(msg)
+
+ for location, f, backup_path, c in backup_entries:
+ if location in vfsmap and backup_path:
+ undo_files.append((vfsmap[location], backup_path))
+
+ undo_files.append((svfs, backup_listing))
+ for location, undo_path in UNDO_FILES_MAY_NEED_CLEANUP:
+ undo_files.append((vfsmap[location], undo_path % undo_prefix))
+ for undovfs, undofile in undo_files:
+ try:
+ undovfs.unlink(undofile)
+ except OSError as e:
+ if e.errno != errno.ENOENT:
+ msg = _(b'error removing %s: %s\n')
+ msg %= (undovfs.join(undofile), stringutil.forcebytestr(e))
+ report(msg)
+
+
def _playback(
journal,
report,
@@ -152,6 +209,7 @@
self._offsetmap = {}
self._newfiles = set()
self._journal = journalname
+ self._journal_files = []
self._undoname = undoname
self._queue = []
# A callback to do something just after releasing transaction.
@@ -632,10 +690,25 @@
scope)"""
self._abort()
+ @active
+ def add_journal(self, vfs_id, path):
+ self._journal_files.append((vfs_id, path))
+
def _writeundo(self):
"""write transaction data for possible future undo call"""
if self._undoname is None:
return
+ cleanup_undo_files(
+ self._report,
+ self._vfsmap,
+ undo_prefix=self._undoname,
+ )
+
+ def undoname(fn: bytes) -> bytes:
+ base, name = os.path.split(fn)
+ assert name.startswith(self._journal)
+ new_name = name.replace(self._journal, self._undoname, 1)
+ return os.path.join(base, new_name)
undo_backup_path = b"%s.backupfiles" % self._undoname
undobackupfile = self._opener.open(undo_backup_path, b'w')
@@ -653,13 +726,20 @@
)
continue
vfs = self._vfsmap[l]
- base, name = vfs.split(b)
- assert name.startswith(self._journal), name
- uname = name.replace(self._journal, self._undoname, 1)
- u = vfs.reljoin(base, uname)
+ u = undoname(b)
util.copyfile(vfs.join(b), vfs.join(u), hardlink=True)
undobackupfile.write(b"%s\0%s\0%s\0%d\n" % (l, f, u, c))
undobackupfile.close()
+ for vfs, src in self._journal_files:
+ dest = undoname(src)
+ # if src and dest refer to a same file, vfs.rename is a no-op,
+ # leaving both src and dest on disk. delete dest to make sure
+ # the rename couldn't be such a no-op.
+ vfs.tryunlink(dest)
+ try:
+ vfs.rename(src, dest)
+ except FileNotFoundError: # journal file does not yet exist
+ pass
def _abort(self):
entries = self.readjournal()
@@ -737,6 +817,32 @@
)
+def read_backup_files(report, fp):
+ """parse an (already open) backup file an return contained backup entries
+
+ entries are in the form: (location, file, backupfile, xxx)
+
+ :location: the vfs identifier (vfsmap's key)
+ :file: original file path (in the vfs)
+ :backupfile: path of the backup (in the vfs)
+ :cache: a boolean currently always set to False
+ """
+ lines = fp.readlines()
+ backupentries = []
+ if lines:
+ ver = lines[0][:-1]
+ if ver != (b'%d' % version):
+ report(BAD_VERSION_MSG)
+ else:
+ for line in lines[1:]:
+ if line:
+ # Shave off the trailing newline
+ line = line[:-1]
+ l, f, b, c = line.split(b'\0')
+ backupentries.append((l, f, b, bool(c)))
+ return backupentries
+
+
def rollback(
opener,
vfsmap,
@@ -776,19 +882,8 @@
backupjournal = b"%s.backupfiles" % file
if opener.exists(backupjournal):
- fp = opener.open(backupjournal)
- lines = fp.readlines()
- if lines:
- ver = lines[0][:-1]
- if ver != (b'%d' % version):
- report(BAD_VERSION_MSG)
- else:
- for line in lines[1:]:
- if line:
- # Shave off the trailing newline
- line = line[:-1]
- l, f, b, c = line.split(b'\0')
- backupentries.append((l, f, b, bool(c)))
+ with opener.open(backupjournal) as fp:
+ backupentries = read_backup_files(report, fp)
if skip_journal_pattern is not None:
keep = lambda x: not skip_journal_pattern.match(x[1])
backupentries = [x for x in backupentries if keep(x)]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/relnotes/6.4 Mon Mar 20 23:16:14 2023 +0100
@@ -0,0 +1,144 @@
+= Mercurial 6.4rc0 =
+
+== New Features ==
+
+ * There is a new internal merge tool called `internal:union-other-first`.
+ It works like `internal:union` but add other side on top of local.
+ * Pullbundles are enabled by default
+ * delta-find: add a way to control the number of bases tested at the same time
+ * changelog-v2: add a configuration to disable rank computation
+ * debug: add an option to display statistic about a bundling operation
+ * debug: add an option to display statistic about a unbundling operation
+ * delta-find: add a delta-reuse policy that blindly accepts incoming deltas
+ * debug: add debug-revlog-stats command
+ * dirstate: add narrow support to `verify`
+ * verify: also check dirstate
+ * commit: add --draft option to use draft phase
+ * amend: add a --draft option to set phase to draft
+ * debug: add a config to abort update early
+ * rhg: implement checkexec to support weird filesystems
+ * debugshell: allow commands to be specified as a CLI argument
+ * rhg-files: add support for narrow when specifying a revision
+ * rust-narrow: enable narrow support for plain `rhg files`
+
+== Bug Fixes ==
+
+Aside from the following (unordered) commits which made it through a manual filter, there are a bunch of typing improvements and fixes, removal of deprecated code and general code cleanup.
+
+ * lfs: improve an exception message for blob corruption detected on transfer
+ * revlog: use the user facing filename as the display_id for filelogs
+ * rust-status: query fs traversal metadata lazily
+ * shelve: add Shelf.changed_files for resolving changed files in a plugin
+ * demandimport: ensure lazyloaderex sets loader attributes (issue6725)
+ * typing: fix a syntax error in mercurial/cext/bdiff.pyi
+ * cffi: fix a bytes vs str issue on macOS when listing directories
+ * changelog-v2: fix the docket `struct`
+ * schemes: fix a broken check for drive letter conflicts
+ * worker: avoid reading 1 byte at a time from the OS pipe
+ * rust-narrow: fix loop that never loops
+ * setup: Ensure target directory exists with building rust extension
+ * dirstate: invalidate changes when parent-change fails
+ * dirstate: warn about non-explicitly rolledback parent-change
+ * dirstate: write dirstate on successful exit of changing_parents context
+ * largefile: make sure we hold the lock when updating the second dirstate
+ * dirstate: enforce holding the lock while doing any changes
+ * run-tests: stop ignoring venv-installed packages
+ * transaction: run abort callback in all cases
+ * transaction: quietly rollback if no other changes than temporary files
+ * debugrebuilddirstate: double check that no transaction is open
+ * dirstate: do not write an empty dirstate just for backup
+ * locking: take the `wlock` for the full `hg add` duration
+ * locking: take the `wlock` for the full `hg remove` duration
+ * locking: take the `wlock` for the full `hg forget` duration
+ * locking: take the `wlock` for the full `hg addremove` duration
+ * locking: grab the wlock before touching the dirstate in `perfdirstatewrite`
+ * locking: hold the wlock for the full duration of the "keyword demo"
+ * mq: properly take the wlock during the full qfold operation
+ * dirstate: invalidate the dirstate change on transaction failure
+ * status: fix post status writing
+ * status: fix post status invalidation
+ * dirstate: avoid transaction backup/restore if we do not hold the lock
+ * rollback: explicitly skip dirstate rollback when applicable
+ * dirstate-guard: remove the feature
+ * dirstate: make `restorebackup` more robust when it is a noop
+ * dirstate: generalize the dirstate's invalidation on transaction abort
+ * dirstate: detect potential fishy transaction patterns while changing
+ * mq: write the dirstate before stripping
+ * dirstate: explicitly backup the datafile
+ * localrepo: enforce a clean dirstate when the transaction open
+ * localrepo: "blindly" do a dirstate backup at the end of the transaction
+ * dirstate: remove the dedicated backup logic
+ * rhg: fix a bug in path_encode
+ * dirstate: invalidate on all exceptions
+ * large-files: make sure we write newly initialized standin file early
+ * dirstate: warn if dirty when starting an edition
+ * dirstate: track that changes are pending in a transaction
+ * dirstate: distinct transaction callback from largefile
+ * automv: lock the repository before searching for renames
+ * dirstate: only reload the dirstate when it may have changed
+ * dirstate: cleanup the `_map` property cache
+ * status: invalidate dirstate on LockError
+ * dirstate: check that dirstate is clean at the initial context opening
+ * dirstate: have `running_status` write the dirstate when holding the lock
+ * dirstate: have `running_status` warn when exiting with a dirty dirstate
+ * narrow: widden the lock context in `tracking`
+ * narrow: enforce that narrow spec is written within a transaction
+ * transaction: no longer explicitly cache phaseroots
+ * transaction: no longer explicitly cache bookmarks
+ * transaction: use the standard transaction mechanism to backup branch
+ * bundlerepo: handle changegroup induced phase movement in the associated method
+ * bundlerepo: apply phase data stored in the bundle instead of assuming `draft`
+ * config-item: declare undeclared path suboption
+ * narrow: read pending file when applicable
+
+== Backwards Compatibility Changes ==
+ * rust: upgrade supported Rust toolchain version
+ * rust: move all crates in the main workspace to edition 2021
+ * hg-core: upgrade `zstd` dependency
+ * hg-core: upgrade `clap` dependency
+ * hg-core: upgrade all remaining dependencies
+ * hg-cpython: upgrade dependencies
+ * rhg: upgrade `clap` dependency
+ * rhg: upgrade the remainder of the dependencies
+
+== Internal API Changes ==
+
+ * Many APIs around the dirstate have been made much stricter with regards to
+ locking and transaction handling
+ * Some dirstate APIs have been renamed/removed
+ * In both cases, you should get loud complaints in your tests if you do
+ something wrong.
+
+== Miscellaneous ==
+
+ * pullbundle support no longer requires setting a server-side option,
+ providing a .hg/pullbundles.manifest according to the syntax specified in
+ 'hg help -e clonebundles' is enough.
+ * debug-delta-find: add a --source option
+ * delta-find: add debug information about reuse of cached data
+ * delta-find: set the default candidate chunk size to 10
+ * attr: vendor 22.1.0
+ * configitems: add a default value for "merge-tools.xxx.regappend"
+ * debugrevlog: display total stored information
+ * emitrevision: if we need to compute a delta on the fly, try p1 or p2 first
+ * emitrevision: consider ancestors revision to emit as available base
+ * find-delta: pass the cache-delta usage policy alongside the cache-delta
+ * delta-find: use a smarter object for snapshot caching
+ * delta-find: use sets instead of list in the snapshot cache
+ * delta-find: make sure we only use newer full snapshot as candidate
+ * delta-find: use a single snapshot cache when applying a group to an object
+ * bundleoperation: optionnaly record the `remote` that produced the bundle
+ * bundle: when forcing acceptance of incoming delta also accept snapshot
+ * bundle: emit full snapshot as is, without doing a redelta
+ * pathutil: slightly faster path audit in the common case
+ * merge: don't pay for pathconflicts if there are none
+ * merge: short-circuit the _checkfs loop upon getting ENOENT
+ * merge: disable the whole filesystem access loop if [_realfs] is false
+ * merge: cache the fs checks made during [_checkunknownfiles]
+ * rust: use `logging_timer` instead of `micro_timer`
+ * rust: run `cargo clippy`
+ * makefile: add `cargo clippy` to tests if cargo is available
+ * heptapod-ci: add `clippy` to the CI
+ * convert: use a priority queue for sorting commits, to make sorting faster
+ * delta-find: adjust the default candidate group chunk size
+ * delta-find: declare the "paths..*:pulled-delta-reuse-policy option
\ No newline at end of file
--- a/relnotes/next Thu Mar 09 13:02:13 2023 -0600
+++ b/relnotes/next Mon Mar 20 23:16:14 2023 +0100
@@ -2,9 +2,6 @@
== New Features ==
- * There is a new internal merge tool called `internal:union-other-first`.
- It works like `internal:union` but add other side on top of local.
-
== Default Format Change ==
These changes affect newly created repositories (or new clones) done with
@@ -19,7 +16,3 @@
== Internal API Changes ==
== Miscellaneous ==
-
- * pullbundle support no longer requires setting a server-side option,
- providing a .hg/pullbundles.manifest according to the syntax specified in
- 'hg help -e clonebundles' is enough.
--- a/rust/Cargo.lock Thu Mar 09 13:02:13 2023 -0600
+++ b/rust/Cargo.lock Mon Mar 20 23:16:14 2023 +0100
@@ -1023,9 +1023,9 @@
[[package]]
name = "rayon"
-version = "1.6.1"
+version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
+checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
dependencies = [
"either",
"rayon-core",
@@ -1033,9 +1033,9 @@
[[package]]
name = "rayon-core"
-version = "1.10.2"
+version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b"
+checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
@@ -1425,18 +1425,18 @@
[[package]]
name = "zstd"
-version = "0.11.2+zstd.1.5.2"
+version = "0.12.3+zstd.1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4"
+checksum = "76eea132fb024e0e13fd9c2f5d5d595d8a967aa72382ac2f9d39fcc95afd0806"
dependencies = [
"zstd-safe",
]
[[package]]
name = "zstd-safe"
-version = "5.0.2+zstd.1.5.2"
+version = "6.0.4+zstd.1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db"
+checksum = "7afb4b54b8910cf5447638cb54bf4e8a65cbedd783af98b98c62ffe91f185543"
dependencies = [
"libc",
"zstd-sys",
@@ -1444,10 +1444,11 @@
[[package]]
name = "zstd-sys"
-version = "2.0.1+zstd.1.5.2"
+version = "2.0.7+zstd.1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fd07cbbc53846d9145dbffdf6dd09a7a0aa52be46741825f5c97bdd4f73f12b"
+checksum = "94509c3ba2fe55294d752b79842c530ccfab760192521df74a081a78d2b3c7f5"
dependencies = [
"cc",
"libc",
+ "pkg-config",
]
--- a/rust/hg-core/Cargo.toml Thu Mar 09 13:02:13 2023 -0600
+++ b/rust/hg-core/Cargo.toml Mon Mar 20 23:16:14 2023 +0100
@@ -24,7 +24,7 @@
rand = "0.8.5"
rand_pcg = "0.3.1"
rand_distr = "0.4.3"
-rayon = "1.6.1"
+rayon = "1.7.0"
regex = "1.7.0"
sha-1 = "0.10.0"
twox-hash = "1.6.3"
@@ -34,10 +34,8 @@
crossbeam-channel = "0.5.6"
log = "0.4.17"
memmap2 = { version = "0.5.8", features = ["stable_deref_trait"] }
-zstd = "0.11.2"
+zstd = "0.12"
format-bytes = "0.3.0"
-# once_cell 1.15 uses edition 2021, while the heptapod CI
-# uses an old version of Cargo that doesn't support it.
once_cell = "1.16.0"
# We don't use the `miniz-oxide` backend to not change rhg benchmarks and until
--- a/rust/hg-core/src/dirstate_tree/on_disk.rs Thu Mar 09 13:02:13 2023 -0600
+++ b/rust/hg-core/src/dirstate_tree/on_disk.rs Mon Mar 20 23:16:14 2023 +0100
@@ -415,9 +415,9 @@
fn synthesize_unix_mode(&self) -> u32 {
let file_type = if self.flags().contains(Flags::MODE_IS_SYMLINK) {
- libc::S_IFLNK
+ libc::S_IFLNK as u32
} else {
- libc::S_IFREG
+ libc::S_IFREG as u32
};
let permissions = if self.flags().contains(Flags::MODE_EXEC_PERM) {
0o755
--- a/rust/hg-core/src/dirstate_tree/status.rs Thu Mar 09 13:02:13 2023 -0600
+++ b/rust/hg-core/src/dirstate_tree/status.rs Mon Mar 20 23:16:14 2023 +0100
@@ -244,7 +244,7 @@
match self.parent {
None => false,
Some(parent) => {
- *(parent.cache.get_or_init(|| {
+ *(self.cache.get_or_init(|| {
parent.force(ignore_fn) || ignore_fn(self.path)
}))
}
@@ -433,16 +433,21 @@
return Ok(children_all_have_dirstate_node_or_are_ignored);
}
+ let readdir_succeeded;
let mut fs_entries = if let Ok(entries) = self.read_dir(
directory_hg_path,
&directory_entry.fs_path,
is_at_repo_root,
) {
+ readdir_succeeded = true;
entries
} else {
// Treat an unreadable directory (typically because of insufficient
// permissions) like an empty directory. `self.read_dir` has
// already called `self.io_error` so a warning will be emitted.
+ // We still need to remember that there was an error so that we
+ // know not to cache this result.
+ readdir_succeeded = false;
Vec::new()
};
@@ -495,6 +500,7 @@
Ok(has_dirstate_node_or_is_ignored)
})
.try_reduce(|| true, |a, b| Ok(a && b))
+ .map(|res| res && readdir_succeeded)
}
fn traverse_fs_and_dirstate<'ancestor>(
--- a/rust/hg-core/src/vfs.rs Thu Mar 09 13:02:13 2023 -0600
+++ b/rust/hg-core/src/vfs.rs Mon Mar 20 23:16:14 2023 +0100
@@ -193,3 +193,13 @@
r == 0 && buf.f_type as u32 == libc::NFS_SUPER_MAGIC as u32
}
}
+
+/// Similar to what Cargo does; although detecting NFS (or non-local
+/// file systems) _should_ be possible on other operating systems,
+/// we'll just assume that mmap() works there, for now; after all,
+/// _some_ functionality is better than a compile error, i.e. none at
+/// all
+#[cfg(not(target_os = "linux"))]
+pub(crate) fn is_on_nfs_mount(_path: impl AsRef<Path>) -> bool {
+ false
+}
--- a/rust/rhg/Cargo.toml Thu Mar 09 13:02:13 2023 -0600
+++ b/rust/rhg/Cargo.toml Mon Mar 20 23:16:14 2023 +0100
@@ -22,4 +22,4 @@
format-bytes = "0.3.0"
users = "0.11.0"
which = "4.3.0"
-rayon = "1.6.1"
+rayon = "1.7.0"
--- a/tests/common-pattern.py Thu Mar 09 13:02:13 2023 -0600
+++ b/tests/common-pattern.py Mon Mar 20 23:16:14 2023 +0100
@@ -136,6 +136,11 @@
# FormatMessage(ERROR_FILE_NOT_FOUND)
br'The system cannot find the file specified',
),
+ br'$EACCES$': (
+ br'Permission denied \(os error 13\)',
+ # strerror
+ br'Permission denied',
+ ),
br'$ENOTDIR$': (
# strerror()
br'Not a directory',
--- a/tests/run-tests.py Thu Mar 09 13:02:13 2023 -0600
+++ b/tests/run-tests.py Mon Mar 20 23:16:14 2023 +0100
@@ -54,6 +54,7 @@
import json
import multiprocessing
import os
+import packaging.version as version
import platform
import queue
import random
@@ -72,12 +73,6 @@
import uuid
import xml.dom.minidom as minidom
-try:
- # PEP 632 recommend the use of `packaging.version` to replace the
- # deprecated `distutil.version`. So lets do it.
- import packaging.version as version
-except ImportError:
- import distutils.version as version
if sys.version_info < (3, 5, 0):
print(
@@ -799,8 +794,8 @@
try:
import coverage
- covver = version.StrictVersion(coverage.__version__).version
- if covver < (3, 3):
+ covver = version.Version(coverage.__version__)
+ if covver < version.Version("3.3"):
parser.error('coverage options require coverage 3.3 or later')
except ImportError:
parser.error('coverage options now require the coverage package')
--- a/tests/test-blackbox.t Thu Mar 09 13:02:13 2023 -0600
+++ b/tests/test-blackbox.t Mon Mar 20 23:16:14 2023 +0100
@@ -322,8 +322,8 @@
#if unix-permissions
$ chmod -w .hg
$ hg log -r. -T '{rev}\n' --config blackbox.maxsize=1 --debug
- warning: cannot rename '$TESTTMP/blackboxtest3/.hg/blackbox.log.1' to '$TESTTMP/blackboxtest3/.hg/blackbox.log': Permission denied
- warning: cannot write to blackbox.log: Permission denied
+ warning: cannot rename '$TESTTMP/blackboxtest3/.hg/blackbox.log.1' to '$TESTTMP/blackboxtest3/.hg/blackbox.log': $EACCES$
+ warning: cannot write to blackbox.log: $EACCES$
1
$ chmod +w .hg
#endif
@@ -470,15 +470,16 @@
> raise RuntimeError('raise')
> EOF
- $ cat >> $HGRCPATH << EOF
+
+ $ hg init $TESTTMP/blackbox-exception-only --config blackbox.track=commandexception
+ $ cat >> $TESTTMP/blackbox-exception-only/.hg/hgrc << EOF
> [blackbox]
> track = commandexception
> [extensions]
> raise=$TESTTMP/raise.py
> EOF
+ $ cd $TESTTMP/blackbox-exception-only
- $ hg init $TESTTMP/blackbox-exception-only
- $ cd $TESTTMP/blackbox-exception-only
#if chg
(chg exits 255 because it fails to receive an exit code)
@@ -495,3 +496,25 @@
$ tail -2 .hg/blackbox.log
RuntimeError: raise
+ $ cd ..
+
+Check we did not broke `hg mv`
+------------------------------
+(we did in 6.4rc)
+
+basic setup
+
+ $ hg init blackbox-file-move
+ $ cd blackbox-file-move
+ $ echo foo > foo
+ $ hg add foo
+ $ hg commit -m 'foo'
+
+copy a file
+
+ $ hg copy foo bar
+
+move a file
+
+ $ hg mv foo goo
+
--- a/tests/test-clone.t Thu Mar 09 13:02:13 2023 -0600
+++ b/tests/test-clone.t Mon Mar 20 23:16:14 2023 +0100
@@ -633,7 +633,7 @@
$ mkdir a
$ chmod 000 a
$ hg clone a b
- abort: Permission denied: *$TESTTMP/fail/a/.hg* (glob)
+ abort: $EACCES$: *$TESTTMP/fail/a/.hg* (glob)
[255]
Inaccessible destination
@@ -641,7 +641,7 @@
$ hg init b
$ cd b
$ hg clone . ../a
- abort: Permission denied: *../a* (glob)
+ abort: $EACCES$: *../a* (glob)
[255]
$ cd ..
$ chmod 700 a
--- a/tests/test-convert.t Thu Mar 09 13:02:13 2023 -0600
+++ b/tests/test-convert.t Mon Mar 20 23:16:14 2023 +0100
@@ -468,7 +468,7 @@
$ chmod 000 bogusdir
$ hg convert a bogusdir
- abort: Permission denied: *bogusdir* (glob)
+ abort: $EACCES$: *bogusdir* (glob)
[255]
user permissions should succeed
--- a/tests/test-empty.t Thu Mar 09 13:02:13 2023 -0600
+++ b/tests/test-empty.t Mon Mar 20 23:16:14 2023 +0100
@@ -40,7 +40,6 @@
hgrc
requires
store
- undo.backup.branch
wcache
Should be empty (except for the "basic" requires):
--- a/tests/test-hardlinks.t Thu Mar 09 13:02:13 2023 -0600
+++ b/tests/test-hardlinks.t Mon Mar 20 23:16:14 2023 +0100
@@ -141,8 +141,6 @@
1 r3/.hg/store/phaseroots
1 r3/.hg/store/requires
1 r3/.hg/store/undo
- 1 r3/.hg/store/undo.backup.fncache (repofncache !)
- 1 r3/.hg/store/undo.backup.phaseroots
1 r3/.hg/store/undo.backupfiles
Push to repo r1 should break up most hardlinks in r2:
@@ -253,8 +251,6 @@
2 r4/.hg/store/phaseroots
2 r4/.hg/store/requires
2 r4/.hg/store/undo
- 2 r4/.hg/store/undo.backup.fncache (repofncache !)
- 2 r4/.hg/store/undo.backup.phaseroots
2 r4/.hg/store/undo.backupfiles
[24] r4/.hg/undo.backup.branch (re)
2 r4/\.hg/undo\.backup\.dirstate (re)
@@ -308,8 +304,6 @@
2 r4/.hg/store/phaseroots
2 r4/.hg/store/requires
2 r4/.hg/store/undo
- 2 r4/.hg/store/undo.backup.fncache (repofncache !)
- 2 r4/.hg/store/undo.backup.phaseroots
2 r4/.hg/store/undo.backupfiles
[23] r4/.hg/undo.backup.branch (re)
2 r4/\.hg/undo\.backup\.dirstate (re)
--- a/tests/test-help.t Thu Mar 09 13:02:13 2023 -0600
+++ b/tests/test-help.t Mon Mar 20 23:16:14 2023 +0100
@@ -1988,7 +1988,7 @@
$ "$PYTHON" <<EOF
> def escape(s):
- > return b''.join(b'\\u%x' % ord(uc) for uc in s.decode('cp932'))
+ > return b''.join(br'\\u%x' % ord(uc) for uc in s.decode('cp932'))
> # translation of "record" in ja_JP.cp932
> upper = b"\x8bL\x98^"
> # str.lower()-ed section name should be treated as different one
--- a/tests/test-hgrc.t Thu Mar 09 13:02:13 2023 -0600
+++ b/tests/test-hgrc.t Mon Mar 20 23:16:14 2023 +0100
@@ -59,7 +59,7 @@
#if unix-permissions no-root
$ chmod u-r $TESTTMP/included
$ hg showconfig section
- config error at $TESTTMP/hgrc:2: cannot include $TESTTMP/included (Permission denied*) (glob)
+ config error at $TESTTMP/hgrc:2: cannot include $TESTTMP/included ($EACCES$*) (glob)
[255]
#endif
--- a/tests/test-journal-exists.t Thu Mar 09 13:02:13 2023 -0600
+++ b/tests/test-journal-exists.t Mon Mar 20 23:16:14 2023 +0100
@@ -47,7 +47,7 @@
$ hg -R foo unbundle repo.hg
adding changesets
- abort: Permission denied: '$TESTTMP/repo/foo/.hg/store/.00changelog.i-*' (glob)
+ abort: $EACCES$: '$TESTTMP/repo/foo/.hg/store/.00changelog.i-*' (glob)
[255]
$ if test -f foo/.hg/store/journal; then echo 'journal exists :-('; fi
--- a/tests/test-largefiles-cache.t Thu Mar 09 13:02:13 2023 -0600
+++ b/tests/test-largefiles-cache.t Mon Mar 20 23:16:14 2023 +0100
@@ -189,7 +189,6 @@
$ find src/.hg/largefiles/* | egrep "(dirstate|$hash)" | sort
src/.hg/largefiles/dirstate
src/.hg/largefiles/e2fb5f2139d086ded2cb600d5a91a196e76bf020
- src/.hg/largefiles/undo.backup.dirstate
Verify that backwards compatibility is maintained for old storage layout
$ mv src/.hg/largefiles/$hash share_dst/.hg/largefiles
--- a/tests/test-lock-badness.t Thu Mar 09 13:02:13 2023 -0600
+++ b/tests/test-lock-badness.t Mon Mar 20 23:16:14 2023 +0100
@@ -135,7 +135,7 @@
$ hg -R b push a
pushing to a
searching for changes
- abort: could not lock repository a: Permission denied
+ abort: could not lock repository a: $EACCES$
[20]
$ chmod 700 a/.hg/store
--- a/tests/test-minirst.py Thu Mar 09 13:02:13 2023 -0600
+++ b/tests/test-minirst.py Mon Mar 20 23:16:14 2023 +0100
@@ -154,7 +154,7 @@
debugformats('options', options)
-fields = b"""
+fields = br"""
:a: First item.
:ab: Second item. Indentation and wrapping
is handled automatically.
--- a/tests/test-permissions.t Thu Mar 09 13:02:13 2023 -0600
+++ b/tests/test-permissions.t Mon Mar 20 23:16:14 2023 +0100
@@ -24,7 +24,7 @@
$ chmod -r .hg/store/data/a.i
$ hg verify -q
- abort: Permission denied: '$TESTTMP/t/.hg/store/data/a.i'
+ abort: $EACCES$: '$TESTTMP/t/.hg/store/data/a.i'
[255]
$ chmod +r .hg/store/data/a.i
@@ -36,7 +36,7 @@
$ echo barber > a
$ hg commit -m "2"
trouble committing a!
- abort: Permission denied: '$TESTTMP/t/.hg/store/data/a.i'
+ abort: $EACCES$: '$TESTTMP/t/.hg/store/data/a.i'
[255]
$ chmod -w .
@@ -64,7 +64,7 @@
(fsmonitor makes "hg status" avoid accessing to "dir")
$ hg status
- dir: Permission denied* (glob)
+ dir: $EACCES$* (glob)
M a
#endif
--- a/tests/test-persistent-nodemap.t Thu Mar 09 13:02:13 2023 -0600
+++ b/tests/test-persistent-nodemap.t Mon Mar 20 23:16:14 2023 +0100
@@ -811,8 +811,7 @@
- manifest
$ ls -1 .hg/store/ | egrep '00(changelog|manifest)(\.n|-.*\.nd)'
- undo.backup.00changelog.n
- undo.backup.00manifest.n
+ [1]
$ hg debugnodemap --metadata
@@ -858,8 +857,6 @@
00changelog.n
00manifest-*.nd (glob)
00manifest.n
- undo.backup.00changelog.n
- undo.backup.00manifest.n
$ hg debugnodemap --metadata
uid: * (glob)
--- a/tests/test-push-race.t Thu Mar 09 13:02:13 2023 -0600
+++ b/tests/test-push-race.t Mon Mar 20 23:16:14 2023 +0100
@@ -50,6 +50,10 @@
> limit = 100
> test_default_timeout = os.environ.get('HGTEST_TIMEOUT_DEFAULT')
> test_timeout = os.environ.get('HGTEST_TIMEOUT')
+ > if test_default_timeout is not None:
+ > test_default_timeout = int(test_default_timeout)
+ > if test_timeout is not None:
+ > test_timeout = int(test_timeout)
> if (
> test_default_timeout is not None
> and test_timeout is not None
--- a/tests/test-repair-strip.t Thu Mar 09 13:02:13 2023 -0600
+++ b/tests/test-repair-strip.t Mon Mar 20 23:16:14 2023 +0100
@@ -53,9 +53,9 @@
transaction abort!
failed to truncate data/b.i
rollback failed - please run hg recover
- (failure reason: [Errno *] Permission denied .hg/store/data/b.i') (glob)
+ (failure reason: [Errno *] $EACCES$ .hg/store/data/b.i') (glob)
strip failed, backup bundle
- abort: Permission denied .hg/store/data/b.i'
+ abort: $EACCES$ .hg/store/data/b.i'
% after update 0, strip 2
abandoned transaction found - run hg recover
checking changesets
@@ -89,7 +89,7 @@
date: Thu Jan 01 00:00:00 1970 +0000
summary: a
- abort: Permission denied .hg/store/data/b.i'
+ abort: $EACCES$ .hg/store/data/b.i'
% after update 0, strip 2
checking changesets
checking manifests
@@ -110,9 +110,9 @@
transaction abort!
failed to truncate 00manifest.i
rollback failed - please run hg recover
- (failure reason: [Errno *] Permission denied .hg/store/00manifest.i') (glob)
+ (failure reason: [Errno *] $EACCES$ .hg/store/00manifest.i') (glob)
strip failed, backup bundle
- abort: Permission denied .hg/store/00manifest.i'
+ abort: $EACCES$ .hg/store/00manifest.i'
% after update 0, strip 2
abandoned transaction found - run hg recover
checking changesets
--- a/tests/test-ssh-bundle1.t Thu Mar 09 13:02:13 2023 -0600
+++ b/tests/test-ssh-bundle1.t Mon Mar 20 23:16:14 2023 +0100
@@ -403,9 +403,9 @@
$ hg push --ssh "sh ../ssh.sh"
pushing to ssh://user@dummy/*/remote (glob)
searching for changes
- remote: Permission denied
+ remote: $EACCES$
remote: abort: pretxnopen.hg-ssh hook failed
- remote: Permission denied
+ remote: $EACCES$
remote: pushkey-abort: prepushkey.hg-ssh hook failed
updating 6c0482d977a3 to public failed!
[1]
--- a/tests/test-ssh-repoerror.t Thu Mar 09 13:02:13 2023 -0600
+++ b/tests/test-ssh-repoerror.t Mon Mar 20 23:16:14 2023 +0100
@@ -13,7 +13,7 @@
$ chmod a-rx no-read
$ hg id ssh://user@dummy/no-read
- remote: abort: Permission denied: *$TESTTMP/no-read/.hg* (glob)
+ remote: abort: $EACCES$: *$TESTTMP/no-read/.hg* (glob)
abort: no suitable response from remote hg
[255]
@@ -31,7 +31,7 @@
> done
$ hg id ssh://user@dummy/other
- remote: abort: Permission denied: '$TESTTMP/other/.hg/requires'
+ remote: abort: $EACCES$: '$TESTTMP/other/.hg/requires'
abort: no suitable response from remote hg
[255]
@@ -47,7 +47,7 @@
$ chmod a-rx deep
$ hg id ssh://user@dummy/deep/nested
- remote: abort: Permission denied: *$TESTTMP/deep/nested/.hg* (glob)
+ remote: abort: $EACCES$: *$TESTTMP/deep/nested/.hg* (glob)
abort: no suitable response from remote hg
[255]
--- a/tests/test-ssh.t Thu Mar 09 13:02:13 2023 -0600
+++ b/tests/test-ssh.t Mon Mar 20 23:16:14 2023 +0100
@@ -456,7 +456,7 @@
$ hg push --ssh "sh ../ssh.sh"
pushing to ssh://user@dummy/*/remote (glob)
searching for changes
- remote: Permission denied
+ remote: $EACCES$
remote: pretxnopen.hg-ssh hook failed
abort: push failed on remote
[100]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-status-committed-and-ignored.t Mon Mar 20 23:16:14 2023 +0100
@@ -0,0 +1,33 @@
+#testcases dirstate-v1 dirstate-v2
+
+#if dirstate-v2
+ $ cat >> $HGRCPATH << EOF
+ > [format]
+ > use-dirstate-v2=1
+ > [storage]
+ > dirstate-v2.slow-path=allow
+ > EOF
+#endif
+
+ $ rm -rf r
+
+ $ hg init r
+ $ cd r
+ $ mkdir d1
+ $ mkdir d2
+ $ touch d1/f d2/f
+ $ hg commit -Am '.'
+ adding d1/f
+ adding d2/f
+ $ echo 'syntax:re' >> .hgignore
+ $ echo '^d1$' >> .hgignore
+ $ hg commit -Am "ignore d1"
+ adding .hgignore
+
+Now d1 is a directory that's both committed and ignored.
+Untracked files in d2 are still shown, but ones in d1 are ignored:
+
+ $ touch d1/g
+ $ touch d2/g
+ $ RAYON_NUM_THREADS=1 hg status
+ ? d2/g
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-status-eacces.t Mon Mar 20 23:16:14 2023 +0100
@@ -0,0 +1,45 @@
+#testcases dirstate-v1 dirstate-v2
+
+#if dirstate-v2
+ $ cat >> $HGRCPATH << EOF
+ > [format]
+ > use-dirstate-v2=1
+ > [storage]
+ > dirstate-v2.slow-path=allow
+ > EOF
+#endif
+
+
+The proliferation of status implementations can be confusing:
+- The pure python implementation:
+(no-rhg pure !)
+- The C implementation:
+(no-rhg no-rust no-pure !)
+- The two rust implementations:
+(rhg !)
+(no-rhg rust !)
+
+ $ hg init repo1
+ $ cd repo1
+ $ mkdir d1
+ $ touch d1/x
+ $ hg commit -Am.
+ adding d1/x
+ $ touch d1/y
+ $ chmod -r d1
+ $ hg status
+ d1: $EACCES$
+ ! d1/x (rhg !)
+ ! d1/x (no-rhg rust !)
+ $ hg status
+ d1: $EACCES$
+ ! d1/x (rust !)
+ ! d1/x (no-rust rhg !)
+ $ chmod +r d1
+ $ hg status
+ ? d1/y
+
+ $ touch d1/z
+ $ hg status
+ ? d1/y
+ ? d1/z
--- a/tests/test-status.t Thu Mar 09 13:02:13 2023 -0600
+++ b/tests/test-status.t Mon Mar 20 23:16:14 2023 +0100
@@ -849,7 +849,7 @@
$ chmod 0 subdir
$ hg status --include subdir
- subdir: Permission denied
+ subdir: $EACCES$
R subdir/removed
! subdir/clean
! subdir/deleted
--- a/tests/test-template-map.t Thu Mar 09 13:02:13 2023 -0600
+++ b/tests/test-template-map.t Mon Mar 20 23:16:14 2023 +0100
@@ -1260,7 +1260,7 @@
$ touch q
$ chmod 0 q
$ hg log --style ./q
- abort: Permission denied: './q'
+ abort: $EACCES$: './q'
[255]
#endif
@@ -1309,7 +1309,7 @@
$ echo 'changeset = q' >> t
#if unix-permissions no-root
$ hg log --style ./t
- abort: template file ./q: Permission denied
+ abort: template file ./q: $EACCES$
[255]
$ rm -f q
#endif
--- a/tests/testlib/persistent-nodemap-race-ext.py Thu Mar 09 13:02:13 2023 -0600
+++ b/tests/testlib/persistent-nodemap-race-ext.py Mon Mar 20 23:16:14 2023 +0100
@@ -1,4 +1,4 @@
-"""Create the race condition for issue6554
+r"""Create the race condition for issue6554
The persistent nodemap issues had an issue where a second writer could
overwrite the data that a previous write just wrote. The would break the append