You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2010/09/28 19:35:26 UTC
svn commit: r1002283 [8/10] - in /subversion/branches/javahl-ra: ./ build/
notes/ notes/http-and-webdav/ notes/wc-ng/ subversion/bindings/javahl/native/
subversion/bindings/javahl/src/org/apache/subversion/javahl/
subversion/bindings/javahl/src/org/tig...
Modified: subversion/branches/javahl-ra/subversion/svn/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svn/cl.h?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svn/cl.h (original)
+++ subversion/branches/javahl-ra/subversion/svn/cl.h Tue Sep 28 17:35:22 2010
@@ -229,6 +229,7 @@ typedef struct svn_cl__opt_state_t
svn_boolean_t show_diff; /* produce diff output */
svn_boolean_t internal_diff; /* override diff_cmd in config file */
svn_boolean_t use_git_diff_format; /* Use git's extended diff format */
+ svn_boolean_t old_patch_target_names; /* Use target names from old side */
} svn_cl__opt_state_t;
Modified: subversion/branches/javahl-ra/subversion/svn/commit-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svn/commit-cmd.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svn/commit-cmd.c (original)
+++ subversion/branches/javahl-ra/subversion/svn/commit-cmd.c Tue Sep 28 17:35:22 2010
@@ -97,6 +97,21 @@ svn_cl__commit(apr_getopt_t *os,
if (opt_state->depth == svn_depth_unknown)
opt_state->depth = svn_depth_infinity;
+ /* Copies are done server-side, and cheaply, which means they're
+ * effectively always done with infinite depth.
+ * This is a potential cause of confusion for users trying to commit
+ * copied subtrees in part by restricting the commit's depth.
+ * See issue #3699. */
+ if (opt_state->depth < svn_depth_infinity)
+ SVN_ERR(svn_cmdline_printf(pool,
+ _("svn: warning: The depth of this commit "
+ "is '%s', but copied directories will "
+ "regardless be committed with depth '%s'. "
+ "You must remove unwanted children of those "
+ "directories in a separate commit.\n"),
+ svn_depth_to_word(opt_state->depth),
+ svn_depth_to_word(svn_depth_infinity)));
+
cfg = apr_hash_get(ctx->config, SVN_CONFIG_CATEGORY_CONFIG,
APR_HASH_KEY_STRING);
if (cfg)
Modified: subversion/branches/javahl-ra/subversion/svn/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svn/main.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svn/main.c (original)
+++ subversion/branches/javahl-ra/subversion/svn/main.c Tue Sep 28 17:35:22 2010
@@ -122,6 +122,7 @@ typedef enum {
opt_show_diff,
opt_internal_diff,
opt_use_git_diff_format,
+ opt_old_patch_target_names,
} svn_cl__longopt_t;
/* Option codes and descriptions for the command line client.
@@ -357,6 +358,10 @@ const apr_getopt_option_t svn_cl__option
{"reverse-diff", opt_reverse_diff, 0,
N_("apply the unidiff in reverse\n"
" "
+ "This option also reverses patch target names; the\n"
+ " "
+ "--old-patch-target-names option will prevent this.\n"
+ " "
"[alias: --rd]")},
{"ignore-whitespace", opt_ignore_whitespace, 0,
N_("ignore whitespace during pattern matching\n"
@@ -373,6 +378,19 @@ const apr_getopt_option_t svn_cl__option
{"git", opt_use_git_diff_format, 0,
N_("use git's extended diff format\n")},
+ {"old-patch-target-names", opt_old_patch_target_names, 0,
+ N_("use target names from the old side of a patch.\n"
+ " "
+ "If a diff header contains\n"
+ " "
+ " --- foo.c\n"
+ " "
+ " +++ foo.c.new\n"
+ " "
+ "this option will cause the name \"foo.c\" to be used\n"
+ " "
+ "[alias: --optn]")},
+
/* Long-opt Aliases
*
* These have NULL desriptions, but an option code that matches some
@@ -403,6 +421,7 @@ const apr_getopt_option_t svn_cl__option
{"idiff", opt_internal_diff, 0, NULL},
{"nul", opt_no_unlock, 0, NULL},
{"keep-lock", opt_no_unlock, 0, NULL},
+ {"optn", opt_old_patch_target_names, 0, NULL},
{0, 0, 0, 0},
};
@@ -852,7 +871,7 @@ const svn_opt_subcommand_desc2_t svn_cl_
" do not agree with.\n"
),
{'q', opt_dry_run, opt_strip_count, opt_reverse_diff,
- opt_ignore_whitespace} },
+ opt_ignore_whitespace, opt_old_patch_target_names} },
{ "propdel", svn_cl__propdel, {"pdel", "pd"}, N_
("Remove a property from files, dirs, or revisions.\n"
@@ -1788,6 +1807,9 @@ main(int argc, const char *argv[])
case opt_use_git_diff_format:
opt_state.use_git_diff_format = TRUE;
break;
+ case opt_old_patch_target_names:
+ opt_state.old_patch_target_names = TRUE;
+ break;
default:
/* Hmmm. Perhaps this would be a good place to squirrel away
opts that commands like svn diff might need. Hmmm indeed. */
@@ -2065,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
@@ -2274,9 +2308,6 @@ main(int argc, const char *argv[])
pool)))
svn_handle_error2(err, stderr, TRUE, "svn: ");
- /* svn can safely create instance of QApplication class. */
- svn_auth_set_parameter(ab, "svn:auth:qapplication-safe", "1");
-
ctx->auth_baton = ab;
/* Set up conflict resolution callback. */
Modified: subversion/branches/javahl-ra/subversion/svn/move-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svn/move-cmd.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svn/move-cmd.c (original)
+++ subversion/branches/javahl-ra/subversion/svn/move-cmd.c Tue Sep 28 17:35:22 2010
@@ -84,7 +84,7 @@ svn_cl__move(apr_getopt_t *os,
SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, pool));
- err = svn_client_move6(targets, dst_path, opt_state->force,
+ err = svn_client_move6(targets, dst_path,
TRUE, opt_state->parents, opt_state->revprop_table,
svn_cl__print_commit_info, NULL, ctx, pool);
Modified: subversion/branches/javahl-ra/subversion/svn/patch-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svn/patch-cmd.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svn/patch-cmd.c (original)
+++ subversion/branches/javahl-ra/subversion/svn/patch-cmd.c Tue Sep 28 17:35:22 2010
@@ -74,6 +74,7 @@ svn_cl__patch(apr_getopt_t *os,
SVN_ERR(svn_client_patch(abs_patch_path, abs_target_path,
opt_state->dry_run, opt_state->strip_count,
+ opt_state->old_patch_target_names,
opt_state->reverse_diff,
opt_state->ignore_whitespace,
TRUE, NULL, NULL, ctx, pool, pool));
Modified: subversion/branches/javahl-ra/subversion/svn/switch-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svn/switch-cmd.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svn/switch-cmd.c (original)
+++ subversion/branches/javahl-ra/subversion/svn/switch-cmd.c Tue Sep 28 17:35:22 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/javahl-ra/subversion/svn/upgrade-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svn/upgrade-cmd.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svn/upgrade-cmd.c (original)
+++ subversion/branches/javahl-ra/subversion/svn/upgrade-cmd.c Tue Sep 28 17:35:22 2010
@@ -31,6 +31,7 @@
#include "svn_client.h"
#include "svn_error_codes.h"
#include "svn_error.h"
+#include "svn_path.h"
#include "cl.h"
#include "svn_private_config.h"
@@ -59,6 +60,19 @@ svn_cl__upgrade(apr_getopt_t *os,
SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, scratch_pool));
+ /* Don't even attempt to modify the working copy if any of the
+ * targets look like URLs. URLs are invalid input. */
+ for (i = 0; i < targets->nelts; i++)
+ {
+ const char *target = APR_ARRAY_IDX(targets, i, const char *);
+
+ if (svn_path_is_url(target))
+ return svn_error_return(svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR,
+ NULL,
+ _("'%s' is not a local path"),
+ target));
+ }
+
iterpool = svn_pool_create(scratch_pool);
for (i = 0; i < targets->nelts; i++)
{
Modified: subversion/branches/javahl-ra/subversion/svnrdump/dump_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnrdump/dump_editor.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnrdump/dump_editor.c (original)
+++ subversion/branches/javahl-ra/subversion/svnrdump/dump_editor.c Tue Sep 28 17:35:22 2010
@@ -27,12 +27,19 @@
#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"
#define ARE_VALID_COPY_ARGS(p,r) ((p) && SVN_IS_VALID_REVNUM(r))
+#ifdef SVN_DEBUG
+#define LDR_DBG(x) SVN_DBG(x)
+#else
+#define LDR_DBG(x) while(0)
+#endif
+
/* The baton used by the dump editor. */
struct dump_edit_baton {
/* The output stream we write the dumpfile to */
@@ -60,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).
*
@@ -91,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);
@@ -113,7 +148,7 @@ make_dir_baton(const char *path,
new_db->copyfrom_rev = copyfrom_rev;
new_db->added = added;
new_db->written_out = FALSE;
- new_db->deleted_entries = apr_hash_make(pool);
+ new_db->deleted_entries = apr_hash_make(eb->pool);
return new_db;
}
@@ -133,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,
@@ -166,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;
}
@@ -175,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
@@ -197,10 +246,10 @@ dump_node(struct dump_edit_baton *eb,
apr_pool_t *pool)
{
/* Remove leading slashes from path and copyfrom_path */
- if (path && strcmp(path, "/"))
+ if (path)
path = ((*path == '/') ? path + 1 : path);
- if (copyfrom_path && strcmp(copyfrom_path, "/"))
+ if (copyfrom_path)
copyfrom_path = ((*copyfrom_path == '/') ?
copyfrom_path + 1 : copyfrom_path);
@@ -221,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"));
@@ -234,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/
@@ -251,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:
@@ -259,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:
@@ -271,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;
}
@@ -290,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;
}
@@ -315,6 +369,7 @@ open_root(void *edit_baton,
struct dump_edit_baton *eb = edit_baton;
/* Allocate a special pool for the edit_baton to avoid pool
lifetime issues */
+
eb->pool = svn_pool_create(pool);
eb->props = apr_hash_make(eb->pool);
eb->deleted_props = apr_hash_make(eb->pool);
@@ -322,6 +377,8 @@ open_root(void *edit_baton,
*root_baton = make_dir_baton(NULL, NULL, SVN_INVALID_REVNUM,
edit_baton, NULL, FALSE, pool);
+ LDR_DBG(("open_root %p\n", *root_baton));
+
return SVN_NO_ERROR;
}
@@ -332,14 +389,19 @@ delete_entry(const char *path,
apr_pool_t *pool)
{
struct dir_baton *pb = parent_baton;
- const char *mypath = apr_pstrdup(pool, 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, mypath, 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;
}
@@ -358,8 +420,13 @@ add_directory(const char *path,
= make_dir_baton(path, copyfrom_path, copyfrom_rev, pb->eb, pb, TRUE, pool);
svn_boolean_t is_copy;
+ 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);
@@ -398,8 +465,13 @@ open_directory(const char *path,
const char *copyfrom_path = NULL;
svn_revnum_t copyfrom_rev = SVN_INVALID_REVNUM;
+ 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. */
@@ -423,14 +495,22 @@ close_directory(void *dir_baton,
{
struct dir_baton *db = dir_baton;
struct dump_edit_baton *eb = db->eb;
+ apr_pool_t *iterpool;
apr_hash_index_t *hi;
- apr_pool_t *iterpool = svn_pool_create(pool);
+
+ LDR_DBG(("close_directory %p\n", dir_baton));
/* Some pending properties to dump? */
- SVN_ERR(dump_props(eb, &(eb->dump_props_pending), TRUE, pool));
+ SVN_ERR(dump_props(eb, &(eb->dump_props), TRUE, pool));
- /* Dump the directory entries */
- for (hi = apr_hash_first(pool, db->deleted_entries); hi;
+ /* 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);
+
+ /* Dump the deleted directory entries */
+ for (hi = apr_hash_first(iterpool, db->deleted_entries); hi;
hi = apr_hash_next(hi))
{
const void *key;
@@ -438,12 +518,11 @@ close_directory(void *dir_baton,
apr_hash_this(hi, &key, NULL, NULL);
path = key;
- svn_pool_clear(iterpool);
-
SVN_ERR(dump_node(db->eb, path, svn_node_unknown, svn_node_action_delete,
- FALSE, NULL, SVN_INVALID_REVNUM, iterpool));
+ FALSE, NULL, SVN_INVALID_REVNUM, pool));
}
+ svn_hash__clear(db->deleted_entries, pool);
svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
@@ -460,8 +539,13 @@ add_file(const char *path,
void *val;
svn_boolean_t is_copy;
+ 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);
@@ -500,8 +584,13 @@ open_file(const char *path,
const char *copyfrom_path = NULL;
svn_revnum_t copyfrom_rev = SVN_INVALID_REVNUM;
+ 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. */
@@ -530,12 +619,14 @@ change_dir_prop(void *parent_baton,
{
struct dir_baton *db = parent_baton;
+ LDR_DBG(("change_dir_prop %p\n", parent_baton));
+
if (svn_property_kind(NULL, name) != svn_prop_regular_kind)
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, "");
@@ -544,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;
}
@@ -566,20 +661,22 @@ change_file_prop(void *file_baton,
{
struct dump_edit_baton *eb = file_baton;
+ LDR_DBG(("change_file_prop %p\n", file_baton));
+
if (svn_property_kind(NULL, name) != svn_prop_regular_kind)
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;
}
@@ -620,6 +717,8 @@ apply_textdelta(void *file_baton, const
hb->pool = handler_pool;
hb->eb = eb;
+ LDR_DBG(("apply_textdelta %p\n", file_baton));
+
/* Use a temporary file to measure the text-content-length */
SVN_ERR(svn_stream_open_unique(&(hb->delta_filestream), &hb->delta_abspath,
NULL, svn_io_file_del_none, hb->pool,
@@ -650,11 +749,13 @@ close_file(void *file_baton,
svn_stream_t *delta_filestream;
apr_finfo_t *info = apr_pcalloc(pool, sizeof(apr_finfo_t));
- /* Some pending properties to dump? */
- SVN_ERR(dump_props(eb, &(eb->dump_props_pending), FALSE, pool));
+ LDR_DBG(("close_file %p\n", file_baton));
- /* The prop headers have already been dumped in dump_node; now dump
- the text headers. */
+ /* 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));
+
+ /* Dump the text headers */
if (eb->dump_text)
{
/* Text-delta: true */
@@ -686,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",
@@ -697,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 */
@@ -728,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;
@@ -737,6 +839,7 @@ static svn_error_t *
close_edit(void *edit_baton, apr_pool_t *pool)
{
struct dump_edit_baton *eb = edit_baton;
+ LDR_DBG(("close_edit\n"));
svn_pool_destroy(eb->pool);
return SVN_NO_ERROR;
Modified: subversion/branches/javahl-ra/subversion/svnrdump/dump_editor.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnrdump/dump_editor.h?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnrdump/dump_editor.h (original)
+++ subversion/branches/javahl-ra/subversion/svnrdump/dump_editor.h Tue Sep 28 17:35:22 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/javahl-ra/subversion/svnrdump/load_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnrdump/load_editor.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnrdump/load_editor.c (original)
+++ subversion/branches/javahl-ra/subversion/svnrdump/load_editor.c Tue Sep 28 17:35:22 2010
@@ -30,9 +30,15 @@
#include "svn_path.h"
#include "svn_ra.h"
#include "svn_io.h"
+#include "svn_private_config.h"
+
+#include <apr_network_io.h>
#include "load_editor.h"
+#define SVNRDUMP_PROP_LOCK SVN_PROP_PREFIX "rdump-lock"
+#define LOCK_RETRIES 10
+
#ifdef SVN_DEBUG
#define LDR_DBG(x) SVN_DBG(x)
#else
@@ -50,6 +56,117 @@ 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.
+ *
+ * ### TODO: Make this function more generic and
+ * expose it through a header for use by other Subversion
+ * applications to avoid duplication.
+ */
+static svn_error_t *
+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"));
+
+ 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,
+ subpool));
+
+ if (reposlocktoken)
+ {
+ /* Did we get it? If so, we're done, otherwise we sleep. */
+ if (strcmp(reposlocktoken->data, mylocktoken->data) == 0)
+ return SVN_NO_ERROR;
+ else
+ {
+ SVN_ERR(svn_cmdline_printf
+ (pool, _("Failed to get lock on destination "
+ "repos, currently held by '%s'\n"),
+ reposlocktoken->data));
+
+ apr_sleep(apr_time_from_sec(1));
+ }
+ }
+ else if (i < LOCK_RETRIES - 1)
+ {
+ const svn_string_t *unset = NULL;
+
+ /* Except in the very last iteration, try to set the lock. */
+ 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);
+ }
+ }
+
+ return svn_error_createf(APR_EINVAL, NULL,
+ _("Couldn't get lock on destination repos "
+ "after %d attempts"), i);
+}
static svn_error_t *
new_revision_record(void **revision_baton,
@@ -116,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;
@@ -238,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));
@@ -247,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;
}
@@ -328,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). */
@@ -353,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;
}
@@ -486,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);
@@ -536,16 +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;
-
- /* ### TODO: Figure out if we're allowed to set revprops before
- ### we're too late and mess up the repository. svnsync uses some
- ### sort of locking mechanism. */
+ 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(&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));
+ 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/javahl-ra/subversion/svnrdump/load_editor.h
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnrdump/load_editor.h?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnrdump/load_editor.h (original)
+++ subversion/branches/javahl-ra/subversion/svnrdump/load_editor.h Tue Sep 28 17:35:22 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/javahl-ra/subversion/svnrdump/svnrdump.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnrdump/svnrdump.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnrdump/svnrdump.c (original)
+++ subversion/branches/javahl-ra/subversion/svnrdump/svnrdump.c Tue Sep 28 17:35:22 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/javahl-ra/subversion/svnserve/cyrus_auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnserve/cyrus_auth.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnserve/cyrus_auth.c (original)
+++ subversion/branches/javahl-ra/subversion/svnserve/cyrus_auth.c Tue Sep 28 17:35:22 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/javahl-ra/subversion/svnserve/serve.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnserve/serve.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnserve/serve.c (original)
+++ subversion/branches/javahl-ra/subversion/svnserve/serve.c Tue Sep 28 17:35:22 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;
}
@@ -1452,6 +1505,14 @@ static svn_error_t *get_dir(svn_ra_svn_c
svn_pool_clear(subpool);
file_path = svn_uri_join(full_path, name, subpool);
+
+ if (! lookup_access(subpool, b, conn, svn_authz_read,
+ file_path, FALSE))
+ {
+ apr_hash_set(entries, name, APR_HASH_KEY_STRING, NULL);
+ continue;
+ }
+
entry = apr_pcalloc(pool, sizeof(*entry));
if (dirent_fields & SVN_DIRENT_KIND)
@@ -2755,6 +2816,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 },
@@ -2978,7 +3040,8 @@ 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. */
- SVN_ERR(svn_ra_svn_write_cmd_response(conn, pool, "nn()(wwwwwww)",
+ /* Server-side capabilities list: */
+ 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,
@@ -2986,6 +3049,7 @@ 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));
/* Read client response, which we assume to be in version 2 format:
Modified: subversion/branches/javahl-ra/subversion/svnsync/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/svnsync/main.c?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/svnsync/main.c (original)
+++ subversion/branches/javahl-ra/subversion/svnsync/main.c Tue Sep 28 17:35:22 2010
@@ -284,18 +284,77 @@ 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.
+ * given RA SESSION. This lock is just a revprop change attempt in a
+ * time-delay loop. This function is duplicated by svnrdump in
+ * load_editor.c.
+ *
+ * ### TODO: Make this function more generic and
+ * expose it through a header for use by other Subversion
+ * 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"));
@@ -303,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. */
@@ -331,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);
}
}
@@ -381,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(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));
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));
}
@@ -451,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);
@@ -535,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
{
@@ -670,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' ***/
@@ -743,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
@@ -809,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
@@ -891,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;
@@ -997,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
@@ -1110,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)
@@ -1215,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. */
@@ -1309,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
@@ -1545,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
@@ -1589,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,
@@ -2033,15 +2149,7 @@ main(int argc, const char *argv[])
check_cancel, NULL,
pool);
if (! err)
- {
- /* svnsync can safely create instance of QApplication class. */
- svn_auth_set_parameter(opt_baton.source_auth_baton,
- "svn:auth:qapplication-safe", "1");
- svn_auth_set_parameter(opt_baton.sync_auth_baton,
- "svn:auth:qapplication-safe", "1");
-
- err = (*subcommand->cmd_func)(os, &opt_baton, pool);
- }
+ err = (*subcommand->cmd_func)(os, &opt_baton, pool);
if (err)
{
/* For argument-related problems, suggest using the 'help'
Propchange: subversion/branches/javahl-ra/subversion/tests/cmdline/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Tue Sep 28 17:35:22 2010
@@ -6,4 +6,5 @@ httpd-*
*~
.*~
entries-dump
+atomic-ra-revprop-change
.libs
Modified: subversion/branches/javahl-ra/subversion/tests/cmdline/authz_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/tests/cmdline/authz_tests.py?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/tests/cmdline/authz_tests.py (original)
+++ subversion/branches/javahl-ra/subversion/tests/cmdline/authz_tests.py Tue Sep 28 17:35:22 2010
@@ -1091,9 +1091,8 @@ test_list = [ None,
Skip(wc_wc_copy, svntest.main.is_ra_type_file),
Skip(wc_wc_copy_revert,
svntest.main.is_ra_type_file),
- XFail(Skip(authz_recursive_ls,
- svntest.main.is_ra_type_file),
- svntest.main.is_ra_type_svn),
+ Skip(authz_recursive_ls,
+ svntest.main.is_ra_type_file),
]
if __name__ == '__main__':
Modified: subversion/branches/javahl-ra/subversion/tests/cmdline/copy_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/tests/cmdline/copy_tests.py?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/tests/cmdline/copy_tests.py (original)
+++ subversion/branches/javahl-ra/subversion/tests/cmdline/copy_tests.py Tue Sep 28 17:35:22 2010
@@ -3799,106 +3799,6 @@ def allow_unversioned_parent_for_copy_sr
wc2_dir,
copy_to_path)
-
-#----------------------------------------------------------------------
-# Issue #2986
-def replaced_local_source_for_incoming_copy(sbox):
- "update receives copy, but local source is replaced"
- sbox.build()
- wc_dir = sbox.wc_dir
- other_wc_dir = wc_dir + '-other'
-
- # These paths are for regular content testing.
- tau_path = os.path.join(wc_dir, 'A', 'D', 'G', 'tau')
- rho_url = sbox.repo_url + '/A/D/G/rho'
- pi_url = sbox.repo_url + '/A/D/G/pi'
- other_G_path = os.path.join(other_wc_dir, 'A', 'D', 'G')
- other_rho_path = os.path.join(other_G_path, 'rho')
-
- # These paths are for properties testing.
- H_path = os.path.join(wc_dir, 'A', 'D', 'H')
- chi_path = os.path.join(H_path, 'chi')
- psi_path = os.path.join(H_path, 'psi')
- omega_path = os.path.join(H_path, 'omega')
- psi_url = sbox.repo_url + '/A/D/H/psi'
- chi_url = sbox.repo_url + '/A/D/H/chi'
- other_H_path = os.path.join(other_wc_dir, 'A', 'D', 'H')
- other_psi_path = os.path.join(other_H_path, 'psi')
- other_omega_path = os.path.join(other_H_path, 'omega')
-
- # Prepare for properties testing. If the regular content bug
- # reappears, we still want to be able to test for the property bug
- # independently. That means making two files have the same content,
- # to avoid encountering the checksum error that might reappear in a
- # regression. So here we do that, as well as set the marker
- # property that we'll check for later. The reason to set the marker
- # property in this commit, rather than later, is so that we pass the
- # conditional in update_editor.c:locate_copyfrom() that compares the
- # revisions.
- svntest.main.file_write(chi_path, "Same contents for two files.\n")
- svntest.main.file_write(psi_path, "Same contents for two files.\n")
- svntest.actions.run_and_verify_svn(None, None, [], 'propset',
- 'chi-prop', 'chi-val', chi_path)
- svntest.actions.run_and_verify_svn(None, None, [], 'ci',
- '-m', 'identicalize contents', wc_dir);
- svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
-
- # Make the duplicate working copy.
- svntest.main.safe_rmtree(other_wc_dir)
- shutil.copytree(wc_dir, other_wc_dir)
-
- try:
- ## Test properties. ##
-
- # Commit a replacement from the first working copy.
- svntest.actions.run_and_verify_svn(None, None, [], 'rm',
- omega_path);
- svntest.actions.run_and_verify_svn(None, None, [], 'cp',
- psi_url, omega_path);
- svntest.actions.run_and_verify_svn(None, None, [], 'ci',
- '-m', 'a propset and a copy', wc_dir);
-
- # Now schedule a replacement in the second working copy, then update
- # to receive the replacement from the first working copy, with the
- # source being the now-scheduled-replace file.
- svntest.actions.run_and_verify_svn(None, None, [], 'rm',
- other_psi_path);
- svntest.actions.run_and_verify_svn(None, None, [], 'cp',
- chi_url, other_psi_path);
- svntest.actions.run_and_verify_svn(None, None, [], 'up',
- other_wc_dir)
- exit_code, output, errput = svntest.main.run_svn(None, 'proplist',
- '-v', other_omega_path)
- if len(errput):
- raise svntest.Failure("unexpected error output: %s" % errput)
- if len(output):
- raise svntest.Failure("unexpected properties found on '%s': %s"
- % (other_omega_path, output))
-
- ## Test regular content. ##
-
- # Commit a replacement from the first working copy.
- svntest.actions.run_and_verify_svn(None, None, [], 'rm',
- tau_path);
- svntest.actions.run_and_verify_svn(None, None, [], 'cp',
- rho_url, tau_path);
- svntest.actions.run_and_verify_svn(None, None, [], 'ci',
- '-m', 'copy rho to tau', wc_dir);
-
- # Now schedule a replacement in the second working copy, then update
- # to receive the replacement from the first working copy, with the
- # source being the now-scheduled-replace file.
- svntest.actions.run_and_verify_svn(None, None, [], 'rm',
- other_rho_path);
- svntest.actions.run_and_verify_svn(None, None, [], 'cp',
- pi_url, other_rho_path);
- svntest.actions.run_and_verify_svn(None, None, [], 'up',
- other_wc_dir)
-
- finally:
- svntest.main.safe_rmtree(other_wc_dir)
-
-
def unneeded_parents(sbox):
"svn cp --parents FILE_URL DIR_URL"
@@ -4771,60 +4671,6 @@ def move_added_nodes(sbox):
expected_status.add({'X/Z' : Item(status='A ', wc_rev='0')})
svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status)
-def locate_wrong_origin(sbox):
- "update editor locates invalid file source"
-
- sbox.build()
-
- iota = os.path.join(sbox.wc_dir, 'iota')
- gamma = os.path.join(sbox.wc_dir, 'A/D/gamma')
-
- D1 = os.path.join(sbox.wc_dir, 'D1')
- D2 = os.path.join(sbox.wc_dir, 'D2')
-
- main.run_svn(None, 'mkdir', D1, D2)
- main.run_svn(None, 'cp', iota, os.path.join(D1, 'iota'))
- main.run_svn(None, 'cp', gamma, os.path.join(D2, 'iota'))
-
- main.run_svn(None, 'ci', sbox.wc_dir, '-m', 'Add 2*iotas in r2')
- main.run_svn(None, 'rm', D1)
-
- main.run_svn(None, 'ci', sbox.wc_dir, '-m', 'Why?')
-
- main.run_svn(None, 'cp', D2, D1)
- main.run_svn(None, 'ci', sbox.wc_dir, '-m', 'Replace one iota')
-
- # <= 1.6 needs a new checkout here to reproduce, but not since r961831.
- # so we just perform an update
- main.run_svn(None, 'up', sbox.wc_dir)
-
- main.run_svn(None, 'cp', sbox.repo_url + '/D1/iota@2',
- sbox.repo_url + '/iobeta', '-m', 'Copy iota')
-
-
- expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 4)
- expected_status.add({
- 'D1' : Item(status=' ', wc_rev='4'),
- 'D1/iota' : Item(status=' ', wc_rev='4'),
- 'D2' : Item(status=' ', wc_rev='4'),
- 'D2/iota' : Item(status=' ', wc_rev='4'),
- })
- svntest.actions.run_and_verify_status(sbox.wc_dir, expected_status)
-
- # The next update receives an add_file('/D1/iota', 2), which it then tries
- # to locate in the local working copy. It finds a '/D1/iota' in the expected
- # place, with a last-changed revision of 2 and a local revision of HEAD-1
- #
- # locate_copyfrom identifies this file as correct because
- # * last-mod <= 2 and
- # * 2 <= REV
- #
- # Luckily close_file() receives an expected_checksum which makes us fail, or
- # we would have a completely broken working copy
-
- # So this gives a Checksum mismatch error.
- main.run_svn(None, 'up', sbox.wc_dir)
-
# This test currently fails, but should work ok once we move to single DB
def copy_over_deleted_dir(sbox):
"copy a directory over a deleted directory"
@@ -4910,7 +4756,6 @@ test_list = [ None,
copy_make_parents_repo_repo,
URI_encoded_repos_to_wc,
allow_unversioned_parent_for_copy_src,
- replaced_local_source_for_incoming_copy,
unneeded_parents,
double_parents_with_url,
copy_into_absent_dir,
@@ -4929,9 +4774,6 @@ test_list = [ None,
changed_data_should_match_checkout,
XFail(changed_dir_data_should_match_checkout),
move_added_nodes,
- # Serf needs a different testcase for this issue
- XFail(Skip(locate_wrong_origin,
- svntest.main.is_ra_type_dav_serf)),
copy_over_deleted_dir,
]
Modified: subversion/branches/javahl-ra/subversion/tests/cmdline/input_validation_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/tests/cmdline/input_validation_tests.py?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/tests/cmdline/input_validation_tests.py (original)
+++ subversion/branches/javahl-ra/subversion/tests/cmdline/input_validation_tests.py Tue Sep 28 17:35:22 2010
@@ -166,6 +166,13 @@ def invalid_merge_args(sbox):
run_and_verify_svn_in_wc(sbox, "svn: Path '.*' does not exist",
'merge', '-c42', '^/mu', 'nonexistent')
+def invalid_wcpath_upgrade(sbox):
+ "non-working copy paths for 'upgrade'"
+ sbox.build(read_only=True)
+ for target in _invalid_wc_path_targets:
+ run_and_verify_svn_in_wc(sbox, "svn:.*is not a local path", 'upgrade',
+ target, target)
+
########################################################################
# Run the tests
@@ -184,6 +191,7 @@ test_list = [ None,
invalid_import_args,
invalid_log_targets,
invalid_merge_args,
+ invalid_wcpath_upgrade,
]
if __name__ == '__main__':
Modified: subversion/branches/javahl-ra/subversion/tests/cmdline/merge_reintegrate_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/tests/cmdline/merge_reintegrate_tests.py?rev=1002283&r1=1002282&r2=1002283&view=diff
==============================================================================
--- subversion/branches/javahl-ra/subversion/tests/cmdline/merge_reintegrate_tests.py (original)
+++ subversion/branches/javahl-ra/subversion/tests/cmdline/merge_reintegrate_tests.py Tue Sep 28 17:35:22 2010
@@ -2075,8 +2075,8 @@ def added_subtrees_with_mergeinfo_break_
#----------------------------------------------------------------------
# Test for issue #3648 '2-URL merges incorrectly reverse-merge mergeinfo
# for merge target'.
-def two_URL_merge_removes_valid_mergefino_from_target(sbox):
- "2-URL merge removes valid mergefino from target"
+def two_URL_merge_removes_valid_mergeinfo_from_target(sbox):
+ "2-URL merge removes valid mergeinfo from target"
sbox.build()
wc_dir = sbox.wc_dir
@@ -2254,7 +2254,7 @@ test_list = [ None,
server_has_mergeinfo),
reintegrate_with_self_referential_mergeinfo,
added_subtrees_with_mergeinfo_break_reintegrate,
- two_URL_merge_removes_valid_mergefino_from_target,
+ two_URL_merge_removes_valid_mergeinfo_from_target,
]
if __name__ == '__main__':