subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From julianf...@apache.org
Subject svn commit: r1661674 - /subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c
Date Mon, 23 Feb 2015 13:54:50 GMT
Author: julianfoad
Date: Mon Feb 23 13:54:50 2015
New Revision: 1661674

URL: http://svn.apache.org/r1661674
Log:
On the 'move-tracking-2' branch: add an interactive mode to svnmover.

* subversion/svnmover/svnmover.c
  (execute): Move log message handling from here to sub_main().
  (usage): Improve the help message.
  (parse_actions): New function factored out from sub_main().
  (sub_main): Read input interactively if not provided and if not in
    non-interactive mode.

Modified:
    subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c

Modified: subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c?rev=1661674&r1=1661673&r2=1661674&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c (original)
+++ subversion/branches/move-tracking-2/subversion/svnmover/svnmover.c Mon Feb 23 13:54:50
2015
@@ -1351,7 +1351,6 @@ svn_branch_log(svn_editor3_t *editor,
 static svn_error_t *
 execute(const apr_array_header_t *actions,
         const char *anchor_url,
-        const char *log_msg,
         apr_hash_t *revprops,
         svn_revnum_t base_revision,
         svn_client_ctx_t *ctx,
@@ -1365,15 +1364,6 @@ execute(const apr_array_header_t *action
   int i;
   svn_error_t *err;
 
-  /* Put the log message in the list of revprops, and check that the user
-     did not try to supply any other "svn:*" revprops. */
-  if (svn_prop_has_svn_prop(revprops, pool))
-    return svn_error_create(SVN_ERR_CLIENT_PROPERTY_NAME, NULL,
-                            _("Standard properties can't be set "
-                              "explicitly as revision properties"));
-  svn_hash_sets(revprops, SVN_PROP_REVISION_LOG,
-                svn_string_create(log_msg, pool));
-
   SVN_ERR(mtcc_create(&mtcc,
                       anchor_url, base_revision, revprops,
                       commit_callback, NULL,
@@ -1685,12 +1675,16 @@ static void
 usage(FILE *stream, apr_pool_t *pool)
 {
   svn_error_clear(svn_cmdline_fputs(
-    _("usage: svnmover ACTION...\n"
-      "Subversion mover command client.\n"
-      "Type 'svnmover --version' to see the program version.\n"
+    _("usage: svnmover [-U REPO_URL] [ACTION...]\n"
+      "A client for experimenting with move tracking.\n"
+      "\n"
+      "  Perform URL-based ACTIONs on a Subversion repository, committing the\n"
+      "  result as a (single) new revision, similar to svnmucc.\n"
       "\n"
-      "  Perform one or more Subversion repository URL-based ACTIONs, committing\n"
-      "  the result as a (single) new revision.\n"
+      "  With no ACTIONs, read actions interactively from standard input, making\n"
+      "  one commit for each line of input.\n"
+      "\n"
+      "  Store move tracking metadata either in local files or in revprops.\n"
       "\n"
       "Actions:\n"
       "  ls-br                  : list all branches in this family\n"
@@ -1862,6 +1856,109 @@ log_message_func(const char **log_msg,
     }
 }
 
+/* Parse the action arguments into action structures. */
+static svn_error_t *
+parse_actions(apr_array_header_t **actions,
+              apr_array_header_t *action_args,
+              const char *root_url,
+              const char *anchor,
+              apr_pool_t *pool)
+{
+  int i;
+
+  *actions = apr_array_make(pool, 1, sizeof(struct action *));
+
+  for (i = 0; i < action_args->nelts; ++i)
+    {
+      int j, num_url_args;
+      const char *action_string = APR_ARRAY_IDX(action_args, i, const char *);
+      struct action *action = apr_pcalloc(pool, sizeof(*action));
+      const char *cp_from_rev = NULL;
+
+      /* First, parse the action. */
+      if (! strcmp(action_string, "?") || ! strcmp(action_string, "h")
+          || ! strcmp(action_string, "help"))
+        {
+          usage(stdout, pool);
+          return SVN_NO_ERROR;
+        }
+      for (j = 0; j < sizeof(action_defn) / sizeof(action_defn[0]); j++)
+        {
+          if (strcmp(action_string, action_defn[j].name) == 0)
+            {
+              action->action = action_defn[j].code;
+              num_url_args = action_defn[j].num_args;
+              break;
+            }
+        }
+      if (j == sizeof(action_defn) / sizeof(action_defn[0]))
+        return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
+                                 "'%s' is not an action",
+                                 action_string);
+
+      if (action->action == ACTION_CP)
+        {
+          /* next argument is the copy source revision */
+          if (++i == action_args->nelts)
+            return svn_error_trace(insufficient());
+          cp_from_rev = APR_ARRAY_IDX(action_args, i, const char *);
+        }
+
+      /* Parse the required number of URLs. */
+      for (j = 0; j < num_url_args; ++j)
+        {
+          const char *path, *url;
+
+          if (++i == action_args->nelts)
+            return svn_error_trace(insufficient());
+          path = APR_ARRAY_IDX(action_args, i, const char *);
+
+          if (cp_from_rev && j == 0)
+            {
+              path = apr_psprintf(pool, "%s@%s", path, cp_from_rev);
+            }
+
+          SVN_ERR(svn_opt_parse_path(&action->rev_spec[j], &path, path, pool));
+
+          /* If there's a ROOT_URL, we expect URL to be a path
+             relative to ROOT_URL (and we build a full url from the
+             combination of the two).  Otherwise, it should be a full
+             url. */
+          if (svn_path_is_url(path))
+            {
+              url = path;
+              path = svn_uri_skip_ancestor(root_url, url, pool);
+            }
+          else
+            {
+              if (! root_url)
+                return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
+                                         "'%s' is not a URL, and "
+                                         "--root-url (-U) not provided",
+                                         path);
+              url = svn_path_url_add_component2(root_url, path, pool);
+            }
+          url = sanitize_url(url, pool);
+          action->path[j] = path;
+
+          if (! anchor)
+            anchor = url;
+          else
+            {
+              anchor = svn_uri_get_longest_ancestor(anchor, url, pool);
+              if (!anchor || !anchor[0])
+                return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
+                                         "URLs in the action list do not "
+                                         "share a common ancestor");
+            }
+        }
+
+      APR_ARRAY_PUSH(*actions, struct action *) = action;
+    }
+
+  return SVN_NO_ERROR;
+}
+
 /*
  * On success, leave *EXIT_CODE untouched and return SVN_NO_ERROR. On error,
  * either return an error to be displayed, or set *EXIT_CODE to non-zero and
@@ -1870,8 +1967,7 @@ log_message_func(const char **log_msg,
 static svn_error_t *
 sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
 {
-  apr_array_header_t *actions = apr_array_make(pool, 1,
-                                               sizeof(struct action *));
+  apr_array_header_t *actions;
   const char *anchor = NULL;
   svn_error_t *err = SVN_NO_ERROR;
   apr_getopt_t *opts;
@@ -1916,6 +2012,7 @@ sub_main(int *exit_code, int argc, const
   apr_array_header_t *config_options;
   svn_boolean_t non_interactive = FALSE;
   svn_boolean_t force_interactive = FALSE;
+  svn_boolean_t interactive_actions;
   svn_boolean_t trust_server_cert = FALSE;
   svn_boolean_t no_auth_cache = FALSE;
   svn_revnum_t base_revision = SVN_INVALID_REVNUM;
@@ -1925,7 +2022,6 @@ sub_main(int *exit_code, int argc, const
   svn_config_t *cfg_config;
   svn_client_ctx_t *ctx;
   const char *log_msg;
-  int i;
 
   /* Check library versions */
   SVN_ERR(check_lib_versions());
@@ -2096,6 +2192,15 @@ sub_main(int *exit_code, int argc, const
   if (! log_msg)
     return SVN_NO_ERROR;
 
+  /* Put the log message in the list of revprops, and check that the user
+     did not try to supply any other "svn:*" revprops. */
+  if (svn_prop_has_svn_prop(revprops, pool))
+    return svn_error_create(SVN_ERR_CLIENT_PROPERTY_NAME, NULL,
+                            _("Standard properties can't be set "
+                              "explicitly as revision properties"));
+  svn_hash_sets(revprops, SVN_PROP_REVISION_LOG,
+                svn_string_create(log_msg, pool));
+
   /* Copy the rest of our command-line arguments to an array,
      UTF-8-ing them along the way. */
   /* If there are extra arguments in a supplementary file, tack those
@@ -2113,122 +2218,54 @@ sub_main(int *exit_code, int argc, const
       svn_cstring_split_append(action_args, contents_utf8->data, "\n\r",
                                FALSE, pool);
     }
-  /* Append the root URL temporarily as a reference for repos-relative URLs. */
-  if (root_url)
-    APR_ARRAY_PUSH(action_args, const char *) = root_url;
-  /* Parse arguments -- converting local style to internal style,
-   * repos-relative URLs to regular URLs, etc. */
-  SVN_ERR(svn_client_args_to_target_array2(&action_args, opts, action_args,
-                                           ctx, FALSE, pool));
-  if (root_url)
-    action_args->nelts--;
-
-  /* Now, we iterate over the combined set of arguments -- our actions. */
-  for (i = 0; i < action_args->nelts; ++i)
-    {
-      int j, num_url_args;
-      const char *action_string = APR_ARRAY_IDX(action_args, i, const char *);
-      struct action *action = apr_pcalloc(pool, sizeof(*action));
-      const char *cp_from_rev = NULL;
 
-      /* First, parse the action. */
-      if (! strcmp(action_string, "?") || ! strcmp(action_string, "h")
-          || ! strcmp(action_string, "help"))
+  interactive_actions = !(opts->ind < opts->argc
+                          || extra_args_file
+                          || non_interactive);
+
+  do
+    {
+      /* Parse arguments -- converting local style to internal style,
+       * repos-relative URLs to regular URLs, etc., appending the root
+       * URL temporarily as a reference for repos-relative URLs. */
+      if (root_url)
+        APR_ARRAY_PUSH(action_args, const char *) = root_url;
+      SVN_ERR(svn_client_args_to_target_array2(&action_args, opts, action_args,
+                                               ctx, FALSE, pool));
+      if (root_url)
+        action_args->nelts--;
+
+      if ((err = parse_actions(&actions,
+                               action_args, root_url, anchor,
+                               pool))
+          || (err = execute(actions, anchor, revprops,
+                            base_revision, ctx, pool)))
         {
-          usage(stdout, pool);
-          return SVN_NO_ERROR;
-        }
-      for (j = 0; j < sizeof(action_defn) / sizeof(action_defn[0]); j++)
-        {
-          if (strcmp(action_string, action_defn[j].name) == 0)
+          if (err->apr_err == SVN_ERR_AUTHN_FAILED && non_interactive)
+            err = svn_error_quick_wrap(err,
+                                       _("Authentication failed and interactive"
+                                         " prompting is disabled; see the"
+                                         " --force-interactive option"));
+          if (interactive_actions)
             {
-              action->action = action_defn[j].code;
-              num_url_args = action_defn[j].num_args;
-              break;
+              svn_handle_warning2(stderr, err, "svnmover: ");
+              svn_error_clear(err);
             }
-        }
-      if (j == sizeof(action_defn) / sizeof(action_defn[0]))
-        return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
-                                 "'%s' is not an action",
-                                 action_string);
-
-      if (action->action == ACTION_CP)
-        {
-          /* next argument is the copy source revision */
-          if (++i == action_args->nelts)
-            return svn_error_trace(insufficient());
-          cp_from_rev = APR_ARRAY_IDX(action_args, i, const char *);
+          else
+            SVN_ERR(err);
         }
 
-      /* Parse the required number of URLs. */
-      for (j = 0; j < num_url_args; ++j)
+      /* Possibly read more actions from the command line */
+      if (interactive_actions)
         {
-          const char *path, *url;
+          const char *input;
 
-          if (++i == action_args->nelts)
-            return svn_error_trace(insufficient());
-          path = APR_ARRAY_IDX(action_args, i, const char *);
-
-          if (cp_from_rev && j == 0)
-            {
-              path = apr_psprintf(pool, "%s@%s", path, cp_from_rev);
-            }
-
-          SVN_ERR(svn_opt_parse_path(&action->rev_spec[j], &path, path, pool));
-
-          /* If there's a ROOT_URL, we expect URL to be a path
-             relative to ROOT_URL (and we build a full url from the
-             combination of the two).  Otherwise, it should be a full
-             url. */
-          if (svn_path_is_url(path))
-            {
-              url = path;
-              path = svn_uri_skip_ancestor(root_url, url, pool);
-            }
-          else
-            {
-              if (! root_url)
-                return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
-                                         "'%s' is not a URL, and "
-                                         "--root-url (-U) not provided",
-                                         path);
-              url = svn_path_url_add_component2(root_url, path, pool);
-            }
-          url = sanitize_url(url, pool);
-          action->path[j] = path;
-
-          if (! anchor)
-            anchor = url;
-          else
-            {
-              anchor = svn_uri_get_longest_ancestor(anchor, url, pool);
-              if (!anchor || !anchor[0])
-                return svn_error_createf(SVN_ERR_INCORRECT_PARAMS, NULL,
-                                         "URLs in the action list do not "
-                                         "share a common ancestor");
-            }
+          SVN_ERR(svn_cmdline_prompt_user2(&input, "svnmover> ", NULL, pool));
+          action_args = svn_cstring_split(input, " ",
+                                          TRUE /*chop_whitespace*/, pool);
         }
-
-      APR_ARRAY_PUSH(actions, struct action *) = action;
-    }
-
-  if (! actions->nelts)
-    {
-      *exit_code = EXIT_FAILURE;
-      usage(stderr, pool);
-      return SVN_NO_ERROR;
-    }
-
-  if ((err = execute(actions, anchor, log_msg, revprops,
-                     base_revision, ctx, pool)))
-    {
-      if (err->apr_err == SVN_ERR_AUTHN_FAILED && non_interactive)
-        err = svn_error_quick_wrap(err,
-                                   _("Authentication failed and interactive"
-                                     " prompting is disabled; see the"
-                                     " --force-interactive option"));
-      return err;
     }
+  while (interactive_actions);
 
   return SVN_NO_ERROR;
 }



Mime
View raw message