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