[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-02 23:04:13 CEST

Patch follows in-lined comments.

On Tue, Oct 01, 2002 at 06:16:25PM +0100, Philip Martin wrote:
> mark benedetto king <bking@Inquira.Com> writes:
>
> > So, the right thing to do is just use entry->url, and not worry about
> > it being null.
>
> Try
>
> $ touch foo
> $ svn add foo
> $ svn info foo
>

Eek. You're right (a look at take_from_entry() explains why).

> The svn_wc_entry_t for foo will contain a null URL. Now if you
> relocate the parent directory your code just skips foo, which looks
> like the correct thing to do. But if you try to relocate foo itself,
> your old code used to make up an URL, and your new code dumps core.
>
> Now that you are not trying to make up an URL you don't need to get or
> check the this_dir entry for the single file case either.

Since it's not under revision control, I think we can't do anything
other than punt.

>
> Other things to consider:
>
> Should attempting to relocate a file without an URL generate an error?
> Looks like ordinary switch fails here :-(

Yes, see above.

>
> If there is an URL but it doesn't match the "from" prefix, should
> there be an error?
>

My gut says "no", but my gut is frequently wrong about interface
behaviour.

> If a single file, or subdirectory, has been switched, then its URL
> won't be simply parent directory URL + name. If while relocating a
> directory you come across a child with an URL that doesn't match the
> "from" prefix, while the parent directory has an URL that does match,
> should there be an error?

No, I don't think so.

>
> --
> Philip Martin
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
> For additional commands, e-mail: dev-help@subversion.tigris.org

--ben

New option for svn switch: "--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. Thanks to Greg Hudson for noticing that
the log message was no longer in sync with the patch.

* 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__longopt_t): Added enum for new option.
  (svn_cl__opt_state_t): Added entry for new option.

* subversion/clients/cmdline/switch-cmd.c
  (rewrite_urls): New function: calls svn_client_relocate().
  (svn_cl__switch): Call rewrite_urls() instead of normal switch logic
  when appropriate.

* subversion/clients/cmdline/main.c
  (svn_cl__options): Added entry for new option.
  (svn_cl__cmd_table): Updated entry for switch to support new option.
  (main): Added support for new option.

* 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 Wed Oct 2 00:55:30 2002
@@ -0,0 +1,120 @@
+/*
+ * 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 *entry = apr_hash_get(entries, base, APR_HASH_KEY_STRING);
+ if (!entry)
+ return svn_error_create(SVN_ERR_ENTRY_NOT_FOUND, 0, NULL, pool,
+ "missing entry");
+
+ if (!entry->url)
+ return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, 0, NULL, pool,
+ "entry '%s' has no URL", path);
+
+ 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 Wed Oct 2 16:37:23 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__relocate_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 relocate; /* 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 Wed Oct 2 16:37:47 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->relocate)
+ 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 Wed Oct 2 16:36:58 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"},
+ {"relocate", svn_cl__relocate_opt, 0,
+ "relocate via url-rewriting"},
     {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 --relocate [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__relocate_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__relocate_opt:
+ opt_state.relocate = 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 Wed Oct 2 16:42:22 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 --relocate [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
+ --relocate : relocate via url-rewriting
 

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Wed Oct 2 23:11:57 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.