comparison hgext/largefiles/lfutil.py @ 15794:0d91211dd12f

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.
author Levi Bard <levi@unity3d.com>
date Sat, 07 Jan 2012 19:05:59 +0100
parents 3ef07ecdb0d5
children 3e5b6045ccfc
comparison
equal deleted inserted replaced
15793:3ef07ecdb0d5 15794:0d91211dd12f
152 lfdirstate = largefiles_dirstate(opener, ui, repo.root, 152 lfdirstate = largefiles_dirstate(opener, ui, repo.root,
153 repo.dirstate._validate) 153 repo.dirstate._validate)
154 154
155 # If the largefiles dirstate does not exist, populate and create 155 # If the largefiles dirstate does not exist, populate and create
156 # it. This ensures that we create it on the first meaningful 156 # it. This ensures that we create it on the first meaningful
157 # largefiles operation in a new clone. It also gives us an easy 157 # largefiles operation in a new clone.
158 # way to forcibly rebuild largefiles state:
159 # rm .hg/largefiles/dirstate && hg status
160 # Or even, if things are really messed up:
161 # rm -rf .hg/largefiles && hg status
162 if not os.path.exists(os.path.join(admin, 'dirstate')): 158 if not os.path.exists(os.path.join(admin, 'dirstate')):
163 util.makedirs(admin) 159 util.makedirs(admin)
164 matcher = getstandinmatcher(repo) 160 matcher = getstandinmatcher(repo)
165 for standin in dirstate_walk(repo.dirstate, matcher): 161 for standin in dirstate_walk(repo.dirstate, matcher):
166 lfile = splitstandin(standin) 162 lfile = splitstandin(standin)
170 if hash == hashfile(repo.wjoin(lfile)): 166 if hash == hashfile(repo.wjoin(lfile)):
171 lfdirstate.normal(lfile) 167 lfdirstate.normal(lfile)
172 except OSError, err: 168 except OSError, err:
173 if err.errno != errno.ENOENT: 169 if err.errno != errno.ENOENT:
174 raise 170 raise
175
176 lfdirstate.write()
177
178 return lfdirstate 171 return lfdirstate
179 172
180 def lfdirstate_status(lfdirstate, repo, rev): 173 def lfdirstate_status(lfdirstate, repo, rev):
181 wlock = repo.wlock() 174 match = match_.always(repo.root, repo.getcwd())
182 try: 175 s = lfdirstate.status(match, [], False, False, False)
183 match = match_.always(repo.root, repo.getcwd()) 176 unsure, modified, added, removed, missing, unknown, ignored, clean = s
184 s = lfdirstate.status(match, [], False, False, False) 177 for lfile in unsure:
185 unsure, modified, added, removed, missing, unknown, ignored, clean = s 178 if repo[rev][standin(lfile)].data().strip() != \
186 for lfile in unsure: 179 hashfile(repo.wjoin(lfile)):
187 if repo[rev][standin(lfile)].data().strip() != \ 180 modified.append(lfile)
188 hashfile(repo.wjoin(lfile)): 181 else:
189 modified.append(lfile) 182 clean.append(lfile)
190 else: 183 lfdirstate.normal(lfile)
191 clean.append(lfile)
192 lfdirstate.normal(lfile)
193 lfdirstate.write()
194 finally:
195 wlock.release()
196 return (modified, added, removed, missing, unknown, ignored, clean) 184 return (modified, added, removed, missing, unknown, ignored, clean)
197 185
198 def listlfiles(repo, rev=None, matcher=None): 186 def listlfiles(repo, rev=None, matcher=None):
199 '''return a list of largefiles in the working copy or the 187 '''return a list of largefiles in the working copy or the
200 specified changeset''' 188 specified changeset'''