Noorul Islam K M <noo...@collab.net> writes: > From: http://subversion.tigris.org/issues/show_bug.cgi?id=3942 > ======================================================================= > The svnadmin command currently allows you to list and remove locks. It > would be useful if you could also create locks. Suggested syntax would > be something like: > > svnadmin lock REPOS PATH USERNAME COMMENT-FILE TOKEN > > Where COMMENT-FILE is handled similar to svnadmin setrevprop TOKEN would > be optional. If not provided a lock token would be generated. > > The reason I would like this subcommand is that it would make it > possible to build a system for synchronizing locks between a master and > slave. A post-lock hook on master could send this info to slaves and > they could use it to create the lock on the slaves (with the same lock > token). It seems like it would be possible for someone to use this > command to store lock information along with a dumpfile and recreate > them after restoring repository from a dump. That is not my goal, but I > think it is another possible usage. > > Buddied by: cmpilato > ======================================================================== > > I would like to work on this enhancement. If someone else is already > working on this please let me know. >
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. 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 The command locks the PATH by USERNAME setting comment from COMMENT-FILE. The optional TOKEN argument mentioned in issue tracker will be implemented in another patch. * 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/svnadmin_tests.py (lock): New test for 'lock' sub command. (test_list): Add new test. Patch by: Noorul Islam K M <noorul{_AT_}collab.net> ]]] Thanks and Regards Noorul
Index: subversion/tests/cmdline/svnadmin_tests.py =================================================================== --- subversion/tests/cmdline/svnadmin_tests.py (revision 1146981) +++ subversion/tests/cmdline/svnadmin_tests.py (working copy) @@ -1381,6 +1381,51 @@ '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. + 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: E160042: 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) + ######################################################################## # Run the tests @@ -1410,6 +1455,7 @@ hotcopy_symlink, load_bad_props, verify_non_utf8_paths, + lock, ] if __name__ == '__main__': Index: subversion/svnadmin/main.c =================================================================== --- subversion/svnadmin/main.c (revision 1146981) +++ 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,11 @@ {'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\n\n" + "Lock PATH by USERNAME setting comments from COMMENT-FILE.\n"), + {0} }, {"lslocks", subcommand_lslocks, {0}, N_ ("usage: svnadmin lslocks REPOS_PATH [PATH-IN-REPOS]\n\n" @@ -1378,7 +1385,74 @@ 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; + char *comment; + svn_stringbuf_t *file_contents; + const char *lock_path_utf8; + svn_lock_t *lock; + svn_revnum_t revnum; + apr_pool_t *subpool = svn_pool_create(pool); + /* Expect three more arguments: PATH USERNAME COMMENT-FILE */ + SVN_ERR(parse_args(&args, os, 3, 3, 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 *); + 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)); + comment = file_contents->data; + + /* Enforce that the comment be xml-escapable. */ + if (comment) + { + if (! svn_xml_is_xml_safe(comment, strlen(comment))) + return svn_error_create + (SVN_ERR_XML_UNESCAPABLE_DATA, NULL, + _("Lock comment contains illegal characters")); + } + + SVN_ERR(svn_fs_youngest_rev(&revnum, fs, subpool)); + + SVN_ERR(svn_utf_cstring_to_utf8(&lock_path_utf8, lock_path, subpool)); + + SVN_ERR(svn_repos_fs_lock(&lock, repos, lock_path_utf8, + NULL, /* token */ + comment, + 0, /* is_dav_comment */ + 0, /* No expiration time. */ + 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) {