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/08/10 22:56:05 UTC
svn commit: r984206 [31/35] - in /subversion/branches/ignore-mergeinfo: ./
build/ build/generator/ build/generator/templates/ build/hudson/
build/hudson/jobs/subversion-1.6.x-solaris/
build/hudson/jobs/subversion-1.6.x-ubuntu/ build/hudson/jobs/subvers...
Modified: subversion/branches/ignore-mergeinfo/subversion/svnadmin/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/svnadmin/main.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/svnadmin/main.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/svnadmin/main.c Tue Aug 10 20:55:56 2010
@@ -230,7 +230,8 @@ enum
svnadmin__wait,
svnadmin__pre_1_4_compatible,
svnadmin__pre_1_5_compatible,
- svnadmin__pre_1_6_compatible
+ svnadmin__pre_1_6_compatible,
+ svnadmin__pre_1_7_compatible
};
/* Option codes and descriptions.
@@ -316,6 +317,10 @@ static const apr_getopt_option_t options
N_("use format compatible with Subversion versions\n"
" earlier than 1.6")},
+ {"pre-1.7-compatible", svnadmin__pre_1_7_compatible, 0,
+ N_("use format compatible with Subversion versions\n"
+ " earlier than 1.7")},
+
{NULL}
};
@@ -336,7 +341,8 @@ static const svn_opt_subcommand_desc2_t
"Create a new, empty repository at REPOS_PATH.\n"),
{svnadmin__bdb_txn_nosync, svnadmin__bdb_log_keep,
svnadmin__config_dir, svnadmin__fs_type, svnadmin__pre_1_4_compatible,
- svnadmin__pre_1_5_compatible, svnadmin__pre_1_6_compatible } },
+ svnadmin__pre_1_5_compatible, svnadmin__pre_1_6_compatible,
+ svnadmin__pre_1_7_compatible} },
{"deltify", subcommand_deltify, {0}, N_
("usage: svnadmin deltify [-r LOWER[:UPPER]] REPOS_PATH\n\n"
@@ -488,6 +494,7 @@ struct svnadmin_opt_state
svn_boolean_t pre_1_4_compatible; /* --pre-1.4-compatible */
svn_boolean_t pre_1_5_compatible; /* --pre-1.5-compatible */
svn_boolean_t pre_1_6_compatible; /* --pre-1.6-compatible */
+ svn_boolean_t pre_1_7_compatible; /* --pre-1.7-compatible */
svn_opt_revision_t start_revision, end_revision; /* -r X[:Y] */
svn_boolean_t help; /* --help or -? */
svn_boolean_t version; /* --version */
@@ -578,6 +585,11 @@ subcommand_create(apr_getopt_t *os, void
APR_HASH_KEY_STRING,
"1");
+ if (opt_state->pre_1_7_compatible)
+ apr_hash_set(fs_config, SVN_FS_CONFIG_PRE_1_7_COMPATIBLE,
+ APR_HASH_KEY_STRING,
+ "1");
+
SVN_ERR(svn_config_get_config(&config, opt_state->config_dir, pool));
SVN_ERR(svn_repos_create(&repos, opt_state->repository_path,
NULL, NULL,
@@ -638,6 +650,38 @@ subcommand_deltify(apr_getopt_t *os, voi
}
+/* Baton for repos_progress_handler */
+struct progress_baton
+{
+ svn_boolean_t dumping;
+ svn_stream_t *progress_stream;
+};
+
+/* Implementation of svn_repos_progress_func_t to wrap the output to a
+ response stream for svn_repos_dump_fs2() and svn_repos_verify_fs() */
+static svn_error_t *
+repos_progress_handler(void * baton,
+ svn_revnum_t revision,
+ const char *warning_text,
+ apr_pool_t *scratch_pool)
+{
+ struct progress_baton *pb = baton;
+
+ if (warning_text != NULL)
+ {
+ apr_size_t len = strlen(warning_text);
+ return svn_error_return(svn_stream_write(pb->progress_stream,
+ warning_text, &len));
+ }
+
+ return svn_error_return(svn_stream_printf(pb->progress_stream, scratch_pool,
+ pb->dumping
+ ? _("* Dumped revision %ld.\n")
+ : _("* Verified revision %ld.\n"),
+ revision));
+}
+
+
/* Baton for recode_write(). */
struct recode_write_baton
{
@@ -685,9 +729,10 @@ subcommand_dump(apr_getopt_t *os, void *
struct svnadmin_opt_state *opt_state = baton;
svn_repos_t *repos;
svn_fs_t *fs;
- svn_stream_t *stdout_stream, *stderr_stream = NULL;
+ svn_stream_t *stdout_stream;
svn_revnum_t lower = SVN_INVALID_REVNUM, upper = SVN_INVALID_REVNUM;
svn_revnum_t youngest;
+ struct progress_baton pb = { 0 };
SVN_ERR(open_repos(&repos, opt_state->repository_path, pool));
fs = svn_repos_fs(repos);
@@ -719,12 +764,14 @@ subcommand_dump(apr_getopt_t *os, void *
/* Progress feedback goes to STDERR, unless they asked to suppress it. */
if (! opt_state->quiet)
- stderr_stream = recode_stream_create(stderr, pool);
+ pb.progress_stream = recode_stream_create(stderr, pool);
- SVN_ERR(svn_repos_dump_fs2(repos, stdout_stream, stderr_stream,
- lower, upper, opt_state->incremental,
- opt_state->use_deltas, check_cancel, NULL,
- pool));
+ pb.dumping = TRUE;
+ SVN_ERR(svn_repos_dump_fs3(repos, stdout_stream, lower, upper,
+ opt_state->incremental, opt_state->use_deltas,
+ !opt_state->quiet ? repos_progress_handler : NULL,
+ !opt_state->quiet ? &pb : NULL,
+ check_cancel, NULL, pool));
return SVN_NO_ERROR;
}
@@ -1173,10 +1220,10 @@ static svn_error_t *
subcommand_verify(apr_getopt_t *os, void *baton, apr_pool_t *pool)
{
struct svnadmin_opt_state *opt_state = baton;
- svn_stream_t *stderr_stream;
svn_repos_t *repos;
svn_fs_t *fs;
svn_revnum_t youngest, lower, upper;
+ struct progress_baton pb = { 0 };
SVN_ERR(open_repos(&repos, opt_state->repository_path, pool));
fs = svn_repos_fs(repos);
@@ -1193,14 +1240,14 @@ subcommand_verify(apr_getopt_t *os, void
upper = lower;
}
- if (opt_state->quiet)
- stderr_stream = NULL;
- else
- stderr_stream = recode_stream_create(stderr, pool);
+ if (! opt_state->quiet)
+ pb.progress_stream = recode_stream_create(stderr, pool);
- SVN_ERR(open_repos(&repos, opt_state->repository_path, pool));
- return svn_repos_verify_fs(repos, stderr_stream, lower, upper,
- check_cancel, NULL, pool);
+ return svn_repos_verify_fs2(repos, lower, upper,
+ !opt_state->quiet
+ ? repos_progress_handler : NULL,
+ !opt_state->quiet ? &pb : NULL,
+ check_cancel, NULL, pool);
}
@@ -1226,7 +1273,6 @@ subcommand_lslocks(apr_getopt_t *os, voi
apr_array_header_t *targets;
svn_repos_t *repos;
const char *fs_path = "/";
- svn_fs_t *fs;
apr_hash_t *locks;
apr_hash_index_t *hi;
@@ -1240,7 +1286,6 @@ subcommand_lslocks(apr_getopt_t *os, voi
fs_path = APR_ARRAY_IDX(targets, 0, const char *);
SVN_ERR(open_repos(&repos, opt_state->repository_path, pool));
- fs = svn_repos_fs(repos);
/* Fetch all locks on or below the root directory. */
SVN_ERR(svn_repos_fs_get_locks(&locks, repos, fs_path, NULL, NULL, pool));
@@ -1443,7 +1488,7 @@ main(int argc, const char *argv[])
apr_pool_t *pool;
const svn_opt_subcommand_desc2_t *subcommand = NULL;
- struct svnadmin_opt_state opt_state;
+ struct svnadmin_opt_state opt_state = { 0 };
apr_getopt_t *os;
int opt_id;
apr_array_header_t *received_opts;
@@ -1484,7 +1529,6 @@ main(int argc, const char *argv[])
}
/* Initialize opt_state. */
- memset(&opt_state, 0, sizeof(opt_state));
opt_state.start_revision.kind = svn_opt_revision_unspecified;
opt_state.end_revision.kind = svn_opt_revision_unspecified;
@@ -1572,6 +1616,9 @@ main(int argc, const char *argv[])
case svnadmin__pre_1_6_compatible:
opt_state.pre_1_6_compatible = TRUE;
break;
+ case svnadmin__pre_1_7_compatible:
+ opt_state.pre_1_7_compatible = TRUE;
+ break;
case svnadmin__fs_type:
err = svn_utf_cstring_to_utf8(&opt_state.fs_type, opt_arg, pool);
if (err)
Modified: subversion/branches/ignore-mergeinfo/subversion/svndumpfilter/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/svndumpfilter/main.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/svndumpfilter/main.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/svndumpfilter/main.c Tue Aug 10 20:55:56 2010
@@ -191,6 +191,9 @@ struct parse_baton_t
apr_hash_t *dropped_nodes;
apr_hash_t *renumber_history; /* svn_revnum_t -> struct revmap_t */
svn_revnum_t last_live_revision;
+ /* The oldest original revision, greater than r0, in the input
+ stream which was not filtered. */
+ svn_revnum_t oldest_original_rev;
};
struct revision_baton_t
@@ -393,6 +396,11 @@ output_revision(struct revision_baton_t
SVN_ERR(svn_stream_write(rb->pb->out_stream,
props->data, &(props->len)));
+ /* Stash the oldest original rev not dropped. */
+ if (rb->rev_orig > 0
+ && !SVN_IS_VALID_REVNUM(rb->pb->oldest_original_rev))
+ rb->pb->oldest_original_rev = rb->rev_orig;
+
if (rb->pb->do_renumber_revs)
{
svn_revnum_t *rr_key;
@@ -670,6 +678,25 @@ adjust_mergeinfo(svn_string_t **final_va
apr_pool_t *subpool = svn_pool_create(pool);
SVN_ERR(svn_mergeinfo_parse(&mergeinfo, initial_val->data, subpool));
+
+ /* Issue #3020: If we are skipping missing merge sources, then also
+ filter mergeinfo ranges as old or older than the oldest revision in the
+ dump stream. Those older than the oldest obviously refer to history
+ outside of the dump stream. The oldest rev itself is present in the
+ dump, but cannot be a valid merge source revision since it is the
+ start of all history. E.g. if we dump -r100:400 then dumpfilter the
+ result with --skip-missing-merge-sources, any mergeinfo with revision
+ 100 implies a change of -r99:100, but r99 is part of the history we
+ want filtered. This is analogous to how r1 is always meaningless as
+ a merge source revision.
+
+ If the oldest rev is r0 then there is nothing to filter. */
+ if (rb->pb->skip_missing_merge_sources && rb->pb->oldest_original_rev > 0)
+ SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(
+ &mergeinfo, mergeinfo,
+ rb->pb->oldest_original_rev, 0,
+ FALSE, subpool, subpool));
+
for (hi = apr_hash_first(subpool, mergeinfo); hi; hi = apr_hash_next(hi))
{
const char *merge_source = svn__apr_hash_index_key(hi);
@@ -977,7 +1004,12 @@ parse_baton_initialize(struct parse_bato
apr_file_open_stdout, pool));
baton->do_exclude = do_exclude;
- baton->do_renumber_revs = opt_state->renumber_revs;
+
+ /* Ignore --renumber-revs if there can't possibly be
+ anything to renumber. */
+ baton->do_renumber_revs =
+ (opt_state->renumber_revs && opt_state->drop_empty_revs);
+
baton->drop_empty_revs = opt_state->drop_empty_revs;
baton->preserve_revprops = opt_state->preserve_revprops;
baton->quiet = opt_state->quiet;
@@ -988,6 +1020,7 @@ parse_baton_initialize(struct parse_bato
baton->dropped_nodes = apr_hash_make(pool);
baton->renumber_history = apr_hash_make(pool);
baton->last_live_revision = SVN_INVALID_REVNUM;
+ baton->oldest_original_rev = SVN_INVALID_REVNUM;
/* This is non-ideal: We should pass through the version of the
* input dumpstream. However, our API currently doesn't allow that.
Modified: subversion/branches/ignore-mergeinfo/subversion/svnserve/cyrus_auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/svnserve/cyrus_auth.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/svnserve/cyrus_auth.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/svnserve/cyrus_auth.c Tue Aug 10 20:55:56 2010
@@ -102,7 +102,7 @@ static sasl_callback_t callbacks[] =
{ SASL_CB_LIST_END, NULL, NULL }
};
-static svn_error_t *initialize(apr_pool_t *pool)
+static svn_error_t *initialize(void *baton, apr_pool_t *pool)
{
int result;
apr_status_t status;
@@ -127,7 +127,8 @@ static svn_error_t *initialize(apr_pool_
svn_error_t *cyrus_init(apr_pool_t *pool)
{
- SVN_ERR(svn_atomic__init_once(&svn_ra_svn__sasl_status, initialize, pool));
+ SVN_ERR(svn_atomic__init_once(&svn_ra_svn__sasl_status,
+ initialize, NULL, pool));
return SVN_NO_ERROR;
}
Modified: subversion/branches/ignore-mergeinfo/subversion/svnsync/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/svnsync/main.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/svnsync/main.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/svnsync/main.c Tue Aug 10 20:55:56 2010
@@ -107,27 +107,37 @@ static const svn_opt_subcommand_desc2_t
{ SVNSYNC_OPTS_DEFAULT, 'q', svnsync_opt_allow_non_empty,
svnsync_opt_disable_locking } },
{ "synchronize", synchronize_cmd, { "sync" },
- N_("usage: svnsync synchronize DEST_URL\n"
+ N_("usage: svnsync synchronize DEST_URL [SOURCE_URL]\n"
"\n"
"Transfer all pending revisions to the destination from the source\n"
- "with which it was initialized.\n"),
+ "with which it was initialized.\n"
+ "\n"
+ "If SOURCE_URL is provided, use that as the source repository URL,\n"
+ "ignoring what is recorded in the destination repository as the\n"
+ "source URL. Specifying SOURCE_URL is recommended in particular\n"
+ "if untrusted users/administrators may have write access to the\n"
+ "DEST_URL repository.\n"),
{ SVNSYNC_OPTS_DEFAULT, 'q', svnsync_opt_disable_locking } },
{ "copy-revprops", copy_revprops_cmd, { 0 },
- N_("usage: svnsync copy-revprops DEST_URL [REV[:REV2]]\n"
+ N_("usage:\n"
+ "\n"
+ " 1. svnsync copy-revprops DEST_URL [SOURCE_URL]\n"
+ " 2. svnsync copy-revprops DEST_URL REV[:REV2]\n"
"\n"
"Copy the revision properties in a given range of revisions to the\n"
- "destination from the source with which it was initialized.\n"
+ "destination from the source with which it was initialized. If the\n"
+ "revision range is not specified, it defaults to all revisions in\n"
+ "the DEST_URL repository. Note also that the 'HEAD' revision is the\n"
+ "latest in DEST_URL, not necessarily the latest in SOURCE_URL.\n"
"\n"
- "If REV and REV2 are provided, copy properties for the revisions\n"
- "specified by that range, inclusively. If only REV is provided,\n"
- "copy properties for that revision alone. If REV is not provided,\n"
- "copy properties for all revisions previously transferred to the\n"
- "destination.\n"
+ "If SOURCE_URL is provided, use that as the source repository URL,\n"
+ "ignoring what is recorded in the destination repository as the\n"
+ "source URL. Specifying SOURCE_URL is recommended in particular\n"
+ "if untrusted users/administrators may have write access to the\n"
+ "DEST_URL repository.\n"
"\n"
- "REV and REV2 must be revisions which were previously transferred\n"
- "to the destination. You may use \"HEAD\" for either revision to\n"
- "mean \"the last revision transferred\".\n"),
- { SVNSYNC_OPTS_DEFAULT, 'q', svnsync_opt_disable_locking } },
+ "Form 2 is deprecated syntax, equivalent to specifying \"-rREV[:REV2]\".\n"),
+ { SVNSYNC_OPTS_DEFAULT, 'q', 'r', svnsync_opt_disable_locking } },
{ "info", info_cmd, { 0 },
N_("usage: svnsync info DEST_URL\n"
"\n"
@@ -146,6 +156,14 @@ static const apr_getopt_option_t svnsync
{
{"quiet", 'q', 0,
N_("print as little as possible") },
+ {"revision", 'r', 1,
+ N_("operate on revision ARG (or range ARG1:ARG2)\n"
+ " "
+ "A revision argument can be one of:\n"
+ " "
+ " NUMBER revision number\n"
+ " "
+ " 'HEAD' latest in repository") },
{"allow-non-empty", svnsync_opt_allow_non_empty, 0,
N_("allow a non-empty destination repository") },
{"non-interactive", svnsync_opt_non_interactive, 0,
@@ -214,6 +232,8 @@ typedef struct {
svn_boolean_t allow_non_empty;
svn_boolean_t version;
svn_boolean_t help;
+ svn_opt_revision_t start_rev;
+ svn_opt_revision_t end_rev;
} opt_baton_t;
@@ -840,10 +860,12 @@ commit_callback(const svn_commit_info_t
/* Set *FROM_SESSION to an RA session associated with the source
- * repository of the synchronization, as determined by reading
- * svn:sync- properties from the destination repository (associated
- * with TO_SESSION). Set LAST_MERGED_REV to the value of the property
- * which records the most recently synchronized revision.
+ * repository of the synchronization. If FROM_URL is non-NULL, use it
+ * as the source repository URL; otherwise, determine the source
+ * repository URL by reading svn:sync- properties from the destination
+ * repository (associated with TO_SESSION). Set LAST_MERGED_REV to
+ * the value of the property which records the most recently
+ * synchronized revision.
*
* CALLBACKS is a vtable of RA callbacks to provide when creating
* *FROM_SESSION. CONFIG is a configuration hash.
@@ -851,28 +873,34 @@ commit_callback(const svn_commit_info_t
static svn_error_t *
open_source_session(svn_ra_session_t **from_session,
svn_string_t **last_merged_rev,
+ const char *from_url,
svn_ra_session_t *to_session,
svn_ra_callbacks2_t *callbacks,
apr_hash_t *config,
void *baton,
apr_pool_t *pool)
{
- svn_string_t *from_url, *from_uuid;
+ svn_string_t *from_url_str, *from_uuid_str;
SVN_ERR(svn_ra_rev_prop(to_session, 0, SVNSYNC_PROP_FROM_URL,
- &from_url, pool));
+ &from_url_str, pool));
SVN_ERR(svn_ra_rev_prop(to_session, 0, SVNSYNC_PROP_FROM_UUID,
- &from_uuid, pool));
+ &from_uuid_str, pool));
SVN_ERR(svn_ra_rev_prop(to_session, 0, SVNSYNC_PROP_LAST_MERGED_REV,
last_merged_rev, pool));
- if (! from_url || ! from_uuid || ! *last_merged_rev)
+ if (! from_url_str || ! from_uuid_str || ! *last_merged_rev)
return svn_error_create
(APR_EINVAL, NULL,
_("Destination repository has not been initialized"));
+ /* ### TODO: Should we validate that FROM_URL_STR->data matches any
+ provided FROM_URL here? */
+ if (! from_url)
+ from_url = from_url_str->data;
+
/* Open the session to copy the revision data. */
- SVN_ERR(svn_ra_open3(from_session, from_url->data, from_uuid->data,
+ SVN_ERR(svn_ra_open3(from_session, from_url, from_uuid_str->data,
callbacks, baton, config, pool));
return SVN_NO_ERROR;
@@ -1137,8 +1165,8 @@ do_synchronize(svn_ra_session_t *to_sess
replay_baton_t *rb;
int normalized_rev_props_count = 0;
- SVN_ERR(open_source_session(&from_session,
- &last_merged_rev, to_session,
+ SVN_ERR(open_source_session(&from_session, &last_merged_rev,
+ baton->from_url, to_session,
&(baton->source_callbacks), baton->config,
baton, pool));
@@ -1267,7 +1295,7 @@ synchronize_cmd(apr_getopt_t *os, void *
opt_baton_t *opt_baton = b;
apr_array_header_t *targets;
subcommand_baton_t *baton;
- const char *to_url;
+ const char *to_url, *from_url;
SVN_ERR(svn_opt__args_to_target_array(&targets, os,
apr_array_make(pool, 0,
@@ -1275,16 +1303,27 @@ synchronize_cmd(apr_getopt_t *os, void *
pool));
if (targets->nelts < 1)
return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
- if (targets->nelts > 1)
+ if (targets->nelts > 2)
return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, 0, NULL);
to_url = APR_ARRAY_IDX(targets, 0, const char *);
-
if (! svn_path_is_url(to_url))
return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
_("Path '%s' is not a URL"), to_url);
- baton = make_subcommand_baton(opt_baton, to_url, NULL, 0, 0, pool);
+ if (targets->nelts == 2)
+ {
+ from_url = APR_ARRAY_IDX(targets, 1, const char *);
+ if (! svn_path_is_url(from_url))
+ return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("Path '%s' is not a URL"), from_url);
+ }
+ else
+ {
+ from_url = NULL; /* we'll read it from the destination repos */
+ }
+
+ baton = make_subcommand_baton(opt_baton, to_url, from_url, 0, 0, pool);
SVN_ERR(svn_ra_open3(&to_session, 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));
@@ -1315,7 +1354,7 @@ do_copy_revprops(svn_ra_session_t *to_se
int normalized_rev_props_count = 0;
SVN_ERR(open_source_session(&from_session, &last_merged_rev,
- to_session,
+ baton->from_url, to_session,
&(baton->source_callbacks), baton->config,
baton, pool));
@@ -1355,6 +1394,78 @@ do_copy_revprops(svn_ra_session_t *to_se
}
+/* Set *START_REVNUM to the revision number associated with
+ START_REVISION, or to SVN_INVALID_REVNUM if START_REVISION
+ represents "HEAD"; if END_REVISION is specified, set END_REVNUM to
+ the revision number associated with END_REVISION or to
+ SVN_INVALID_REVNUM if END_REVISION represents "HEAD"; otherwise set
+ END_REVNUM to the same value as START_REVNUM.
+
+ As a special case, if neither START_REVISION nor END_REVISION is
+ specified, set *START_REVNUM to 0 and set *END_REVNUM to
+ SVN_INVALID_REVNUM.
+
+ Freak out if either START_REVISION or END_REVISION represents an
+ explicit but invalid revision number. */
+static svn_error_t *
+resolve_revnums(svn_revnum_t *start_revnum,
+ svn_revnum_t *end_revnum,
+ svn_opt_revision_t start_revision,
+ svn_opt_revision_t end_revision)
+{
+ svn_revnum_t start_rev, end_rev;
+
+ /* Special case: neither revision is specified? This is like
+ -r0:HEAD. */
+ if ((start_revision.kind == svn_opt_revision_unspecified) &&
+ (end_revision.kind == svn_opt_revision_unspecified))
+ {
+ start_rev = 0;
+ end_rev = SVN_INVALID_REVNUM;
+ return SVN_NO_ERROR;
+ }
+
+ /* Get the start revision, which must be either HEAD or a number
+ (which is required to be a valid one). */
+ if (start_revision.kind == svn_opt_revision_head)
+ {
+ start_rev = SVN_INVALID_REVNUM;
+ }
+ else
+ {
+ start_rev = start_revision.value.number;
+ if (! SVN_IS_VALID_REVNUM(start_rev))
+ return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("Invalid revision number (%ld)"),
+ start_rev);
+ }
+
+ /* Get the end revision, which must be unspecified (meaning,
+ "same as the start_rev"), HEAD, or a number (which is
+ required to be a valid one). */
+ if (end_revision.kind == svn_opt_revision_unspecified)
+ {
+ end_rev = start_rev;
+ }
+ else if (end_revision.kind == svn_opt_revision_head)
+ {
+ end_rev = SVN_INVALID_REVNUM;
+ }
+ else
+ {
+ end_rev = end_revision.value.number;
+ if (! SVN_IS_VALID_REVNUM(end_rev))
+ return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("Invalid revision number (%ld)"),
+ end_rev);
+ }
+
+ *start_revnum = start_rev;
+ *end_revnum = end_rev;
+ return SVN_NO_ERROR;
+}
+
+
/* SUBCOMMAND: copy-revprops */
static svn_error_t *
copy_revprops_cmd(apr_getopt_t *os, void *b, apr_pool_t *pool)
@@ -1363,7 +1474,8 @@ copy_revprops_cmd(apr_getopt_t *os, void
opt_baton_t *opt_baton = b;
apr_array_header_t *targets;
subcommand_baton_t *baton;
- const char *to_url;
+ const char *to_url = NULL;
+ const char *from_url;
svn_opt_revision_t start_revision, end_revision;
svn_revnum_t start_rev = 0, end_rev = SVN_INVALID_REVNUM;
@@ -1373,77 +1485,80 @@ copy_revprops_cmd(apr_getopt_t *os, void
if (os->argc - os->ind < 1)
return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
- /* If there are two args, the last one is a revision range. We'll
- effectively pop it from the end of the list. Why? Because
- svn_opt__args_to_target_array() does waaaaay too many useful
- things for us not to use it. */
+ /* If there are two args, the last one is either a revision range or
+ the source URL. */
if (os->argc - os->ind == 2)
{
- const char *rev_str = os->argv[--(os->argc)];
+ const char *arg_str = os->argv[os->argc - 1];
+ const char *utf_arg_str;
- start_revision.kind = svn_opt_revision_unspecified;
- end_revision.kind = svn_opt_revision_unspecified;
- if ((svn_opt_parse_revision(&start_revision, &end_revision,
- rev_str, pool) != 0)
- || ((start_revision.kind != svn_opt_revision_number)
- && (start_revision.kind != svn_opt_revision_head))
- || ((end_revision.kind != svn_opt_revision_number)
- && (end_revision.kind != svn_opt_revision_head)
- && (end_revision.kind != svn_opt_revision_unspecified)))
- return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("'%s' is not a valid revision range"),
- rev_str);
+ SVN_ERR(svn_utf_cstring_to_utf8(&utf_arg_str, arg_str, pool));
- /* Get the start revision, which must be either HEAD or a number
- (which is required to be a valid one). */
- if (start_revision.kind == svn_opt_revision_head)
+ if (! svn_path_is_url(utf_arg_str))
{
- start_rev = SVN_INVALID_REVNUM;
- }
- else
- {
- start_rev = start_revision.value.number;
- if (! SVN_IS_VALID_REVNUM(start_rev))
+ /* This is the old "... TO_URL REV[:REV2]" syntax.
+ Revisions come only from this argument. (We effectively
+ pop that last argument from the end of the argument list
+ so svn_opt__args_to_target_array() can do its thang.) */
+ os->argc--;
+
+ if ((opt_baton->start_rev.kind != svn_opt_revision_unspecified)
+ || (opt_baton->end_rev.kind != svn_opt_revision_unspecified))
+ return svn_error_create(
+ SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("Cannot specify revisions via both command-line arguments "
+ "and the --revision (-r) option"));
+
+ start_revision.kind = svn_opt_revision_unspecified;
+ end_revision.kind = svn_opt_revision_unspecified;
+ if (svn_opt_parse_revision(&start_revision, &end_revision,
+ arg_str, pool) != 0)
return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("Invalid revision number (%ld)"),
- start_rev);
- }
+ _("Invalid revision range '%s' provided"),
+ arg_str);
- /* Get the end revision, which must be unspecified (meaning,
- "same as the start_rev"), HEAD, or a number (which is
- required to be a valid one). */
- if (end_revision.kind == svn_opt_revision_unspecified)
- {
- end_rev = start_rev;
- }
- else if (end_revision.kind == svn_opt_revision_head)
- {
- end_rev = SVN_INVALID_REVNUM;
+ SVN_ERR(resolve_revnums(&start_rev, &end_rev,
+ start_revision, end_revision));
+
+ SVN_ERR(svn_opt__args_to_target_array(
+ &targets, os,
+ apr_array_make(pool, 1, sizeof(const char *)), pool));
+ if (targets->nelts != 1)
+ return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
+ to_url = APR_ARRAY_IDX(targets, 0, const char *);
+ from_url = NULL;
}
+ }
+
+ if (! to_url)
+ {
+ /* This is the "... TO_URL SOURCE_URL" syntax. Revisions
+ come only from the --revision parameter. */
+ SVN_ERR(resolve_revnums(&start_rev, &end_rev,
+ opt_baton->start_rev, opt_baton->end_rev));
+
+ SVN_ERR(svn_opt__args_to_target_array(
+ &targets, os,
+ apr_array_make(pool, 2, sizeof(const char *)), pool));
+ if (targets->nelts < 1)
+ return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
+ if (targets->nelts > 2)
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, 0, NULL);
+ to_url = APR_ARRAY_IDX(targets, 0, const char *);
+ if (targets->nelts == 2)
+ from_url = APR_ARRAY_IDX(targets, 1, const char *);
else
- {
- end_rev = end_revision.value.number;
- if (! SVN_IS_VALID_REVNUM(end_rev))
- return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("Invalid revision number (%ld)"),
- end_rev);
- }
+ from_url = NULL;
}
- SVN_ERR(svn_opt__args_to_target_array(&targets, os,
- apr_array_make(pool, 1,
- sizeof(const char *)),
- pool));
- if (targets->nelts != 1)
- return svn_error_create(SVN_ERR_CL_INSUFFICIENT_ARGS, 0, NULL);
-
- to_url = APR_ARRAY_IDX(targets, 0, const char *);
-
if (! svn_path_is_url(to_url))
return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
_("Path '%s' is not a URL"), to_url);
-
- baton = make_subcommand_baton(opt_baton, to_url, NULL,
+ if (from_url && (! svn_path_is_url(from_url)))
+ return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("Path '%s' is not a URL"), from_url);
+
+ baton = make_subcommand_baton(opt_baton, to_url, from_url,
start_rev, end_rev, pool);
SVN_ERR(svn_ra_open3(&to_session, baton->to_url, NULL,
&(baton->sync_callbacks), baton, baton->config, pool));
@@ -1572,6 +1687,7 @@ main(int argc, const char *argv[])
const char *username = NULL, *source_username = NULL, *sync_username = NULL;
const char *password = NULL, *source_password = NULL, *sync_password = NULL;
apr_array_header_t *config_options = NULL;
+ apr_allocator_t *allocator;
if (svn_cmdline_init("svnsync", stderr) != EXIT_SUCCESS)
{
@@ -1582,13 +1698,25 @@ main(int argc, const char *argv[])
if (err)
return svn_cmdline_handle_exit_error(err, NULL, "svnsync: ");
- pool = svn_pool_create(NULL);
+ /* Create our top-level pool. Use a separate mutexless allocator,
+ * given this application is single threaded.
+ */
+ if (apr_allocator_create(&allocator))
+ return EXIT_FAILURE;
+
+ apr_allocator_max_free_set(allocator, SVN_ALLOCATOR_RECOMMENDED_MAX_FREE);
+
+ pool = svn_pool_create_ex(NULL, allocator);
+ apr_allocator_owner_set(allocator, pool);
err = svn_ra_initialize(pool);
if (err)
return svn_cmdline_handle_exit_error(err, pool, "svnsync: ");
+ /* Initialize the option baton. */
memset(&opt_baton, 0, sizeof(opt_baton));
+ opt_baton.start_rev.kind = svn_opt_revision_unspecified;
+ opt_baton.end_rev.kind = svn_opt_revision_unspecified;
received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int));
@@ -1699,6 +1827,35 @@ main(int argc, const char *argv[])
opt_baton.quiet = TRUE;
break;
+ case 'r':
+ if (svn_opt_parse_revision(&opt_baton.start_rev,
+ &opt_baton.end_rev,
+ opt_arg, pool) != 0)
+ {
+ const char *utf8_opt_arg;
+ err = svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool);
+ if (! err)
+ err = svn_error_createf(
+ SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("Syntax error in revision argument '%s'"),
+ utf8_opt_arg);
+ return svn_cmdline_handle_exit_error(err, pool, "svnsync: ");
+ }
+
+ /* We only allow numbers and 'HEAD'. */
+ if (((opt_baton.start_rev.kind != svn_opt_revision_number) &&
+ (opt_baton.start_rev.kind != svn_opt_revision_head))
+ || ((opt_baton.end_rev.kind != svn_opt_revision_number) &&
+ (opt_baton.end_rev.kind != svn_opt_revision_head) &&
+ (opt_baton.end_rev.kind != svn_opt_revision_unspecified)))
+ {
+ err = svn_error_createf(
+ SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("Invalid revision range '%s' provided"), opt_arg);
+ return svn_cmdline_handle_exit_error(err, pool, "svnsync: ");
+ }
+ break;
+
case '?':
case 'h':
opt_baton.help = TRUE;
Modified: subversion/branches/ignore-mergeinfo/subversion/svnversion/main.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/svnversion/main.c?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/svnversion/main.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/svnversion/main.c Tue Aug 10 20:55:56 2010
@@ -290,6 +290,16 @@ main(int argc, const char *argv[])
return EXIT_FAILURE;
}
+ if (! SVN_IS_VALID_REVNUM(res->min_rev))
+ {
+ /* Local uncommitted modifications, no revision info was found. */
+ SVN_INT_ERR(svn_cmdline_printf(pool, _("Uncommitted local addition, "
+ "copy or move%s"),
+ no_newline ? "" : "\n"));
+ svn_pool_destroy(pool);
+ return EXIT_SUCCESS;
+ }
+
/* Build compact '123[:456]M?S?' string. */
SVN_INT_ERR(svn_cmdline_printf(pool, "%ld", res->min_rev));
if (res->min_rev != res->max_rev)
Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/authz_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/authz_tests.py?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/authz_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/authz_tests.py Tue Aug 10 20:55:56 2010
@@ -903,6 +903,42 @@ def authz_access_required_at_repo_root(s
root_url + '/A-copy/B/E/beta',
root_url + '/A-copy/C')
+def authz_access_required_at_repo_root2(sbox):
+ "more authz issue #3242 - update to renamed file"
+
+ sbox.build(create_wc = False)
+ root_url = sbox.repo_url
+
+ # Now we get all restrictive.
+ write_authz_file(sbox, {'/': '* =',
+ '/A': 'jrandom = rw'})
+ write_restrictive_svnserve_conf(sbox.repo_dir)
+
+ # Rename a file.
+ svntest.main.run_svn(None, 'mv',
+ '-m', 'rename file in readable writable space',
+ root_url + '/A/B/E/alpha',
+ root_url + '/A/B/E/alpha-renamed')
+
+ # Check out original greek sub tree below /A/B/E
+ # and update it to the above rename.
+ wc_dir = sbox.add_wc_path('ABE')
+ os.mkdir(wc_dir)
+ svntest.main.run_svn(None, 'co', '-r', '1', root_url + '/A/B/E', wc_dir)
+ svntest.main.run_svn(None, 'up', wc_dir)
+
+ # Rename a directory.
+ svntest.main.run_svn(None, 'mv',
+ '-m', 'rename diretory in readable writable space',
+ root_url + '/A/D/H',
+ root_url + '/A/D/a g e')
+
+ # Check out original greek sub tree below /A/D
+ # and update it to the above rename.
+ wc_dir = sbox.add_wc_path('AD')
+ os.mkdir(wc_dir)
+ svntest.main.run_svn(None, 'co', '-r', '1', root_url + '/A/D', wc_dir)
+ svntest.main.run_svn(None, 'up', wc_dir)
def multiple_matches(sbox):
"multiple lines matching a user"
@@ -962,6 +998,8 @@ test_list = [ None,
svntest.main.is_ra_type_file)),
Skip(authz_access_required_at_repo_root,
svntest.main.is_ra_type_file),
+ Skip(authz_access_required_at_repo_root2,
+ svntest.main.is_ra_type_file),
Skip(multiple_matches, svntest.main.is_ra_type_file),
]
Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/basic_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/basic_tests.py?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/basic_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/basic_tests.py Tue Aug 10 20:55:56 2010
@@ -378,9 +378,8 @@ def basic_corruption(sbox):
# Modify mu's text-base, so we get a checksum failure the first time
# we try to commit.
- tb_dir_path = os.path.join(wc_dir, 'A',
- svntest.main.get_admin_name(), 'text-base')
- mu_tb_path = os.path.join(tb_dir_path, 'mu.svn-base')
+ mu_tb_path = svntest.wc.text_base_path(mu_path)
+ tb_dir_path = os.path.dirname(mu_tb_path)
mu_saved_tb_path = mu_tb_path + "-saved"
tb_dir_saved_mode = os.stat(tb_dir_path)[stat.ST_MODE]
mu_tb_saved_mode = os.stat(mu_tb_path)[stat.ST_MODE]
@@ -424,9 +423,9 @@ def basic_corruption(sbox):
# Modify mu's text-base, so we get a checksum failure the first time
# we try to update.
- tb_dir_path = os.path.join(other_wc, 'A',
- svntest.main.get_admin_name(), 'text-base')
- mu_tb_path = os.path.join(tb_dir_path, 'mu.svn-base')
+ other_mu_path = os.path.join(other_wc, 'A', 'mu')
+ mu_tb_path = svntest.wc.text_base_path(other_mu_path)
+ tb_dir_path = os.path.dirname(mu_tb_path)
mu_saved_tb_path = mu_tb_path + "-saved"
tb_dir_saved_mode = os.stat(tb_dir_path)[stat.ST_MODE]
mu_tb_saved_mode = os.stat(mu_tb_path)[stat.ST_MODE]
@@ -2455,7 +2454,7 @@ def basic_add_svn_format_file(sbox):
sbox.build()
wc_dir = sbox.wc_dir
- entries_path = os.path.join(wc_dir, '.svn', 'format')
+ entries_path = os.path.join(wc_dir, svntest.main.get_admin_name(), 'format')
output = svntest.actions.get_virginal_state(wc_dir, 1)
@@ -2478,6 +2477,26 @@ def basic_mkdir_mix_targets(sbox):
svntest.actions.run_and_verify_svn(None, None, expected_error,
'mkdir', '-m', 'log_msg', Y_url, 'subdir')
+def delete_from_url_with_spaces(sbox):
+ "delete a directory with ' ' using its url"
+
+ sbox.build()
+ sbox.simple_mkdir(os.path.join(sbox.wc_dir, 'Dir With Spaces'))
+ sbox.simple_mkdir(os.path.join(sbox.wc_dir, 'Dir With'))
+ sbox.simple_mkdir(os.path.join(sbox.wc_dir, 'Dir With/Spaces'))
+
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'ci', sbox.wc_dir, '-m', 'Added dir')
+
+ # This fails on 1.6.11 with an escaping error.
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'rm', sbox.repo_url + '/Dir%20With%20Spaces',
+ '-m', 'Deleted')
+
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'rm', sbox.repo_url + '/Dir%20With/Spaces',
+ '-m', 'Deleted')
+
#----------------------------------------------------------------------
########################################################################
@@ -2534,6 +2553,7 @@ test_list = [ None,
basic_auth_test,
basic_add_svn_format_file,
basic_mkdir_mix_targets,
+ delete_from_url_with_spaces,
]
if __name__ == '__main__':
Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/changelist_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/changelist_tests.py?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/changelist_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/changelist_tests.py Tue Aug 10 20:55:56 2010
@@ -45,9 +45,10 @@ def mod_all_files(wc_dir, new_text):
"""Walk over working copy WC_DIR, appending NEW_TEXT to all the
files in that tree (but not inside the .svn areas of that tree)."""
+ dot_svn = svntest.main.get_admin_name()
for dirpath, dirs, files in os.walk(wc_dir):
- if ".svn" in dirs:
- dirs.remove(".svn")
+ if dot_svn in dirs:
+ dirs.remove(dot_svn)
for name in files:
svntest.main.file_append(os.path.join(dirpath, name), new_text)
@@ -57,9 +58,10 @@ def changelist_all_files(wc_dir, name_fu
noting its string return value (or None, if we wish to remove the
file from a changelist)."""
+ dot_svn = svntest.main.get_admin_name()
for dirpath, dirs, files in os.walk(wc_dir):
- if ".svn" in dirs:
- dirs.remove(".svn")
+ if dot_svn in dirs:
+ dirs.remove(dot_svn)
for name in files:
full_path = os.path.join(dirpath, name)
clname = name_func(full_path)
Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/commit_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/commit_tests.py?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/commit_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/commit_tests.py Tue Aug 10 20:55:56 2010
@@ -1126,7 +1126,7 @@ def commit_in_dir_scheduled_for_addition
svntest.actions.run_and_verify_commit(wc_dir,
None,
None,
- "unversioned",
+ "not under version control",
mu_path)
Q_path = os.path.join(wc_dir, 'Q')
@@ -1961,7 +1961,7 @@ def mods_in_schedule_delete(sbox):
None, wc_dir)
# Unversioned file still exists
- actual_contents = svntest.main.file_read(foo_path)
+ actual_contents = open(foo_path).read()
if actual_contents != foo_contents:
raise svntest.Failure
Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/copy_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/copy_tests.py?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/copy_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/copy_tests.py Tue Aug 10 20:55:56 2010
@@ -980,7 +980,7 @@ def repos_to_wc(sbox):
expected_output = svntest.actions.get_virginal_state(wc_dir, 1)
expected_output.add({
- 'pi' : Item(status='A ', wc_rev='1'),
+ 'pi' : Item(status='A ', wc_rev='0', entry_rev='1'),
})
svntest.actions.run_and_verify_status(wc_dir, expected_output)
@@ -1735,7 +1735,13 @@ def mixed_wc_to_url(sbox):
wc_dir = sbox.wc_dir
Z_url = sbox.repo_url + '/A/D/Z'
+ Z2_url = sbox.repo_url + '/A/D/Z2'
G_path = os.path.join(wc_dir, 'A', 'D', 'G')
+ B_path = os.path.join(wc_dir, 'A', 'B')
+ X_path = os.path.join(wc_dir, 'A', 'D', 'G', 'X')
+ Y_path = os.path.join(wc_dir, 'A', 'D', 'G', 'Y')
+ E_path = os.path.join(wc_dir, 'A', 'D', 'G', 'X', 'E')
+ alpha_path = os.path.join(wc_dir, 'A', 'D', 'G', 'X', 'E', 'alpha')
pi_path = os.path.join(wc_dir, 'A', 'D', 'G', 'pi')
rho_path = os.path.join(wc_dir, 'A', 'D', 'G', 'rho')
@@ -1752,10 +1758,46 @@ def mixed_wc_to_url(sbox):
# Make another modification to A/D/G/rho, but don't commit it.
svntest.main.file_append(rho_path, "Second modification to rho.\n")
+ # Copy into the source, delete part of the copy, add a non-copied directory
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'cp', B_path, X_path)
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'rm', alpha_path)
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'mkdir', Y_path)
+
# Now copy local A/D/G to create new directory A/D/Z the repository.
svntest.actions.run_and_verify_svn(None, None, [],
'cp', '-m', "Make a copy.",
G_path, Z_url)
+ expected_output = svntest.verify.UnorderedOutput([
+ 'A + A/D/Z/\n',
+ ' (from A/D/G/:r1)\n',
+ 'A + A/D/Z/X/\n',
+ ' (from A/B/:r1)\n',
+ 'D A/D/Z/X/E/alpha\n',
+ 'A A/D/Z/Y/\n',
+ 'D A/D/Z/pi\n',
+ 'D A/D/Z/rho\n',
+ 'A + A/D/Z/rho\n',
+ ' (from A/D/G/rho:r3)\n',
+ ])
+ svntest.actions.run_and_verify_svnlook(None, expected_output, [],
+ 'changed', sbox.repo_dir,
+ '--copy-info')
+
+ # Copy from copied source
+ svntest.actions.run_and_verify_svn(None, None, [],
+ 'cp', '-m', "Make a copy.",
+ E_path, Z2_url)
+ expected_output = svntest.verify.UnorderedOutput([
+ 'A + A/D/Z2/\n',
+ ' (from A/B/E/:r1)\n',
+ 'D A/D/Z2/alpha\n',
+ ])
+ svntest.actions.run_and_verify_svnlook(None, expected_output, [],
+ 'changed', sbox.repo_dir,
+ '--copy-info')
# Check out A/D/Z. If it has pi, that's a bug; or if its rho does
# not have the second local mod, that's also a bug.
@@ -1764,7 +1806,7 @@ def mixed_wc_to_url(sbox):
'co', Z_url, wc_dir)
if os.path.exists(os.path.join(wc_dir, 'pi')):
- raise svntest.Failure
+ raise svntest.Failure("Path 'pi' exists but should be gone.")
fp = open(os.path.join(wc_dir, 'rho'), 'r')
found_it = 0
@@ -1772,7 +1814,7 @@ def mixed_wc_to_url(sbox):
if re.match("^Second modification to rho.", line):
found_it = 1
if not found_it:
- raise svntest.Failure
+ raise svntest.Failure("The second modification to rho didn't make it.")
#----------------------------------------------------------------------
@@ -4389,6 +4431,36 @@ def nonrecursive_commit_of_copy(sbox):
None,
wc_dir, '--depth', 'immediates')
+def copy_added_dir_with_copy(sbox):
+ """copy of new dir with copied file keeps history"""
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ new_dir = os.path.join(wc_dir, 'NewDir');
+ new_dir2 = os.path.join(wc_dir, 'NewDir2');
+
+ # Alias for svntest.actions.run_and_verify_svn
+ rav_svn = svntest.actions.run_and_verify_svn
+
+ rav_svn(None, None, [], 'mkdir', new_dir)
+ rav_svn(None, None, [], 'cp', os.path.join(wc_dir, 'A', 'mu'), new_dir)
+ rav_svn(None, None, [], 'cp', new_dir, new_dir2)
+
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+
+ expected_status.add(
+ {
+ 'NewDir' : Item(status='A ', wc_rev='0'),
+ 'NewDir/mu' : Item(status='A ', copied='+', wc_rev='-'),
+ 'NewDir2' : Item(status='A ', wc_rev='0'),
+ 'NewDir2/mu' : Item(status='A ', copied='+', wc_rev='-'),
+ })
+
+ # Currently this fails because NewDir2/mu loses its history in the copy
+ # from NewDir to NewDir2
+ svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
########################################################################
# Run the tests
@@ -4479,6 +4551,7 @@ test_list = [ None,
XFail(move_below_move),
reverse_merge_move,
XFail(nonrecursive_commit_of_copy),
+ XFail(copy_added_dir_with_copy),
]
if __name__ == '__main__':
Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/depth_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/depth_tests.py?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/depth_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/depth_tests.py Tue Aug 10 20:55:56 2010
@@ -2694,7 +2694,7 @@ test_list = [ None,
pull_in_tree_with_depth_option,
fold_tree_with_unversioned_modified_items,
depth_empty_update_on_file,
- XFail(excluded_path_update_operation),
+ excluded_path_update_operation,
excluded_path_misc_operation,
excluded_receive_remote_removal,
exclude_keeps_hidden_entries,
Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/diff_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/diff_tests.py?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/diff_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/diff_tests.py Tue Aug 10 20:55:56 2010
@@ -698,8 +698,7 @@ def dont_diff_binary_file(sbox):
wc_dir = sbox.wc_dir
# Add a binary file to the project.
- theta_contents = svntest.main.file_read(
- os.path.join(sys.path[0], "theta.bin"), 'rb')
+ theta_contents = open(os.path.join(sys.path[0], "theta.bin"), 'rb').read()
# Write PNG file data into 'A/theta'.
theta_path = os.path.join(wc_dir, 'A', 'theta')
svntest.main.file_write(theta_path, theta_contents, 'wb')
@@ -2604,6 +2603,9 @@ def diff_in_renamed_folder(sbox):
'A/D/C' : Item(verb='Adding'),
'A/D/C/kappa' : Item(verb='Adding'),
})
+ ### right now, we cannot denote that kappa is a local-add rather than a
+ ### child of the A/D/C copy. thus, it appears in the status output as a
+ ### (M)odified child.
svntest.actions.run_and_verify_commit(wc_dir, expected_output,
None, None, wc_dir)
@@ -2997,7 +2999,7 @@ def diff_external_diffcmd(sbox):
"iota\t(revision 1)\n",
"-L\n",
"iota\t(working copy)\n",
- os.path.abspath(os.path.join('.svn', 'text-base', 'iota.svn-base')) + "\n",
+ os.path.abspath(svntest.wc.text_base_path("iota")) + "\n",
os.path.abspath("iota") + "\n"])
# Check that the output of diff corresponds with the expected arguments,
@@ -3229,7 +3231,7 @@ test_list = [ None,
diff_weird_author,
diff_ignore_whitespace,
diff_ignore_eolstyle,
- diff_in_renamed_folder,
+ XFail(diff_in_renamed_folder),
diff_with_depth,
diff_ignore_eolstyle_empty_lines,
diff_backward_repos_wc_copy,
Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/externals_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/externals_tests.py?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/externals_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/externals_tests.py Tue Aug 10 20:55:56 2010
@@ -162,27 +162,13 @@ def externals_test_setup(sbox):
externals_desc = \
external_url_for["A/B/gamma"] + " gamma\n"
- (fd, tmp_f) = tempfile.mkstemp(dir=wc_init_dir)
- svntest.main.file_append(tmp_f, externals_desc)
- svntest.actions.run_and_verify_svn(None, None, [],
- 'pset',
- '-F', tmp_f, 'svn:externals', B_path)
-
- os.close(fd)
- os.remove(tmp_f)
+ change_external(B_path, externals_desc, commit=False)
externals_desc = \
"exdir_G " + external_url_for["A/C/exdir_G"] + "\n" + \
external_url_for["A/C/exdir_H"] + " exdir_H\n"
- (fd, tmp_f) = tempfile.mkstemp(dir=wc_init_dir)
- svntest.main.file_append(tmp_f, externals_desc)
- svntest.actions.run_and_verify_svn(None, None, [],
- 'pset',
- '-F', tmp_f, 'svn:externals', C_path)
-
- os.close(fd)
- os.remove(tmp_f)
+ change_external(C_path, externals_desc, commit=False)
external_url_for["A/D/exdir_A"] = "^/../" + other_repo_basename + "/A"
external_url_for["A/D/exdir_A/G/"] = scheme_relative_other_repo_url + \
@@ -200,11 +186,7 @@ def externals_test_setup(sbox):
external_url_for["A/D/x/y/z/blah"] + " x/y/z/blah" + \
"\n"
- svntest.main.file_append(tmp_f, externals_desc)
- svntest.actions.run_and_verify_svn(None, None, [], 'pset',
- '-F', tmp_f, 'svn:externals', D_path)
-
- os.remove(tmp_f)
+ change_external(D_path, externals_desc, commit=False)
# Commit the property changes.
@@ -224,15 +206,26 @@ def externals_test_setup(sbox):
return external_url_for
-def change_external(path, new_val):
+def change_external(path, new_val, commit=True):
"""Change the value of the externals property on PATH to NEW_VAL,
- and commit the change."""
+ and commit the change unless COMMIT is False."""
(fd, tmp_f) = tempfile.mkstemp(dir=svntest.main.temp_dir)
svntest.main.file_append(tmp_f, new_val)
svntest.actions.run_and_verify_svn(None, None, [], 'pset',
'-F', tmp_f, 'svn:externals', path)
- svntest.actions.run_and_verify_svn(None, None, [], 'ci',
- '-m', 'log msg', '--quiet', path)
+ if commit:
+ svntest.actions.run_and_verify_svn(None, None, [], 'ci',
+ '-m', 'log msg', '--quiet', path)
+ os.close(fd)
+ os.remove(tmp_f)
+
+def change_external_expect_error(path, new_val, expected_err):
+ """Try to change the value of the externals property on PATH to NEW_VAL,
+ but expect to get an error message that matches EXPECTED_ERR."""
+ (fd, tmp_f) = tempfile.mkstemp(dir=svntest.main.temp_dir)
+ svntest.main.file_append(tmp_f, new_val)
+ svntest.actions.run_and_verify_svn(None, None, expected_err, 'pset',
+ '-F', tmp_f, 'svn:externals', path)
os.close(fd)
os.remove(tmp_f)
@@ -303,9 +296,7 @@ def checkout_with_externals(sbox):
"This is the file 'omega'.\n"),
(os.path.join(wc_dir, "A", "B", "gamma"),
"This is the file 'gamma'.\n")):
- fp = open(path, 'r')
- lines = fp.readlines()
- if not ((len(lines) == 1) and (lines[0] == contents)):
+ if open(path).read() != contents:
raise svntest.Failure("Unexpected contents for rev 1 of " + path)
#----------------------------------------------------------------------
@@ -566,14 +557,11 @@ def update_receive_change_under_external
svntest.actions.run_and_verify_svn(None, None, [], 'up', wc_dir)
external_gamma_path = os.path.join(wc_dir, 'A', 'D', 'exdir_A', 'D', 'gamma')
- fp = open(external_gamma_path, 'r')
- lines = fp.readlines()
- if not ((len(lines) == 2)
- and (lines[0] == "This is the file 'gamma'.\n")
- and (lines[1] == "New text in other gamma.\n")):
+ contents = open(external_gamma_path).read()
+ if contents != ("This is the file 'gamma'.\n"
+ "New text in other gamma.\n"):
raise svntest.Failure("Unexpected contents for externally modified " +
external_gamma_path)
- fp.close()
# Commit more modifications
other_rho_path = os.path.join(other_wc_dir, 'A', 'D', 'G', 'rho')
@@ -594,14 +582,11 @@ def update_receive_change_under_external
'up', os.path.join(wc_dir, "A", "C"))
external_rho_path = os.path.join(wc_dir, 'A', 'C', 'exdir_G', 'rho')
- fp = open(external_rho_path, 'r')
- lines = fp.readlines()
- if not ((len(lines) == 2)
- and (lines[0] == "This is the file 'rho'.\n")
- and (lines[1] == "New text in other rho.\n")):
+ contents = open(external_rho_path).read()
+ if contents != ("This is the file 'rho'.\n"
+ "New text in other rho.\n"):
raise svntest.Failure("Unexpected contents for externally modified " +
external_rho_path)
- fp.close()
#----------------------------------------------------------------------
@@ -627,13 +612,7 @@ def modify_and_update_receive_new_extern
"exdir_Z " + external_url_for["A/D/exdir_A/H"] + \
"\n"
- (fd, tmp_f) = tempfile.mkstemp()
- svntest.main.file_append(tmp_f, externals_desc)
- svntest.actions.run_and_verify_svn(None, None, [],
- 'pset', '-F', tmp_f,
- 'svn:externals', B_path)
- os.close(fd)
- os.remove(tmp_f)
+ change_external(B_path, externals_desc, commit=False)
# Now cd into A/B and try updating
was_cwd = os.getcwd()
@@ -664,15 +643,9 @@ def disallow_dot_or_dotdot_directory_ref
# Try to set illegal externals in the original WC.
def set_externals_for_path_expect_error(path, val):
- (fd, tmp_f) = tempfile.mkstemp()
- svntest.main.file_append(tmp_f, val)
expected_err = ".*Invalid svn:externals property on '.*': target " + \
"'.*' is an absolute path or involves '..'.*"
- svntest.actions.run_and_verify_svn(None, None, expected_err,
- 'pset', '-F', tmp_f,
- 'svn:externals', path)
- os.close(fd)
- os.remove(tmp_f)
+ change_external_expect_error(path, val, expected_err)
B_path = os.path.join(wc_dir, 'A', 'B')
G_path = os.path.join(wc_dir, 'A', 'D', 'G')
@@ -745,18 +718,15 @@ def export_with_externals(sbox):
# Pick some files, make sure their contents are as expected.
exdir_G_pi_path = os.path.join(wc_dir, "A", "C", "exdir_G", "pi")
- fp = open(exdir_G_pi_path, 'r')
- lines = fp.readlines()
- if not ((len(lines) == 2) \
- and (lines[0] == "This is the file 'pi'.\n") \
- and (lines[1] == "Added to pi in revision 3.\n")):
+ contents = open(exdir_G_pi_path).read()
+ if contents != ("This is the file 'pi'.\n"
+ "Added to pi in revision 3.\n"):
raise svntest.Failure("Unexpected contents for rev 1 of " +
exdir_G_pi_path)
exdir_H_omega_path = os.path.join(wc_dir, "A", "C", "exdir_H", "omega")
- fp = open(exdir_H_omega_path, 'r')
- lines = fp.readlines()
- if not ((len(lines) == 1) and (lines[0] == "This is the file 'omega'.\n")):
+ contents = open(exdir_H_omega_path).read()
+ if contents != "This is the file 'omega'.\n":
raise svntest.Failure("Unexpected contents for rev 1 of " +
exdir_H_omega_path)
@@ -842,13 +812,10 @@ def external_with_peg_and_op_revision(sb
'up', wc_dir)
external_chi_path = os.path.join(wc_dir, 'A', 'D', 'exdir_A', 'H', 'chi')
- fp = open(external_chi_path, 'r')
- lines = fp.readlines()
- if not ((len(lines) == 1)
- and (lines[0] == "This is the file 'chi'.\n")):
+ contents = open(external_chi_path).read()
+ if contents != "This is the file 'chi'.\n":
raise svntest.Failure("Unexpected contents for externally modified " +
external_chi_path)
- fp.close()
#----------------------------------------------------------------------
@@ -882,9 +849,8 @@ def new_style_externals(sbox):
for dir_name in ["exdir_H", "exdir_I"]:
exdir_X_omega_path = os.path.join(wc_dir, "A", "C", dir_name, "omega")
- fp = open(exdir_X_omega_path, 'r')
- lines = fp.readlines()
- if not ((len(lines) == 1) and (lines[0] == "This is the file 'omega'.\n")):
+ contents = open(exdir_X_omega_path).read()
+ if contents != "This is the file 'omega'.\n":
raise svntest.Failure("Unexpected contents for rev 1 of " +
exdir_X_omega_path)
@@ -917,36 +883,16 @@ def disallow_propset_invalid_formatted_e
'arg1 -r1',
'arg1 -r 1',
]:
- (fd, tmp_f) = tempfile.mkstemp()
- svntest.main.file_append(tmp_f, ext)
- svntest.actions.run_and_verify_svn("No error for externals '%s'" % ext,
- None,
- '.*Error parsing svn:externals.*',
- 'propset',
- '-F',
- tmp_f,
- 'svn:externals',
- A_path)
- os.close(fd)
- os.remove(tmp_f)
+ change_external_expect_error(A_path, ext,
+ '.*Error parsing svn:externals.*')
for ext in [ '-r abc arg1 arg2',
'-rabc arg1 arg2',
'arg1 -r abc arg2',
'arg1 -rabc arg2',
]:
- (fd, tmp_f) = tempfile.mkstemp()
- svntest.main.file_append(tmp_f, ext)
- svntest.actions.run_and_verify_svn("No error for externals '%s'" % ext,
- None,
- '.*Error parsing svn:externals.*',
- 'propset',
- '-F',
- tmp_f,
- 'svn:externals',
- A_path)
- os.close(fd)
- os.remove(tmp_f)
+ change_external_expect_error(A_path, ext,
+ '.*Error parsing svn:externals.*')
for ext in [ 'http://example.com/ http://example.com/',
'-r1 http://example.com/ http://example.com/',
@@ -954,38 +900,18 @@ def disallow_propset_invalid_formatted_e
'http://example.com/ -r1 http://example.com/',
'http://example.com/ -r 1 http://example.com/',
]:
- (fd, tmp_f) = tempfile.mkstemp()
- svntest.main.file_append(tmp_f, ext)
- svntest.actions.run_and_verify_svn("No error for externals '%s'" % ext,
- None,
- '.*cannot use two absolute URLs.*',
- 'propset',
- '-F',
- tmp_f,
- 'svn:externals',
- A_path)
- os.close(fd)
- os.remove(tmp_f)
+ change_external_expect_error(A_path, ext,
+ '.*cannot use two absolute URLs.*')
for ext in [ 'http://example.com/ -r1 foo',
'http://example.com/ -r 1 foo',
'-r1 foo http://example.com/',
'-r 1 foo http://example.com/'
]:
- (fd, tmp_f) = tempfile.mkstemp()
- svntest.main.file_append(tmp_f, ext)
- svntest.actions.run_and_verify_svn("No error for externals '%s'" % ext,
- None,
- '.*cannot use a URL \'.*\' as the ' \
- 'target directory for an external ' \
- 'definition.*',
- 'propset',
- '-F',
- tmp_f,
- 'svn:externals',
- A_path)
- os.close(fd)
- os.remove(tmp_f)
+ change_external_expect_error(A_path, ext,
+ '.*cannot use a URL \'.*\' as the ' \
+ 'target directory for an external ' \
+ 'definition.*')
#----------------------------------------------------------------------
@@ -1114,14 +1040,10 @@ def can_place_file_external_into_dir_ext
repo_url, wc_dir)
beta1_path = os.path.join(wc_dir, 'A', 'B', 'E', 'beta')
- f = open(beta1_path)
- beta1_contents = f.read()
- f.close()
+ beta1_contents = open(beta1_path).read()
beta2_path = os.path.join(wc_dir, 'A', 'D-copy', 'G', 'beta')
- f = open(beta2_path)
- beta2_contents = f.read()
- f.close()
+ beta2_contents = open(beta2_path).read()
if beta1_contents != beta2_contents:
raise svntest.Failure("Contents of '%s' and '%s' do not match" %
@@ -1177,8 +1099,7 @@ def binary_file_externals(sbox):
wc_dir = sbox.wc_dir
# Add a binary file A/theta, write PNG file data into it.
- theta_contents = svntest.main.file_read(
- os.path.join(sys.path[0], "theta.bin"), 'rb')
+ theta_contents = open(os.path.join(sys.path[0], "theta.bin"), 'rb').read()
theta_path = os.path.join(wc_dir, 'A', 'theta')
svntest.main.file_write(theta_path, theta_contents, 'wb')
@@ -1334,9 +1255,6 @@ def switch_relative_external(sbox):
ext_path = os.path.join(D_path, 'ext')
externals_prop = "../B ext\n"
change_external(D_path, externals_prop)
- svntest.actions.run_and_verify_svn(None, None, [],
- 'ci', '-m', 'log msg',
- '--quiet', wc_dir)
# Update our working copy, and create a "branch" (A => A_copy)
svntest.actions.run_and_verify_svn(None, None, [], 'up',
@@ -1425,11 +1343,7 @@ def relegate_external(sbox):
# point external to the other repository
externals_desc = other_repo_url + '/A/B/E external\n'
- (fd, tmp_f) = tempfile.mkstemp()
- svntest.main.file_append(tmp_f, externals_desc)
- svntest.actions.run_and_verify_svn(None, None, [],
- 'pset', '-F', tmp_f,
- 'svn:externals', A_path)
+ change_external(A_path, externals_desc, commit=False)
# Update "relegates", i.e. throws-away and recreates, the external
expected_output = svntest.wc.State(wc_dir, {
Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/getopt_tests_data/svn_help_log_switch_stdout Tue Aug 10 20:55:56 2010
@@ -53,6 +53,27 @@ Valid options:
--with-all-revprops : retrieve all revision properties
--with-no-revprops : retrieve no revision properties
--with-revprop ARG : retrieve revision property ARG
+ --show-diff : produce diff output
+ [alias: --diff]
+ --diff-cmd ARG : use ARG as diff command
+ --internal-diff : override diff-cmd specified in config file
+ [alias: --idiff]
+ -x [--extensions] ARG : Default: '-u'. When Subversion is invoking an
+ external diff program, ARG is simply passed along
+ to the program. But when Subversion is using its
+ default internal diff implementation, or when
+ Subversion is displaying blame annotations, ARG
+ could be any of the following:
+ -u (--unified):
+ Output 3 lines of unified context.
+ -b (--ignore-space-change):
+ Ignore changes in the amount of white space.
+ -w (--ignore-all-space):
+ Ignore all white space.
+ --ignore-eol-style:
+ Ignore changes in EOL style.
+ -p (--show-c-function):
+ Show C function name in diff output.
Global options:
--username ARG : specify a username ARG
Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/lock_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/lock_tests.py?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/lock_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/lock_tests.py Tue Aug 10 20:55:56 2010
@@ -1472,6 +1472,43 @@ def lock_path_not_in_head(sbox):
svntest.actions.run_and_verify_svn2(None, None, expected_lock_fail_err_re,
0, 'lock', lambda_path)
+def verify_path_escaping(sbox):
+ "verify escaping of lock paths"
+
+ sbox.build()
+ wc_dir = sbox.wc_dir
+
+ # Add test paths using two characters that need escaping in a url, but
+ # are within the normal ascii range
+ file1 = os.path.join(wc_dir, 'file #1')
+ file2 = os.path.join(wc_dir, 'file #2')
+ file3 = os.path.join(wc_dir, 'file #3')
+
+ svntest.main.file_write(file1, 'File 1')
+ svntest.main.file_write(file2, 'File 2')
+ svntest.main.file_write(file3, 'File 3')
+
+ svntest.main.run_svn(None, 'add', file1, file2, file3)
+
+ svntest.main.run_svn(None, 'ci', '-m', 'commit', wc_dir)
+
+ svntest.main.run_svn(None, 'lock', '-m', 'lock 1', file1)
+ svntest.main.run_svn(None, 'lock', '-m', 'lock 2', sbox.repo_url + '/file%20%232')
+ svntest.main.run_svn(None, 'lock', '-m', 'lock 3', file3)
+ svntest.main.run_svn(None, 'unlock', sbox.repo_url + '/file%20%233')
+
+ expected_status = svntest.actions.get_virginal_state(wc_dir, 1)
+ expected_status.add(
+ {
+ 'file #1' : Item(status=' ', writelocked='K', wc_rev='2'),
+ 'file #2' : Item(status=' ', writelocked='O', wc_rev='2'),
+ 'file #3' : Item(status=' ', writelocked='B', wc_rev='2')
+ });
+
+ # Make sure the file locking is reported correctly
+ svntest.actions.run_and_verify_status(wc_dir, expected_status)
+
+
########################################################################
# Run the tests
@@ -1515,6 +1552,7 @@ test_list = [ None,
lock_funky_comment_chars,
lock_twice_in_one_wc,
lock_path_not_in_head,
+ verify_path_escaping,
]
if __name__ == '__main__':
Modified: subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_authz_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_authz_tests.py?rev=984206&r1=984205&r2=984206&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_authz_tests.py (original)
+++ subversion/branches/ignore-mergeinfo/subversion/tests/cmdline/merge_authz_tests.py Tue Aug 10 20:55:56 2010
@@ -224,7 +224,6 @@ def mergeinfo_and_skipped_paths(sbox):
# parent of a missing child and the sibling of missing child, but the former
# always takes precedence in terms of getting *non*-inheritable mergeinfo.
expected_output = wc.State(A_COPY_2_path, {
- 'D/G' : Item(status=' ', treeconflict='C'),
'D/H/omega' : Item(status='U '),
})
expected_mergeinfo_output = wc.State(A_COPY_2_path, {
@@ -238,7 +237,6 @@ def mergeinfo_and_skipped_paths(sbox):
})
expected_status = wc.State(A_COPY_2_path, {
'' : Item(status=' M', wc_rev=8),
- 'D/G' : Item(status='! ', treeconflict='C'),
'D/H/chi' : Item(status=' ', wc_rev=8),
'D/H/omega' : Item(status='MM', wc_rev=8),
'D/H' : Item(status=' M', wc_rev=8),
@@ -272,6 +270,7 @@ def mergeinfo_and_skipped_paths(sbox):
})
expected_skip = wc.State(A_COPY_2_path, {
'B/E' : Item(),
+ 'D/G' : Item(),
'D/H/psi' : Item(),
})
saved_cwd = os.getcwd()
@@ -577,6 +576,130 @@ def merge_fails_if_subtree_is_deleted_on
[], 'merge', '-r1:6', '--force',
A_url, Acopy_path)
+def reintegrate_fails_if_no_root_access(sbox):
+ "reintegrate fails if no root access"
+
+ # If a user is authorized to a reintegrate source and target, they
+ # should be able to reintegrate, regardless of what authorization
+ # they have to parents of the source and target.
+ #
+ # See http://subversion.tigris.org/issues/show_bug.cgi?id=3242#desc78
+
+ # Some paths we'll care about
+ wc_dir = sbox.wc_dir
+ A_path = os.path.join(wc_dir, 'A')
+ A_COPY_path = os.path.join(wc_dir, 'A_COPY')
+ beta_COPY_path = os.path.join(wc_dir, 'A_COPY', 'B', 'E', 'beta')
+ rho_COPY_path = os.path.join(wc_dir, 'A_COPY', 'D', 'G', 'rho')
+ omega_COPY_path = os.path.join(wc_dir, 'A_COPY', 'D', 'H', 'omega')
+ psi_COPY_path = os.path.join(wc_dir, 'A_COPY', 'D', 'H', 'psi')
+
+ # Copy A@1 to A_COPY in r2, and then make some changes to A in r3-6.
+ sbox.build()
+ wc_dir = sbox.wc_dir
+ expected_disk, expected_status = set_up_branch(sbox)
+
+ # Make a change on the branch, to A_COPY/mu, commit in r7.
+ svntest.main.file_write(os.path.join(wc_dir, "A_COPY", "mu"),
+ "Changed on the branch.")
+ expected_output = wc.State(wc_dir, {'A_COPY/mu' : Item(verb='Sending')})
+ expected_status.tweak('A_COPY/mu', wc_rev=7)
+ svntest.actions.run_and_verify_commit(wc_dir, expected_output,
+ expected_status, None, wc_dir)
+ expected_disk.tweak('A_COPY/mu', contents='Changed on the branch.')
+
+ # Update the WC.
+ svntest.main.run_svn(None, 'up', wc_dir)
+
+
+ # Sync A_COPY with A.
+ expected_output = expected_merge_output([[2,7]],
+ ['U ' + beta_COPY_path + '\n',
+ 'U ' + rho_COPY_path + '\n',
+ 'U ' + omega_COPY_path + '\n',
+ 'U ' + psi_COPY_path + '\n',
+ # Mergeinfo notification
+ ' U ' + A_COPY_path + '\n'])
+ svntest.actions.run_and_verify_svn(None, expected_output, [], 'merge',
+ sbox.repo_url + '/A', A_COPY_path)
+ svntest.main.run_svn(None, 'ci', '-m', 'synch A_COPY with A', wc_dir)
+
+ # Update so we are ready for reintegrate.
+ svntest.main.run_svn(None, 'up', wc_dir)
+
+ # Change authz file so everybody has access to everything but the root.
+ if is_ra_type_svn() or is_ra_type_dav():
+ write_restrictive_svnserve_conf(sbox.repo_dir)
+ write_authz_file(sbox, {"/" : "* =",
+ "/A" : "* = rw",
+ "/A_COPY" : "* = rw",
+ "/iota" : "* = rw"})
+
+ # Now reintegrate A_COPY back to A. The lack of access to the root of the
+ # repository shouldn't be a problem.
+ expected_output = wc.State(A_path, {
+ 'mu' : Item(status='U '),
+ })
+ expected_mergeinfo_output = wc.State(A_path, {
+ '' : Item(status=' G'),
+ })
+ expected_elision_output = wc.State(A_path, {
+ })
+ expected_disk = wc.State('', {
+ '' : Item(props={SVN_PROP_MERGEINFO : '/A_COPY:2-8'}),
+ 'B' : Item(),
+ 'B/lambda' : Item("This is the file 'lambda'.\n"),
+ 'B/E' : Item(),
+ 'B/E/alpha' : Item("This is the file 'alpha'.\n"),
+ 'B/E/beta' : Item("New content"),
+ 'B/F' : Item(),
+ 'mu' : Item("Changed on the branch."),
+ 'C' : Item(),
+ 'D' : Item(),
+ 'D/gamma' : Item("This is the file 'gamma'.\n"),
+ 'D/G' : Item(),
+ 'D/G/pi' : Item("This is the file 'pi'.\n"),
+ 'D/G/rho' : Item("New content"),
+ 'D/G/tau' : Item("This is the file 'tau'.\n"),
+ 'D/H' : Item(),
+ 'D/H/chi' : Item("This is the file 'chi'.\n"),
+ 'D/H/omega' : Item("New content"),
+ 'D/H/psi' : Item("New content"),
+ })
+ expected_status = wc.State(A_path, {
+ "B" : Item(status=' ', wc_rev=8),
+ "B/lambda" : Item(status=' ', wc_rev=8),
+ "B/E" : Item(status=' ', wc_rev=8),
+ "B/E/alpha" : Item(status=' ', wc_rev=8),
+ "B/E/beta" : Item(status=' ', wc_rev=8),
+ "B/F" : Item(status=' ', wc_rev=8),
+ "mu" : Item(status='M ', wc_rev=8),
+ "C" : Item(status=' ', wc_rev=8),
+ "D" : Item(status=' ', wc_rev=8),
+ "D/gamma" : Item(status=' ', wc_rev=8),
+ "D/G" : Item(status=' ', wc_rev=8),
+ "D/G/pi" : Item(status=' ', wc_rev=8),
+ "D/G/rho" : Item(status=' ', wc_rev=8),
+ "D/G/tau" : Item(status=' ', wc_rev=8),
+ "D/H" : Item(status=' ', wc_rev=8),
+ "D/H/chi" : Item(status=' ', wc_rev=8),
+ "D/H/omega" : Item(status=' ', wc_rev=8),
+ "D/H/psi" : Item(status=' ', wc_rev=8),
+ "" : Item(status=' M', wc_rev=8),
+ })
+ expected_skip = wc.State(A_path, {})
+ svntest.actions.run_and_verify_merge(A_path, None, None,
+ sbox.repo_url + '/A_COPY', None,
+ expected_output,
+ expected_mergeinfo_output,
+ expected_elision_output,
+ expected_disk,
+ expected_status,
+ expected_skip,
+ None, None, None, None,
+ None, True, True,
+ '--reintegrate')
+
########################################################################
# Run the tests
@@ -588,6 +711,9 @@ test_list = [ None,
svntest.main.server_has_mergeinfo),
SkipUnless(merge_fails_if_subtree_is_deleted_on_src,
server_has_mergeinfo),
+ SkipUnless(Skip(reintegrate_fails_if_no_root_access,
+ svntest.main.is_ra_type_file),
+ svntest.main.server_has_mergeinfo),
]
if __name__ == '__main__':