# HG changeset patch # User mpm@selenic.com # Date 2005-05-26 16:53:04 # Node ID 0b4c5cb953d9a3c636a52a5109ecf192f2b3ee9f # Parent 5c331d941c7f7e15618059f770c8ecd8a9d902a3 Simply repository locking This is a first pass at implementing repo locking. Next up, journal recovery and undo. diff --git a/mercurial/hg.py b/mercurial/hg.py --- a/mercurial/hg.py +++ b/mercurial/hg.py @@ -7,7 +7,7 @@ import sys, struct, sha, socket, os, time, re, urllib2 import urllib -from mercurial import byterange +from mercurial import byterange, lock from mercurial.transaction import * from mercurial.revlog import * from difflib import SequenceMatcher @@ -297,7 +297,17 @@ class localrepository: return transaction(self.opener, self.join("journal"), self.join("undo")) + def lock(self, wait = 1): + try: + return lock.lock(self.join("lock"), 0) + except lock.LockHeld, inst: + if wait: + self.ui.warn("waiting for lock held by %s\n" % inst.args[0]) + return lock.lock(self.join("lock"), wait) + raise inst + def commit(self, parent, update = None, text = ""): + self.lock() try: remove = [ l[:-1] for l in self.opener("to-remove") ] os.unlink(self.join("to-remove")) @@ -612,6 +622,7 @@ class localrepository: yield "".join([l, f, g]) def addchangegroup(self, generator): + self.lock() class genread: def __init__(self, generator): self.g = generator diff --git a/mercurial/lock.py b/mercurial/lock.py new file mode 100644 --- /dev/null +++ b/mercurial/lock.py @@ -0,0 +1,46 @@ +# lock.py - simple locking scheme for mercurial +# +# Copyright 2005 Matt Mackall +# +# This software may be used and distributed according to the terms +# of the GNU General Public License, incorporated herein by reference. + +import os, time + +class LockHeld(Exception): + pass + +class lock: + def __init__(self, file, wait = 1): + self.f = file + self.held = 0 + self.wait = wait + self.lock() + + def __del__(self): + self.release() + + def lock(self): + while 1: + try: + self.trylock() + return 1 + except LockHeld, inst: + if self.wait: + time.sleep(1) + continue + raise inst + + def trylock(self): + pid = os.getpid() + try: + os.symlink(str(pid), self.f) + self.held = 1 + except: + raise LockHeld(os.readlink(self.f)) + + def release(self): + if self.held: + self.held = 0 + os.unlink(self.f) +