[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: [PATCH] Issue 3942 - Provide new subcommand on svnadmin to create a lock

From: Noorul Islam K M <noorul_at_collab.net>
Date: Mon, 18 Jul 2011 12:41:59 +0530

"C. Michael Pilato" <cmpilato_at_collab.net> writes:

> On 07/15/2011 08:58 AM, Noorul Islam K M wrote:
>
>> As first step I implemented the following syntax.
>>
>> svnadmin lock REPOS PATH USERNAME COMMENT-FILE
>>
>> I will add the optional TOKEN argument later. I hope I am progressing in
>> the right direction.
>
> I've not reviewed this work, but you might also consider allowing this
> subcommand to accept --bypass-hooks, too.

Bert/Julian/Mike,

Thank you for your review comments and suggestions.

Please find attached the updated patch which contains the following
modifications.

1) Add optional TOKEN argument. So the syntax becomes.

svnadmin lock REPOS PATH USERNAME COMMENT-FILE [TOKEN]

2) Incorporated Julian's review comments

2.a) No longer checking comments xml validity because this is already
done in svn_fs_lock() which is again called by svn_repos_fs_lock()

2.b) Used SVN_INVALID_REVNUM instead of youngest revision.

2.c) I am not sure whether the comment should be optional.

3) Implemented --bypass-hooks

Log
[[[
Fix issue #3942. Add new sub command 'lock' for 'svnadmin'. The
following syntax is implemented in this patch.

svnadmin lock REPOS PATH USERNAME COMMENT-FILE [TOKEN]

The command locks the PATH by USERNAME setting comment from
COMMENT-FILE. If the optional TOKEN is given then it is used as lock
token. If --bypass-hooks options is passed then bypass the repository
hook system.

* subversion/svnadmin/main.c
  (svn_opt_subcommand_t): New sub command.
  (svn_opt_subcommand_desc2_t): Add description.
  (subcommand_lock): Implement it.

* subversion/tests/cmdline/svntest/main.py
  (get_pre_lock_hook_path): Return the path of the pre-lock hook script.

* subversion/tests/cmdline/svnadmin_tests.py
  (lock): New test for 'lock' sub command.
  (test_list): Add new test.

]]]

Thanks and Regards
Noorul

Index: subversion/tests/cmdline/svnadmin_tests.py
===================================================================
--- subversion/tests/cmdline/svnadmin_tests.py (revision 1147759)
+++ subversion/tests/cmdline/svnadmin_tests.py (working copy)
@@ -1381,6 +1381,79 @@
     'STDERR', expected_stderr, errput):
     raise svntest.Failure
 
+def lock(sbox):
+ "svnadmin lock tests"
+ sbox.build(create_wc=False)
+
+ comment_path = os.path.join(svntest.main.temp_dir, "comment")
+ svntest.main.file_write(comment_path, "dummy comment")
+
+ invalid_comment_path = os.path.join(svntest.main.temp_dir, "invalid_comment")
+ svntest.main.file_write(invalid_comment_path, "character is invalid")
+
+ # Test illegal character in comment file.
+ expected_error = "svnadmin: E130004: Lock comment contains " + \
+ "illegal characters"
+ svntest.actions.run_and_verify_svnadmin(None, None,
+ expected_error, "lock",
+ sbox.repo_dir,
+ "iota", "jrandom",
+ invalid_comment_path)
+
+ # Test locking path with --bypass-hooks
+ expected_output = "iota locked by user 'jrandom'."
+ svntest.actions.run_and_verify_svnadmin(None, expected_output,
+ None, "lock",
+ sbox.repo_dir,
+ "iota", "jrandom",
+ comment_path,
+ "--bypass-hooks")
+
+ # Remove lock
+ svntest.actions.run_and_verify_svnadmin(None, None,
+ None, "rmlocks",
+ sbox.repo_dir, "iota")
+
+ # Test locking path without --bypass-hooks
+ expected_output = "iota locked by user 'jrandom'."
+ svntest.actions.run_and_verify_svnadmin(None, expected_output,
+ None, "lock",
+ sbox.repo_dir,
+ "iota", "jrandom",
+ comment_path)
+
+ # Test locking already locked path.
+ expected_error = "svnadmin: E160035: Path '/iota' is already " + \
+ "locked by user 'jrandom' in filesystem"
+ svntest.actions.run_and_verify_svnadmin(None, None,
+ expected_error, "lock",
+ sbox.repo_dir,
+ "iota", "jrandom",
+ comment_path)
+
+ # Test locking non-existent path.
+ expected_error = "svnadmin: E160013: Path '/non-existent' " + \
+ "doesn't exist in HEAD revision"
+ svntest.actions.run_and_verify_svnadmin(None, None,
+ expected_error, "lock",
+ sbox.repo_dir,
+ "non-existent", "jrandom",
+ comment_path)
+
+ # Test locking path without --bypass-hooks to see that hook script
+ # is really getting executed.
+ expected_error = "svnadmin: E165001: Lock blocked by pre-lock hook " + \
+ "\(exit code 1\) with no output."
+
+ hook_path = svntest.main.get_pre_lock_hook_path(sbox.repo_dir)
+ svntest.main.create_python_hook_script(hook_path, 'import sys; sys.exit(1)')
+
+ svntest.actions.run_and_verify_svnadmin(None, None,
+ expected_error, "lock",
+ sbox.repo_dir,
+ "iota", "jrandom",
+ comment_path)
+
 ########################################################################
 # Run the tests
 
@@ -1410,6 +1483,7 @@
               hotcopy_symlink,
               load_bad_props,
               verify_non_utf8_paths,
+ lock,
              ]
 
 if __name__ == '__main__':
Index: subversion/tests/cmdline/svntest/main.py
===================================================================
--- subversion/tests/cmdline/svntest/main.py (revision 1147759)
+++ subversion/tests/cmdline/svntest/main.py (working copy)
@@ -317,6 +317,11 @@
 
   return os.path.join(repo_dir, "hooks", "pre-revprop-change")
 
+def get_pre_lock_hook_path(repo_dir):
+ "Return the path of the pre-lock hook script in REPO_DIR."
+
+ return os.path.join(repo_dir, "hooks", "pre-lock")
+
 def get_svnserve_conf_file_path(repo_dir):
   "Return the path of the svnserve.conf file in REPO_DIR."
 
Index: subversion/svnadmin/main.c
===================================================================
--- subversion/svnadmin/main.c (revision 1147759)
+++ subversion/svnadmin/main.c (working copy)
@@ -40,6 +40,7 @@
 #include "svn_props.h"
 #include "svn_time.h"
 #include "svn_user.h"
+#include "svn_xml.h"
 
 #include "private/svn_opt_private.h"
 
@@ -152,6 +153,7 @@
   subcommand_load,
   subcommand_list_dblogs,
   subcommand_list_unused_dblogs,
+ subcommand_lock,
   subcommand_lslocks,
   subcommand_lstxns,
   subcommand_pack,
@@ -356,6 +358,12 @@
    {'q', svnadmin__ignore_uuid, svnadmin__force_uuid,
     svnadmin__use_pre_commit_hook, svnadmin__use_post_commit_hook,
     svnadmin__parent_dir, svnadmin__bypass_prop_validation, 'M'} },
+
+ {"lock", subcommand_lock, {0}, N_
+ ("usage: svnadmin lock REPOS_PATH PATH USERNAME COMMENT-FILE [TOKEN]\n\n"
+ "Lock PATH by USERNAME setting comments from COMMENT-FILE.\n"
+ "If provided use TOKEN as lock token.\n"),
+ {svnadmin__bypass_hooks} },
 
   {"lslocks", subcommand_lslocks, {0}, N_
    ("usage: svnadmin lslocks REPOS_PATH [PATH-IN-REPOS]\n\n"
@@ -1378,7 +1386,75 @@
                            opt_state->clean_logs, pool);
 }
 
+/* This implements `svn_opt_subcommand_t'. */
+static svn_error_t *
+subcommand_lock(apr_getopt_t *os, void *baton, apr_pool_t *pool)
+{
+ struct svnadmin_opt_state *opt_state = baton;
+ svn_repos_t *repos;
+ svn_fs_t *fs;
+ svn_fs_access_t *access;
+ apr_array_header_t *args;
+ const char *username;
+ const char *lock_path;
+ const char *comment_file_name;
+ svn_stringbuf_t *file_contents;
+ const char *lock_path_utf8;
+ svn_lock_t *lock;
+ apr_pool_t *subpool = svn_pool_create(pool);
+ const char *lock_token = NULL;
 
+ /* Expect three more arguments: PATH USERNAME COMMENT-FILE */
+ SVN_ERR(parse_args(&args, os, 3, 4, pool));
+ lock_path = APR_ARRAY_IDX(args, 0, const char *);
+ username = APR_ARRAY_IDX(args, 1, const char *);
+ comment_file_name = APR_ARRAY_IDX(args, 2, const char *);
+
+ /* Expect one more optional argument: TOKEN */
+ if (args->nelts == 4)
+ lock_token = APR_ARRAY_IDX(args, 3, const char *);
+
+ SVN_ERR(target_arg_to_dirent(&comment_file_name, comment_file_name, pool));
+
+ SVN_ERR(open_repos(&repos, opt_state->repository_path, pool));
+ fs = svn_repos_fs(repos);
+
+ /* Create an access context describing the user. */
+ SVN_ERR(svn_fs_create_access(&access, username, pool));
+
+ /* Attach the access context to the filesystem. */
+ SVN_ERR(svn_fs_set_access(fs, access));
+
+ SVN_ERR(svn_stringbuf_from_file2(&file_contents, comment_file_name, pool));
+
+ SVN_ERR(svn_utf_cstring_to_utf8(&lock_path_utf8, lock_path, subpool));
+
+ if (opt_state->bypass_hooks)
+ SVN_ERR(svn_fs_lock(&lock, fs, lock_path_utf8,
+ lock_token,
+ file_contents->data, /* comment */
+ 0, /* is_dav_comment */
+ 0, /* no expiration time. */
+ SVN_INVALID_REVNUM,
+ FALSE, subpool));
+ else
+ SVN_ERR(svn_repos_fs_lock(&lock, repos, lock_path_utf8,
+ lock_token,
+ file_contents->data, /* comment */
+ 0, /* is_dav_comment */
+ 0, /* no expiration time. */
+ SVN_INVALID_REVNUM,
+ FALSE, subpool));
+
+ SVN_ERR(svn_cmdline_printf(subpool,
+ _("%s locked by user '%s'.\n"),
+ lock_path, username));
+
+ svn_pool_destroy(subpool);
+
+ return SVN_NO_ERROR;
+}
+
 static svn_error_t *
 subcommand_lslocks(apr_getopt_t *os, void *baton, apr_pool_t *pool)
 {
Received on 2011-07-18 09:14:35 CEST

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.