Patchwork D11785: status: gather fixup info at comparison time

login
register
mail settings
Submitter phabricator
Date Nov. 24, 2021, 11:13 a.m.
Message ID <differential-rev-PHID-DREV-resklclimuvaaee3ivax-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/50113/
State New
Headers show

Comments

phabricator - Nov. 24, 2021, 11:13 a.m.
marmoute created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  This is still racy, but the API make it possible for it to not be racy. This
  also unlock other cleanups that we are about to do.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D11785

AFFECTED FILES
  mercurial/context.py

CHANGE DETAILS




To: marmoute, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/mercurial/context.py b/mercurial/context.py
--- a/mercurial/context.py
+++ b/mercurial/context.py
@@ -46,6 +46,9 @@ 
     dateutil,
     stringutil,
 )
+from .dirstateutils import (
+    timestamp,
+)
 
 propertycache = util.propertycache
 
@@ -1814,7 +1817,20 @@ 
                 ):
                     modified.append(f)
                 else:
-                    fixup.append(f)
+                    # XXX not that we have a race windows here since we gather
+                    # the stats after we compared so the file might have
+                    # changed.
+                    #
+                    # However this have been the case because and the
+                    # refactoring moving the code here is improving the
+                    # situation by narrowing the race and moving the two steps
+                    # (comparison + stat) in the same location. So making this
+                    # "correct" is now possible.
+                    s = self[f].lstat()
+                    mode = s.st_mode
+                    size = s.st_size
+                    mtime = timestamp.mtime_of(s)
+                    fixup.append((f, (mode, size, mtime)))
             except (IOError, OSError):
                 # A file become inaccessible in between? Mark it as deleted,
                 # matching dirstate behavior (issue5584).
@@ -1842,13 +1858,13 @@ 
                     if dirstate.identity() == oldid:
                         if fixup:
                             if dirstate.pendingparentchange():
-                                normal = lambda f: dirstate.update_file(
+                                normal = lambda f, pfd: dirstate.update_file(
                                     f, p1_tracked=True, wc_tracked=True
                                 )
                             else:
                                 normal = dirstate.set_clean
-                            for f in fixup:
-                                normal(f)
+                            for f, pdf in fixup:
+                                normal(f, pdf)
                             # write changes out explicitly, because nesting
                             # wlock at runtime may prevent 'wlock.release()'
                             # after this block from doing so for subsequent
@@ -1890,7 +1906,7 @@ 
             s.deleted.extend(deleted2)
 
             if fixup and clean:
-                s.clean.extend(fixup)
+                s.clean.extend((f for f, _ in fixup))
 
         self._poststatusfixup(s, fixup)