##// END OF EJS Templates
repovfs: add a ward to check if locks are properly taken...
Boris Feld -
r33436:9bb4decd default
parent child Browse files
Show More
@@ -234,6 +234,7 b' def reposetup(ui, repo):'
234
234
235 if util.safehasattr(ui, 'setrepo'):
235 if util.safehasattr(ui, 'setrepo'):
236 ui.setrepo(repo)
236 ui.setrepo(repo)
237 repo._wlockfreeprefix.add('blackbox.log')
237
238
238 @command('^blackbox',
239 @command('^blackbox',
239 [('l', 'limit', 10, _('the number of events to show')),
240 [('l', 'limit', 10, _('the number of events to show')),
@@ -69,6 +69,7 b' def extsetup(ui):'
69 def reposetup(ui, repo):
69 def reposetup(ui, repo):
70 if repo.local():
70 if repo.local():
71 repo.journal = journalstorage(repo)
71 repo.journal = journalstorage(repo)
72 repo._wlockfreeprefix.add('namejournal')
72
73
73 dirstate, cached = localrepo.isfilecached(repo, 'dirstate')
74 dirstate, cached = localrepo.isfilecached(repo, 'dirstate')
74 if cached:
75 if cached:
@@ -122,6 +122,10 b' def uisetup(ui):'
122 cmdutil.extraexport.append('pullurl')
122 cmdutil.extraexport.append('pullurl')
123 cmdutil.extraexportmap['pullurl'] = _addpullheader
123 cmdutil.extraexportmap['pullurl'] = _addpullheader
124
124
125 def reposetup(ui, repo):
126 if not repo.local():
127 return
128 repo._wlockfreeprefix.add('last-email.txt')
125
129
126 def prompt(ui, prompt, default=None, rest=':'):
130 def prompt(ui, prompt, default=None, rest=':'):
127 if default:
131 if default:
@@ -300,6 +300,26 b' class localrepository(object):'
300 # only functions defined in module of enabled extensions are invoked
300 # only functions defined in module of enabled extensions are invoked
301 featuresetupfuncs = set()
301 featuresetupfuncs = set()
302
302
303 # list of prefix for file which can be written without 'wlock'
304 # Extensions should extend this list when needed
305 _wlockfreeprefix = {
306 # We migh consider requiring 'wlock' for the next
307 # two, but pretty much all the existing code assume
308 # wlock is not needed so we keep them excluded for
309 # now.
310 'hgrc',
311 'requires',
312 # XXX cache is a complicatged business someone
313 # should investigate this in depth at some point
314 'cache/',
315 # XXX shouldn't be dirstate covered by the wlock?
316 'dirstate',
317 # XXX bisect was still a bit too messy at the time
318 # this changeset was introduced. Someone should fix
319 # the remainig bit and drop this line
320 'bisect.state',
321 }
322
303 def __init__(self, baseui, path, create=False):
323 def __init__(self, baseui, path, create=False):
304 self.requirements = set()
324 self.requirements = set()
305 self.filtername = None
325 self.filtername = None
@@ -319,10 +339,13 b' class localrepository(object):'
319 self.auditor = pathutil.pathauditor(self.root, self._checknested)
339 self.auditor = pathutil.pathauditor(self.root, self._checknested)
320 self.nofsauditor = pathutil.pathauditor(self.root, self._checknested,
340 self.nofsauditor = pathutil.pathauditor(self.root, self._checknested,
321 realfs=False)
341 realfs=False)
322 self.vfs = vfsmod.vfs(self.path)
323 self.baseui = baseui
342 self.baseui = baseui
324 self.ui = baseui.copy()
343 self.ui = baseui.copy()
325 self.ui.copy = baseui.copy # prevent copying repo configuration
344 self.ui.copy = baseui.copy # prevent copying repo configuration
345 self.vfs = vfsmod.vfs(self.path)
346 if (self.ui.configbool('devel', 'all-warnings') or
347 self.ui.configbool('devel', 'check-locks')):
348 self.vfs.audit = self._getvfsward(self.vfs.audit)
326 # A list of callback to shape the phase if no data were found.
349 # A list of callback to shape the phase if no data were found.
327 # Callback are in the form: func(repo, roots) --> processed root.
350 # Callback are in the form: func(repo, roots) --> processed root.
328 # This list it to be filled by extension during repo setup
351 # This list it to be filled by extension during repo setup
@@ -441,6 +464,38 b' class localrepository(object):'
441 # Signature to cached matcher instance.
464 # Signature to cached matcher instance.
442 self._sparsematchercache = {}
465 self._sparsematchercache = {}
443
466
467 def _getvfsward(self, origfunc):
468 """build a ward for self.vfs"""
469 rref = weakref.ref(self)
470 def checkvfs(path, mode=None):
471 ret = origfunc(path, mode=mode)
472 repo = rref()
473 if (repo is None
474 or not util.safehasattr(repo, '_wlockref')
475 or not util.safehasattr(repo, '_lockref')):
476 return
477 if mode in (None, 'r', 'rb'):
478 return
479 if path.startswith(repo.path):
480 # truncate name relative to the repository (.hg)
481 path = path[len(repo.path) + 1:]
482 if path.startswith('journal.'):
483 # journal is covered by 'lock'
484 if repo._currentlock(repo._lockref) is None:
485 repo.ui.develwarn('write with no lock: "%s"' % path,
486 stacklevel=2)
487 elif repo._currentlock(repo._wlockref) is None:
488 # rest of vfs files are covered by 'wlock'
489 #
490 # exclude special files
491 for prefix in self._wlockfreeprefix:
492 if path.startswith(prefix):
493 return
494 repo.ui.develwarn('write with no wlock: "%s"' % path,
495 stacklevel=2)
496 return ret
497 return checkvfs
498
444 def close(self):
499 def close(self):
445 self._writecaches()
500 self._writecaches()
446
501
@@ -44,6 +44,11 b''
44 > wl.release()
44 > wl.release()
45 > lo.release()
45 > lo.release()
46 >
46 >
47 > @command(b'no-wlock-write', [], '')
48 > def nowlockwrite(ui, repo):
49 > with repo.vfs(b'branch', 'a'):
50 > pass
51 >
47 > @command(b'stripintr', [], '')
52 > @command(b'stripintr', [], '')
48 > def stripintr(ui, repo):
53 > def stripintr(ui, repo):
49 > lo = repo.lock()
54 > lo = repo.lock()
@@ -104,6 +109,11 b''
104 $ hg properlocking
109 $ hg properlocking
105 $ hg nowaitlocking
110 $ hg nowaitlocking
106
111
112 Writing without lock
113
114 $ hg no-wlock-write
115 devel-warn: write with no wlock: "branch" at: $TESTTMP/buggylocking.py:* (nowlockwrite) (glob)
116
107 Stripping from a transaction
117 Stripping from a transaction
108
118
109 $ echo a > a
119 $ echo a > a
General Comments 0
You need to be logged in to leave comments. Login now