diff --git a/osc-staging.py b/osc-staging.py index 051075f8..ae3bb783 100644 --- a/osc-staging.py +++ b/osc-staging.py @@ -76,6 +76,12 @@ def _full_project_name(self, project): warnings.warn('%s project not recognized.' % project) return project +def lock_needed(cmd, opts): + return not( + cmd in ('acheck', 'check', 'frozenage', 'rebuild', 'unlock') or + (cmd == 'list' and not opts.supersede) + ) + @cmdln.option('--move', action='store_true', help='force the selection to become a move') @@ -352,12 +358,8 @@ def do_staging(self, subcmd, opts, *args): if opts.wipe_cache: Cache.delete_all() - lock = OBSLock(opts.apiurl, opts.project, reason=cmd) - if cmd == 'unlock': - lock.release(force=True) - return - - with lock: + needed = lock_needed(cmd, opts) + with OBSLock(opts.apiurl, opts.project, reason=cmd, needed=needed) as lock: api = StagingAPI(opts.apiurl, opts.project) config.apply_remote(api) @@ -578,3 +580,5 @@ def do_staging(self, subcmd, opts, *args): PrioCommand(api).perform(args[1:]) elif cmd == 'supersede': SupersedeCommand(api).perform(args[1:]) + elif cmd == 'unlock': + lock.release(force=True) diff --git a/osclib/obslock.py b/osclib/obslock.py index d3ce935e..5f1ec7b9 100644 --- a/osclib/obslock.py +++ b/osclib/obslock.py @@ -28,7 +28,7 @@ from osc.core import http_POST class OBSLock(object): """Implement a distributed lock using a shared OBS resource.""" - def __init__(self, apiurl, project, ttl=3600, reason=None): + def __init__(self, apiurl, project, ttl=3600, reason=None, needed=True): self.apiurl = apiurl self.project = project self.lock = conf.config[project]['lock'] @@ -39,6 +39,7 @@ class OBSLock(object): self.reason = reason self.reason_sub = None self.locked = False + self.needed = needed def _signature(self): """Create a signature with a timestamp.""" @@ -83,6 +84,8 @@ class OBSLock(object): http_POST(url, data=data) def acquire(self): + if not self.needed: return self + # If the project doesn't have locks configured, raise a # Warning (but continue the operation) if not self.lock: @@ -121,6 +124,8 @@ class OBSLock(object): return self def release(self, force=False): + if not force and not self.needed: return + # If the project do not have locks configured, simply ignore # the operation. if not self.lock: diff --git a/tests/obslock_tests.py b/tests/obslock_tests.py index 0a7175db..5319565c 100644 --- a/tests/obslock_tests.py +++ b/tests/obslock_tests.py @@ -122,3 +122,19 @@ class TestOBSLock(unittest.TestCase): with lock: _, reason, _, _ = lock._parse(lock._read()) self.assertEqual(reason, 'some reason at hashnight') + + def test_needed(self): + lock1 = self.obs_lock() + lock2 = self.obs_lock() + lock2.user = 'user2' + lock2.needed = False + + self.assertFalse(lock1.locked) + self.assertFalse(lock2.locked) + + with lock1: + self.assertTrue(lock1.locked) + with lock2: + self.assertFalse(lock2.locked) + user, _, _, _ = lock2._parse(lock2._read()) + self.assertEqual(user, lock1.user, 'lock1 remains')