Show More
@@ -0,0 +1,11 b'' | |||||
|
1 | #!/bin/sh | |||
|
2 | ||||
|
3 | hg init a | |||
|
4 | echo a > a/a | |||
|
5 | hg --cwd a ci -A -m a | |||
|
6 | hg clone a b | |||
|
7 | echo b > b/b | |||
|
8 | hg --cwd b ci -A -m b | |||
|
9 | chmod 100 a/.hg | |||
|
10 | hg --cwd b push ../a | |||
|
11 | chmod 700 a/.hg |
@@ -0,0 +1,4 b'' | |||||
|
1 | adding a | |||
|
2 | adding b | |||
|
3 | pushing to ../a | |||
|
4 | abort: could not lock repository ../a: Permission denied |
@@ -1244,12 +1244,8 b' def copy(ui, repo, *pats, **opts):' | |||||
1244 | should properly record copied files, this information is not yet |
|
1244 | should properly record copied files, this information is not yet | |
1245 | fully used by merge, nor fully reported by log. |
|
1245 | fully used by merge, nor fully reported by log. | |
1246 | """ |
|
1246 | """ | |
1247 | try: |
|
1247 | wlock = repo.wlock(0) | |
1248 | wlock = repo.wlock(0) |
|
1248 | errs, copied = docopy(ui, repo, pats, opts, wlock) | |
1249 | errs, copied = docopy(ui, repo, pats, opts, wlock) |
|
|||
1250 | except lock.LockHeld, inst: |
|
|||
1251 | ui.warn(_("repository lock held by %s\n") % inst.args[0]) |
|
|||
1252 | errs = 1 |
|
|||
1253 | return errs |
|
1249 | return errs | |
1254 |
|
1250 | |||
1255 | def debugancestor(ui, index, rev1, rev2): |
|
1251 | def debugancestor(ui, index, rev1, rev2): | |
@@ -2256,18 +2252,14 b' def rename(ui, repo, *pats, **opts):' | |||||
2256 | should properly record rename files, this information is not yet |
|
2252 | should properly record rename files, this information is not yet | |
2257 | fully used by merge, nor fully reported by log. |
|
2253 | fully used by merge, nor fully reported by log. | |
2258 | """ |
|
2254 | """ | |
2259 | try: |
|
2255 | wlock = repo.wlock(0) | |
2260 | wlock = repo.wlock(0) |
|
2256 | errs, copied = docopy(ui, repo, pats, opts, wlock) | |
2261 | errs, copied = docopy(ui, repo, pats, opts, wlock) |
|
2257 | names = [] | |
2262 | names = [] |
|
2258 | for abs, rel, exact in copied: | |
2263 | for abs, rel, exact in copied: |
|
2259 | if ui.verbose or not exact: | |
2264 | if ui.verbose or not exact: |
|
2260 | ui.status(_('removing %s\n') % rel) | |
2265 | ui.status(_('removing %s\n') % rel) |
|
2261 | names.append(abs) | |
2266 | names.append(abs) |
|
2262 | repo.remove(names, True, wlock) | |
2267 | repo.remove(names, True, wlock) |
|
|||
2268 | except lock.LockHeld, inst: |
|
|||
2269 | ui.warn(_("repository lock held by %s\n") % inst.args[0]) |
|
|||
2270 | errs = 1 |
|
|||
2271 | return errs |
|
2263 | return errs | |
2272 |
|
2264 | |||
2273 | def revert(ui, repo, *pats, **opts): |
|
2265 | def revert(ui, repo, *pats, **opts): | |
@@ -3252,6 +3244,15 b' def dispatch(args):' | |||||
3252 | sys.exit(1) |
|
3244 | sys.exit(1) | |
3253 | except hg.RepoError, inst: |
|
3245 | except hg.RepoError, inst: | |
3254 | u.warn(_("abort: "), inst, "!\n") |
|
3246 | u.warn(_("abort: "), inst, "!\n") | |
|
3247 | except lock.LockHeld, inst: | |||
|
3248 | if inst.errno == errno.ETIMEDOUT: | |||
|
3249 | reason = _('timed out waiting for lock held by %s') % inst.locker | |||
|
3250 | else: | |||
|
3251 | reason = _('lock held by %s') % inst.locker | |||
|
3252 | u.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason)) | |||
|
3253 | except lock.LockUnavailable, inst: | |||
|
3254 | u.warn(_("abort: could not lock %s: %s\n") % | |||
|
3255 | (inst.desc or inst.filename, inst.strerror)) | |||
3255 | except revlog.RevlogError, inst: |
|
3256 | except revlog.RevlogError, inst: | |
3256 | u.warn(_("abort: "), inst, "!\n") |
|
3257 | u.warn(_("abort: "), inst, "!\n") | |
3257 | except SignalInterrupt: |
|
3258 | except SignalInterrupt: |
@@ -31,6 +31,7 b' class localrepository(object):' | |||||
31 | raise repo.RepoError(_("repository %s not found") % path) |
|
31 | raise repo.RepoError(_("repository %s not found") % path) | |
32 |
|
32 | |||
33 | self.root = os.path.abspath(path) |
|
33 | self.root = os.path.abspath(path) | |
|
34 | self.origroot = path | |||
34 | self.ui = ui.ui(parentui=parentui) |
|
35 | self.ui = ui.ui(parentui=parentui) | |
35 | self.opener = util.opener(self.path) |
|
36 | self.opener = util.opener(self.path) | |
36 | self.wopener = util.opener(self.root) |
|
37 | self.wopener = util.opener(self.root) | |
@@ -261,32 +262,31 b' class localrepository(object):' | |||||
261 | self.tagscache = None |
|
262 | self.tagscache = None | |
262 | self.nodetagscache = None |
|
263 | self.nodetagscache = None | |
263 |
|
264 | |||
264 |
def do_lock(self, lockname, wait, releasefn=None, acquirefn=None |
|
265 | def do_lock(self, lockname, wait, releasefn=None, acquirefn=None, | |
|
266 | desc=None): | |||
265 | try: |
|
267 | try: | |
266 | l = lock.lock(self.join(lockname), 0, releasefn) |
|
268 | l = lock.lock(self.join(lockname), 0, releasefn, desc=desc) | |
267 | except lock.LockHeld, inst: |
|
269 | except lock.LockHeld, inst: | |
268 | if not wait: |
|
270 | if not wait: | |
269 |
raise |
|
271 | raise | |
270 |
self.ui.warn(_("waiting for lock held by %s\n") % |
|
272 | self.ui.warn(_("waiting for lock on %s held by %s\n") % | |
271 | try: |
|
273 | (desc, inst.args[0])) | |
272 |
|
|
274 | # default to 600 seconds timeout | |
273 |
|
|
275 | l = lock.lock(self.join(lockname), | |
274 |
|
|
276 | int(self.ui.config("ui", "timeout") or 600), | |
275 |
|
|
277 | releasefn, desc=desc) | |
276 | except lock.LockHeld, inst: |
|
|||
277 | raise util.Abort(_("timeout while waiting for " |
|
|||
278 | "lock held by %s") % inst.args[0]) |
|
|||
279 | if acquirefn: |
|
278 | if acquirefn: | |
280 | acquirefn() |
|
279 | acquirefn() | |
281 | return l |
|
280 | return l | |
282 |
|
281 | |||
283 | def lock(self, wait=1): |
|
282 | def lock(self, wait=1): | |
284 |
return self.do_lock("lock", wait, acquirefn=self.reload |
|
283 | return self.do_lock("lock", wait, acquirefn=self.reload, | |
|
284 | desc=_('repository %s') % self.origroot) | |||
285 |
|
285 | |||
286 | def wlock(self, wait=1): |
|
286 | def wlock(self, wait=1): | |
287 | return self.do_lock("wlock", wait, |
|
287 | return self.do_lock("wlock", wait, self.dirstate.write, | |
288 |
self. |
|
288 | self.wreload, | |
289 |
self. |
|
289 | desc=_('working directory of %s') % self.origroot) | |
290 |
|
290 | |||
291 | def checkfilemerge(self, filename, text, filelog, manifest1, manifest2): |
|
291 | def checkfilemerge(self, filename, text, filelog, manifest1, manifest2): | |
292 | "determine whether a new filenode is needed" |
|
292 | "determine whether a new filenode is needed" |
@@ -8,10 +8,16 b'' | |||||
8 | from demandload import * |
|
8 | from demandload import * | |
9 | demandload(globals(), 'errno os socket time util') |
|
9 | demandload(globals(), 'errno os socket time util') | |
10 |
|
10 | |||
11 |
class LockException( |
|
11 | class LockException(IOError): | |
12 | pass |
|
12 | def __init__(self, errno, strerror, filename, desc): | |
|
13 | IOError.__init__(self, errno, strerror, filename) | |||
|
14 | self.desc = desc | |||
|
15 | ||||
13 | class LockHeld(LockException): |
|
16 | class LockHeld(LockException): | |
14 | pass |
|
17 | def __init__(self, errno, filename, desc, locker): | |
|
18 | LockException.__init__(self, errno, 'Lock held', filename, desc) | |||
|
19 | self.locker = locker | |||
|
20 | ||||
15 | class LockUnavailable(LockException): |
|
21 | class LockUnavailable(LockException): | |
16 | pass |
|
22 | pass | |
17 |
|
23 | |||
@@ -24,7 +30,7 b' class lock(object):' | |||||
24 | # old-style lock: symlink to pid |
|
30 | # old-style lock: symlink to pid | |
25 | # new-style lock: symlink to hostname:pid |
|
31 | # new-style lock: symlink to hostname:pid | |
26 |
|
32 | |||
27 | def __init__(self, file, timeout=-1, releasefn=None): |
|
33 | def __init__(self, file, timeout=-1, releasefn=None, desc=None): | |
28 | self.f = file |
|
34 | self.f = file | |
29 | self.held = 0 |
|
35 | self.held = 0 | |
30 | self.timeout = timeout |
|
36 | self.timeout = timeout | |
@@ -32,6 +38,7 b' class lock(object):' | |||||
32 | self.id = None |
|
38 | self.id = None | |
33 | self.host = None |
|
39 | self.host = None | |
34 | self.pid = None |
|
40 | self.pid = None | |
|
41 | self.desc = desc | |||
35 | self.lock() |
|
42 | self.lock() | |
36 |
|
43 | |||
37 | def __del__(self): |
|
44 | def __del__(self): | |
@@ -49,7 +56,8 b' class lock(object):' | |||||
49 | if timeout > 0: |
|
56 | if timeout > 0: | |
50 | timeout -= 1 |
|
57 | timeout -= 1 | |
51 | continue |
|
58 | continue | |
52 | raise inst |
|
59 | raise LockHeld(errno.ETIMEDOUT, inst.filename, self.desc, | |
|
60 | inst.locker) | |||
53 |
|
61 | |||
54 | def trylock(self): |
|
62 | def trylock(self): | |
55 | if self.id is None: |
|
63 | if self.id is None: | |
@@ -64,9 +72,11 b' class lock(object):' | |||||
64 | if why.errno == errno.EEXIST: |
|
72 | if why.errno == errno.EEXIST: | |
65 | locker = self.testlock() |
|
73 | locker = self.testlock() | |
66 | if locker: |
|
74 | if locker: | |
67 |
raise LockHeld( |
|
75 | raise LockHeld(errno.EAGAIN, self.f, self.desc, | |
|
76 | locker) | |||
68 | else: |
|
77 | else: | |
69 |
raise LockUnavailable(why |
|
78 | raise LockUnavailable(why.errno, why.strerror, | |
|
79 | why.filename, self.desc) | |||
70 |
|
80 | |||
71 | def testlock(self): |
|
81 | def testlock(self): | |
72 | '''return id of locker if lock is valid, else None.''' |
|
82 | '''return id of locker if lock is valid, else None.''' |
General Comments 0
You need to be logged in to leave comments.
Login now