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

Re: [PATCH] implement "svn switch --only-rewrite-urls"

From: mark benedetto king <bking_at_inquira.com>
Date: 2002-09-30 22:42:44 CEST

Comments inline, updated patch below. Sorry it took me so long
to respond.

On Tue, Sep 24, 2002 at 12:14:01PM +0100, Philip Martin wrote:
> mark benedetto king <bking@inquira.com> writes:
>
> I don't really like this approach, I'd prefer a command that contacts
> the new repository, to ensure that we don't get invalid text-bases.
> The current patch would be the only client command that, by design,
> will allow the user to produce a corrupt working copy.
>

Neither do I, but one step at a time... I need to get these changes
out of my WC.

> That said, here is a short review to help get this working with the
> recent access baton changes :)
>

Thanks once again for your (always constructive) criticism.

> I don't like the optional access baton, just make it required. Yes,
> there are already some optional ones (I put them in) but I'd like to
> remove those and I don't think we should add more of them.
>

Done.

> > +svn_error_t *
> > +svn_wc_relocate (const char *path,
> > + svn_wc_adm_access_t *adm_access,
> > + const char *from,
> > + const char *to,
> > + apr_pool_t *pool);
>
> Do we need to support the --nonrecursive option?
>

Done.

> >
> > +/* Recursively modify a working copy directory DIR, changing any
> > + repository URLs that begin with FROM to begin with TO instead. */
> > +svn_error_t *
> > +svn_client_relocate (const char *dir,
> > + const char *from,
> > + const char *to,
> > + apr_pool_t *pool);
>
> Support --nonrecursive here as well?

Done.

> > +
> > + SVN_ERR (svn_wc_check_wc (path, &is_wc, pool));
> > + if (! is_wc)
> > + return svn_error_createf
> > + (SVN_ERR_WC_NOT_DIRECTORY, 0, NULL, pool,
> > + "svn_wc_cleanup: %s is not a working copy directory", path);
>
> Need to support PATH being a file.
>

Done.

> > +
> > + if (! adm_access)
> > + {
> > + SVN_ERR (svn_wc_adm_open (&adm_access, NULL, path, TRUE, TRUE, pool));
>
> Put this bit into svn_client_relocate.

Done.

>
> > + root = TRUE;
> > + }
> > +
> > + from_len = strlen(from);
> > +
> > + SVN_ERR (svn_wc_entries_read (&entries, path, FALSE, pool));
>
> Need to pass ADM_ACCESS.

Done.

> > + if ((entry->kind == svn_node_dir)
> > + && (strcmp (key, SVN_WC_ENTRY_THIS_DIR) != 0))
> > + {
> > + /* Recurse */
> > + const char *subdir = svn_path_join (path, key, pool);
>
> You will need to add something like
>
> svn_wc_adm_access_t *subdir_access;
> SVN_ERR (svn_wc_adm_retrieve (&subdir_access, adm_access, subdir,
> pool));
>
> > + SVN_ERR (svn_wc_relocate (subdir, adm_access, from, to, pool));
>
> and pass subdir_access instead of adm_access.

Done.

>
> > + }
> > +
> > + if (entry->url &&
> > + (strncmp(entry->url, from, from_len) == 0))
> > + entry->url = apr_psprintf (pool, "%s%s", to, entry->url + from_len);
>
> You will be modifying the cache, but I think it's OK since you are
> about to write it out again.

Right.

>
> > + }
> > +
> > + SVN_ERR (svn_wc__entries_write (entries, path, pool));
>
> Need to pass ADM_ACCESS.

Done.
>
> > +
> > + if (root)
> > + svn_wc_adm_close(adm_access);
>
> Put this bit into svn_client_relocate.

Done.

> > + SVN_ERR (svn_io_check_path (dir, &kind, pool));
> > + if (kind != svn_node_dir)
> > + return svn_error_createf (SVN_ERR_WC_NOT_DIRECTORY, 0, NULL, pool,
> > + "Cannot relocate '%s' -- not a directory",
> > + dir);
> > +
>
> We need to support files, so don't bother with the above check. Just
> do something like
>
> svn_wc_adm_access_t *adm_access;
> SVN_ERR (svn_wc_adm_probe_open (&adm_access, NULL, path, TRUE, recurse,
> pool));
>
> > + return svn_wc_relocate (dir, NULL, from, to, pool);
>
> Pass adm_access to svn_wc_relocate, and then close it.
>
> SVN_ERR (svn_wc_adm_close (adm_access));
>

Done.

--ben

Patch:

New subcommand: "relocate". Useful for when the URL by which the
repository must be referred to has changed. This happens most
frequently for mobile users.

* subversion/include/svn_wc.h
  (svn_wc_relocate): Prototype for new function.

* subversion/include/svn_client.h
  (svn_client_relocate): Prototype for new function.

* subversion/libsvn_wc/relocate.c
  New file. Includes implementation of svn_wc_relocate().
  Should eventually verify that new URL is valid; doesn't
  do any validation at all right now.

* subversion/libsvn_client/relocate.c
  New file. Includes implementation of svn_client_relocate().

* subversion/clients/cmdline/cl.h
  (svn_cl__relocate): Added subcommand prototype. Fixed
  alphabetical-order of resolve/revert.

* subversion/clients/cmdline/relocate-cmd.c
  New file. Includes implementation of svn_cl__relocate().

* subversion/clients/cmdline/main.c
  (svn_cl__cmd_table): Added entry for "relocate".

* subversion/tests/clients/cmdline/getopt_tests_data/svn_help_log_switch_stdout
  Adjust expected output.

Index: subversion/include/svn_wc.h
===================================================================
--- subversion/include/svn_wc.h
+++ subversion/include/svn_wc.h Fri Sep 27 18:55:43 2002
@@ -1481,6 +1481,19 @@
                 svn_wc_adm_access_t *optional_adm_access,
                 apr_pool_t *pool);
 
+/* Changing repository references at PATH that begin with
+ FROM to begin with TO instead. Perform necessary allocations in
+ POOL. If RECURSE is true, do so.
+
+ ADM_ACCESS is an access baton for the directory containing
+ PATH. ADM_ACCESS must not be NULL. */
+svn_error_t *
+svn_wc_relocate (const char *path,
+ svn_wc_adm_access_t *adm_access,
+ const char *from,
+ const char *to,
+ svn_boolean_t recurse,
+ apr_pool_t *pool);
 
 /* Revert changes to PATH (perhaps in a RECURSIVE fashion). Perform
    necessary allocations in POOL.
Index: subversion/include/svn_client.h
===================================================================
--- subversion/include/svn_client.h
+++ subversion/include/svn_client.h Fri Sep 27 18:55:44 2002
@@ -652,6 +652,17 @@
                     apr_pool_t *pool);
 
 
+/* Modify a working copy directory DIR, changing any
+ repository URLs that begin with FROM to begin with TO instead,
+ recursing into subdirectories if RECURSE is true. */
+svn_error_t *
+svn_client_relocate (const char *dir,
+ const char *from,
+ const char *to,
+ svn_boolean_t recurse,
+ apr_pool_t *pool);
+
+
 /* Restore the pristine version of a working copy PATH, effectively
    undoing any local mods. If PATH is a directory, and RECURSIVE is
    TRUE, this will be a recursive operation.
Index: subversion/libsvn_wc/relocate.c
===================================================================
--- subversion/libsvn_wc/relocate.c
+++ subversion/libsvn_wc/relocate.c Mon Sep 30 16:26:04 2002
@@ -0,0 +1,123 @@
+/*
+ * relocate.c: do wc repos relocation
+ *
+ * ====================================================================
+ * Copyright (c) 2000-2002 CollabNet. All rights reserved.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://subversion.tigris.org/license-1.html.
+ * If newer versions of this license are posted there, you may use a
+ * newer version instead, at your option.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals. For exact contribution history, see the revision
+ * history and logs, available at http://subversion.tigris.org/.
+ * ====================================================================
+ */
+
+
+
+#include "svn_wc.h"
+#include "svn_error.h"
+#include "svn_string.h"
+#include "svn_xml.h"
+#include "svn_pools.h"
+#include "svn_io.h"
+
+#include "wc.h"
+#include "entries.h"
+
+
+svn_error_t *
+svn_wc_relocate (const char *path,
+ svn_wc_adm_access_t *adm_access,
+ const char *from,
+ const char *to,
+ svn_boolean_t recurse,
+ apr_pool_t *pool)
+{
+ enum svn_node_kind kind;
+ apr_hash_t *entries = NULL;
+ apr_hash_index_t *hi;
+ svn_boolean_t is_file = FALSE;
+ char *base;
+ int from_len;
+
+ SVN_ERR(svn_io_check_path(path, &kind, pool));
+
+ if (kind == svn_node_file)
+ {
+ base = svn_path_basename(path, pool);
+ path = svn_path_remove_component_nts(path, pool);
+ is_file = TRUE;
+ }
+
+ from_len = strlen(from);
+
+ SVN_ERR(svn_wc_entries_read(&entries, adm_access, FALSE, pool));
+
+ if (is_file)
+ {
+ const char *url;
+ svn_wc_entry_t *this_dir = apr_hash_get(entries,
+ SVN_WC_ENTRY_THIS_DIR,
+ APR_HASH_KEY_STRING);
+ svn_wc_entry_t *entry = apr_hash_get(entries, base, APR_HASH_KEY_STRING);
+ if (!this_dir)
+ return svn_error_create(SVN_ERR_ENTRY_NOT_FOUND, 0, NULL, pool,
+ "missing default entry");
+ if (!entry)
+ return svn_error_create(SVN_ERR_ENTRY_NOT_FOUND, 0, NULL, pool,
+ "missing entry");
+
+ url = entry->url? entry->url : this_dir->url;
+ if (url &&
+ (strncmp(url, from, from_len) == 0))
+ entry->url = apr_psprintf (pool, "%s%s", to, url + from_len);
+
+ SVN_ERR(svn_wc__entries_write (entries, adm_access, pool));
+
+ return SVN_NO_ERROR;
+ }
+
+ for (hi = apr_hash_first(pool, entries); hi; hi = apr_hash_next(hi))
+ {
+ const void *key;
+ void *val;
+ svn_wc_entry_t *entry;
+
+ apr_hash_this(hi, &key, NULL, &val);
+ entry = val;
+
+
+ if (recurse
+ && (entry->kind == svn_node_dir)
+ && (strcmp(key, SVN_WC_ENTRY_THIS_DIR) != 0))
+ {
+ svn_wc_adm_access_t *subdir_access;
+ const char *subdir = svn_path_join (path, key, pool);
+ SVN_ERR(svn_wc_adm_retrieve(&subdir_access, adm_access, subdir,
+ pool));
+ SVN_ERR(svn_wc_relocate(subdir, subdir_access, from,
+ to, recurse, pool));
+ }
+
+ if (entry->url &&
+ (strncmp(entry->url, from, from_len) == 0))
+ entry->url = apr_psprintf (pool, "%s%s", to, entry->url + from_len);
+ }
+
+ SVN_ERR(svn_wc__entries_write (entries, adm_access, pool));
+
+ return SVN_NO_ERROR;
+}
+
+
+
+/*
+ * local variables:
+ * eval: (load-file "../../tools/dev/svn-dev.el")
+ * end:
+ */
+
Index: subversion/libsvn_client/relocate.c
===================================================================
--- subversion/libsvn_client/relocate.c
+++ subversion/libsvn_client/relocate.c Tue Sep 24 17:27:07 2002
@@ -0,0 +1,63 @@
+/*
+ * relocate.c: wrapper around wc relocation functionality.
+ *
+ * ====================================================================
+ * Copyright (c) 2000-2002 CollabNet. All rights reserved.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://subversion.tigris.org/license-1.html.
+ * If newer versions of this license are posted there, you may use a
+ * newer version instead, at your option.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals. For exact contribution history, see the revision
+ * history and logs, available at http://subversion.tigris.org/.
+ * ====================================================================
+ */
+
+/* ==================================================================== */
+
+
+
+/*** Includes. ***/
+
+#include "svn_wc.h"
+#include "svn_client.h"
+#include "svn_string.h"
+#include "svn_pools.h"
+#include "svn_error.h"
+#include "svn_path.h"
+#include "client.h"
+
+
+
+/*** Code. ***/
+
+svn_error_t *
+svn_client_relocate (const char *path,
+ const char *from,
+ const char *to,
+ svn_boolean_t recurse,
+ apr_pool_t *pool)
+{
+ svn_wc_adm_access_t *adm_access;
+ svn_error_t *err;
+ svn_error_t *err2;
+
+ SVN_ERR (svn_wc_adm_probe_open(&adm_access, NULL, path,
+ TRUE, recurse, pool));
+
+ err = svn_wc_relocate(path, adm_access, from, to, recurse, pool);
+
+ err2 = svn_wc_adm_close(adm_access);
+
+ return err ? err : err2;
+}
+
+
+
+/*
+ * local variables:
+ * eval: (load-file "../../tools/dev/svn-dev.el")
+ * end: */
Index: subversion/clients/cmdline/cl.h
===================================================================
--- subversion/clients/cmdline/cl.h
+++ subversion/clients/cmdline/cl.h Mon Sep 30 15:19:59 2002
@@ -54,7 +54,8 @@
   svn_cl__xml_opt,
   svn_cl__strict_opt,
   svn_cl__no_ignore_opt,
- svn_cl__no_auth_cache_opt
+ svn_cl__no_auth_cache_opt,
+ svn_cl__only_rewrite_urls_opt
 } svn_cl__longopt_t;
 
 
@@ -94,6 +95,7 @@
   svn_boolean_t xml; /* output in xml, e.g., "svn log --xml" */
   svn_boolean_t no_ignore; /* disregard default ignores & svn:ignore's */
   svn_boolean_t no_auth_cache; /* do not cache authentication information */
+ svn_boolean_t only_rewrite_urls; /* rewrite urls (svn switch) */
 } svn_cl__opt_state_t;
 
 
Index: subversion/clients/cmdline/switch-cmd.c
===================================================================
--- subversion/clients/cmdline/switch-cmd.c
+++ subversion/clients/cmdline/switch-cmd.c Mon Sep 30 15:25:31 2002
@@ -21,18 +21,54 @@
 
 
 /*** Includes. ***/
-
 #include "svn_wc.h"
 #include "svn_client.h"
 #include "svn_string.h"
 #include "svn_path.h"
 #include "svn_delta.h"
 #include "svn_error.h"
+#include "svn_pools.h"
 #include "cl.h"
 
 
 /*** Code. ***/
 
+static svn_error_t *
+rewrite_urls(apr_array_header_t *targets,
+ svn_boolean_t recurse,
+ apr_pool_t *pool)
+{
+ apr_pool_t *subpool;
+ const char *from;
+ const char *to;
+ int i;
+
+ if (targets->nelts < 2)
+ return svn_error_create (SVN_ERR_CL_ARG_PARSING_ERROR, 0, 0, pool, "");
+
+ from = ((const char **) (targets->elts))[0];
+ to = ((const char **) (targets->elts))[1];
+
+ subpool = svn_pool_create (pool);
+
+ if (targets->nelts == 2)
+ {
+ SVN_ERR(svn_client_relocate ("", from, to, recurse, pool));
+ }
+ else
+ {
+ for (i = 2; i < targets->nelts; i++)
+ {
+ const char *target = ((const char **) (targets->elts))[i];
+ SVN_ERR (svn_client_relocate (target, from, to, recurse, subpool));
+ svn_pool_clear (subpool);
+ }
+ }
+
+ svn_pool_destroy (subpool);
+ return SVN_NO_ERROR;
+}
+
 
 /* This implements the `svn_opt_subcommand_t' interface. */
 svn_error_t *
@@ -59,6 +95,10 @@
                                          &(opt_state->end_revision),
                                          FALSE, pool));
 
+ /* handle only-rewrite case specially */
+ if (opt_state->only_rewrite_urls)
+ return rewrite_urls (targets, !opt_state->nonrecursive, pool);
+
   if ((targets->nelts < 1) || (targets->nelts > 2))
     return svn_error_create (SVN_ERR_CL_ARG_PARSING_ERROR, 0, 0, pool, "");
 
Index: subversion/clients/cmdline/main.c
===================================================================
--- subversion/clients/cmdline/main.c
+++ subversion/clients/cmdline/main.c Fri Sep 27 20:07:19 2002
@@ -85,6 +85,8 @@
                       "disregard default and svn:ignore property ignores"},
     {"no-auth-cache", svn_cl__no_auth_cache_opt, 0,
                       "do not cache authentication tokens"},
+ {"only-rewrite-urls", svn_cl__only_rewrite_urls_opt, 0,
+ "only rewrite urls; do not contact a repository"},
     {0, 0, 0, 0}
   };
 
@@ -378,10 +380,12 @@
   
   { "switch", svn_cl__switch, {"sw"},
     "Update working copy to mirror a new URL\n"
- "usage: switch REPOS_URL [TARGET]\n\n"
+ "usage: switch REPOS_URL [TARGET] or\n"
+ " switch --only-rewrite-urls [FROM] [TO] [TARGET ...]\n\n"
     " Note: this is the way to move a working copy to a new branch.\n",
     { 'r', 'D', 'N', 'q', svn_cl__auth_username_opt,
- svn_cl__auth_password_opt, svn_cl__no_auth_cache_opt} },
+ svn_cl__auth_password_opt, svn_cl__no_auth_cache_opt,
+ svn_cl__only_rewrite_urls_opt } },
  
   { "update", svn_cl__update, {"up"},
     "Bring changes from the repository into the working copy.\n"
@@ -404,7 +408,6 @@
   { NULL, NULL, {0}, NULL, {0} }
 };
 
-
 
 /*** Main. ***/
 
@@ -667,6 +670,9 @@
       case svn_cl__no_auth_cache_opt:
         opt_state.no_auth_cache = TRUE;
         break;
+ case svn_cl__only_rewrite_urls_opt:
+ opt_state.only_rewrite_urls = TRUE;
+ break;
       case 'x':
         err = svn_utf_cstring_to_utf8 (&opt_state.extensions, opt_arg,
                                        NULL, pool);
Index: subversion/tests/clients/cmdline/getopt_tests_data/svn_help_log_switch_stdout
===================================================================
--- subversion/tests/clients/cmdline/getopt_tests_data/svn_help_log_switch_stdout
+++ subversion/tests/clients/cmdline/getopt_tests_data/svn_help_log_switch_stdout Thu Sep 26 17:44:42 2002
@@ -27,7 +27,8 @@
   --xml : output in xml
 
 switch (sw): Update working copy to mirror a new URL
-usage: switch REPOS_URL [TARGET]
+usage: switch REPOS_URL [TARGET] or
+ switch --only-rewrite-urls [FROM] [TO] [TARGET ...]
 
    Note: this is the way to move a working copy to a new branch.
 
@@ -39,4 +40,5 @@
   --username arg : specify a username ARG
   --password arg : specify a password ARG
   --no-auth-cache : do not cache authentication tokens
+ --only-rewrite-urls : only rewrite urls; do not contact a repository
 

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Mon Sep 30 22:50:18 2002

This is an archived mail posted to the Subversion Dev mailing list.