[PATCH] Preliminary locking solution
From: Stein Roger Skafløtten <srsmail_at_hotmail.com>
Date: 2004-07-31 13:41:23 CEST
Hi all,
The attached patch implements a preliminary solution for locking files
A main goal was to change as little as possible and be non-intrusive:
It would be nice to have this functionality in the API, but I realize
[My first attempt on the client was to create a cute little python script,
Usage
lock: Locks the file(s).
Use the --force option to aquire the lock even if the file is locked
With -v, also print lock tokens.
Valid options:
Sample output: "svn lock --username=gorilla *.*"
Successfully locked design.tiff
Sample, verbose output: "svn lock --force -verbose project.prj"
Successfully locked project.prj (lock-c3JzL3Rlt3QxLnR4dA---)
[You can see that this is in fact the lock token by doing a
---
unlock: Unlocks the file(s).
usage: unlock [PATH]
Unlocks the file(s). If a file is locked by another user, an
error message will be shown.
Valid options:
--targets arg : pass contents of file ARG as additional args
--username arg : specify a username ARG
--password arg : specify a password ARG
--no-auth-cache : do not cache authentication tokens
--non-interactive : do no interactive prompting
--config-dir arg : read user configuration files from directory
ARG
Sample output: "svn unlock *.*"
Successfully unlocked subversion.gif
Could not unlock air.ogg: The file is locked by 'mozart'
Could not unlock productlist.pdf: Not a versioned resource
Successfully unlocked design.tiff
Successfully unlocked project.xls
Successfully unlocked banjo-budget.xls
---
Attempting to commit changes a file locked by someone else
(the lock-related message is at the end of the entire commit
error message):
$svn ci -m="changed some stuff" test.doc
Sending test.doc
Transmitting file data .svn: Commit failed (details follow):
svn: MERGE request failed on '/myrepos/gorilla'
svn:
'pre-commit' hook failed with error output:
pete has exclusively locked gorilla/test.doc
OK, so it would be nice if the "Commit failed" message was customizable...
Applying the patch
------------------
1. Rebuild the client
The patch adds locking capabilities to the command line client by
introducing two sub commands (changed main.c / cl.h and added
lock-cmd.c and unlock-cmd.c)
2. Install server hooks
a) Make sure "lock-commit.py" and "lock-revprop-change.py" are
executable.
b) Change pre-revprop-change and post-revprop-change to call
"lock-revprop-change.py"
c) Change pre-commit to call "lock-commit.py"
I've included sample hooks at the end of this mail.
lock-commit.py
--------------
Called from pre-commit to check if any of the CRUD'ed files are locked
by another user. If so, the commit fails. Locks on moved/deleted files
are removed; see script comments for details.
lock-revprop-change.py
----------------------
Called from the pre-revprop-change and post-revprop-change hooks. When
called from pre, the script checks whether or not the user can lock the
file. In post, the script patches the lock token (removes FLAG - see
below) and sets the locktoken revprop = username.
Internals... how files get locked
---------------------------------
The exclusive lock implementation features creative use of the revprops
on revision 0. When a file is locked, a new revprop is created on rev 0
(called the lock tocken), and the value of that revprop is the user who
locks the file. When the file is unlocked, the revprop is removed. Also,
if the file is deleted/moved, any "dangling" locks will be removed upon
commit.
The revprop naming scheme is as follows:
locktoken ::= FLAG "lock-" base64(path-in-repos)
lockvalue ::= username
FLAG ::= R | F | N
where
R means remove lock
F means forced lock
N means non-forced lock
The flags are actually removed on the server side as they are just there
to tell the hook scripts what to do. Initially I actually tried to use the
propvalue for this, but a bug in pre-1.1 prevents pre-revprop-change hooks
from reading the value (I wanted this patch to work with older servers.)
Someone might want to add WebDAV LOCK support which requires (IIRC) a
universally unique lock identifier. In that case, just add the repos-uuid
to the lock token.
The path is base64 encoded except that [\n,=,+] are all replaced with '-'
in order to form valid revprop names.
Sample hook scripts
-------------------
1. pre-commit
# check if any of the changed files are locked by another user
/.../hook-scripts/lock-commit.py "$REPOS" "$TXN" || exit 1
exit 0
2. pre-revprop-change
# we only allow lock and log prop's to be changed (change as you see fit)
if [ "$PROPNAME" = "svn:log" ]; then exit 0; fi
if [ "${PROPNAME:1:5}" != "lock-" ]; then exit 1; fi
# check whether or not the file can be locked
/.../hook-scripts/lock-revprop-change.py pre "$REPOS" "$PROPNAME" "$USER" ||
exit 1
exit 0
3. post-revprop-change
# patches propval to contain username -or- removes the revprop if the FLAG
is 'R'
/.../hook-scripts/lock-revprop-change.py post "$REPOS" "$PROPNAME" "$USER"
|| exit 1
exit 0
Future enhancements (?)
-----------------------
a) Make svn up/svn lock set non-mergable files read-only and have
'svn lock' make them readable.
b) 'svn st' could perhaps show lock status... or is that mixing unrelated
information?
c) 'svnadmin' should be able to list and remove all locks in a repository
(simple)
d) Implement all the clever ideas discussed on the dev list and
locking-notes.txt
e) Fix bugs?
Well... happy locking.
/Stein Roger
_________________________________________________________________
MSN Messenger http://www.msn.no/messenger Den korteste veien mellom deg og
dine venner
---------------------------------------------------------------------
|
This is an archived mail posted to the Subversion Dev mailing list.
This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.