# HG changeset patch # User Pierre-Yves David # Date 1677119144 -3600 # Node ID f18e4608bb617e2c42a9fbedae4adb4cfd704b39 # Parent 8bc14ac53a41acf701401b1bfc872e7bd33bbf47 narrow: delegate the dirstate's narrow spec writing to the transaction This make it more transactional and will help us to simplify their backup. The implementation is not great, but it keep the patch simple as this is not the time for a larger refactoring yet. diff -r 8bc14ac53a41 -r f18e4608bb61 mercurial/localrepo.py --- a/mercurial/localrepo.py Thu Feb 23 04:15:16 2023 +0100 +++ b/mercurial/localrepo.py Thu Feb 23 03:25:44 2023 +0100 @@ -1470,6 +1470,7 @@ self._postdsstatus = [] self._pending_narrow_pats = None + self._pending_narrow_pats_dirstate = None # generic mapping between names and nodes self.names = namespaces.namespaces() diff -r 8bc14ac53a41 -r f18e4608bb61 mercurial/narrowspec.py --- a/mercurial/narrowspec.py Thu Feb 23 04:15:16 2023 +0100 +++ b/mercurial/narrowspec.py Thu Feb 23 03:25:44 2023 +0100 @@ -212,8 +212,34 @@ def copytoworkingcopy(repo): + repo = repo.unfiltered() + tr = repo.currenttransaction() spec = format(*repo.narrowpats) - repo.vfs.write(DIRSTATE_FILENAME, spec) + if tr is None: + repo.vfs.write(DIRSTATE_FILENAME, spec) + else: + + reporef = weakref.ref(repo) + + def clean_pending(tr): + r = reporef() + if r is not None: + r._pending_narrow_pats_dirstate = None + + tr.addpostclose(b'narrow-spec-dirstate', clean_pending) + tr.addabort(b'narrow-spec-dirstate', clean_pending) + repo._pending_narrow_pats_dirstate = repo.narrowpats + + def write_spec(f): + f.write(spec) + + tr.addfilegenerator( + # XXX think about order at some point + b"narrow-spec-dirstate", + (DIRSTATE_FILENAME,), + write_spec, + location=b'plain', + ) def savebackup(repo, backupname): @@ -328,8 +354,10 @@ if getattr(repo, '_updatingnarrowspec', False): return storespec = repo.narrowpats - wcspec = repo.vfs.tryread(DIRSTATE_FILENAME) - wcspec = parseconfig(repo.ui, wcspec) + wcspec = repo._pending_narrow_pats_dirstate + if wcspec is None: + oldspec = repo.vfs.tryread(DIRSTATE_FILENAME) + wcspec = parseconfig(repo.ui, oldspec) if wcspec != storespec: raise error.StateError( _(b"working copy's narrowspec is stale"), @@ -343,11 +371,15 @@ When assumeclean=True, files that are not known to be clean will also be deleted. It is then up to the caller to make sure they are clean. """ - oldspec = repo.vfs.tryread(DIRSTATE_FILENAME) + old = repo._pending_narrow_pats_dirstate + if old is None: + oldspec = repo.vfs.tryread(DIRSTATE_FILENAME) + oldincludes, oldexcludes = parseconfig(repo.ui, oldspec) + else: + oldincludes, oldexcludes = old newincludes, newexcludes = repo.narrowpats repo._updatingnarrowspec = True - oldincludes, oldexcludes = parseconfig(repo.ui, oldspec) oldmatch = match(repo.root, include=oldincludes, exclude=oldexcludes) newmatch = match(repo.root, include=newincludes, exclude=newexcludes) addedmatch = matchmod.differencematcher(newmatch, oldmatch)