You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2010/09/26 13:59:01 UTC
svn commit: r1001417 [6/7] - in /subversion/branches/performance: ./ build/
notes/ notes/http-and-webdav/ subversion/bindings/javahl/native/
subversion/bindings/javahl/tests/org/apache/subversion/javahl/
subversion/bindings/javahl/tests/org/tigris/subv...
Modified: subversion/branches/performance/subversion/svn/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/svn/main.c?rev=1001417&r1=1001416&r2=1001417&view=diff
==============================================================================
--- subversion/branches/performance/subversion/svn/main.c (original)
+++ subversion/branches/performance/subversion/svn/main.c Sun Sep 26 11:58:58 2010
@@ -2087,12 +2087,24 @@ main(int argc, const char *argv[])
}
}
- if (opt_state.relocate && (opt_state.depth != svn_depth_unknown))
+ /* Relocation is infinite-depth only. */
+ if (opt_state.relocate)
{
- err = svn_error_create(SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
- _("--relocate and --depth are mutually "
- "exclusive"));
- return svn_cmdline_handle_exit_error(err, pool, "svn: ");
+ if (opt_state.depth != svn_depth_unknown)
+ {
+ err = svn_error_create(SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
+ _("--relocate and --depth are mutually "
+ "exclusive"));
+ return svn_cmdline_handle_exit_error(err, pool, "svn: ");
+ }
+ if (! descend)
+ {
+ err = svn_error_create(
+ SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
+ _("--relocate and --non-recursive (-N) are mutually "
+ "exclusive"));
+ return svn_cmdline_handle_exit_error(err, pool, "svn: ");
+ }
}
/* Only a few commands can accept a revision range; the rest can take at
Modified: subversion/branches/performance/subversion/svn/switch-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/svn/switch-cmd.c?rev=1001417&r1=1001416&r2=1001417&view=diff
==============================================================================
--- subversion/branches/performance/subversion/svn/switch-cmd.c (original)
+++ subversion/branches/performance/subversion/svn/switch-cmd.c Sun Sep 26 11:58:58 2010
@@ -41,7 +41,6 @@
static svn_error_t *
rewrite_urls(const apr_array_header_t *targets,
- svn_boolean_t recurse,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
@@ -67,7 +66,7 @@ rewrite_urls(const apr_array_header_t *t
if (targets->nelts == 2)
{
- SVN_ERR(svn_client_relocate("", from, to, recurse, ctx, pool));
+ SVN_ERR(svn_client_relocate2("", from, to, ctx, pool));
}
else
{
@@ -75,8 +74,7 @@ rewrite_urls(const apr_array_header_t *t
{
const char *target = APR_ARRAY_IDX(targets, i, const char *);
svn_pool_clear(subpool);
- SVN_ERR(svn_client_relocate(target, from, to, recurse,
- ctx, subpool));
+ SVN_ERR(svn_client_relocate2(target, from, to, ctx, subpool));
}
}
@@ -109,9 +107,7 @@ svn_cl__switch(apr_getopt_t *os,
/* handle only-rewrite case specially */
if (opt_state->relocate)
- return rewrite_urls(targets,
- SVN_DEPTH_IS_RECURSIVE(opt_state->depth),
- ctx, scratch_pool);
+ return rewrite_urls(targets, ctx, scratch_pool);
if (targets->nelts < 1)
return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
Modified: subversion/branches/performance/subversion/svnrdump/dump_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/svnrdump/dump_editor.c?rev=1001417&r1=1001416&r2=1001417&view=diff
==============================================================================
--- subversion/branches/performance/subversion/svnrdump/dump_editor.c (original)
+++ subversion/branches/performance/subversion/svnrdump/dump_editor.c Sun Sep 26 11:58:58 2010
@@ -27,6 +27,7 @@
#include "svn_repos.h"
#include "svn_path.h"
#include "svn_props.h"
+#include "svn_subst.h"
#include "svn_dirent_uri.h"
#include "dump_editor.h"
@@ -66,11 +67,41 @@ struct dump_edit_baton {
const char *base_checksum;
/* Flags to trigger dumping props and text */
- svn_boolean_t dump_props;
svn_boolean_t dump_text;
- svn_boolean_t dump_props_pending;
+ svn_boolean_t dump_props;
+ svn_boolean_t dump_newlines;
};
+/* Normalize the line ending style of the values of properties in PROPS
+ * that "need translation" (according to svn_prop_needs_translation(),
+ * currently all svn:* props) so that they contain only LF (\n) line endings.
+ */
+svn_error_t *
+normalize_props(apr_hash_t *props,
+ apr_pool_t *pool)
+{
+ apr_hash_index_t *hi;
+ const char *key, *cstring;
+ const svn_string_t *value;
+
+ for (hi = apr_hash_first(pool, props); hi; hi = apr_hash_next(hi))
+ {
+ key = svn__apr_hash_index_key(hi);
+ value = svn__apr_hash_index_val(hi);
+
+ if (svn_prop_needs_translation(key))
+ {
+ SVN_ERR(svn_subst_translate_cstring2(value->data, &cstring,
+ "\n", TRUE,
+ NULL, FALSE,
+ pool));
+ value = svn_string_create(cstring, pool);
+ apr_hash_set(props, key, APR_HASH_KEY_STRING, value);
+ }
+ }
+ return SVN_NO_ERROR;
+}
+
/* Make a directory baton to represent the directory at path (relative
* to the edit_baton).
*
@@ -97,17 +128,15 @@ make_dir_baton(const char *path,
struct dir_baton *new_db = apr_pcalloc(pool, sizeof(*new_db));
const char *abspath;
- /* Disallow a path relative to nothing. */
- SVN_ERR_ASSERT_NO_RETURN(!path || pb);
-
/* Construct the full path of this node. */
if (pb)
abspath = svn_uri_join("/", path, pool);
else
- abspath = "/";
+ abspath = apr_pstrdup(pool, "/");
- /* Remove leading slashes from copyfrom paths. */
- if (copyfrom_path && strcmp(copyfrom_path, "/"))
+ /* Strip leading slash from copyfrom_path so that the path is
+ canonical and svn_relpath_join can be used */
+ if (copyfrom_path)
copyfrom_path = ((*copyfrom_path == '/') ?
copyfrom_path + 1 : copyfrom_path);
@@ -139,6 +168,7 @@ dump_props(struct dump_edit_baton *eb,
if (trigger_var && !*trigger_var)
return SVN_NO_ERROR;
+ SVN_ERR(normalize_props(eb->props, eb->pool));
svn_stringbuf_setempty(eb->propstring);
propstream = svn_stream_from_stringbuf(eb->propstring, eb->pool);
SVN_ERR(svn_hash_write_incremental(eb->props, eb->deleted_props,
@@ -172,8 +202,8 @@ dump_props(struct dump_edit_baton *eb,
SVN_ERR(svn_stream_printf(eb->stream, pool, "\n\n"));
/* Cleanup so that data is never dumped twice. */
- svn_hash__clear(eb->props, pool);
- svn_hash__clear(eb->deleted_props, pool);
+ svn_hash__clear(eb->props, eb->pool);
+ svn_hash__clear(eb->deleted_props, eb->pool);
if (trigger_var)
*trigger_var = FALSE;
}
@@ -181,6 +211,19 @@ dump_props(struct dump_edit_baton *eb,
return SVN_NO_ERROR;
}
+static svn_error_t *
+dump_newlines(struct dump_edit_baton *eb,
+ svn_boolean_t *trigger_var,
+ apr_pool_t *pool)
+{
+ if (trigger_var && *trigger_var)
+ {
+ SVN_ERR(svn_stream_printf(eb->stream, pool, "\n\n"));
+ *trigger_var = FALSE;
+ }
+ return SVN_NO_ERROR;
+}
+
/*
* Write out a node record for PATH of type KIND under EB->FS_ROOT.
* ACTION describes what is happening to the node (see enum
@@ -227,6 +270,9 @@ dump_node(struct dump_edit_baton *eb,
switch (action)
{
case svn_node_action_change:
+ /* We are here after a change_file_prop or change_dir_prop. They
+ set up whatever dump_props they needed to- nothing to
+ do here but print node action information */
SVN_ERR(svn_stream_printf(eb->stream, pool,
SVN_REPOS_DUMPFILE_NODE_ACTION
": change\n"));
@@ -240,7 +286,9 @@ dump_node(struct dump_edit_baton *eb,
SVN_REPOS_DUMPFILE_NODE_ACTION
": replace\n"));
- eb->dump_props_pending = TRUE;
+ /* Wait for a change_*_prop to be called before dumping
+ anything */
+ eb->dump_props = TRUE;
break;
}
/* More complex case: is_copy is true, and copyfrom_path/
@@ -257,7 +305,6 @@ dump_node(struct dump_edit_baton *eb,
/* We can leave this routine quietly now, don't need to dump any
content; that was already done in the second record. */
- eb->dump_props = FALSE;
break;
case svn_node_action_delete:
@@ -265,10 +312,10 @@ dump_node(struct dump_edit_baton *eb,
SVN_REPOS_DUMPFILE_NODE_ACTION
": delete\n"));
- /* We can leave this routine quietly now, don't need to dump
- any content. */
+ /* We can leave this routine quietly now. Nothing more to do-
+ print a couple of newlines because we're not dumping props or
+ text. */
SVN_ERR(svn_stream_printf(eb->stream, pool, "\n\n"));
- eb->dump_props = FALSE;
break;
case svn_node_action_add:
@@ -277,15 +324,17 @@ dump_node(struct dump_edit_baton *eb,
if (!is_copy)
{
- /* eb->dump_props_pending for files is handled in close_file
+ /* eb->dump_props for files is handled in close_file
which is called immediately. However, directories are not
closed until all the work inside them has been done;
- eb->dump_props_pending for directories is handled in all the
+ eb->dump_props for directories is handled in all the
functions that can possibly be called after add_directory:
add_directory, open_directory, delete_entry, close_directory,
add_file, open_file. change_dir_prop is a special case. */
- eb->dump_props_pending = TRUE;
+ /* Wait for a change_*_prop to be called before dumping
+ anything */
+ eb->dump_props = TRUE;
break;
}
@@ -296,19 +345,18 @@ dump_node(struct dump_edit_baton *eb,
": %s\n",
copyfrom_rev, copyfrom_path));
- /* Ugly hack: If a directory was copied from a previous revision,
- nothing else can be done, and close_file won't be called to
- write two blank lines. Write them here otherwise the `svnadmin
- load` parser will fail. */
+ /* Ugly hack: If a directory was copied from a previous
+ revision, nothing like close_file will be called to write two
+ blank lines. If change_dir_prop is called, props are dumped
+ (along with the necessary PROPS-END\n\n and we're good. So
+ set a dump_newlines here to print the newlines unless
+ change_dir_prop is called next otherwise the `svnadmin load`
+ parser will fail. */
if (kind == svn_node_dir)
- SVN_ERR(svn_stream_printf(eb->stream, pool, "\n\n"));
+ eb->dump_newlines = TRUE;
break;
}
-
- /* Dump property headers */
- SVN_ERR(dump_props(eb, &(eb->dump_props), FALSE, pool));
-
return SVN_NO_ERROR;
}
@@ -345,11 +393,15 @@ delete_entry(const char *path,
LDR_DBG(("delete_entry %s\n", path));
/* Some pending properties to dump? */
- SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props_pending), TRUE, pool));
+ SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props), TRUE, pool));
+
+ /* Some pending newlines to dump? */
+ SVN_ERR(dump_newlines(pb->eb, &(pb->eb->dump_newlines), pool));
/* Add this path to the deleted_entries of the parent directory
baton. */
- apr_hash_set(pb->deleted_entries, path, APR_HASH_KEY_STRING, pb);
+ apr_hash_set(pb->deleted_entries, apr_pstrdup(pb->eb->pool, path),
+ APR_HASH_KEY_STRING, pb);
return SVN_NO_ERROR;
}
@@ -371,7 +423,10 @@ add_directory(const char *path,
LDR_DBG(("add_directory %s\n", path));
/* Some pending properties to dump? */
- SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props_pending), TRUE, pool));
+ SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props), TRUE, pool));
+
+ /* Some pending newlines to dump? */
+ SVN_ERR(dump_newlines(pb->eb, &(pb->eb->dump_newlines), pool));
/* This might be a replacement -- is the path already deleted? */
val = apr_hash_get(pb->deleted_entries, path, APR_HASH_KEY_STRING);
@@ -413,7 +468,10 @@ open_directory(const char *path,
LDR_DBG(("open_directory %s\n", path));
/* Some pending properties to dump? */
- SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props_pending), TRUE, pool));
+ SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props), TRUE, pool));
+
+ /* Some pending newlines to dump? */
+ SVN_ERR(dump_newlines(pb->eb, &(pb->eb->dump_newlines), pool));
/* If the parent directory has explicit comparison path and rev,
record the same for this one. */
@@ -442,12 +500,15 @@ close_directory(void *dir_baton,
LDR_DBG(("close_directory %p\n", dir_baton));
+ /* Some pending properties to dump? */
+ SVN_ERR(dump_props(eb, &(eb->dump_props), TRUE, pool));
+
+ /* Some pending newlines to dump? */
+ SVN_ERR(dump_newlines(eb, &(eb->dump_newlines), pool));
+
/* Create a pool just for iterations to allocate a loop variable */
iterpool = svn_pool_create(pool);
- /* Some pending properties to dump? */
- SVN_ERR(dump_props(eb, &(eb->dump_props_pending), TRUE, pool));
-
/* Dump the deleted directory entries */
for (hi = apr_hash_first(iterpool, db->deleted_entries); hi;
hi = apr_hash_next(hi))
@@ -481,7 +542,10 @@ add_file(const char *path,
LDR_DBG(("add_file %s\n", path));
/* Some pending properties to dump? */
- SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props_pending), TRUE, pool));
+ SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props), TRUE, pool));
+
+ /* Some pending newlines to dump? */
+ SVN_ERR(dump_newlines(pb->eb, &(pb->eb->dump_newlines), pool));
/* This might be a replacement -- is the path already deleted? */
val = apr_hash_get(pb->deleted_entries, path, APR_HASH_KEY_STRING);
@@ -523,7 +587,10 @@ open_file(const char *path,
LDR_DBG(("open_file %s\n", path));
/* Some pending properties to dump? */
- SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props_pending), TRUE, pool));
+ SVN_ERR(dump_props(pb->eb, &(pb->eb->dump_props), TRUE, pool));
+
+ /* Some pending newlines to dump? */
+ SVN_ERR(dump_newlines(pb->eb, &(pb->eb->dump_newlines), pool));
/* If the parent directory has explicit copyfrom path and rev,
record the same for this one. */
@@ -558,8 +625,8 @@ change_dir_prop(void *parent_baton,
return SVN_NO_ERROR;
if (value)
- apr_hash_set(db->eb->props, apr_pstrdup(pool, name),
- APR_HASH_KEY_STRING, svn_string_dup(value, pool));
+ apr_hash_set(db->eb->props, apr_pstrdup(db->eb->pool, name),
+ APR_HASH_KEY_STRING, svn_string_dup(value, db->eb->pool));
else
apr_hash_set(db->eb->deleted_props, apr_pstrdup(pool, name),
APR_HASH_KEY_STRING, "");
@@ -568,17 +635,21 @@ change_dir_prop(void *parent_baton,
{
/* If db->written_out is set, it means that the node information
corresponding to this directory has already been written: don't
- do anything; dump_props_pending will take care of dumping the
+ do anything; dump_props will take care of dumping the
props. If it not, dump the node itself before dumping the
props. */
SVN_ERR(dump_node(db->eb, db->abspath, svn_node_dir,
svn_node_action_change, FALSE, db->copyfrom_path,
db->copyfrom_rev, pool));
-
- SVN_ERR(dump_props(db->eb, NULL, TRUE, pool));
db->written_out = TRUE;
}
+
+ /* Dump props whether or not the directory has been written
+ out. Then disable printing a couple of extra newlines */
+ SVN_ERR(dump_props(db->eb, NULL, TRUE, pool));
+ db->eb->dump_newlines = FALSE;
+
return SVN_NO_ERROR;
}
@@ -596,16 +667,16 @@ change_file_prop(void *file_baton,
return SVN_NO_ERROR;
if (value)
- apr_hash_set(eb->props, apr_pstrdup(pool, name),
- APR_HASH_KEY_STRING, svn_string_dup(value, pool));
+ apr_hash_set(eb->props, apr_pstrdup(eb->pool, name),
+ APR_HASH_KEY_STRING, svn_string_dup(value, eb->pool));
else
- apr_hash_set(eb->deleted_props, apr_pstrdup(pool, name),
+ apr_hash_set(eb->deleted_props, apr_pstrdup(eb->pool, name),
APR_HASH_KEY_STRING, "");
/* Dump the property headers and wait; close_file might need
to write text headers too depending on whether
apply_textdelta is called */
- eb->dump_props_pending = TRUE;
+ eb->dump_props = TRUE;
return SVN_NO_ERROR;
}
@@ -680,11 +751,11 @@ close_file(void *file_baton,
LDR_DBG(("close_file %p\n", file_baton));
- /* Some pending properties to dump? */
- SVN_ERR(dump_props(eb, &(eb->dump_props_pending), FALSE, pool));
+ /* Some pending properties to dump? Dump just the headers- dump the
+ props only after dumping the text headers too (if present) */
+ SVN_ERR(dump_props(eb, &(eb->dump_props), FALSE, pool));
- /* The prop headers have already been dumped in dump_node; now dump
- the text headers. */
+ /* Dump the text headers */
if (eb->dump_text)
{
/* Text-delta: true */
@@ -716,7 +787,7 @@ close_file(void *file_baton,
/* Content-length: 1549 */
/* If both text and props are absent, skip this header */
- if (eb->dump_props || eb->dump_props_pending)
+ if (eb->dump_props)
SVN_ERR(svn_stream_printf(eb->stream, pool,
SVN_REPOS_DUMPFILE_CONTENT_LENGTH
": %ld\n\n",
@@ -727,17 +798,16 @@ close_file(void *file_baton,
": %ld\n\n",
(unsigned long)info->size));
- /* Dump the props; the propstring should have already been
- written in dump_node or above */
- if (eb->dump_props || eb->dump_props_pending)
+ /* Dump the props now */
+ if (eb->dump_props)
{
SVN_ERR(svn_stream_write(eb->stream, eb->propstring->data,
&(eb->propstring->len)));
/* Cleanup */
- eb->dump_props = eb->dump_props_pending = FALSE;
- svn_hash__clear(eb->props, pool);
- svn_hash__clear(eb->deleted_props, pool);
+ eb->dump_props = FALSE;
+ svn_hash__clear(eb->props, eb->pool);
+ svn_hash__clear(eb->deleted_props, eb->pool);
}
/* Dump the text */
@@ -758,6 +828,8 @@ close_file(void *file_baton,
eb->dump_text = FALSE;
}
+ /* Write a couple of blank lines for matching output with `svnadmin
+ dump` */
SVN_ERR(svn_stream_printf(eb->stream, pool, "\n\n"));
return SVN_NO_ERROR;
Modified: subversion/branches/performance/subversion/svnrdump/dump_editor.h
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/svnrdump/dump_editor.h?rev=1001417&r1=1001416&r2=1001417&view=diff
==============================================================================
--- subversion/branches/performance/subversion/svnrdump/dump_editor.h (original)
+++ subversion/branches/performance/subversion/svnrdump/dump_editor.h Sun Sep 26 11:58:58 2010
@@ -87,4 +87,12 @@ get_dump_editor(const svn_delta_editor_t
svn_stream_t *stream,
apr_pool_t *pool);
+/**
+ * Normalize the line ending style of the values of properties in @a
+ * rev_props using @a pool for memory allocation.
+ */
+svn_error_t *
+normalize_props(apr_hash_t *props,
+ apr_pool_t *pool);
+
#endif
Modified: subversion/branches/performance/subversion/svnrdump/load_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/svnrdump/load_editor.c?rev=1001417&r1=1001416&r2=1001417&view=diff
==============================================================================
--- subversion/branches/performance/subversion/svnrdump/load_editor.c (original)
+++ subversion/branches/performance/subversion/svnrdump/load_editor.c Sun Sep 26 11:58:58 2010
@@ -56,6 +56,12 @@ commit_callback(const svn_commit_info_t
return SVN_NO_ERROR;
}
+/* See subversion/svnsync/main.c for docstring */
+static svn_boolean_t is_atomicity_error(svn_error_t *err)
+{
+ return svn_error_has_cause(err, SVN_ERR_FS_PROP_BASEVALUE_MISMATCH);
+}
+
/* Acquire a lock (of sorts) on the repository associated with the
* given RA SESSION. This lock is just a revprop change attempt in a
* time-delay loop. This function is duplicated by svnsync in main.c.
@@ -65,14 +71,36 @@ commit_callback(const svn_commit_info_t
* applications to avoid duplication.
*/
static svn_error_t *
-get_lock(svn_ra_session_t *session, apr_pool_t *pool)
+get_lock(const svn_string_t **lock_string_p,
+ svn_ra_session_t *session,
+ apr_pool_t *pool)
{
char hostname_str[APRMAXHOSTLEN + 1] = { 0 };
svn_string_t *mylocktoken, *reposlocktoken;
apr_status_t apr_err;
+ svn_boolean_t be_atomic;
apr_pool_t *subpool;
int i;
+ SVN_ERR(svn_ra_has_capability(session, &be_atomic,
+ SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+ pool));
+ if (! be_atomic)
+ {
+ /* Pre-1.7 server. Can't lock without a race condition.
+ See issue #3546.
+ */
+ svn_error_t *err;
+
+ err = svn_error_create(
+ SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+ _("Target server does not support atomic revision property "
+ "edits; consider upgrading it to 1.7 or using an external "
+ "locking program"));
+ svn_handle_warning2(stderr, err, "svnrdump: ");
+ svn_error_clear(err);
+ }
+
apr_err = apr_gethostname(hostname_str, sizeof(hostname_str), pool);
if (apr_err)
return svn_error_wrap_apr(apr_err, _("Can't get local hostname"));
@@ -80,10 +108,15 @@ get_lock(svn_ra_session_t *session, apr_
mylocktoken = svn_string_createf(pool, "%s:%s", hostname_str,
svn_uuid_generate(pool));
+ /* If we succeed, this is what the property will be set to. */
+ *lock_string_p = mylocktoken;
+
subpool = svn_pool_create(pool);
for (i = 0; i < LOCK_RETRIES; ++i)
{
+ svn_error_t *err;
+
svn_pool_clear(subpool);
SVN_ERR(svn_ra_rev_prop(session, 0, SVNRDUMP_PROP_LOCK, &reposlocktoken,
@@ -106,9 +139,27 @@ get_lock(svn_ra_session_t *session, apr_
}
else if (i < LOCK_RETRIES - 1)
{
+ const svn_string_t *unset = NULL;
+
/* Except in the very last iteration, try to set the lock. */
- SVN_ERR(svn_ra_change_rev_prop(session, 0, SVNRDUMP_PROP_LOCK,
- mylocktoken, subpool));
+ err = svn_ra_change_rev_prop2(session, 0, SVNRDUMP_PROP_LOCK,
+ be_atomic ? &unset : NULL,
+ mylocktoken, subpool);
+
+ if (be_atomic && err && is_atomicity_error(err))
+ /* Someone else has the lock. Let's loop. */
+ svn_error_clear(err);
+ else if (be_atomic && err == SVN_NO_ERROR)
+ /* We have the lock.
+
+ However, for compatibility with concurrent svnsync's that don't
+ support atomicity, loop anyway to double-check that they haven't
+ overwritten our lock.
+ */
+ continue;
+ else
+ /* Genuine error, or we aren't atomic and need to loop. */
+ SVN_ERR(err);
}
}
@@ -182,6 +233,7 @@ new_node_record(void **node_baton,
void *commit_edit_baton;
char *ancestor_path;
apr_array_header_t *residual_open_path;
+ char *relpath_compose;
const char *nb_dirname;
apr_size_t residual_close_count;
int i;
@@ -304,8 +356,11 @@ new_node_record(void **node_baton,
for (i = 0; i < residual_open_path->nelts; i ++)
{
- SVN_ERR(commit_editor->open_directory(APR_ARRAY_IDX(residual_open_path,
- i, const char *),
+ relpath_compose =
+ svn_relpath_join(rb->db->relpath,
+ APR_ARRAY_IDX(residual_open_path, i, const char *),
+ rb->pool);
+ SVN_ERR(commit_editor->open_directory(relpath_compose,
rb->db->baton,
rb->rev - 1,
rb->pool, &child_baton));
@@ -313,10 +368,7 @@ new_node_record(void **node_baton,
child_db = apr_pcalloc(rb->pool, sizeof(*child_db));
child_db->baton = child_baton;
child_db->depth = rb->db->depth + 1;
- child_db->relpath = svn_relpath_join(rb->db->relpath,
- APR_ARRAY_IDX(residual_open_path,
- i, const char *),
- rb->pool);
+ child_db->relpath = relpath_compose;
child_db->parent = rb->db;
rb->db = child_db;
}
@@ -394,8 +446,8 @@ set_revision_property(void *baton,
else
/* Special handling for revision 0; this is safe because the
commit_editor hasn't been created yet. */
- SVN_ERR(svn_ra_change_rev_prop(rb->pb->session, rb->rev, name, value,
- rb->pool));
+ SVN_ERR(svn_ra_change_rev_prop2(rb->pb->session, rb->rev,
+ name, NULL, value, rb->pool));
/* Remember any datestamp/ author that passes through (see comment
in close_revision). */
@@ -419,14 +471,21 @@ set_node_property(void *baton,
commit_editor = nb->rb->pb->commit_editor;
pool = nb->rb->pool;
- LDR_DBG(("Applying properties on %p\n", nb->file_baton));
- if (nb->kind == svn_node_file)
- SVN_ERR(commit_editor->change_file_prop(nb->file_baton, name,
- value, pool));
- else
- SVN_ERR(commit_editor->change_dir_prop(nb->rb->db->baton, name,
- value, pool));
-
+ switch (nb->kind)
+ {
+ case svn_node_file:
+ LDR_DBG(("Applying properties on %p\n", nb->file_baton));
+ SVN_ERR(commit_editor->change_file_prop(nb->file_baton, name,
+ value, pool));
+ break;
+ case svn_node_dir:
+ LDR_DBG(("Applying properties on %p\n", nb->rb->db->baton));
+ SVN_ERR(commit_editor->change_dir_prop(nb->rb->db->baton, name,
+ value, pool));
+ break;
+ default:
+ break;
+ }
return SVN_NO_ERROR;
}
@@ -552,12 +611,12 @@ close_revision(void *baton)
/* svn_fs_commit_txn rewrites the datestamp/ author property-
rewrite it by hand after closing the commit_editor. */
- SVN_ERR(svn_ra_change_rev_prop(rb->pb->session, rb->rev,
- SVN_PROP_REVISION_DATE,
- rb->datestamp, rb->pool));
- SVN_ERR(svn_ra_change_rev_prop(rb->pb->session, rb->rev,
- SVN_PROP_REVISION_AUTHOR,
- rb->author, rb->pool));
+ SVN_ERR(svn_ra_change_rev_prop2(rb->pb->session, rb->rev,
+ SVN_PROP_REVISION_DATE,
+ NULL, rb->datestamp, rb->pool));
+ SVN_ERR(svn_ra_change_rev_prop2(rb->pb->session, rb->rev,
+ SVN_PROP_REVISION_AUTHOR,
+ NULL, rb->author, rb->pool));
svn_pool_destroy(rb->pool);
@@ -602,14 +661,25 @@ drive_dumpstream_loader(svn_stream_t *st
svn_ra_session_t *session,
apr_pool_t *pool)
{
- struct parse_baton *pb;
- pb = parse_baton;
+ struct parse_baton *pb = parse_baton;
+ const svn_string_t *lock_string;
+ svn_boolean_t be_atomic;
+ svn_error_t *err;
+
+ SVN_ERR(svn_ra_has_capability(session, &be_atomic,
+ SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+ pool));
- SVN_ERR(get_lock(session, pool));
+ SVN_ERR(get_lock(&lock_string, session, pool));
SVN_ERR(svn_ra_get_repos_root2(session, &(pb->root_url), pool));
SVN_ERR(svn_repos_parse_dumpstream2(stream, parser, parse_baton,
NULL, NULL, pool));
- SVN_ERR(svn_ra_change_rev_prop(session, 0, SVNRDUMP_PROP_LOCK, NULL, pool));
+ err = svn_ra_change_rev_prop2(session, 0, SVNRDUMP_PROP_LOCK,
+ be_atomic ? &lock_string : NULL, NULL, pool);
+ if (is_atomicity_error(err))
+ return svn_error_quick_wrap(err,
+ _("\"svnrdump load\"'s lock was stolen; "
+ "can't remove it"));
return SVN_NO_ERROR;
}
Modified: subversion/branches/performance/subversion/svnrdump/load_editor.h
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/svnrdump/load_editor.h?rev=1001417&r1=1001416&r2=1001417&view=diff
==============================================================================
--- subversion/branches/performance/subversion/svnrdump/load_editor.h (original)
+++ subversion/branches/performance/subversion/svnrdump/load_editor.h Sun Sep 26 11:58:58 2010
@@ -89,11 +89,10 @@ struct revision_baton
};
/**
- * Build up a load editor @a parser for parsing a dumpfile stream from @a stream
- * set to fire the appropriate callbacks in load editor along with a
- * @a parser_baton, using @a pool for all memory allocations. The
- * @a editor/ @a edit_baton are central to the functionality of the
- * parser.
+ * Build up a dumpstream parser @a parser (and corresponding baton @a
+ * parse_baton) to fire the appropriate callbacks in a commit editor
+ * set to commit to session @a session. Use @a pool for all memory
+ * allocations.
*/
svn_error_t *
get_dumpstream_loader(const svn_repos_parse_fns2_t **parser,
@@ -102,8 +101,10 @@ get_dumpstream_loader(const svn_repos_pa
apr_pool_t *pool);
/**
- * Drive the load editor @a editor using the data in @a stream using
- * @a pool for all memory allocations.
+ * Drive the dumpstream loader described by @a parser and @a
+ * parse_baton to parse and commit the stream @a stream to the
+ * location described by @a session. Use @a pool for all memory
+ * allocations.
*/
svn_error_t *
drive_dumpstream_loader(svn_stream_t *stream,
Modified: subversion/branches/performance/subversion/svnrdump/svnrdump.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/svnrdump/svnrdump.c?rev=1001417&r1=1001416&r2=1001417&view=diff
==============================================================================
--- subversion/branches/performance/subversion/svnrdump/svnrdump.c (original)
+++ subversion/branches/performance/subversion/svnrdump/svnrdump.c Sun Sep 26 11:58:58 2010
@@ -110,7 +110,7 @@ struct replay_baton {
svn_boolean_t quiet;
};
-typedef struct {
+typedef struct opt_baton_t {
svn_ra_session_t *session;
const char *url;
svn_revnum_t start_revision;
@@ -137,6 +137,7 @@ replay_revstart(svn_revnum_t revision,
SVN_ERR(svn_stream_printf(stdout_stream, pool,
SVN_REPOS_DUMPFILE_REVISION_NUMBER
": %ld\n", revision));
+ SVN_ERR(normalize_props(rev_props, pool));
propstring = svn_stringbuf_create_ensure(0, pool);
revprop_stream = svn_stream_from_stringbuf(propstring, pool);
SVN_ERR(svn_hash_write2(rev_props, revprop_stream, "PROPS-END", pool));
Modified: subversion/branches/performance/subversion/svnserve/cyrus_auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/svnserve/cyrus_auth.c?rev=1001417&r1=1001416&r2=1001417&view=diff
==============================================================================
--- subversion/branches/performance/subversion/svnserve/cyrus_auth.c (original)
+++ subversion/branches/performance/subversion/svnserve/cyrus_auth.c Sun Sep 26 11:58:58 2010
@@ -361,7 +361,7 @@ svn_error_t *cyrus_auth_request(svn_ra_s
if ((p = strchr(user, '@')) != NULL)
/* Drop the realm part. */
- b->user = apr_pstrndup(b->pool, user, p - (char *)user);
+ b->user = apr_pstrndup(b->pool, user, p - (const char *)user);
else
{
svn_error_t *err;
Modified: subversion/branches/performance/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/svnserve/serve.c?rev=1001417&r1=1001416&r2=1001417&view=diff
==============================================================================
--- subversion/branches/performance/subversion/svnserve/serve.c (original)
+++ subversion/branches/performance/subversion/svnserve/serve.c Sun Sep 26 11:58:58 2010
@@ -994,6 +994,65 @@ static svn_error_t *get_dated_rev(svn_ra
return SVN_NO_ERROR;
}
+/* Common logic for change_rev_prop() and change_rev_prop2(). */
+static svn_error_t *do_change_rev_prop(svn_ra_svn_conn_t *conn,
+ server_baton_t *b,
+ svn_revnum_t rev,
+ const char *name,
+ const svn_string_t *const *old_value_p,
+ const svn_string_t *value,
+ apr_pool_t *pool)
+{
+ SVN_ERR(must_have_access(conn, pool, b, svn_authz_write, NULL, FALSE));
+ SVN_ERR(log_command(b, conn, pool, "%s",
+ svn_log__change_rev_prop(rev, name, pool)));
+ SVN_CMD_ERR(svn_repos_fs_change_rev_prop4(b->repos, rev, b->user,
+ name, old_value_p, value,
+ TRUE, TRUE,
+ authz_check_access_cb_func(b), b,
+ pool));
+ SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, ""));
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *change_rev_prop2(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
+ apr_array_header_t *params, void *baton)
+{
+ server_baton_t *b = baton;
+ svn_revnum_t rev;
+ const char *name;
+ svn_string_t *value;
+ const svn_string_t *const *old_value_p;
+ svn_string_t *old_value;
+ svn_boolean_t dont_care;
+
+ SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "rc(?s)(b?s)",
+ &rev, &name, &value,
+ &dont_care, &old_value));
+
+ /* Argument parsing. */
+ if (dont_care)
+ old_value_p = NULL;
+ else
+ old_value_p = (const svn_string_t *const *)&old_value;
+
+ /* Input validation. */
+ if (dont_care && old_value)
+ {
+ svn_error_t *err;
+ err = svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
+ "'previous-value' and 'dont-care' cannot both be "
+ "set in 'change-rev-prop2' request");
+ return log_fail_and_flush(err, b, conn, pool);
+ }
+
+ /* Do it. */
+ SVN_ERR(do_change_rev_prop(conn, b, rev, name, old_value_p, value, pool));
+
+ return SVN_NO_ERROR;
+}
+
static svn_error_t *change_rev_prop(svn_ra_svn_conn_t *conn, apr_pool_t *pool,
apr_array_header_t *params, void *baton)
{
@@ -1006,14 +1065,8 @@ static svn_error_t *change_rev_prop(svn_
optional element pattern "(?s)" isn't used. */
SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "rc?s", &rev, &name, &value));
- SVN_ERR(must_have_access(conn, pool, b, svn_authz_write, NULL, FALSE));
- SVN_ERR(log_command(b, conn, pool, "%s",
- svn_log__change_rev_prop(rev, name, pool)));
- SVN_CMD_ERR(svn_repos_fs_change_rev_prop3(b->repos, rev, b->user,
- name, value, TRUE, TRUE,
- authz_check_access_cb_func(b), b,
- pool));
- SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, ""));
+ SVN_ERR(do_change_rev_prop(conn, b, rev, name, NULL, value, pool));
+
return SVN_NO_ERROR;
}
@@ -2768,6 +2821,7 @@ static const svn_ra_svn_cmd_entry_t main
{ "get-latest-rev", get_latest_rev },
{ "get-dated-rev", get_dated_rev },
{ "change-rev-prop", change_rev_prop },
+ { "change-rev-prop2",change_rev_prop2 },
{ "rev-proplist", rev_proplist },
{ "rev-prop", rev_prop },
{ "commit", commit },
@@ -2992,7 +3046,7 @@ svn_error_t *serve(svn_ra_svn_conn_t *co
/* Send greeting. We don't support version 1 any more, so we can
* send an empty mechlist. */
if (params->compression_level > 0)
- SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, "nn()(wwwwwww)",
+ SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, "nn()(wwwwwwww)",
(apr_uint64_t) 2, (apr_uint64_t) 2,
SVN_RA_SVN_CAP_EDIT_PIPELINE,
SVN_RA_SVN_CAP_SVNDIFF1,
@@ -3000,15 +3054,17 @@ svn_error_t *serve(svn_ra_svn_conn_t *co
SVN_RA_SVN_CAP_COMMIT_REVPROPS,
SVN_RA_SVN_CAP_DEPTH,
SVN_RA_SVN_CAP_LOG_REVPROPS,
+ SVN_RA_SVN_CAP_ATOMIC_REVPROPS,
SVN_RA_SVN_CAP_PARTIAL_REPLAY));
else
- SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, "nn()(wwwwww)",
+ SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, "nn()(wwwwwww)",
(apr_uint64_t) 2, (apr_uint64_t) 2,
SVN_RA_SVN_CAP_EDIT_PIPELINE,
SVN_RA_SVN_CAP_ABSENT_ENTRIES,
SVN_RA_SVN_CAP_COMMIT_REVPROPS,
SVN_RA_SVN_CAP_DEPTH,
SVN_RA_SVN_CAP_LOG_REVPROPS,
+ SVN_RA_SVN_CAP_ATOMIC_REVPROPS,
SVN_RA_SVN_CAP_PARTIAL_REPLAY));
/* Read client response, which we assume to be in version 2 format:
Modified: subversion/branches/performance/subversion/svnsync/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/svnsync/main.c?rev=1001417&r1=1001416&r2=1001417&view=diff
==============================================================================
--- subversion/branches/performance/subversion/svnsync/main.c (original)
+++ subversion/branches/performance/subversion/svnsync/main.c Sun Sep 26 11:58:58 2010
@@ -284,6 +284,37 @@ check_lib_versions(void)
}
+/* Does ERR mean "the current value of the revprop isn't equal to
+ the *OLD_VALUE_P you gave me"?
+ */
+static svn_boolean_t is_atomicity_error(svn_error_t *err)
+{
+ return svn_error_has_cause(err, SVN_ERR_FS_PROP_BASEVALUE_MISMATCH);
+}
+
+/* Remove the lock on SESSION iff the lock is owned by MYLOCKTOKEN. */
+static svn_error_t *
+maybe_unlock(svn_ra_session_t *session,
+ const svn_string_t *mylocktoken,
+ apr_pool_t *scratch_pool)
+{
+ svn_string_t *reposlocktoken;
+ svn_boolean_t be_atomic;
+
+ SVN_ERR(svn_ra_has_capability(session, &be_atomic,
+ SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+ scratch_pool));
+
+ SVN_ERR(svn_ra_rev_prop(session, 0, SVNSYNC_PROP_LOCK, &reposlocktoken,
+ scratch_pool));
+ if (reposlocktoken && strcmp(reposlocktoken->data, mylocktoken->data) == 0)
+ SVN_ERR(svn_ra_change_rev_prop2(session, 0, SVNSYNC_PROP_LOCK,
+ be_atomic ? &mylocktoken : NULL, NULL,
+ scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
/* Acquire a lock (of sorts) on the repository associated with the
* given RA SESSION. This lock is just a revprop change attempt in a
* time-delay loop. This function is duplicated by svnrdump in
@@ -294,14 +325,36 @@ check_lib_versions(void)
* applications to avoid duplication.
*/
static svn_error_t *
-get_lock(svn_ra_session_t *session, apr_pool_t *pool)
+get_lock(const svn_string_t **lock_string_p,
+ svn_ra_session_t *session,
+ apr_pool_t *pool)
{
char hostname_str[APRMAXHOSTLEN + 1] = { 0 };
svn_string_t *mylocktoken, *reposlocktoken;
apr_status_t apr_err;
+ svn_boolean_t be_atomic;
apr_pool_t *subpool;
int i;
+ SVN_ERR(svn_ra_has_capability(session, &be_atomic,
+ SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+ pool));
+ if (! be_atomic)
+ {
+ /* Pre-1.7 server. Can't lock without a race condition.
+ See issue #3546.
+ */
+ svn_error_t *err;
+
+ err = svn_error_create(
+ SVN_ERR_UNSUPPORTED_FEATURE, NULL,
+ _("Target server does not support atomic revision property "
+ "edits; consider upgrading it to 1.7 or using an external "
+ "locking program"));
+ svn_handle_warning2(stderr, err, "svnsync: ");
+ svn_error_clear(err);
+ }
+
apr_err = apr_gethostname(hostname_str, sizeof(hostname_str), pool);
if (apr_err)
return svn_error_wrap_apr(apr_err, _("Can't get local hostname"));
@@ -309,17 +362,29 @@ get_lock(svn_ra_session_t *session, apr_
mylocktoken = svn_string_createf(pool, "%s:%s", hostname_str,
svn_uuid_generate(pool));
+ /* If we succeed, this is what the property will be set to. */
+ *lock_string_p = mylocktoken;
+
subpool = svn_pool_create(pool);
#define SVNSYNC_LOCK_RETRIES 10
for (i = 0; i < SVNSYNC_LOCK_RETRIES; ++i)
{
+ svn_error_t *err;
+
svn_pool_clear(subpool);
- SVN_ERR(check_cancel(NULL));
+
+ /* If we're cancelled, don't leave a stray lock behind. */
+ err = check_cancel(NULL);
+ if (err && err->apr_err == SVN_ERR_CANCELLED)
+ return svn_error_compose_create(
+ maybe_unlock(session, mylocktoken, subpool),
+ err);
+ else
+ SVN_ERR(err);
SVN_ERR(svn_ra_rev_prop(session, 0, SVNSYNC_PROP_LOCK, &reposlocktoken,
subpool));
-
if (reposlocktoken)
{
/* Did we get it? If so, we're done, otherwise we sleep. */
@@ -337,9 +402,27 @@ get_lock(svn_ra_session_t *session, apr_
}
else if (i < SVNSYNC_LOCK_RETRIES - 1)
{
+ const svn_string_t *unset = NULL;
+
/* Except in the very last iteration, try to set the lock. */
- SVN_ERR(svn_ra_change_rev_prop(session, 0, SVNSYNC_PROP_LOCK,
- mylocktoken, subpool));
+ err = svn_ra_change_rev_prop2(session, 0, SVNSYNC_PROP_LOCK,
+ be_atomic ? &unset : NULL,
+ mylocktoken, subpool);
+
+ if (be_atomic && err && is_atomicity_error(err))
+ /* Someone else has the lock. Let's loop. */
+ svn_error_clear(err);
+ else if (be_atomic && err == SVN_NO_ERROR)
+ /* We have the lock.
+
+ However, for compatibility with concurrent svnsync's that don't
+ support atomicity, loop anyway to double-check that they haven't
+ overwritten our lock.
+ */
+ continue;
+ else
+ /* Genuine error, or we aren't atomic and need to loop. */
+ SVN_ERR(err);
}
}
@@ -387,12 +470,24 @@ with_locked(svn_ra_session_t *session,
apr_pool_t *pool)
{
svn_error_t *err, *err2;
+ const svn_string_t *lock_string;
+ svn_boolean_t be_atomic;
- SVN_ERR(get_lock(session, pool));
+ SVN_ERR(svn_ra_has_capability(session, &be_atomic,
+ SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+ pool));
+
+ SVN_ERR(get_lock(&lock_string, session, pool));
err = func(session, baton, pool);
- err2 = svn_ra_change_rev_prop(session, 0, SVNSYNC_PROP_LOCK, NULL, pool);
+ err2 = svn_ra_change_rev_prop2(session, 0, SVNSYNC_PROP_LOCK,
+ be_atomic ? &lock_string : NULL, NULL, pool);
+ if (is_atomicity_error(err2))
+ err2 = svn_error_quick_wrap(err2,
+ _("svnsync's lock was stolen; "
+ "can't remove it"));
+
return svn_error_compose_create(err, svn_error_return(err2));
}
@@ -457,8 +552,8 @@ remove_props_not_in_source(svn_ra_sessio
/* Delete property if the name can't be found in SOURCE_PROPS. */
if (! apr_hash_get(source_props, propname, APR_HASH_KEY_STRING))
- SVN_ERR(svn_ra_change_rev_prop(session, rev, propname, NULL,
- subpool));
+ SVN_ERR(svn_ra_change_rev_prop2(session, rev, propname, NULL,
+ NULL, subpool));
}
svn_pool_destroy(subpool);
@@ -541,8 +636,8 @@ write_revprops(int *filtered_count,
if (strncmp(propname, SVNSYNC_PROP_PREFIX,
sizeof(SVNSYNC_PROP_PREFIX) - 1) != 0)
{
- SVN_ERR(svn_ra_change_rev_prop(session, rev, propname, propval,
- subpool));
+ SVN_ERR(svn_ra_change_rev_prop2(session, rev, propname, NULL,
+ propval, subpool));
}
else
{
@@ -676,6 +771,11 @@ make_subcommand_baton(opt_baton_t *opt_b
return b;
}
+static svn_error_t *
+open_target_session(svn_ra_session_t **to_session_p,
+ subcommand_baton_t *baton,
+ apr_pool_t *pool);
+
/*** `svnsync init' ***/
@@ -749,17 +849,17 @@ do_initialize(svn_ra_session_t *to_sessi
"repository"));
}
- SVN_ERR(svn_ra_change_rev_prop(to_session, 0, SVNSYNC_PROP_FROM_URL,
- svn_string_create(baton->from_url, pool),
- pool));
+ SVN_ERR(svn_ra_change_rev_prop2(to_session, 0, SVNSYNC_PROP_FROM_URL, NULL,
+ svn_string_create(baton->from_url, pool),
+ pool));
SVN_ERR(svn_ra_get_uuid2(from_session, &uuid, pool));
- SVN_ERR(svn_ra_change_rev_prop(to_session, 0, SVNSYNC_PROP_FROM_UUID,
- svn_string_create(uuid, pool), pool));
+ SVN_ERR(svn_ra_change_rev_prop2(to_session, 0, SVNSYNC_PROP_FROM_UUID, NULL,
+ svn_string_create(uuid, pool), pool));
- SVN_ERR(svn_ra_change_rev_prop(to_session, 0, SVNSYNC_PROP_LAST_MERGED_REV,
- svn_string_createf(pool, "%ld", latest),
- pool));
+ SVN_ERR(svn_ra_change_rev_prop2(to_session, 0, SVNSYNC_PROP_LAST_MERGED_REV,
+ NULL, svn_string_createf(pool, "%ld", latest),
+ pool));
/* Copy all non-svnsync revprops from the LATEST rev in the source
repository into the destination, notifying about normalized
@@ -815,9 +915,7 @@ initialize_cmd(apr_getopt_t *os, void *b
_("Path '%s' is not a URL"), from_url);
baton = make_subcommand_baton(opt_baton, to_url, from_url, 0, 0, pool);
- SVN_ERR(svn_ra_open4(&to_session, NULL, baton->to_url, NULL,
- &(baton->sync_callbacks), baton, baton->config, pool));
- SVN_ERR(check_if_session_is_at_repos_root(to_session, baton->to_url, pool));
+ SVN_ERR(open_target_session(&to_session, baton, pool));
if (opt_baton->disable_locking)
SVN_ERR(do_initialize(to_session, baton, pool));
else
@@ -897,6 +995,23 @@ open_source_session(svn_ra_session_t **f
return SVN_NO_ERROR;
}
+/* Set *TARGET_SESSION_P to an RA session associated with the target
+ * repository of the synchronization.
+ */
+static svn_error_t *
+open_target_session(svn_ra_session_t **target_session_p,
+ subcommand_baton_t *baton,
+ apr_pool_t *pool)
+{
+ svn_ra_session_t *target_session;
+ SVN_ERR(svn_ra_open4(&target_session, NULL, baton->to_url, NULL,
+ &(baton->sync_callbacks), baton, baton->config, pool));
+ SVN_ERR(check_if_session_is_at_repos_root(target_session, baton->to_url, pool));
+
+ *target_session_p = target_session;
+ return SVN_NO_ERROR;
+}
+
/* Replay baton, used during sychnronization. */
typedef struct {
svn_ra_session_t *from_session;
@@ -1003,11 +1118,11 @@ replay_rev_started(svn_revnum_t revision
NOTE: We have to set this before we start the commit editor,
because ra_svn doesn't let you change rev props during a
commit. */
- SVN_ERR(svn_ra_change_rev_prop(rb->to_session, 0,
- SVNSYNC_PROP_CURRENTLY_COPYING,
- svn_string_createf(pool, "%ld",
- revision),
- pool));
+ SVN_ERR(svn_ra_change_rev_prop2(rb->to_session, 0,
+ SVNSYNC_PROP_CURRENTLY_COPYING,
+ NULL,
+ svn_string_createf(pool, "%ld", revision),
+ pool));
/* The actual copy is just a replay hooked up to a commit. Include
all the revision properties from the source repositories, except
@@ -1116,19 +1231,20 @@ replay_rev_finished(svn_revnum_t revisio
svn_pool_clear(subpool);
/* Ok, we're done, bring the last-merged-rev property up to date. */
- SVN_ERR(svn_ra_change_rev_prop
- (rb->to_session,
+ SVN_ERR(svn_ra_change_rev_prop2(
+ rb->to_session,
0,
SVNSYNC_PROP_LAST_MERGED_REV,
+ NULL,
svn_string_create(apr_psprintf(pool, "%ld", revision),
subpool),
subpool));
/* And finally drop the currently copying prop, since we're done
with this revision. */
- SVN_ERR(svn_ra_change_rev_prop(rb->to_session, 0,
- SVNSYNC_PROP_CURRENTLY_COPYING,
- NULL, subpool));
+ SVN_ERR(svn_ra_change_rev_prop2(rb->to_session, 0,
+ SVNSYNC_PROP_CURRENTLY_COPYING,
+ NULL, NULL, subpool));
/* Notify the user that we copied revision properties. */
if (! rb->sb->quiet)
@@ -1221,12 +1337,12 @@ do_synchronize(svn_ra_session_t *to_sess
end up not being able to tell if there have been bogus
(i.e. non-svnsync) commits to the dest repository. */
- SVN_ERR(svn_ra_change_rev_prop(to_session, 0,
- SVNSYNC_PROP_LAST_MERGED_REV,
- last_merged_rev, pool));
- SVN_ERR(svn_ra_change_rev_prop(to_session, 0,
- SVNSYNC_PROP_CURRENTLY_COPYING,
- NULL, pool));
+ SVN_ERR(svn_ra_change_rev_prop2(to_session, 0,
+ SVNSYNC_PROP_LAST_MERGED_REV,
+ NULL, last_merged_rev, pool));
+ SVN_ERR(svn_ra_change_rev_prop2(to_session, 0,
+ SVNSYNC_PROP_CURRENTLY_COPYING,
+ NULL, NULL, pool));
}
/* If copying > to_latest, then we just fall through to
attempting to copy the revision again. */
@@ -1315,9 +1431,7 @@ synchronize_cmd(apr_getopt_t *os, void *
}
baton = make_subcommand_baton(opt_baton, to_url, from_url, 0, 0, pool);
- SVN_ERR(svn_ra_open4(&to_session, NULL, baton->to_url, NULL,
- &(baton->sync_callbacks), baton, baton->config, pool));
- SVN_ERR(check_if_session_is_at_repos_root(to_session, baton->to_url, pool));
+ SVN_ERR(open_target_session(&to_session, baton, pool));
if (opt_baton->disable_locking)
SVN_ERR(do_synchronize(to_session, baton, pool));
else
@@ -1551,9 +1665,7 @@ copy_revprops_cmd(apr_getopt_t *os, void
baton = make_subcommand_baton(opt_baton, to_url, from_url,
start_rev, end_rev, pool);
- SVN_ERR(svn_ra_open4(&to_session, NULL, baton->to_url, NULL,
- &(baton->sync_callbacks), baton, baton->config, pool));
- SVN_ERR(check_if_session_is_at_repos_root(to_session, baton->to_url, pool));
+ SVN_ERR(open_target_session(&to_session, baton, pool));
if (opt_baton->disable_locking)
SVN_ERR(do_copy_revprops(to_session, baton, pool));
else
@@ -1595,9 +1707,7 @@ info_cmd(apr_getopt_t *os, void *b, apr_
/* Open an RA session to the mirror repository URL. */
baton = make_subcommand_baton(opt_baton, to_url, NULL, 0, 0, pool);
- SVN_ERR(svn_ra_open4(&to_session, NULL, baton->to_url, NULL,
- &(baton->sync_callbacks), baton, baton->config, pool));
- SVN_ERR(check_if_session_is_at_repos_root(to_session, baton->to_url, pool));
+ SVN_ERR(open_target_session(&to_session, baton, pool));
/* Verify that the repos has been initialized for synchronization. */
SVN_ERR(svn_ra_rev_prop(to_session, 0, SVNSYNC_PROP_FROM_URL,
Propchange: subversion/branches/performance/subversion/tests/cmdline/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Sun Sep 26 11:58:58 2010
@@ -6,4 +6,5 @@ httpd-*
*~
.*~
entries-dump
+atomic-ra-revprop-change
.libs
Modified: subversion/branches/performance/subversion/tests/cmdline/prop_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/tests/cmdline/prop_tests.py?rev=1001417&r1=1001416&r2=1001417&view=diff
==============================================================================
--- subversion/branches/performance/subversion/tests/cmdline/prop_tests.py (original)
+++ subversion/branches/performance/subversion/tests/cmdline/prop_tests.py Sun Sep 26 11:58:58 2010
@@ -1973,6 +1973,82 @@ def obstructed_subdirs(sbox):
svntest.actions.run_and_verify_status(wc_dir, expected_status)
+def atomic_over_ra(sbox):
+ "test revprop atomicity guarantees of libsvn_ra"
+
+ sbox.build(create_wc=False)
+ repo_url = sbox.repo_url
+
+ # From this point on, similar to ../libsvn_fs-fs-test.c:revision_props().
+ s1 = "violet"
+ s2 = "wrong value"
+
+ # But test "" explicitly, since the RA layers have to marshal "" and <unset>
+ # differently.
+ s3 = ""
+
+ # Initial state.
+ svntest.actions.enable_revprop_changes(sbox.repo_dir)
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'propset', '--revprop', '-r', '0',
+ 'flower', s1, repo_url)
+
+ # Helpers.
+
+ def expect_old_server_fail(old_value, proposed_value):
+ # We are setting a (possibly "not present") expectation for the old value,
+ # so we should fail.
+ expected_stderr = ".*doesn't advertise.*ATOMIC_REVPROP"
+ svntest.actions.run_and_verify_atomic_ra_revprop_change(
+ None, None, expected_stderr, 1, repo_url, 0, 'flower',
+ old_value, proposed_value)
+
+ # The original value is still there.
+ svntest.actions.check_prop('flower', repo_url, [s1], 0)
+
+ def FAILS_WITH_BPV(not_the_old_value, proposed_value):
+ if svntest.main.server_has_atomic_revprop():
+ svntest.actions.run_and_verify_atomic_ra_revprop_change(
+ None, None, [], 0, repo_url, 0, 'flower',
+ not_the_old_value, proposed_value, True)
+ else:
+ expect_old_server_fail(not_the_old_value, proposed_value)
+
+ def PASSES_WITHOUT_BPV(yes_the_old_value, proposed_value):
+ if svntest.main.server_has_atomic_revprop():
+ svntest.actions.run_and_verify_atomic_ra_revprop_change(
+ None, None, [], 0, repo_url, 0, 'flower',
+ yes_the_old_value, proposed_value, False)
+ else:
+ expect_old_server_fail(yes_the_old_value, proposed_value)
+
+ # Value of "flower" is 's1'.
+ FAILS_WITH_BPV(s2, s1)
+ FAILS_WITH_BPV(s3, s1)
+ PASSES_WITHOUT_BPV(s1, s2)
+
+ # Value of "flower" is 's2'.
+ PASSES_WITHOUT_BPV(s2, s3)
+
+ # Value of "flower" is 's3'.
+ FAILS_WITH_BPV(None, s3)
+ FAILS_WITH_BPV(s1, s3)
+ PASSES_WITHOUT_BPV(s3, s2)
+
+ # Value of "flower" is 's2'.
+ FAILS_WITH_BPV(None, None)
+ FAILS_WITH_BPV(s1, None)
+ FAILS_WITH_BPV(s3, None)
+ PASSES_WITHOUT_BPV(s2, None)
+
+ # Value of "flower" is <not set>.
+ FAILS_WITH_BPV(s2, s1)
+ FAILS_WITH_BPV(s3, s1)
+ PASSES_WITHOUT_BPV(None, s1)
+
+ # Value of "flower" is 's1'.
+ svntest.actions.check_prop('flower', repo_url, [s1], 0)
+
########################################################################
# Run the tests
@@ -2016,6 +2092,7 @@ test_list = [ None,
rm_of_replaced_file,
prop_reject_grind,
obstructed_subdirs,
+ atomic_over_ra,
]
if __name__ == '__main__':
Modified: subversion/branches/performance/subversion/tests/cmdline/svnrdump_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/tests/cmdline/svnrdump_tests.py?rev=1001417&r1=1001416&r2=1001417&view=diff
==============================================================================
--- subversion/branches/performance/subversion/tests/cmdline/svnrdump_tests.py (original)
+++ subversion/branches/performance/subversion/tests/cmdline/svnrdump_tests.py Sun Sep 26 11:58:58 2010
@@ -65,9 +65,12 @@ def build_repos(sbox):
# Create an empty repository.
svntest.main.create_repos(sbox.repo_dir)
-def run_dump_test(sbox, dumpfile_name):
+def run_dump_test(sbox, dumpfile_name, expected_dumpfile_name = None,
+ subdir = None):
"""Load a dumpfile using 'svnadmin load', dump it with 'svnrdump
- dump' and check that the same dumpfile is produced"""
+ dump' and check that the same dumpfile is produced or that
+ expected_dumpfile_name is produced if provided. Additionally, the
+ subdir argument appends itself to the URL"""
# Create an empty sanbox repository
build_repos(sbox)
@@ -83,19 +86,28 @@ def run_dump_test(sbox, dumpfile_name):
'rb').readlines()
svntest.actions.run_and_verify_load(sbox.repo_dir, svnadmin_dumpfile)
+
+ repo_url = sbox.repo_url
+ if subdir:
+ repo_url = repo_url + subdir
# Create a dump file using svnrdump
svnrdump_dumpfile = \
svntest.actions.run_and_verify_svnrdump(None, svntest.verify.AnyOutput,
[], 0, '-q', 'dump',
- sbox.repo_url)
+ repo_url)
+
+ if expected_dumpfile_name:
+ svnadmin_dumpfile = open(os.path.join(svnrdump_tests_dir,
+ expected_dumpfile_name),
+ 'rb').readlines()
# Compare the output from stdout
svntest.verify.compare_and_display_lines(
"Dump files", "DUMP", svnadmin_dumpfile, svnrdump_dumpfile,
None, mismatched_headers_re)
-def run_load_test(sbox, dumpfile_name):
+def run_load_test(sbox, dumpfile_name, expected_dumpfile_name = None):
"""Load a dumpfile using 'svnrdump load', dump it with 'svnadmin
dump' and check that the same dumpfile is produced"""
@@ -130,6 +142,11 @@ def run_load_test(sbox, dumpfile_name):
# Create a dump file using svnadmin dump
svnadmin_dumpfile = svntest.actions.run_and_verify_dump(sbox.repo_dir, True)
+ if expected_dumpfile_name:
+ svnrdump_dumpfile = open(os.path.join(svnrdump_tests_dir,
+ expected_dumpfile_name),
+ 'rb').readlines()
+
# Compare the output from stdout
svntest.verify.compare_and_display_lines(
"Dump files", "DUMP", svnrdump_dumpfile, svnadmin_dumpfile)
@@ -167,6 +184,10 @@ def revision_0_load(sbox):
# docs/ (Added r6)
# README (Added r6)
+def skeleton_dump(sbox):
+ "dump: skeleton repository"
+ run_dump_test(sbox, "skeleton.dump")
+
def skeleton_load(sbox):
"load: skeleton repository"
run_load_test(sbox, "skeleton.dump")
@@ -219,6 +240,22 @@ def tag_empty_trunk_load(sbox):
"load: tag empty trunk"
run_load_test(sbox, "tag-empty-trunk.dump")
+def tag_trunk_with_file_dump(sbox):
+ "dump: tag trunk containing a file"
+ run_dump_test(sbox, "tag-trunk-with-file.dump")
+
+def tag_trunk_with_file_load(sbox):
+ "load: tag trunk containing a file"
+ run_load_test(sbox, "tag-trunk-with-file.dump")
+
+def tag_trunk_with_file2_dump(sbox):
+ "dump: tag trunk containing a file (#2)"
+ run_dump_test(sbox, "tag-trunk-with-file2.dump")
+
+def tag_trunk_with_file2_load(sbox):
+ "load: tag trunk containing a file (#2)"
+ run_load_test(sbox, "tag-trunk-with-file2.dump")
+
def dir_prop_change_dump(sbox):
"dump: directory property changes"
run_dump_test(sbox, "dir-prop-change.dump")
@@ -243,6 +280,16 @@ def copy_revprops_load(sbox):
"load: copy revprops other than svn:*"
run_load_test(sbox, "revprops.dump")
+def only_trunk_dump(sbox):
+ "dump: subdirectory"
+ run_dump_test(sbox, "trunk-only.dump", subdir="/trunk",
+ expected_dumpfile_name="trunk-only.expected.dump")
+
+def only_trunk_A_with_changes_dump(sbox):
+ "dump: subdirectory with changes on root"
+ run_dump_test(sbox, "trunk-A-changes.dump", subdir="/trunk/A",
+ expected_dumpfile_name="trunk-A-changes.expected.dump")
+
def url_encoding_dump(sbox):
"dump: url encoding issues"
run_dump_test(sbox, "url-encoding-bug.dump")
@@ -251,6 +298,24 @@ def url_encoding_load(sbox):
"load: url encoding issues"
run_load_test(sbox, "url-encoding-bug.dump")
+def copy_bad_line_endings_dump(sbox):
+ "dump: inconsistent line endings in svn:props"
+ run_dump_test(sbox, "copy-bad-line-endings.dump",
+ expected_dumpfile_name="copy-bad-line-endings.expected.dump")
+
+def commit_a_copy_of_root_dump(sbox):
+ "dump: commit a copy of root"
+ run_dump_test(sbox, "repo-with-copy-of-root-dir.dump")
+
+def commit_a_copy_of_root_load(sbox):
+ "load: commit a copy of root"
+ run_load_test(sbox, "repo-with-copy-of-root-dir.dump")
+
+def descend_into_replace_dump(sbox):
+ "dump: descending into replaced dir looks in src"
+ run_dump_test(sbox, "descend-into-replace.dump", subdir='/trunk/H',
+ expected_dumpfile_name = "descend-into-replace.expected.dump")
+
########################################################################
# Run the tests
@@ -260,6 +325,7 @@ test_list = [ None,
basic_dump,
revision_0_dump,
revision_0_load,
+ skeleton_dump,
skeleton_load,
copy_and_modify_dump,
copy_and_modify_load,
@@ -269,18 +335,28 @@ test_list = [ None,
modified_in_place_load,
tag_empty_trunk_dump,
tag_empty_trunk_load,
+ tag_trunk_with_file_dump,
+ tag_trunk_with_file_load,
+ tag_trunk_with_file2_dump,
+ tag_trunk_with_file2_load,
dir_prop_change_dump,
- dir_prop_change_load,
+ Wimp("TODO", dir_prop_change_load, svntest.main.is_ra_type_dav),
copy_parent_modify_prop_dump,
copy_parent_modify_prop_load,
url_encoding_dump,
url_encoding_load,
copy_revprops_dump,
- Wimp("TODO", copy_revprops_load),
+ copy_revprops_load,
+ only_trunk_dump,
+ only_trunk_A_with_changes_dump,
no_author_dump,
no_author_load,
- Wimp("TODO", move_and_modify_in_the_same_revision_dump),
- Wimp("TODO", move_and_modify_in_the_same_revision_load),
+ move_and_modify_in_the_same_revision_dump,
+ move_and_modify_in_the_same_revision_load,
+ copy_bad_line_endings_dump,
+ commit_a_copy_of_root_dump,
+ commit_a_copy_of_root_load,
+ descend_into_replace_dump,
]
if __name__ == '__main__':
Modified: subversion/branches/performance/subversion/tests/cmdline/svntest/actions.py
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/tests/cmdline/svntest/actions.py?rev=1001417&r1=1001416&r2=1001417&view=diff
==============================================================================
--- subversion/branches/performance/subversion/tests/cmdline/svntest/actions.py (original)
+++ subversion/branches/performance/subversion/tests/cmdline/svntest/actions.py Sun Sep 26 11:58:58 2010
@@ -147,6 +147,41 @@ def guarantee_greek_repository(path):
main.chmod_tree(path, 0666, 0666)
+def run_and_verify_atomic_ra_revprop_change(message,
+ expected_stdout,
+ expected_stderr,
+ expected_exit,
+ url, revision, propname,
+ old_propval, propval,
+ want_error):
+ """Run atomic-ra-revprop-change helper and check its output and exit code.
+ Transforms OLD_PROPVAL and PROPVAL into a skel.
+ For HTTP, the default HTTP library is used."""
+
+ KEY_OLD_PROPVAL = "old_value_p"
+ KEY_NEW_PROPVAL = "value"
+
+ def skel_make_atom(word):
+ return "%d %s" % (len(word), word)
+
+ def make_proplist_skel_part(nick, val):
+ if val is None:
+ return ""
+ else:
+ return "%s %s" % (skel_make_atom(nick), skel_make_atom(val))
+
+ skel = "( %s %s )" % (make_proplist_skel_part(KEY_OLD_PROPVAL, old_propval),
+ make_proplist_skel_part(KEY_NEW_PROPVAL, propval))
+
+ exit_code, out, err = main.run_atomic_ra_revprop_change(url, revision,
+ propname, skel,
+ want_error)
+ verify.verify_outputs("Unexpected output", out, err,
+ expected_stdout, expected_stderr)
+ verify.verify_exit_code(message, exit_code, expected_exit)
+ return exit_code, out, err
+
+
def run_and_verify_svnlook(message, expected_stdout,
expected_stderr, *varargs):
"""Like run_and_verify_svnlook2, but the expected exit code is
@@ -1735,15 +1770,22 @@ def set_prop(name, value, path, expected
else:
main.run_svn(expected_err, 'propset', name, value, path)
-def check_prop(name, path, exp_out):
- """Verify that property NAME on PATH has a value of EXP_OUT"""
+def check_prop(name, path, exp_out, revprop=None):
+ """Verify that property NAME on PATH has a value of EXP_OUT.
+ If REVPROP is not None, then it is a revision number and
+ a revision property is sought."""
+ if revprop is not None:
+ revprop_options = ['--revprop', '-r', revprop]
+ else:
+ revprop_options = []
# Not using run_svn because binary_mode must be set
exit_code, out, err = main.run_command(main.svn_binary, None, 1, 'pg',
'--strict', name, path,
'--config-dir',
main.default_config_dir,
'--username', main.wc_author,
- '--password', main.wc_passwd)
+ '--password', main.wc_passwd,
+ *revprop_options)
if out != exp_out:
print("svn pg --strict %s output does not match expected." % name)
print("Expected standard output: %s\n" % exp_out)
Modified: subversion/branches/performance/subversion/tests/cmdline/svntest/main.py
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/tests/cmdline/svntest/main.py?rev=1001417&r1=1001416&r2=1001417&view=diff
==============================================================================
--- subversion/branches/performance/subversion/tests/cmdline/svntest/main.py (original)
+++ subversion/branches/performance/subversion/tests/cmdline/svntest/main.py Sun Sep 26 11:58:58 2010
@@ -158,6 +158,8 @@ svnversion_binary = os.path.abspath('../
svndumpfilter_binary = os.path.abspath('../../svndumpfilter/svndumpfilter' + \
_exe)
entriesdump_binary = os.path.abspath('entries-dump' + _exe)
+atomic_ra_revprop_change_binary = os.path.abspath('atomic-ra-revprop-change' + \
+ _exe)
# Location to the pristine repository, will be calculated from test_area_url
# when we know what the user specified for --url.
@@ -639,6 +641,20 @@ def run_entriesdump_subdirs(path):
0, 0, None, '--subdirs', path)
return [line.strip() for line in stdout_lines if not line.startswith("DBG:")]
+def run_atomic_ra_revprop_change(url, revision, propname, skel, want_error):
+ """Run the atomic-ra-revprop-change helper, returning its exit code, stdout,
+ and stderr. For HTTP, default HTTP library is used."""
+ # use spawn_process rather than run_command to avoid copying all the data
+ # to stdout in verbose mode.
+ #exit_code, stdout_lines, stderr_lines = spawn_process(entriesdump_binary,
+ # 0, 0, None, path)
+
+ # This passes HTTP_LIBRARY in addition to our params.
+ return run_command(atomic_ra_revprop_change_binary, True, False,
+ url, revision, propname, skel,
+ options.http_library, want_error and 1 or 0)
+
+
# Chmod recursively on a whole subtree
def chmod_tree(path, mode, mask):
for dirpath, dirs, files in os.walk(path):
@@ -1072,6 +1088,9 @@ def server_has_partial_replay():
def server_enforces_date_syntax():
return options.server_minor_version >= 5
+def server_has_atomic_revprop():
+ return options.server_minor_version >= 7
+
######################################################################
Modified: subversion/branches/performance/subversion/tests/cmdline/svntest/wc.py
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/tests/cmdline/svntest/wc.py?rev=1001417&r1=1001416&r2=1001417&view=diff
==============================================================================
--- subversion/branches/performance/subversion/tests/cmdline/svntest/wc.py (original)
+++ subversion/branches/performance/subversion/tests/cmdline/svntest/wc.py Sun Sep 26 11:58:58 2010
@@ -836,18 +836,23 @@ def text_base_path(file_path):
relpath = os.path.join(tail, relpath).replace(os.sep, '/')
c = db.cursor()
- c.execute("""select checksum from working_node
- where local_relpath = '""" + relpath + """'""")
- checksum = c.fetchone()
- if checksum is None:
+ # NODES conversion is complete enough that we can use it if it exists
+ c.execute("""pragma table_info(nodes)""")
+ if c.fetchone():
+ c.execute("""select checksum from nodes
+ where local_relpath = '""" + relpath + """'
+ and op_depth = 0""")
+ else:
c.execute("""select checksum from base_node
where local_relpath = '""" + relpath + """'""")
- checksum = c.fetchone()[0]
- if checksum is not None and checksum[0:6] == "$md5 $":
- c.execute("""select checksum from pristine
- where md5_checksum = '""" + checksum + """'""")
- checksum = c.fetchone()[0]
- if checksum is None:
+ row = c.fetchone()
+ if row is not None:
+ checksum = row[0]
+ if checksum is not None and checksum[0:6] == "$md5 $":
+ c.execute("""select checksum from pristine
+ where md5_checksum = '""" + checksum + """'""")
+ checksum = c.fetchone()[0]
+ if row is None or checksum is None:
raise svntest.Failure("No SHA1 checksum for " + relpath)
db.close()
@@ -858,8 +863,7 @@ def text_base_path(file_path):
if os.path.isfile(fn):
return fn
- # Calculate per dir location
- return os.path.join(root_path, dot_svn, 'pristine', checksum)
+ raise svntest.Failure("No pristine text for " + relpath)
# ------------
Modified: subversion/branches/performance/subversion/tests/cmdline/switch_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/tests/cmdline/switch_tests.py?rev=1001417&r1=1001416&r2=1001417&view=diff
==============================================================================
--- subversion/branches/performance/subversion/tests/cmdline/switch_tests.py (original)
+++ subversion/branches/performance/subversion/tests/cmdline/switch_tests.py Sun Sep 26 11:58:58 2010
@@ -1049,18 +1049,25 @@ def commit_mods_below_switch(sbox):
def relocate_beyond_repos_root(sbox):
"relocate with prefixes longer than repo root"
- sbox.build(read_only = True)
+ sbox.build(read_only=True, create_wc=False)
+
+ wc_backup = sbox.add_wc_path('backup')
wc_dir = sbox.wc_dir
repo_dir = sbox.repo_dir
repo_url = sbox.repo_url
other_repo_dir, other_repo_url = sbox.add_repo_path('other')
- svntest.main.copy_repos(repo_dir, other_repo_dir, 1, 0)
-
A_url = repo_url + "/A"
+ A_wc_dir = wc_dir
other_A_url = other_repo_url + "/A"
other_B_url = other_repo_url + "/B"
- A_wc_dir = os.path.join(wc_dir, "A")
+
+ svntest.main.safe_rmtree(wc_dir, 1)
+ svntest.actions.run_and_verify_svn(None, None, [], 'checkout',
+ repo_url + '/A', wc_dir)
+
+ svntest.main.copy_repos(repo_dir, other_repo_dir, 1, 0)
+
# A relocate that changes the repo path part of the URL shouldn't work.
# This tests for issue #2380.
@@ -2959,7 +2966,7 @@ def single_file_relocate(sbox):
svntest.main.copy_repos(repo_dir, other_repo_dir, 1, 0)
svntest.main.safe_rmtree(repo_dir, 1)
svntest.actions.run_and_verify_svn(None, None,
- ".*Cannot relocate a single file\n",
+ ".*Cannot relocate.*",
'switch', '--relocate',
iota_url, other_iota_url, iota_path)
Modified: subversion/branches/performance/subversion/tests/libsvn_fs/fs-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/tests/libsvn_fs/fs-test.c?rev=1001417&r1=1001416&r2=1001417&view=diff
==============================================================================
--- subversion/branches/performance/subversion/tests/libsvn_fs/fs-test.c (original)
+++ subversion/branches/performance/subversion/tests/libsvn_fs/fs-test.c Sun Sep 26 11:58:58 2010
@@ -586,12 +586,12 @@ list_directory(const svn_test_opts_t *op
}
-/* If EXPR raises SVN_ERR_BAD_OLD_VALUE, continue; else, fail
+/* If EXPR raises SVN_ERR_FS_PROP_BASEVALUE_MISMATCH, continue; else, fail
* the test. */
#define FAILS_WITH_BOV(expr) \
do { \
svn_error_t *__err = (expr); \
- if (!__err || __err->apr_err != SVN_ERR_BAD_OLD_VALUE) \
+ if (!__err || __err->apr_err != SVN_ERR_FS_PROP_BASEVALUE_MISMATCH) \
return svn_error_create(SVN_ERR_TEST_FAILED, __err, \
"svn_fs_change_rev_prop2() failed to " \
"detect unexpected old value"); \
Modified: subversion/branches/performance/subversion/tests/libsvn_subr/cache-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/tests/libsvn_subr/cache-test.c?rev=1001417&r1=1001416&r2=1001417&view=diff
==============================================================================
--- subversion/branches/performance/subversion/tests/libsvn_subr/cache-test.c (original)
+++ subversion/branches/performance/subversion/tests/libsvn_subr/cache-test.c Sun Sep 26 11:58:58 2010
@@ -55,11 +55,12 @@ deserialize_revnum(void **out,
apr_size_t data_len,
apr_pool_t *pool)
{
- svn_revnum_t *in_rev, *out_rev;
+ const svn_revnum_t *in_rev = (const svn_revnum_t *) data;
+ svn_revnum_t *out_rev;
+
if (data_len != sizeof(*in_rev))
return svn_error_create(SVN_ERR_REVNUM_PARSE_FAILURE, NULL,
_("Bad size for revision number in cache"));
- in_rev = (svn_revnum_t *) data;
out_rev = apr_palloc(pool, sizeof(*out_rev));
*out_rev = *in_rev;
*out = out_rev;
Modified: subversion/branches/performance/subversion/tests/libsvn_subr/target-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/tests/libsvn_subr/target-test.c?rev=1001417&r1=1001416&r2=1001417&view=diff
==============================================================================
--- subversion/branches/performance/subversion/tests/libsvn_subr/target-test.c (original)
+++ subversion/branches/performance/subversion/tests/libsvn_subr/target-test.c Sun Sep 26 11:58:58 2010
@@ -64,7 +64,8 @@ condense_targets_tests_helper(const char
apr_array_header_t *targets;
apr_array_header_t *condensed_targets;
const char *common_path, *common_path2, *curdir;
- char *token, *iter, *exp_common_abs = (char*)exp_common;
+ char *token, *iter;
+ const char *exp_common_abs = exp_common;
int i;
char buf[8192];
Modified: subversion/branches/performance/subversion/tests/libsvn_wc/db-test.c
URL: http://svn.apache.org/viewvc/subversion/branches/performance/subversion/tests/libsvn_wc/db-test.c?rev=1001417&r1=1001416&r2=1001417&view=diff
==============================================================================
--- subversion/branches/performance/subversion/tests/libsvn_wc/db-test.c (original)
+++ subversion/branches/performance/subversion/tests/libsvn_wc/db-test.c Sun Sep 26 11:58:58 2010
@@ -419,7 +419,7 @@ static const char * const TESTING_DATA =
" null, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-d', 1, 'J', 2, 'moved/file', 2, 'normal', null,"
- " 1, null, 'file', 2, " TIME_2s ", '" AUTHOR_2 "', '$md5 $ " MD5_1 " ',"
+ " 1, null, 'file', 2, " TIME_2s ", '" AUTHOR_2 "', '$md5 $" MD5_1 "',"
" '()', 10, null, null, null, null);"
"insert into nodes values ("
" 1, 'J/J-e', 1, 'J', null, null, null, 'not-present', null,"
@@ -486,17 +486,15 @@ static const char * const TESTING_DATA =
" null, null, null, null, null, "
" null, null, null, 0, null, null, '()', 0); "
#endif
-#ifdef SVN_WC__NODES_not_enabled_yet
+#ifdef SVN_WC__NODES
"insert into nodes values ("
- " 1, 'M', null, null, '', 'normal', 'dir', "
- " 1, null, null, "
- " 1, " TIME_1s ", '" AUTHOR_1 "', null, null, null, '()', null, null, "
- " null); "
+ " 1, 'M', 0, '', null, null, null, 'normal', null, "
+ " 1, null, 'dir', 1, " TIME_1s ", '" AUTHOR_1 "', null, '()', "
+ " null, null, null, null, null);"
"insert into nodes values ("
- " 1, 'M/M-a', 'M', 'not-present', 'file', "
- " null, null, "
- " null, null, null, null, null, "
- " null, null, null, 0, null, null, '()', 0); "
+ " 1, 'M/M-a', 1, 'M', null, null, null, 'not-present', null, "
+ " null, null, 'file', null, null, null, null, '()', "
+ " null, 0, null, null, null);"
#endif
);
Modified: subversion/branches/performance/tools/client-side/svnmucc/svnmucc-test.py
URL: http://svn.apache.org/viewvc/subversion/branches/performance/tools/client-side/svnmucc/svnmucc-test.py?rev=1001417&r1=1001416&r2=1001417&view=diff
==============================================================================
--- subversion/branches/performance/tools/client-side/svnmucc/svnmucc-test.py (original)
+++ subversion/branches/performance/tools/client-side/svnmucc/svnmucc-test.py Sun Sep 26 11:58:58 2010
@@ -34,6 +34,10 @@ this_dir = os.path.dirname(os.path.abspa
sys.path.insert(0, '%s/../../../subversion/tests/cmdline' % (this_dir))
import svntest
+# setup the global 'svntest.main.options' object so functions in the
+# module don't freak out.
+svntest.main._parse_options(arglist=[])
+
# calculate the top of the build tree
if len(sys.argv) > 1:
build_top = os.path.abspath(sys.argv[1])
@@ -275,6 +279,13 @@ def main():
run_svnmucc(['M /foo/bar'], #---------
'propdel', 'testprop', 'foo/bar')
+ # revision 18
+ run_svnmucc(['M /foo/z.c',
+ 'M /foo/foo',
+ ], #---------
+ 'propset', 'testprop', 'true', 'foo/z.c',
+ 'propset', 'testprop', 'true', 'foo/foo')
+
# Expected missing revision error
xrun_svnmucc(['svnmucc: \'a\' is not a revision'
], #---------