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)
 {

Reply via email to