changeset 23841:9d25bb84cf6c

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.
author Mads Kiilerich <madski@unity3d.com>
date Fri, 09 Jan 2015 18:38:02 +0100
parents ddc17eaf0f1b
children 91dbb98b3513
files hgext/largefiles/overrides.py tests/test-largefiles-update.t
diffstat 2 files changed, 47 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/largefiles/overrides.py	Fri Jan 09 18:38:02 2015 +0100
+++ b/hgext/largefiles/overrides.py	Fri Jan 09 18:38:02 2015 +0100
@@ -1295,8 +1295,21 @@
             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
--- a/tests/test-largefiles-update.t	Fri Jan 09 18:38:02 2015 +0100
+++ b/tests/test-largefiles-update.t	Fri Jan 09 18:38:02 2015 +0100
@@ -25,6 +25,39 @@
   $ 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