[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-10-01 18:39:49 CEST

Patch follows in-line comments.

On Tue, Oct 01, 2002 at 05:02:21PM +0100, Philip Martin wrote:
> > + url = entry->url;
> > + if (!url)
> > + url = svn_path_join(this_dir->url, base, pool);
>
> This still doesn't look right. If the entry didn't originally have an
> URL why are you creating one? Why is this logic different from the
> logic in the the loop below? If the file doesn't have an URL then I
> don't think relocate should create one. Trying to relocate a file
> without an URL might perhaps produce an error or it might not, I could
> argue either way.
>

Oh, I thought you were just pointing out that I forgot to join in
the basename. :-)

This code is there because I missed the call to resolve_to_defaults()
in svn_entries_read(), so I didn't think that a file entry's URL would
necessarily be populated. Now that I see that entry->url should already
have the correct value, I understand why you were confused. :-)

So, the right thing to do is just use entry->url, and not worry about
it being null.

> > +
> > + if (!strncmp(url, from, from_len))
> > + {
> > + entry->url = apr_psprintf (pool, "%s%s", to, url + from_len);
>
> Didn't spot this yesterday, but this is not right, see below.
>

Seeing.

> > + if (entry->url &&
> > + (strncmp(entry->url, from, from_len) == 0))
> > + entry->url = apr_psprintf (pool, "%s%s", to, entry->url + from_len);
>
> This has the same problem as the single file apr_psprintf above, it
> modifies the access baton's entry cache, but doesn't use the right
> pool. Memory used to modify the access baton entry cache must come
> from the access baton pool. There are two solutions, either a) use
> svn_wc__entry_modify which does its own allocation, or b) use
> svn_wc_adm_access_pool to get the access baton pool for use in
> apr_psprintf. Solution a) is perhaps simpler for someone reading the
> code to understand, but b) is more efficient (at the moment) since it
> doesn't rewrite the entries file for each entry modified.
>

(b) sounds good to me. :-)

--ben

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. These changes were greatly improved
by feedback from Philip Martin.

* 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 Mon Sep 30 18:24:33 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 Mon Sep 30 18:24:33 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 Tue Oct 1 12:31:42 2002
@@ -0,0 +1,122 @@
+/*
+ * 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);
+ is_file = TRUE;
+ }
+
+ from_len = strlen(from);
+
+ SVN_ERR(svn_wc_entries_read(&entries, adm_access, FALSE, pool));
+
+ if (is_file)
+ {
+ 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");
+
+ if (!strncmp(entry->url, from, from_len))
+ {
+ entry->url = apr_psprintf(svn_wc_adm_access_pool(adm_access),
+ "%s%s", to, entry->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(svn_wc_adm_access_pool(adm_access),
+ "%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 Mon Sep 30 18:48:33 2002
@@ -0,0 +1,61 @@
+/*
+ * 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_ERR (svn_wc_adm_probe_open(&adm_access, NULL, path,
+ TRUE, recurse, pool));
+
+ SVN_ERR(svn_wc_relocate(path, adm_access, from, to, recurse, pool));
+
+ SVN_ERR(svn_wc_adm_close(adm_access));
+
+ return SVN_NO_ERROR;
+}
+
+
+
+/*
+ * 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 18:24:33 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 18:24:33 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 Mon Sep 30 18:24:33 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 Mon Sep 30 18:24:33 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 Tue Oct 1 18:47:27 2002

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.