diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py index 0cbe7f9c28..161984adcf 100644 --- a/mercurial/debugcommands.py +++ b/mercurial/debugcommands.py @@ -1275,7 +1275,10 @@ def debuglabelcomplete(ui, repo, *args): @command('debuglocks', [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')), ('W', 'force-wlock', None, - _('free the working state lock (DANGEROUS)'))], + _('free the working state lock (DANGEROUS)')), + ('s', 'set-lock', None, _('set the store lock until stopped')), + ('S', 'set-wlock', None, + _('set the working state lock until stopped'))], _('[OPTION]...')) def debuglocks(ui, repo, **opts): """show or modify state of locks @@ -1294,6 +1297,10 @@ def debuglocks(ui, repo, **opts): instance, on a shared filesystem). Removing locks may also be blocked by filesystem permissions. + Setting a lock will prevent other commands from changing the data. + The command will wait until an interruption (SIGINT, SIGTERM, ...) occurs. + The set locks are removed when the command exits. + Returns 0 if no locks are held. """ @@ -1305,6 +1312,24 @@ def debuglocks(ui, repo, **opts): if opts.get(r'force_lock') or opts.get(r'force_wlock'): return 0 + locks = [] + try: + if opts.get(r'set_wlock'): + try: + locks.append(repo.wlock(False)) + except error.LockHeld: + raise error.Abort(_('wlock is already held')) + if opts.get(r'set_lock'): + try: + locks.append(repo.lock(False)) + except error.LockHeld: + raise error.Abort(_('lock is already held')) + if len(locks): + ui.promptchoice(_("ready to release the lock (y)? $$ &Yes")) + return 0 + finally: + release(*locks) + now = time.time() held = 0 diff --git a/tests/test-completion.t b/tests/test-completion.t index e434babb95..5e812c777b 100644 --- a/tests/test-completion.t +++ b/tests/test-completion.t @@ -274,7 +274,7 @@ Show all commands + options debuginstall: template debugknown: debuglabelcomplete: - debuglocks: force-lock, force-wlock + debuglocks: force-lock, force-wlock, set-lock, set-wlock debugmergestate: debugnamecomplete: debugobsolete: flags, record-parents, rev, exclusive, index, delete, date, user, template diff --git a/tests/test-debugcommands.t b/tests/test-debugcommands.t index 54164be81e..46519deffc 100644 --- a/tests/test-debugcommands.t +++ b/tests/test-debugcommands.t @@ -1,4 +1,6 @@ $ cat << EOF >> $HGRCPATH + > [ui] + > interactive=yes > [format] > usegeneraldelta=yes > EOF @@ -157,7 +159,7 @@ waitlock will wait for file to be created. If it isn't in a reasonable amount of time, displays error message and returns 1 $ waitlock() { > start=`date +%s` - > timeout=1 + > timeout=5 > while [ \( ! -f $1 \) -a \( ! -L $1 \) ]; do > now=`date +%s` > if [ "`expr $now - $start`" -gt $timeout ]; then @@ -167,25 +169,14 @@ amount of time, displays error message and returns 1 > sleep 0.1 > done > } -dolock [wlock] [lock] will set the locks until interrupted $ dolock() { - > declare -A options - > options=([${1:-nolock}]=1 [${2:-nowlock}]=1) - > python < from mercurial import hg, ui as uimod - > import os - > import time - > - > repo = hg.repository(uimod.ui.load(), path='.') - > `[ -n "${options["wlock"]}" ] && echo "with repo.wlock(False):" || echo "if True:"` - > `[ -n "${options["lock"]}" ] && echo "with repo.lock(False):" || echo "if True:"` - > while not os.path.exists('.hg/unlock'): - > time.sleep(0.1) - > os.unlink('.hg/unlock') - > EOF + > { + > waitlock .hg/unlock + > rm -f .hg/unlock + > echo y + > } | hg debuglocks "$@" > /dev/null > } - - $ dolock lock & + $ dolock -s & $ waitlock .hg/store/lock $ hg debuglocks @@ -194,10 +185,12 @@ dolock [wlock] [lock] will set the locks until interrupted [1] $ touch .hg/unlock $ wait + $ [ -f .hg/store/lock ] || echo "There is no lock" + There is no lock * Test setting the wlock - $ dolock wlock & + $ dolock -S & $ waitlock .hg/wlock $ hg debuglocks @@ -206,16 +199,29 @@ dolock [wlock] [lock] will set the locks until interrupted [1] $ touch .hg/unlock $ wait + $ [ -f .hg/wlock ] || echo "There is no wlock" + There is no wlock * Test setting both locks - $ dolock wlock lock & + $ dolock -Ss & $ waitlock .hg/wlock && waitlock .hg/store/lock $ hg debuglocks lock: user *, process * (*s) (glob) wlock: user *, process * (*s) (glob) [2] + +* Test failing to set a lock + + $ hg debuglocks -s + abort: lock is already held + [255] + + $ hg debuglocks -S + abort: wlock is already held + [255] + $ touch .hg/unlock $ wait @@ -225,7 +231,7 @@ dolock [wlock] [lock] will set the locks until interrupted * Test forcing the lock - $ dolock lock & + $ dolock -s & $ waitlock .hg/store/lock $ hg debuglocks @@ -244,7 +250,7 @@ dolock [wlock] [lock] will set the locks until interrupted * Test forcing the wlock - $ dolock wlock & + $ dolock -S & $ waitlock .hg/wlock $ hg debuglocks