| A UI Specification for "Locking" |
| |
| This document describes a user interface of a new locking system for |
| Subversion. It implements the set of features described in the |
| associated functional spec. |
| |
| I. Introduction |
| |
| A. Goals/Audience |
| |
| There are two audiences we need to consider for a locking UI: |
| |
| 1. The enlightened software developer |
| |
| - understands general VC concepts (required for job) |
| - understands concurrency model |
| - has already embraced Subversion (or at least CVS) |
| |
| - ITCH: Some files aren't mergeable, like image files or |
| spreadsheets. Need to force serialized edits on such |
| things, as an occasional exception to concurrency. |
| |
| 2. The reluctant user of version control |
| |
| - bright people, but no time or interest in learning VC concepts |
| - doesn't understand concurrency |
| - doesn't understand "out-of-dateness" or merging procedures |
| |
| - typical examples: |
| - coder who has only used VSS or Clearcase with 100% locking |
| - website developer being forced to use VC |
| - manager being forced to use VC |
| |
| - ITCH: VC system should be effortless, transparent, and |
| idiot proof. VC system should prevent people from |
| wasting editing time, destroying each others |
| changes, all while avoiding concurrency concepts such |
| as "merging" and "out of dateness". |
| |
| |
| B. The "Hijack" Scenario |
| |
| This is specific use-case which is particularly important to |
| making version control usable by the second type of user |
| described above. |
| |
| In this scenario, the user has a tool that circumvents whatever |
| system is in place to enforce serialized editing. In systems |
| like VSS or Clearcase 'copy' views, this usually means an |
| editor that ignores the read-only attribute on a file. When |
| the user goes to commit, they discover that they were supposed |
| to lock the file, and the repository version has changed. What |
| now? |
| |
| The power-svn user would certainly have no problem knowing what |
| to do seeing an error that "the file must be locked to commit", |
| nor would such a user be confused by seeing a subsequent error |
| that the "file is out-of-date". The power user would run 'svn |
| update', resolve conflicts, then lock the file and commit. |
| |
| But the reluctant or ignorant svn user shouldn't (and doesn't |
| need to) be forced to deal with merging and out-of-dateness |
| when working in an "all locking" environment. Here are a few |
| usability case-studies: |
| |
| - Clearcase dynamic views |
| |
| The workspace is always up-to-date, all of the time. And |
| it's impossible to circumvent the read-only bit. So the |
| hijack scenario can't happen at all. |
| |
| - Clearcase copy-based views |
| |
| In the hijack scenario, the user attempts to commit and |
| the client responds by attempting an interactive |
| contextual merge. If not possible, the whole commit |
| fails and a guru is phoned to fix the situation. |
| |
| - Visual Source Safe |
| |
| in the hijack scenario, the user remembers to lock the |
| file long after editing it; VSS asks whether to use the |
| server version or local version of the file. Somebody's |
| edits are lost. |
| |
| It is the recommendation of this document that the command line |
| client produce normal conflicts when 'svn up' is run on a |
| hijacked file; but that for a GUI such as TortoiseSVN, a more |
| friendly (or interactive) procedure is followed -- perhaps one |
| that allows the user to choose between versions of files. |
| |
| |
| II. New Client Behaviors |
| |
| A. Overview |
| |
| This section describes a user interface to accomplish "locking", |
| as described in the functional spec. A new property is used to |
| enforce locking and prevent people from wasting time; lock |
| tokens are objects, stored in the working copy, that represent a |
| lock; and two new subcommands (lock/unlock) are described. |
| |
| B. The "svn:needs-lock" property |
| |
| Create a new "svn:needs-lock" property to indicate that a file |
| should be locked before committing. Just like "svn:executable", |
| the value of the property is irrelevant and the property can be |
| created (or deleted) by any user or administrator. |
| |
| Note that this property doesn't enforce locking. |
| |
| When the Subversion client encounters the "svn:needs-lock" |
| property on a path (on checkout or update), it sets the |
| working-copy path to a read-only state by default. This |
| serves as a reminder to the user that she should lock this |
| path before editing it. When a user locks the path, the |
| Subversion client makes the working-copy path read-write. |
| When the user releases the lock, or if the lock is found to |
| be defunct (see next section), the Subversion client makes |
| the path read-only again. |
| |
| C. Lock manipulation via client |
| |
| 1. Lock Tokens |
| |
| When a user successfully locks a path, the working copy |
| receives a "lock token" from the server. This token is an |
| object that connects your exclusive right to commit to a path |
| with your working copy. |
| |
| You can think of a lock token as a form of authentication for |
| a certain working copy. Why is it important or useful for |
| lock tokens to be attached to only one working copy? |
| |
| [An example: you might lock an unmergeable file using a |
| computer at your office, perhaps as part of a changeset in |
| progress. It should not be possible for a working copy on |
| your home computer to accidentally commit a change to that |
| same file, just because you've authenticated as the user |
| which owns the lock. If you really want to change the file |
| from home, you'd have to "steal" the lock from your other |
| working copy, which is discussed later in this document.] |
| |
| Because locks can be broken or stolen, it is possible for a |
| lock token to become "defunct". A defunct lock cannot be |
| used or released--it is useless and is cleaned up when you |
| next run 'svn update'. |
| |
| 2. New client subcommands |
| |
| Summary: |
| |
| svn lock [--force]: lock (or steal) |
| svn unlock [--force]: release (or break) |
| |
| |
| a. Creating a lock |
| |
| To lock a path, use the 'svn lock' command: |
| |
| $ svn lock foo.c |
| username: harry |
| password: XXXXX |
| [...] |
| 'foo.c' locked by user 'harry'. |
| |
| In order for this command to work, |
| |
| - You *must* provide a username to the server. |
| 'anonymous' locks are not allowed. |
| - The path must not already be locked. |
| - The path must not be out-of-date. |
| |
| The lock command accepts -m or -F to add a lock comment, so |
| others can see why the file was locked. The lock comment |
| is optional. |
| |
| b. Using a lock |
| |
| A lock can be used to make an exclusive commit to a path. |
| Also, if you have a lock, you can opt to "release" |
| (destroy) it when you're done. |
| |
| To make use of a lock, two forms of authentication must be |
| provided to the server: |
| |
| - The authenticated username that owns the lock |
| - A non-defunct lock token |
| |
| If either of these forms of authentication are missing or |
| incorrect, the lock cannot be used. |
| |
| 1. Using a lock to Commit |
| |
| $ svn commit foo.c |
| |
| Upon successful commit, a locked path is released by |
| default. The Subversion client provides an option to |
| retain the lock after commit: |
| |
| $ svn commit foo.c --no-unlock |
| |
| If --no-unlock is not specified, even unmodified files |
| will be considered part of the commit and shown to the |
| user in the list of files to commit. Such files will |
| also be unlocked after the commit. |
| |
| 2. Releasing a lock |
| |
| $ svn unlock foo.c |
| Lock on 'foo.c' has been released. |
| |
| After successful release, the working copy's lock token |
| is gone. |
| |
| c. Breaking a lock |
| |
| "Breaking" a lock is a means of releasing a lock when: |
| |
| - The authenticated username is not the same as the |
| lock owner, or |
| - The working-copy lock representation is unavailable. |
| |
| Use the --force option to the unlock subcommand to |
| break a lock. For example: |
| |
| $ svn unlock foo.c |
| username: sally |
| password: XXXX |
| svn: error: 'foo.c' is locked by user 'harry'. |
| |
| $ svn unlock foo.c --force |
| username: sally |
| password: XXXX |
| Lock on 'foo.c' has been broken. |
| |
| The --force option also accepts a URL, so that the lock |
| can be |
| released without a working copy. |
| |
| d. Stealing a lock |
| |
| "Stealing" a lock is a means of creating a lock when: |
| |
| - The path is locked by you, but you don't have a |
| representation of the lock in your current working |
| copy, or |
| - The path is locked by someone else. |
| |
| In order to steal a lock, a user must be authenticated to |
| the server. |
| |
| Use the --force option to the lock command to steal a |
| lock. For example: |
| |
| $ svn lock foo.c |
| username: sally |
| password: XXXX |
| svn: error: 'foo.c' is locked by user 'harry'. |
| |
| $ svn lock foo.c --force |
| username: sally |
| password: XXXX |
| 'foo.c' locked by user 'sally'. |
| |
| Remember that the 'svn lock' command still requires that the |
| target be up-to-date to succeed. |
| |
| |
| e. Discovering/examining locks |
| |
| 1. seeing lock tokens in a working copy |
| |
| 'svn status' considers a lock token "interesting", and |
| displays it using some new symbol, in a new column: |
| |
| $ svn status |
| M foo.c |
| M K bar.c |
| A baz.c |
| |
| Note that K (locKed) is used instead of the more |
| intuitive L, since L is already in use for another purpose. |
| |
| 2. seeing locks in a repository. |
| |
| 'svn status -u' adds out-of-date information from the |
| server; in a similar manner, this command shows any |
| locks that exist on the server: |
| |
| $ svn status -u |
| M foo.c |
| M K bar.c |
| A * baz.c |
| * file1 |
| O file2 |
| M B file3 |
| M T file42 |
| |
| As with "svn status", the sixth column indicates lock |
| state. The letters have the following meanings: |
| ' ': No lock in either WC or repository. |
| 'K': Locked in the WC and lock token valid in |
| repository. |
| 'O': No lock in WC, lock in repository. (Locked in |
| Other WC.) |
| 'B': Lock in WC, but no lock in repository. (Lock |
| Broken.) |
| 'T': Locked in WC, but locked with another token in |
| repository. (Lock was sTolen.) |
| |
| 3. 'svn info', describes the attributes of a lock-token, |
| if attached to a working object. If invoked on a URL, |
| it displays information about any remote lock |
| attached. |
| |
| $ svn info foo.c |
| Path: foo.c |
| Name: foo.c |
| URL: http://..../ |
| [...] |
| Lock Token: 465610b1-33eb-0310-8a02-cae41507c13a |
| Lock Owner: lundblad |
| Lock Comment: Refactoring. |
| Lock Creation Date: 2004-12-14 14:49:36 +0100 (Tue, 14 Dec 2004) |
| |
| |
| $ svn info http://host/repos/file2 |
| Path: /file2 |
| Name: file2 |
| URL: http://..../ |
| [...] |
| Lock Token: 465610b1-33eb-0310-8a02-cae41507c13b |
| Lock Owner: fitz |
| Lock Comment: Don't touch my file! |
| Lock Creation Date: 2004-12-25 14:49:36 +0100 (Tue, 14 Dec 2004) |
| |
| 4. 'svn update' changes |
| |
| At the start of an update, the client reports any |
| lock-tokens to the server. If a lock token has become |
| "defunct", the client is instructed to destroy the lock |
| token. |
| |
| A new column will be added to the update output to indicate |
| removed lock tokens: |
| |
| svn up |
| U path1 |
| U path2 |
| B path3 |
| C B path4 |
| |
| In the above example, lock tokens for path3 and path4 |
| were removed. Note that 'B' is used even if there is |
| a new lock in the repository. |
| |
| III. New Server Behaviors |
| |
| A. Overview |
| |
| This section describes new server UIs for locking: two new hook |
| scripts, a new 'svnlook' subcommand, and a new 'svnadmin' subcommand. |
| |
| B. Tracking locks |
| |
| The Subversion server holds the master list of all locks for a |
| repository. It responds to client requests to create, release, |
| break and steal locks. |
| |
| C. Enforcement |
| |
| During a commit, the server checks for locks the same way that |
| it checks for out-of-dateness: |
| |
| $ svn commit |
| Sending foo.c |
| Sending bar.c |
| svn: error: 'bar.c' is locked by user 'harry'. |
| |
| |
| D. Configurable Mechanisms |
| |
| 1. New "pre-" hook scripts |
| |
| a. pre-lock |
| |
| Used to authorize lock creation. Invoked whenever a user |
| creates a lock ('svn lock') or steals a lock ('svn lock |
| --force'). If an administrator wants the locking feature |
| completely disabled, just set this hook to always return failure. |
| |
| - input: REPOS, PATH, USER |
| - successful exit means lock is allowed, else deny lock creation. |
| - if path is already locked, hook script can deduce |
| that USER is "stealing" the lock and decide what to do. |
| |
| b. pre-unlock |
| |
| Used to authorize lock releasing. Invoked whenever a user |
| releases a lock ('svn unlock) or breaks a lock ('svn |
| unlock' --force). |
| |
| - input: REPOS, PATH, USER |
| - successful exit means release is allowed, else deny. |
| - if path is already locked, hook script can deduce |
| that USER is "breaking" the lock and decide what to do. |
| |
| 2. New "post-" hook scripts |
| |
| a. post-lock |
| |
| Used to report lock creation. Invoked whenever a user |
| creates a lock ('svn lock') or steals a lock ('svn lock |
| --force'). |
| |
| - input: REPOS, PATH, USER |
| - exit code ignored |
| - can be used to send email, collect statistics, etc. |
| |
| b. post-unlock |
| |
| Used to report lock release. Invoked whenever a user |
| releases a lock ('svn unlock') or breaks a lock ('svn unlock |
| --force'). |
| |
| - input: REPOS, PATH, USER |
| - exit code ignored |
| - can be used to send email, collect statistics, etc. |
| |
| |
| E. Lock manipulation with svnadmin |
| |
| 1. Discovering locks |
| |
| A new 'svnlook listlocks' subcommand shows all current locks |
| in a repository: |
| |
| $ svnlook listlocks /usr/local/svn/repos |
| # harry Aug 16 15:13 /trunk/bar.c |
| # sally Sep 07 09:30 /trunk/doc/foo.doc |
| |
| |
| 2. Unconditional release of locks |
| |
| A new 'svnadmin unlock' subcommand to unconditionally |
| release a lock. Note that this command circumvents hook |
| scripts, much like other svnadmin actions: |
| |
| $ svnadmin unlock /usr/local/svn/repos /trunk/doc/foo.doc |
| Lock on '/trunk/doc/foo.doc' has been released. |
| |
| |
| |
| |