diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py --- a/mercurial/dirstate.py +++ b/mercurial/dirstate.py @@ -27,6 +27,7 @@ policy, pycompat, scmutil, + sparse, txnutil, util, ) @@ -1083,7 +1084,7 @@ results[next(iv)] = st return results - def _rust_status(self, matcher, list_clean): + def _rust_status(self, matcher, list_clean, list_ignored, list_unknown): # Force Rayon (Rust parallelism library) to respect the number of # workers. This is a temporary workaround until Rust code knows # how to read the config file. @@ -1101,16 +1102,45 @@ added, removed, deleted, + clean, + ignored, unknown, - clean, + warnings, + bad, ) = rustmod.status( self._map._rustmap, matcher, self._rootdir, - bool(list_clean), + self._ignorefiles(), + self._checkexec, self._lastnormaltime, - self._checkexec, + bool(list_clean), + bool(list_ignored), + bool(list_unknown), ) + if self._ui.warn: + for item in warnings: + if isinstance(item, tuple): + file_path, syntax = item + msg = _(b"%s: ignoring invalid syntax '%s'\n") % ( + file_path, + syntax, + ) + self._ui.warn(msg) + else: + msg = _(b"skipping unreadable pattern file '%s': %s\n") + self._ui.warn( + msg + % ( + pathutil.canonpath( + self._rootdir, self._rootdir, item + ), + b"No such file or directory", + ) + ) + + for (fn, message) in bad: + matcher.bad(fn, encoding.strtolocal(message)) status = scmutil.status( modified=modified, @@ -1118,7 +1148,7 @@ removed=removed, deleted=deleted, unknown=unknown, - ignored=[], + ignored=ignored, clean=clean, ) return (lookup, status) @@ -1148,26 +1178,34 @@ use_rust = True - allowed_matchers = (matchmod.alwaysmatcher, matchmod.exactmatcher) + allowed_matchers = ( + matchmod.alwaysmatcher, + matchmod.exactmatcher, + matchmod.includematcher, + ) if rustmod is None: use_rust = False + elif self._checkcase: + # Case-insensitive filesystems are not handled yet + use_rust = False elif subrepos: use_rust = False - elif bool(listunknown): - # Pathauditor does not exist yet in Rust, unknown files - # can't be trusted. + elif sparse.enabled: use_rust = False - elif self._ignorefiles() and listignored: - # Rust has no ignore mechanism yet, so don't use Rust for - # commands that need ignore. + elif match.traversedir is not None: use_rust = False elif not isinstance(match, allowed_matchers): # Matchers have yet to be implemented use_rust = False if use_rust: - return self._rust_status(match, listclean) + try: + return self._rust_status( + match, listclean, listignored, listunknown + ) + except rustmod.FallbackError: + pass def noop(f): pass @@ -1249,13 +1287,10 @@ aadd(fn) elif state == b'r': radd(fn) - - return ( - lookup, - scmutil.status( - modified, added, removed, deleted, unknown, ignored, clean - ), + status = scmutil.status( + modified, added, removed, deleted, unknown, ignored, clean ) + return (lookup, status) def matches(self, match): ''' diff --git a/mercurial/match.py b/mercurial/match.py --- a/mercurial/match.py +++ b/mercurial/match.py @@ -666,7 +666,10 @@ class includematcher(basematcher): def __init__(self, root, kindpats, badfn=None): super(includematcher, self).__init__(badfn) - + if rustmod is not None: + # We need to pass the patterns to Rust because they can contain + # patterns from the user interface + self._kindpats = kindpats self._pats, self.matchfn = _buildmatch(kindpats, b'(?:/|$)', root) self._prefix = _prefix(kindpats) roots, dirs, parents = _rootsdirsandparents(kindpats) diff --git a/tests/test-subrepo-deep-nested-change.t b/tests/test-subrepo-deep-nested-change.t --- a/tests/test-subrepo-deep-nested-change.t +++ b/tests/test-subrepo-deep-nested-change.t @@ -355,6 +355,11 @@ R sub1/sub2/folder/test.txt ! sub1/.hgsub ? sub1/x.hgsub + $ hg status -R sub1 + warning: subrepo spec file 'sub1/.hgsub' not found + R .hgsubstate + ! .hgsub + ? x.hgsub $ mv sub1/x.hgsub sub1/.hgsub $ hg update -Cq $ touch sub1/foo