largefiles: correctly handle dirstate status when rebasing
authorNa'Tosha Bard <natosha@unity3d.com>
Sat, 07 Jan 2012 18:43:34 +0100
changeset 15793 3ef07ecdb0d5
parent 15792 7cbba3adabc7
child 15794 0d91211dd12f
largefiles: correctly handle dirstate status when rebasing When rebasing, we need to trust that the standins are always correct. The rebase operation updates the standins according to the changeset it is rebasing. We need to make the largefiles in the working copy match. If we don't make them match, then they get accidentally reverted, either during the rebase or during the next commit after the rebase. This worked previously only becuase we were relying on the behavior that largefiles with a changed standin, but unchanged contents, never showed up in the list of modified largefiles. Unfortunately, pre-commit hooks can get an incorrect status this way, and it also results in extra execution of code. The solution is to simply trust the standins when we are about to commit a rebased changeset, and politely ask updatelfiles() to pull the new contents down. In this case, updatelfiles() will also mark any files it has pulled down as dirty in the lfdirstate so that pre-commit hooks will get correct status output.
hgext/largefiles/lfcommands.py
hgext/largefiles/lfutil.py
hgext/largefiles/reposetup.py
--- a/hgext/largefiles/lfcommands.py	Sat Jan 07 12:42:54 2012 +0100
+++ b/hgext/largefiles/lfcommands.py	Sat Jan 07 18:43:34 2012 +0100
@@ -455,7 +455,13 @@
             ret = -1
     state = repo.dirstate[lfutil.standin(lfile)]
     if state == 'n':
-        lfdirstate.normal(lfile)
+        # When rebasing, we need to synchronize the standin and the largefile,
+        # because otherwise the largefile will get reverted.  But for commit's
+        # sake, we have to mark the file as unclean.
+        if getattr(repo, "_isrebasing", False):
+           lfdirstate.normallookup(lfile)
+        else:
+            lfdirstate.normal(lfile)
     elif state == 'r':
         lfdirstate.remove(lfile)
     elif state == 'a':
--- a/hgext/largefiles/lfutil.py	Sat Jan 07 12:42:54 2012 +0100
+++ b/hgext/largefiles/lfutil.py	Sat Jan 07 18:43:34 2012 +0100
@@ -139,6 +139,8 @@
         return super(largefiles_dirstate, self).drop(unixpath(f))
     def forget(self, f):
         return super(largefiles_dirstate, self).forget(unixpath(f))
+    def normallookup(self, f):
+        return super(largefiles_dirstate, self).normallookup(unixpath(f))
 
 def openlfdirstate(ui, repo):
     '''
--- a/hgext/largefiles/reposetup.py	Sat Jan 07 12:42:54 2012 +0100
+++ b/hgext/largefiles/reposetup.py	Sat Jan 07 18:43:34 2012 +0100
@@ -278,14 +278,18 @@
 
             wlock = repo.wlock()
             try:
+                # Case 0: Rebase
+                # We have to take the time to pull down the new largefiles now.
+                # Otherwise if we are rebasing, any largefiles that were
+                # modified in the destination changesets get overwritten, either
+                # by the rebase or in the first commit after the rebase.
+                # updatelfiles will update the dirstate to mark any pulled
+                # largefiles as modified
                 if getattr(repo, "_isrebasing", False):
-                    # We have to take the time to pull down the new
-                    # largefiles now. Otherwise if we are rebasing,
-                    # any largefiles that were modified in the
-                    # destination changesets get overwritten, either
-                    # by the rebase or in the first commit after the
-                    # rebase.
                     lfcommands.updatelfiles(repo.ui, repo)
+                    result = orig(text=text, user=user, date=date, match=match,
+                                    force=force, editor=editor, extra=extra)
+                    return result
                 # Case 1: user calls commit with no specific files or
                 # include/exclude patterns: refresh and commit all files that
                 # are "dirty".