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.
--- 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".