largefiles: fix inappropriate locking (
issue3182)
Don't lock/write on operations that should be readonly (status).
Always lock when writing the lfdirstate (rollback).
Don't write lfdirstate until after committing; state isn't actually changed
until the commit is complete.
--- a/hgext/largefiles/lfutil.py Sat Jan 07 18:43:34 2012 +0100
+++ b/hgext/largefiles/lfutil.py Sat Jan 07 19:05:59 2012 +0100
@@ -154,11 +154,7 @@
# If the largefiles dirstate does not exist, populate and create
# it. This ensures that we create it on the first meaningful
- # largefiles operation in a new clone. It also gives us an easy
- # way to forcibly rebuild largefiles state:
- # rm .hg/largefiles/dirstate && hg status
- # Or even, if things are really messed up:
- # rm -rf .hg/largefiles && hg status
+ # largefiles operation in a new clone.
if not os.path.exists(os.path.join(admin, 'dirstate')):
util.makedirs(admin)
matcher = getstandinmatcher(repo)
@@ -172,27 +168,19 @@
except OSError, err:
if err.errno != errno.ENOENT:
raise
-
- lfdirstate.write()
-
return lfdirstate
def lfdirstate_status(lfdirstate, repo, rev):
- wlock = repo.wlock()
- try:
- match = match_.always(repo.root, repo.getcwd())
- s = lfdirstate.status(match, [], False, False, False)
- unsure, modified, added, removed, missing, unknown, ignored, clean = s
- for lfile in unsure:
- if repo[rev][standin(lfile)].data().strip() != \
- hashfile(repo.wjoin(lfile)):
- modified.append(lfile)
- else:
- clean.append(lfile)
- lfdirstate.normal(lfile)
- lfdirstate.write()
- finally:
- wlock.release()
+ match = match_.always(repo.root, repo.getcwd())
+ s = lfdirstate.status(match, [], False, False, False)
+ unsure, modified, added, removed, missing, unknown, ignored, clean = s
+ for lfile in unsure:
+ if repo[rev][standin(lfile)].data().strip() != \
+ hashfile(repo.wjoin(lfile)):
+ modified.append(lfile)
+ else:
+ clean.append(lfile)
+ lfdirstate.normal(lfile)
return (modified, added, removed, missing, unknown, ignored, clean)
def listlfiles(repo, rev=None, matcher=None):
--- a/hgext/largefiles/overrides.py Sat Jan 07 18:43:34 2012 +0100
+++ b/hgext/largefiles/overrides.py Sat Jan 07 19:05:59 2012 +0100
@@ -910,15 +910,19 @@
result = orig(ui, repo, **opts)
merge.update(repo, node=None, branchmerge=False, force=True,
partial=lfutil.isstandin)
- lfdirstate = lfutil.openlfdirstate(ui, repo)
- lfiles = lfutil.listlfiles(repo)
- oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev())
- for file in lfiles:
- if file in oldlfiles:
- lfdirstate.normallookup(file)
- else:
- lfdirstate.add(file)
- lfdirstate.write()
+ wlock = repo.wlock()
+ try:
+ lfdirstate = lfutil.openlfdirstate(ui, repo)
+ lfiles = lfutil.listlfiles(repo)
+ oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev())
+ for file in lfiles:
+ if file in oldlfiles:
+ lfdirstate.normallookup(file)
+ else:
+ lfdirstate.add(file)
+ lfdirstate.write()
+ finally:
+ wlock.release()
return result
def override_transplant(orig, ui, repo, *revs, **opts):
--- a/hgext/largefiles/reposetup.py Sat Jan 07 18:43:34 2012 +0100
+++ b/hgext/largefiles/reposetup.py Sat Jan 07 19:05:59 2012 +0100
@@ -147,9 +147,6 @@
result = super(lfiles_repo, self).status(node1, node2, m,
True, clean, unknown, listsubrepos)
if working:
- # hold the wlock while we read largefiles and
- # update the lfdirstate
- wlock = repo.wlock()
try:
# Any non-largefiles that were explicitly listed must be
# taken out or lfdirstate.status will report an error.
@@ -186,7 +183,6 @@
else:
clean.append(lfile)
lfdirstate.normal(lfile)
- lfdirstate.write()
else:
tocheck = unsure + modified + added + clean
modified, added, clean = [], [], []
@@ -201,10 +197,9 @@
clean.append(lfile)
else:
added.append(lfile)
+ finally:
# Replace the original ignore function
lfdirstate._ignore = orig_ignore
- finally:
- wlock.release()
for standin in ctx1.manifest():
if not lfutil.isstandin(standin):
@@ -324,10 +319,13 @@
if not os.path.exists(
repo.wjoin(lfutil.standin(lfile))):
lfdirstate.drop(lfile)
+
+ result = orig(text=text, user=user, date=date, match=match,
+ force=force, editor=editor, extra=extra)
+ # This needs to be after commit; otherwise precommit hooks
+ # get the wrong status
lfdirstate.write()
-
- return orig(text=text, user=user, date=date, match=match,
- force=force, editor=editor, extra=extra)
+ return result
for f in match.files():
if lfutil.isstandin(f):
@@ -359,7 +357,6 @@
lfdirstate.normal(lfile)
else:
lfdirstate.drop(lfile)
- lfdirstate.write()
# Cook up a new matcher that only matches regular files or
# standins corresponding to the big files requested by the
@@ -400,8 +397,12 @@
return f in standins
match.matchfn = matchfn
- return orig(text=text, user=user, date=date, match=match,
+ result = orig(text=text, user=user, date=date, match=match,
force=force, editor=editor, extra=extra)
+ # This needs to be after commit; otherwise precommit hooks
+ # get the wrong status
+ lfdirstate.write()
+ return result
finally:
wlock.release()
--- a/tests/test-largefiles-small-disk.t Sat Jan 07 18:43:34 2012 +0100
+++ b/tests/test-largefiles-small-disk.t Sat Jan 07 19:05:59 2012 +0100
@@ -65,4 +65,3 @@
The largefile is not created in .hg/largefiles:
$ ls bob/.hg/largefiles
- dirstate