[PATCH 3 of 3] largefiles: make linear update set unsure largefiles normal if unchanged

Mads Kiilerich mads at kiilerich.com
Fri Jan 9 18:50:12 CST 2015


# HG changeset patch
# User Mads Kiilerich <madski at unity3d.com>
# Date 1420825082 -3600
#      Fri Jan 09 18:38:02 2015 +0100
# Node ID 68f2429652af3df3dde42ce1e9ebd9e02b910d6c
# Parent  3efb0c54f8e86ea5e78a2509c6746ccdd219196b
largefiles: make linear update set unsure largefiles normal if unchanged

'hg update' would hash all 'unsure' largefiles before performing the merge. It
would update the standins but not detect the very common case where the
largefile never had been changed by the user but just had been marked with an
invalid dirstate mtime to make sure any changes done by the user in the same
second would be detected. The largefile would remain in that state and would
have to be hashed again next time even though it still not had been changed.
Sad trombone.

Instead, for largefiles listed as 'unsure' or 'modified', after updating the
standin with the actual hash, mark the largefile as normal if it turns out to
not be modified relative to the revision in the parent revision. That will
prevent it from being hashed again next time.

diff --git a/hgext/largefiles/overrides.py b/hgext/largefiles/overrides.py
--- a/hgext/largefiles/overrides.py
+++ b/hgext/largefiles/overrides.py
@@ -1295,8 +1295,21 @@ def mergeupdate(orig, repo, node, branch
             unsure, s = lfdirstate.status(match_.always(repo.root,
                                                         repo.getcwd()),
                                           [], False, False, False)
-            for lfile in unsure + s.modified + s.added:
+            pctx = repo['.']
+            for lfile in unsure + s.modified:
+                lfileabs = repo.wvfs.join(lfile)
+                if not os.path.exists(lfileabs):
+                    continue
+                lfhash = lfutil.hashrepofile(repo, lfile)
+                standin = lfutil.standin(lfile)
+                lfutil.writestandin(repo, standin, lfhash,
+                                    lfutil.getexecutable(lfileabs))
+                if (standin in pctx and
+                    lfhash == lfutil.readstandin(repo, lfile, '.')):
+                    lfdirstate.normal(lfile)
+            for lfile in s.added:
                 lfutil.updatestandin(repo, lfutil.standin(lfile))
+            lfdirstate.write()
 
         if linearmerge:
             # Only call updatelfiles on the standins that have changed
diff --git a/tests/test-largefiles-update.t b/tests/test-largefiles-update.t
--- a/tests/test-largefiles-update.t
+++ b/tests/test-largefiles-update.t
@@ -25,6 +25,39 @@ directory (and ".hg/largefiles/dirstate"
   $ hg commit -m '#2'
   created new head
 
+Test that update also updates the lfdirstate of 'unsure' largefiles after
+hashing them:
+
+The previous operations will usually have left us with largefiles with a mtime
+within the same second as the dirstate was written.
+The lfdirstate entries will thus have been written with an invalidated/unset
+mtime to make sure further changes within the same second is detected.
+We will however occasionally be "lucky" and get a tick between writing
+largefiles and writing dirstate so we get valid lfdirstate timestamps. The
+following verification is thus disabled but can be verified manually.
+
+#if false
+  $ hg debugdirstate --large --nodate
+  n 644          7 unset               large1
+  n 644         13 unset               large2
+#endif
+
+Wait to make sure we get a tick so the mtime of the largefiles become valid.
+
+  $ sleep 1
+
+A linear merge will update standins before performing the actual merge. It will
+do a lfdirstate status walk and find 'unset'/'unsure' files, hash them, and
+update the corresponding standins.
+Verify that it actually marks the clean files as clean in lfdirstate so
+we don't have to hash them again next time we update.
+
+  $ hg up
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg debugdirstate --large --nodate
+  n 644          7 set                 large1
+  n 644         13 set                 large2
+
 Test that lfdirstate keeps track of last modification of largefiles and
 prevents unnecessary hashing of content - also after linear/noop update
 


More information about the Mercurial-devel mailing list