changeset 2016:ff5c9a92f556

fix backtrace printed when cannot get lock. change lock error handling code so exceptions have useful info and exception handling in one place. add test case for when cannot get lock.
author Vadim Gelfer <vadim.gelfer@gmail.com>
date Tue, 28 Mar 2006 09:01:07 -0800
parents 182f500805db
children 4c03bc02c779
files mercurial/commands.py mercurial/localrepo.py mercurial/lock.py tests/test-lock-badness tests/test-lock-badness.out
diffstat 5 files changed, 67 insertions(+), 41 deletions(-) [+]
line wrap: on
line diff
--- a/mercurial/commands.py	Sun Mar 26 22:54:05 2006 +0200
+++ b/mercurial/commands.py	Tue Mar 28 09:01:07 2006 -0800
@@ -1244,12 +1244,8 @@
     should properly record copied files, this information is not yet
     fully used by merge, nor fully reported by log.
     """
-    try:
-        wlock = repo.wlock(0)
-        errs, copied = docopy(ui, repo, pats, opts, wlock)
-    except lock.LockHeld, inst:
-        ui.warn(_("repository lock held by %s\n") % inst.args[0])
-        errs = 1
+    wlock = repo.wlock(0)
+    errs, copied = docopy(ui, repo, pats, opts, wlock)
     return errs
 
 def debugancestor(ui, index, rev1, rev2):
@@ -2256,18 +2252,14 @@
     should properly record rename files, this information is not yet
     fully used by merge, nor fully reported by log.
     """
-    try:
-        wlock = repo.wlock(0)
-        errs, copied = docopy(ui, repo, pats, opts, wlock)
-        names = []
-        for abs, rel, exact in copied:
-            if ui.verbose or not exact:
-                ui.status(_('removing %s\n') % rel)
-            names.append(abs)
-        repo.remove(names, True, wlock)
-    except lock.LockHeld, inst:
-        ui.warn(_("repository lock held by %s\n") % inst.args[0])
-        errs = 1
+    wlock = repo.wlock(0)
+    errs, copied = docopy(ui, repo, pats, opts, wlock)
+    names = []
+    for abs, rel, exact in copied:
+        if ui.verbose or not exact:
+            ui.status(_('removing %s\n') % rel)
+        names.append(abs)
+    repo.remove(names, True, wlock)
     return errs
 
 def revert(ui, repo, *pats, **opts):
@@ -3252,6 +3244,15 @@
         sys.exit(1)
     except hg.RepoError, inst:
         u.warn(_("abort: "), inst, "!\n")
+    except lock.LockHeld, inst:
+        if inst.errno == errno.ETIMEDOUT:
+            reason = _('timed out waiting for lock held by %s') % inst.locker
+        else:
+            reason = _('lock held by %s') % inst.locker
+        u.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason))
+    except lock.LockUnavailable, inst:
+        u.warn(_("abort: could not lock %s: %s\n") %
+               (inst.desc or inst.filename, inst.strerror))
     except revlog.RevlogError, inst:
         u.warn(_("abort: "), inst, "!\n")
     except SignalInterrupt:
--- a/mercurial/localrepo.py	Sun Mar 26 22:54:05 2006 +0200
+++ b/mercurial/localrepo.py	Tue Mar 28 09:01:07 2006 -0800
@@ -31,6 +31,7 @@
             raise repo.RepoError(_("repository %s not found") % path)
 
         self.root = os.path.abspath(path)
+        self.origroot = path
         self.ui = ui.ui(parentui=parentui)
         self.opener = util.opener(self.path)
         self.wopener = util.opener(self.root)
@@ -261,32 +262,31 @@
         self.tagscache = None
         self.nodetagscache = None
 
-    def do_lock(self, lockname, wait, releasefn=None, acquirefn=None):
+    def do_lock(self, lockname, wait, releasefn=None, acquirefn=None,
+                desc=None):
         try:
-            l = lock.lock(self.join(lockname), 0, releasefn)
+            l = lock.lock(self.join(lockname), 0, releasefn, desc=desc)
         except lock.LockHeld, inst:
             if not wait:
-                raise inst
-            self.ui.warn(_("waiting for lock held by %s\n") % inst.args[0])
-            try:
-                # default to 600 seconds timeout
-                l = lock.lock(self.join(lockname),
-                              int(self.ui.config("ui", "timeout") or 600),
-                              releasefn)
-            except lock.LockHeld, inst:
-                raise util.Abort(_("timeout while waiting for "
-                                   "lock held by %s") % inst.args[0])
+                raise
+            self.ui.warn(_("waiting for lock on %s held by %s\n") %
+                         (desc, inst.args[0]))
+            # default to 600 seconds timeout
+            l = lock.lock(self.join(lockname),
+                          int(self.ui.config("ui", "timeout") or 600),
+                          releasefn, desc=desc)
         if acquirefn:
             acquirefn()
         return l
 
     def lock(self, wait=1):
-        return self.do_lock("lock", wait, acquirefn=self.reload)
+        return self.do_lock("lock", wait, acquirefn=self.reload,
+                            desc=_('repository %s') % self.origroot)
 
     def wlock(self, wait=1):
-        return self.do_lock("wlock", wait,
-                            self.dirstate.write,
-                            self.wreload)
+        return self.do_lock("wlock", wait, self.dirstate.write,
+                            self.wreload,
+                            desc=_('working directory of %s') % self.origroot)
 
     def checkfilemerge(self, filename, text, filelog, manifest1, manifest2):
         "determine whether a new filenode is needed"
--- a/mercurial/lock.py	Sun Mar 26 22:54:05 2006 +0200
+++ b/mercurial/lock.py	Tue Mar 28 09:01:07 2006 -0800
@@ -8,10 +8,16 @@
 from demandload import *
 demandload(globals(), 'errno os socket time util')
 
-class LockException(Exception):
-    pass
+class LockException(IOError):
+    def __init__(self, errno, strerror, filename, desc):
+        IOError.__init__(self, errno, strerror, filename)
+        self.desc = desc
+
 class LockHeld(LockException):
-    pass
+    def __init__(self, errno, filename, desc, locker):
+        LockException.__init__(self, errno, 'Lock held', filename, desc)
+        self.locker = locker
+
 class LockUnavailable(LockException):
     pass
 
@@ -24,7 +30,7 @@
     # old-style lock: symlink to pid
     # new-style lock: symlink to hostname:pid
 
-    def __init__(self, file, timeout=-1, releasefn=None):
+    def __init__(self, file, timeout=-1, releasefn=None, desc=None):
         self.f = file
         self.held = 0
         self.timeout = timeout
@@ -32,6 +38,7 @@
         self.id = None
         self.host = None
         self.pid = None
+        self.desc = desc
         self.lock()
 
     def __del__(self):
@@ -49,7 +56,8 @@
                     if timeout > 0:
                         timeout -= 1
                     continue
-                raise inst
+                raise LockHeld(errno.ETIMEDOUT, inst.filename, self.desc,
+                               inst.locker)
 
     def trylock(self):
         if self.id is None:
@@ -64,9 +72,11 @@
                 if why.errno == errno.EEXIST:
                     locker = self.testlock()
                     if locker:
-                        raise LockHeld(locker)
+                        raise LockHeld(errno.EAGAIN, self.f, self.desc,
+                                       locker)
                 else:
-                    raise LockUnavailable(why)
+                    raise LockUnavailable(why.errno, why.strerror,
+                                          why.filename, self.desc)
 
     def testlock(self):
         '''return id of locker if lock is valid, else None.'''
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-lock-badness	Tue Mar 28 09:01:07 2006 -0800
@@ -0,0 +1,11 @@
+#!/bin/sh
+
+hg init a
+echo a > a/a
+hg --cwd a ci -A -m a
+hg clone a b
+echo b > b/b
+hg --cwd b ci -A -m b
+chmod 100 a/.hg
+hg --cwd b push ../a
+chmod 700 a/.hg
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-lock-badness.out	Tue Mar 28 09:01:07 2006 -0800
@@ -0,0 +1,4 @@
+adding a
+adding b
+pushing to ../a
+abort: could not lock repository ../a: Permission denied