Modified: subversion/branches/svn-auth-x509/subversion/svn/conflict-callbacks.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/svn/conflict-callbacks.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/svn/conflict-callbacks.c (original) +++ subversion/branches/svn-auth-x509/subversion/svn/conflict-callbacks.c Fri Jan 16 14:01:35 2015 @@ -695,6 +695,10 @@ handle_text_conflict(svn_wc_conflict_res b->path_prefix, desc->local_abspath, scratch_pool))); + /* ### TODO This whole feature availability check is grossly outdated. + DIFF_ALLOWED needs either to be redefined or to go away. + */ + /* Diffing can happen between base and merged, to show conflict markers to the user (this is the typical 3-way merge scenario), or if no base is available, we can show a diff @@ -714,9 +718,15 @@ handle_text_conflict(svn_wc_conflict_res *next_option++ = "p"; if (diff_allowed) { - *next_option++ = "df"; + /* We need one more path for this feature. */ + if (desc->my_abspath) + *next_option++ = "df"; + *next_option++ = "e"; - *next_option++ = "m"; + + /* We need one more path for this feature. */ + if (desc->my_abspath) + *next_option++ = "m"; if (knows_something) *next_option++ = "r"; @@ -781,7 +791,8 @@ handle_text_conflict(svn_wc_conflict_res } else if (strcmp(opt->code, "df") == 0) { - if (! diff_allowed) + /* Re-check preconditions. */ + if (! diff_allowed || desc->my_abspath) { SVN_ERR(svn_cmdline_fprintf(stderr, iterpool, _("Invalid option; there's no " @@ -805,6 +816,15 @@ handle_text_conflict(svn_wc_conflict_res { svn_error_t *err; + /* Re-check preconditions. */ + if (! desc->my_abspath) + { + SVN_ERR(svn_cmdline_fprintf(stderr, iterpool, + _("Invalid option; there's no " + "base path to merge.\n\n"))); + continue; + } + err = svn_cl__merge_file_externally(desc->base_abspath, desc->their_abspath, desc->my_abspath,
Modified: subversion/branches/svn-auth-x509/subversion/svndumpfilter/svndumpfilter.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/svndumpfilter/svndumpfilter.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/svndumpfilter/svndumpfilter.c (original) +++ subversion/branches/svn-auth-x509/subversion/svndumpfilter/svndumpfilter.c Fri Jan 16 14:01:35 2015 @@ -791,10 +791,16 @@ adjust_mergeinfo(svn_string_t **final_va 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. + want filtered. If the oldest rev is r0 then there is nothing to filter. */ + + /* ### This seems to cater only for use cases where the revisions being + processed are not following on from revisions that will already + exist in the destination repository. If the revisions being + processed do follow on, then we might want to keep the mergeinfo + that refers to those older revisions. */ + if (rb->pb->skip_missing_merge_sources && rb->pb->oldest_original_rev > 0) SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges( &mergeinfo, mergeinfo, @@ -852,7 +858,7 @@ adjust_mergeinfo(svn_string_t **final_va svn_hash_sets(final_mergeinfo, merge_source, rangelist); } - SVN_ERR(svn_mergeinfo_sort(final_mergeinfo, subpool)); + SVN_ERR(svn_mergeinfo__canonicalize_ranges(final_mergeinfo, subpool)); SVN_ERR(svn_mergeinfo_to_string(final_val, final_mergeinfo, pool)); svn_pool_destroy(subpool); Modified: subversion/branches/svn-auth-x509/subversion/svnfsfs/stats-cmd.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/svnfsfs/stats-cmd.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/svnfsfs/stats-cmd.c (original) +++ subversion/branches/svn-auth-x509/subversion/svnfsfs/stats-cmd.c Fri Jan 16 14:01:35 2015 @@ -31,6 +31,35 @@ #include "svn_private_config.h" #include "svnfsfs.h" +/* Return the string, allocated in RESULT_POOL, describing the value 2**I. + */ +static const char * +print_two_power(int i, + apr_pool_t *result_pool) +{ + /* These are the SI prefixes for base-1000, the binary ones with base-1024 + are too clumsy and require appending B for "byte" to be intelligible, + e.g. "MiB". + + Therefore, we ignore the official standard and revert to the traditional + contextual use were the base-1000 prefixes are understood as base-1024 + when it came to data sizes. + */ + const char *si_prefixes = " kMGTPEZY"; + + int number = (1 << (i % 10)); + int thousands = i / 10; + + char si_prefix = ((thousands >= 0) && (thousands < strlen(si_prefixes))) + ? si_prefixes[thousands] + : '?'; + + if (si_prefix == ' ') + return apr_psprintf(result_pool, "%d", number); + + return apr_psprintf(result_pool, "%d%c", number, si_prefix); +} + /* Print statistics for the given group of representations to console. * Use POOL for allocations. */ @@ -88,8 +117,8 @@ print_histogram(svn_fs_fs__histogram_t * /* display histogram lines */ for (i = last; i >= first; --i) - printf(_(" [2^%2d, 2^%2d) %15s (%2d%%) bytes in %12s (%2d%%) items\n"), - i-1, i, + printf(_(" %4s .. < %-4s %19s (%2d%%) bytes in %12s (%2d%%) items\n"), + print_two_power(i-1, pool), print_two_power(i, pool), svn__ui64toa_sep(histogram->lines[i].sum, ',', pool), (int)(histogram->lines[i].sum * 100 / histogram->total.sum), svn__ui64toa_sep(histogram->lines[i].count, ',', pool), Modified: subversion/branches/svn-auth-x509/subversion/svnrdump/dump_editor.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/svnrdump/dump_editor.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/svnrdump/dump_editor.c (original) +++ subversion/branches/svn-auth-x509/subversion/svnrdump/dump_editor.c Fri Jan 16 14:01:35 2015 @@ -58,9 +58,6 @@ struct dir_baton /* is this directory a new addition to this revision? */ svn_boolean_t added; - /* has this directory been written to the output stream? */ - svn_boolean_t written_out; - /* the path to this directory */ const char *repos_relpath; /* a relpath */ @@ -179,38 +176,30 @@ make_dir_baton(const char *path, struct dump_edit_baton *eb = edit_baton; struct dir_baton *new_db = apr_pcalloc(pool, sizeof(*new_db)); const char *repos_relpath; - apr_pool_t *dir_pool; /* Construct the full path of this node. */ if (pb) - { - dir_pool = svn_pool_create(pb->pool); - repos_relpath = svn_relpath_canonicalize(path, dir_pool); - } + repos_relpath = svn_relpath_canonicalize(path, pool); else - { - dir_pool = svn_pool_create(eb->pool); - repos_relpath = ""; - } + repos_relpath = ""; /* Strip leading slash from copyfrom_path so that the path is canonical and svn_relpath_join can be used */ if (copyfrom_path) - copyfrom_path = svn_relpath_canonicalize(copyfrom_path, dir_pool); + copyfrom_path = svn_relpath_canonicalize(copyfrom_path, pool); new_db->eb = eb; new_db->parent_dir_baton = pb; - new_db->pool = dir_pool; + new_db->pool = pool; new_db->repos_relpath = repos_relpath; new_db->copyfrom_path = copyfrom_path - ? svn_relpath_canonicalize(copyfrom_path, dir_pool) + ? svn_relpath_canonicalize(copyfrom_path, pool) : NULL; new_db->copyfrom_rev = copyfrom_rev; new_db->added = added; - new_db->written_out = FALSE; - new_db->props = apr_hash_make(dir_pool); - new_db->deleted_props = apr_hash_make(dir_pool); - new_db->deleted_entries = apr_hash_make(dir_pool); + new_db->props = apr_hash_make(pool); + new_db->deleted_props = apr_hash_make(pool); + new_db->deleted_entries = apr_hash_make(pool); return new_db; } @@ -224,15 +213,14 @@ make_file_baton(const char *path, struct dir_baton *pb, apr_pool_t *pool) { - apr_pool_t *file_pool = svn_pool_create(pb->pool); - struct file_baton *new_fb = apr_pcalloc(file_pool, sizeof(*new_fb)); + struct file_baton *new_fb = apr_pcalloc(pool, sizeof(*new_fb)); new_fb->eb = pb->eb; new_fb->parent_dir_baton = pb; - new_fb->pool = file_pool; - new_fb->repos_relpath = svn_relpath_canonicalize(path, file_pool); - new_fb->props = apr_hash_make(file_pool); - new_fb->deleted_props = apr_hash_make(file_pool); + new_fb->pool = pool; + new_fb->repos_relpath = svn_relpath_canonicalize(path, pool); + new_fb->props = apr_hash_make(pool); + new_fb->deleted_props = apr_hash_make(pool); new_fb->is_copy = FALSE; new_fb->copyfrom_path = NULL; new_fb->copyfrom_rev = SVN_INVALID_REVNUM; @@ -351,8 +339,7 @@ do_dump_newlines(struct dump_edit_baton /* * Write out a node record for PATH of type KIND under EB->FS_ROOT. * ACTION describes what is happening to the node (see enum - * svn_node_action). Write record to writable EB->STREAM, using - * EB->BUFFER to write in chunks. + * svn_node_action). Write record to writable EB->STREAM. * * If the node was itself copied, IS_COPY is TRUE and the * path/revision of the copy source are in COPYFROM_PATH/COPYFROM_REV. @@ -636,7 +623,6 @@ open_root(void *edit_baton, /* Remember that we've started but not yet finished handling this directory. */ - new_db->written_out = TRUE; eb->pending_baton = new_db; eb->pending_kind = svn_node_dir; } @@ -715,7 +701,6 @@ add_directory(const char *path, /* Remember that we've started, but not yet finished handling this directory. */ - new_db->written_out = TRUE; pb->eb->pending_baton = new_db; pb->eb->pending_kind = svn_node_dir; @@ -801,7 +786,7 @@ close_directory(void *dir_baton, } /* ### should be unnecessary */ - svn_pool_destroy(db->pool); + apr_hash_clear(db->deleted_entries); return SVN_NO_ERROR; } @@ -1074,8 +1059,6 @@ close_file(void *file_baton, dump` */ SVN_ERR(svn_stream_puts(eb->stream, "\n\n")); - svn_pool_clear(fb->pool); - return SVN_NO_ERROR; } Modified: subversion/branches/svn-auth-x509/subversion/svnrdump/load_editor.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/svnrdump/load_editor.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/svnrdump/load_editor.c (original) +++ subversion/branches/svn-auth-x509/subversion/svnrdump/load_editor.c Fri Jan 16 14:01:35 2015 @@ -320,16 +320,7 @@ renumber_mergeinfo_revs(svn_string_t **f subpool, subpool)); } - SVN_ERR(svn_mergeinfo_sort(final_mergeinfo, subpool)); - - /* Mergeinfo revision sources for r0 and r1 are invalid; you can't merge r0 - or r1. However, svndumpfilter can be abused to produce r1 merge source - revs. So if we encounter any, then strip them out, no need to put them - into the load target. */ - SVN_ERR(svn_mergeinfo__filter_mergeinfo_by_ranges(&final_mergeinfo, - final_mergeinfo, - 1, 0, FALSE, - subpool, subpool)); + SVN_ERR(svn_mergeinfo__canonicalize_ranges(final_mergeinfo, subpool)); SVN_ERR(svn_mergeinfo_to_string(final_val, final_mergeinfo, pool)); svn_pool_destroy(subpool); @@ -887,6 +878,56 @@ set_revision_property(void *baton, return SVN_NO_ERROR; } +/* Adjust mergeinfo: + * - normalize line endings (if all CRLF, change to LF; but error if mixed); + * - adjust revision numbers (see renumber_mergeinfo_revs()); + * - adjust paths (see prefix_mergeinfo_paths()). + */ +static svn_error_t * +adjust_mergeinfo_property(struct revision_baton *rb, + svn_string_t **new_value_p, + const svn_string_t *old_value, + apr_pool_t *result_pool) +{ + struct parse_baton *pb = rb->pb; + svn_string_t prop_val = *old_value; + + /* Tolerate mergeinfo with "\r\n" line endings because some + dumpstream sources might contain as much. If so normalize + the line endings to '\n' and notify that we have made this + correction. */ + if (strstr(prop_val.data, "\r")) + { + const char *prop_eol_normalized; + + SVN_ERR(svn_subst_translate_cstring2(prop_val.data, + &prop_eol_normalized, + "\n", /* translate to LF */ + FALSE, /* no repair */ + NULL, /* no keywords */ + FALSE, /* no expansion */ + result_pool)); + prop_val.data = prop_eol_normalized; + prop_val.len = strlen(prop_eol_normalized); + + /* ### TODO: notify? */ + } + + /* Renumber mergeinfo as appropriate. */ + SVN_ERR(renumber_mergeinfo_revs(new_value_p, &prop_val, rb, + result_pool)); + + if (pb->parent_dir) + { + /* Prefix the merge source paths with PB->parent_dir. */ + /* ASSUMPTION: All source paths are included in the dump stream. */ + SVN_ERR(prefix_mergeinfo_paths(new_value_p, *new_value_p, + pb->parent_dir, result_pool)); + } + + return SVN_NO_ERROR; +} + static svn_error_t * set_node_property(void *baton, const char *name, @@ -898,46 +939,10 @@ set_node_property(void *baton, if (value && strcmp(name, SVN_PROP_MERGEINFO) == 0) { - svn_string_t *renumbered_mergeinfo; - svn_string_t prop_val; - - /* Tolerate mergeinfo with "\r\n" line endings because some - dumpstream sources might contain as much. If so normalize - the line endings to '\n' and make a notification to - PARSE_BATON->FEEDBACK_STREAM that we have made this - correction. */ - if (strstr(value->data, "\r")) - { - const char *prop_eol_normalized; + svn_string_t *new_value; - SVN_ERR(svn_subst_translate_cstring2(value->data, - &prop_eol_normalized, - "\n", /* translate to LF */ - FALSE, /* no repair */ - NULL, /* no keywords */ - FALSE, /* no expansion */ - pool)); - prop_val.data = prop_eol_normalized; - prop_val.len = strlen(prop_eol_normalized); - value = &prop_val; - - /* ### TODO: notify? */ - } - - /* Renumber mergeinfo as appropriate. */ - SVN_ERR(renumber_mergeinfo_revs(&renumbered_mergeinfo, value, - nb->rb, pool)); - value = renumbered_mergeinfo; - - if (nb->rb->pb->parent_dir) - { - /* Prefix the merge source paths with PB->parent_dir. */ - /* ASSUMPTION: All source paths are included in the dump stream. */ - svn_string_t *mergeinfo_val; - SVN_ERR(prefix_mergeinfo_paths(&mergeinfo_val, value, - nb->rb->pb->parent_dir, pool)); - value = mergeinfo_val; - } + SVN_ERR(adjust_mergeinfo_property(nb->rb, &new_value, value, pool)); + value = new_value; } SVN_ERR(svn_rdump__normalize_prop(name, &value, pool)); Modified: subversion/branches/svn-auth-x509/subversion/svnrdump/svnrdump.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/svnrdump/svnrdump.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/svnrdump/svnrdump.c (original) +++ subversion/branches/svn-auth-x509/subversion/svnrdump/svnrdump.c Fri Jan 16 14:01:35 2015 @@ -230,13 +230,10 @@ replay_revstart(svn_revnum_t revision, struct replay_baton *rb = replay_baton; apr_hash_t *normal_props; svn_stringbuf_t *propstring; - svn_stream_t *stdout_stream; svn_stream_t *revprop_stream; - SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool)); - /* Revision-number: 19 */ - SVN_ERR(svn_stream_printf(stdout_stream, pool, + SVN_ERR(svn_stream_printf(rb->stdout_stream, pool, SVN_REPOS_DUMPFILE_REVISION_NUMBER ": %ld\n", revision)); SVN_ERR(svn_rdump__normalize_props(&normal_props, rev_props, pool)); @@ -246,21 +243,20 @@ replay_revstart(svn_revnum_t revision, SVN_ERR(svn_stream_close(revprop_stream)); /* Prop-content-length: 13 */ - SVN_ERR(svn_stream_printf(stdout_stream, pool, + SVN_ERR(svn_stream_printf(rb->stdout_stream, pool, SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH ": %" APR_SIZE_T_FMT "\n", propstring->len)); /* Content-length: 29 */ - SVN_ERR(svn_stream_printf(stdout_stream, pool, + SVN_ERR(svn_stream_printf(rb->stdout_stream, pool, SVN_REPOS_DUMPFILE_CONTENT_LENGTH ": %" APR_SIZE_T_FMT "\n\n", propstring->len)); /* Property data. */ - SVN_ERR(svn_stream_write(stdout_stream, propstring->data, + SVN_ERR(svn_stream_write(rb->stdout_stream, propstring->data, &(propstring->len))); - SVN_ERR(svn_stream_puts(stdout_stream, "\n")); - SVN_ERR(svn_stream_close(stdout_stream)); + SVN_ERR(svn_stream_puts(rb->stdout_stream, "\n")); SVN_ERR(svn_rdump__get_dump_editor(editor, edit_baton, revision, rb->stdout_stream, rb->extra_ra_session, @@ -304,13 +300,10 @@ replay_revstart_v2(svn_revnum_t revision struct replay_baton *rb = replay_baton; apr_hash_t *normal_props; svn_stringbuf_t *propstring; - svn_stream_t *stdout_stream; svn_stream_t *revprop_stream; - SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool)); - /* Revision-number: 19 */ - SVN_ERR(svn_stream_printf(stdout_stream, pool, + SVN_ERR(svn_stream_printf(rb->stdout_stream, pool, SVN_REPOS_DUMPFILE_REVISION_NUMBER ": %ld\n", revision)); SVN_ERR(svn_rdump__normalize_props(&normal_props, rev_props, pool)); @@ -320,21 +313,20 @@ replay_revstart_v2(svn_revnum_t revision SVN_ERR(svn_stream_close(revprop_stream)); /* Prop-content-length: 13 */ - SVN_ERR(svn_stream_printf(stdout_stream, pool, + SVN_ERR(svn_stream_printf(rb->stdout_stream, pool, SVN_REPOS_DUMPFILE_PROP_CONTENT_LENGTH ": %" APR_SIZE_T_FMT "\n", propstring->len)); /* Content-length: 29 */ - SVN_ERR(svn_stream_printf(stdout_stream, pool, + SVN_ERR(svn_stream_printf(rb->stdout_stream, pool, SVN_REPOS_DUMPFILE_CONTENT_LENGTH ": %" APR_SIZE_T_FMT "\n\n", propstring->len)); /* Property data. */ - SVN_ERR(svn_stream_write(stdout_stream, propstring->data, + SVN_ERR(svn_stream_write(rb->stdout_stream, propstring->data, &(propstring->len))); - SVN_ERR(svn_stream_puts(stdout_stream, "\n")); - SVN_ERR(svn_stream_close(stdout_stream)); + SVN_ERR(svn_stream_puts(rb->stdout_stream, "\n")); SVN_ERR(svn_rdump__get_dump_editor_v2(editor, revision, rb->stdout_stream, Modified: subversion/branches/svn-auth-x509/subversion/svnserve/logger.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/svnserve/logger.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/svnserve/logger.c (original) +++ subversion/branches/svn-auth-x509/subversion/svnserve/logger.c Fri Jan 16 14:01:35 2015 @@ -134,7 +134,10 @@ logger__log_error(logger_t *logger, if (len > sizeof(errstr) - sizeof(APR_EOL_STR)) { len = sizeof(errstr) - sizeof(APR_EOL_STR); } + memcpy(errstr + len, APR_EOL_STR, sizeof(APR_EOL_STR)); + len += sizeof(APR_EOL_STR) -1; /* add NL, ex terminating NUL */ + svn_error_clear(svn_stream_write(logger->stream, errstr, &len)); continuation = "-"; Modified: subversion/branches/svn-auth-x509/subversion/svnserve/svnserve.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/svnserve/svnserve.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/svnserve/svnserve.c (original) +++ subversion/branches/svn-auth-x509/subversion/svnserve/svnserve.c Fri Jan 16 14:01:35 2015 @@ -271,6 +271,8 @@ static const apr_getopt_option_t svnserv " " "Default is 16.\n" " " + "0 switches to dynamically sized caches.\n" + " " "[used for FSFS and FSX repositories only]")}, {"cache-txdeltas", SVNSERVE_OPT_CACHE_TXDELTAS, 1, N_("enable or disable caching of deltas between older\n" Modified: subversion/branches/svn-auth-x509/subversion/svnsync/svnsync.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/svnsync/svnsync.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/svnsync/svnsync.c (original) +++ subversion/branches/svn-auth-x509/subversion/svnsync/svnsync.c Fri Jan 16 14:01:35 2015 @@ -764,8 +764,10 @@ open_target_session(svn_ra_session_t **t /*** `svnsync init' ***/ /* Initialize the repository associated with RA session TO_SESSION, - * using information found in BATON, while the repository is - * locked. Implements `with_locked_func_t' interface. + * using information found in BATON. + * + * Implements `with_locked_func_t' interface. The caller has + * acquired a lock on the repository if locking is needed. */ static svn_error_t * do_initialize(svn_ra_session_t *to_session, @@ -1403,8 +1405,10 @@ replay_rev_finished(svn_revnum_t revisio } /* Synchronize the repository associated with RA session TO_SESSION, - * using information found in BATON, while the repository is - * locked. Implements `with_locked_func_t' interface. + * using information found in BATON. + * + * Implements `with_locked_func_t' interface. The caller has + * acquired a lock on the repository if locking is needed. */ static svn_error_t * do_synchronize(svn_ra_session_t *to_session, @@ -1597,8 +1601,10 @@ synchronize_cmd(apr_getopt_t *os, void * /*** `svnsync copy-revprops' ***/ /* Copy revision properties to the repository associated with RA - * session TO_SESSION, using information found in BATON, while the - * repository is locked. Implements `with_locked_func_t' interface. + * session TO_SESSION, using information found in BATON. + * + * Implements `with_locked_func_t' interface. The caller has + * acquired a lock on the repository if locking is needed. */ static svn_error_t * do_copy_revprops(svn_ra_session_t *to_session, Modified: subversion/branches/svn-auth-x509/subversion/svnsync/sync.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/svnsync/sync.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/svnsync/sync.c (original) +++ subversion/branches/svn-auth-x509/subversion/svnsync/sync.c Fri Jan 16 14:01:35 2015 @@ -34,6 +34,8 @@ #include "svn_subst.h" #include "svn_string.h" +#include "private/svn_string_private.h" + #include "sync.h" #include "svn_private_config.h" @@ -83,6 +85,90 @@ normalize_string(const svn_string_t **st return SVN_NO_ERROR; } +/* Remove r0 references from the mergeinfo string *STR. + * + * r0 was never a valid mergeinfo reference and cannot be committed with + * recent servers, but can be committed through a server older than 1.6.18 + * for HTTP or older than 1.6.17 for the other protocols. See issue #4476 + * "Mergeinfo containing r0 makes svnsync and dump and load fail". + * + * Set *WAS_CHANGED to TRUE if *STR was changed, otherwise to FALSE. + */ +static svn_error_t * +remove_r0_mergeinfo(const svn_string_t **str, + svn_boolean_t *was_changed, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + svn_stringbuf_t *new_str = svn_stringbuf_create_empty(result_pool); + apr_array_header_t *lines; + int i; + + SVN_ERR_ASSERT(*str && (*str)->data); + + *was_changed = FALSE; + + /* for each line */ + lines = svn_cstring_split((*str)->data, "\n", FALSE, scratch_pool); + + for (i = 0; i < lines->nelts; i++) + { + char *line = APR_ARRAY_IDX(lines, i, char *); + char *colon; + + /* split at the last colon */ + colon = strrchr(line, ':'); + + if (! colon) + return svn_error_createf(SVN_ERR_MERGEINFO_PARSE_ERROR, NULL, + _("Missing colon in svn:mergeinfo " + "property")); + + /* remove r0 */ + if (colon[1] == '0') + { + char *rangelist; + + rangelist = colon + 1; + + if (strncmp(rangelist, "0*,", 3) == 0) + { + rangelist += 3; + } + else if (strcmp(rangelist, "0*") == 0 + || strncmp(rangelist, "0,", 2) == 0 + || strncmp(rangelist, "0-1*", 4) == 0 + || strncmp(rangelist, "0-1,", 4) == 0 + || strcmp(rangelist, "0-1") == 0) + { + rangelist += 2; + } + else if (strcmp(rangelist, "0") == 0) + { + rangelist += 1; + } + else if (strncmp(rangelist, "0-", 2) == 0) + { + rangelist[0] = '1'; + } + + /* reassemble */ + if (new_str->len) + svn_stringbuf_appendbyte(new_str, '\n'); + svn_stringbuf_appendbytes(new_str, line, colon + 1 - line); + svn_stringbuf_appendcstr(new_str, rangelist); + } + } + + if (strcmp((*str)->data, new_str->data) != 0) + { + *was_changed = TRUE; + } + + *str = svn_stringbuf__morph_into_string(new_str); + return SVN_NO_ERROR; +} + /* Normalize the encoding and line ending style of the values of properties * in REV_PROPS that "need translation" (according to @@ -153,6 +239,7 @@ typedef struct edit_baton_t { svn_boolean_t got_textdeltas; svn_revnum_t base_revision; svn_boolean_t quiet; + svn_boolean_t mergeinfo_tweaked; /* Did we tweak svn:mergeinfo? */ svn_boolean_t strip_mergeinfo; /* Are we stripping svn:mergeinfo? */ svn_boolean_t migrate_svnmerge; /* Are we converting svnmerge.py data? */ svn_boolean_t mergeinfo_stripped; /* Did we strip svn:mergeinfo? */ @@ -414,8 +501,19 @@ change_file_prop(void *file_baton, if (svn_prop_needs_translation(name)) { svn_boolean_t was_normalized; + svn_boolean_t mergeinfo_tweaked = FALSE; + + /* Normalize encoding to UTF-8, and EOL style to LF. */ SVN_ERR(normalize_string(&value, &was_normalized, eb->source_prop_encoding, pool, pool)); + /* Correct malformed mergeinfo. */ + if (strcmp(name, SVN_PROP_MERGEINFO) == 0) + { + SVN_ERR(remove_r0_mergeinfo(&value, &mergeinfo_tweaked, + pool, pool)); + if (mergeinfo_tweaked) + eb->mergeinfo_tweaked = TRUE; + } if (was_normalized) (*(eb->normalized_node_props_counter))++; } @@ -513,8 +611,19 @@ change_dir_prop(void *dir_baton, if (svn_prop_needs_translation(name)) { svn_boolean_t was_normalized; + svn_boolean_t mergeinfo_tweaked = FALSE; + + /* Normalize encoding to UTF-8, and EOL style to LF. */ SVN_ERR(normalize_string(&value, &was_normalized, eb->source_prop_encoding, pool, pool)); + /* Maybe adjust svn:mergeinfo. */ + if (strcmp(name, SVN_PROP_MERGEINFO) == 0) + { + SVN_ERR(remove_r0_mergeinfo(&value, &mergeinfo_tweaked, + pool, pool)); + if (mergeinfo_tweaked) + eb->mergeinfo_tweaked = TRUE; + } if (was_normalized) (*(eb->normalized_node_props_counter))++; } @@ -548,6 +657,10 @@ close_edit(void *edit_baton, { if (eb->got_textdeltas) SVN_ERR(svn_cmdline_printf(pool, "\n")); + if (eb->mergeinfo_tweaked) + SVN_ERR(svn_cmdline_printf(pool, + "NOTE: Adjusted Subversion mergeinfo in " + "this revision.\n")); if (eb->mergeinfo_stripped) SVN_ERR(svn_cmdline_printf(pool, "NOTE: Dropped Subversion mergeinfo " Modified: subversion/branches/svn-auth-x509/subversion/tests/cmdline/basic_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/tests/cmdline/basic_tests.py?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/tests/cmdline/basic_tests.py (original) +++ subversion/branches/svn-auth-x509/subversion/tests/cmdline/basic_tests.py Fri Jan 16 14:01:35 2015 @@ -3146,6 +3146,31 @@ def basic_youngest(sbox): 'youngest', path) +# With 'svn mkdir --parents' the target directory may already exist on disk. +# In that case it was wrongly performing a recursive 'add' on its contents. +def mkdir_parents_target_exists_on_disk(sbox): + "mkdir parents target exists on disk" + + sbox.build() + wc_dir = sbox.wc_dir + + Y_path = sbox.ospath('Y') + Y_Z_path = sbox.ospath('Y/Z') + + os.mkdir(Y_path) + os.mkdir(Y_Z_path) + svntest.actions.run_and_verify_svn(None, None, [], + 'mkdir', '--parents', Y_path) + + # Y should be added, and Z should not. There was a regression in which Z + # was also added. + expected_status = svntest.actions.get_virginal_state(sbox.wc_dir, 1) + expected_status.add({ + 'Y' : Item(status='A ', wc_rev=0), + }) + svntest.actions.run_and_verify_status(wc_dir, expected_status) + + ######################################################################## # Run the tests @@ -3215,6 +3240,7 @@ test_list = [ None, delete_conflicts_one_of_many, peg_rev_on_non_existent_wc_path, basic_youngest, + mkdir_parents_target_exists_on_disk, ] if __name__ == '__main__': Modified: subversion/branches/svn-auth-x509/subversion/tests/cmdline/copy_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/tests/cmdline/copy_tests.py?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/tests/cmdline/copy_tests.py (original) +++ subversion/branches/svn-auth-x509/subversion/tests/cmdline/copy_tests.py Fri Jan 16 14:01:35 2015 @@ -560,7 +560,7 @@ def no_copy_overwrites(sbox): # Repeat the last command. It should *fail* because A/D/H/G already exists. svntest.actions.run_and_verify_svn( "Whoa, I was able to overwrite a directory!", - None, svntest.verify.AnyOutput, + None, ".*'/A/D/H/G'.*", 'cp', dirURL1, dirURL2, '-m', 'fooogle') Modified: subversion/branches/svn-auth-x509/subversion/tests/cmdline/externals_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/tests/cmdline/externals_tests.py?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/tests/cmdline/externals_tests.py (original) +++ subversion/branches/svn-auth-x509/subversion/tests/cmdline/externals_tests.py Fri Jan 16 14:01:35 2015 @@ -3121,7 +3121,7 @@ def move_with_file_externals(sbox): sbox.simple_commit() sbox.simple_update() -@Issue(4185) +@Issue(4185,4529) def pinned_externals(sbox): "pinned external" @@ -3134,6 +3134,7 @@ def pinned_externals(sbox): sbox.simple_mkdir('Z') sbox.simple_commit('') + repo_X_C = repo_url + '/X/C' repo_X_mu = repo_url + '/X/mu' expected_output = verify.RegexOutput( @@ -3153,20 +3154,18 @@ def pinned_externals(sbox): 'old-rev -r 1 ' + repo_X_mu + '\n' + repo_X_mu + ' new-plain\n' + '-r1 ' + repo_X_mu + ' new-rev\n' + - repo_X_mu + '@1 new-peg\n', + repo_X_mu + '@1 new-peg\n' + '-r1 ' + repo_X_C + ' new-dir-rev\n', 'Z') - expected_output = svntest.wc.State(wc_dir, { - 'A/D' : Item(status=' U'), - 'A/D/exdir_E/beta' : Item(status='A '), - 'A/D/exdir_E/alpha' : Item(status='A '), - }) expected_error = "svn: E205011: Failure.*externals" expected_disk = svntest.main.greek_state.copy() expected_disk.add({ # The interesting values 'Z/old-plain' : Item(contents="This is the file 'mu'.\n"), 'Z/new-plain' : Item(contents="This is the file 'mu'.\n"), + 'Z/new-rev' : Item(contents="This is the file 'mu'.\n"), + 'Z/new-dir-rev' : Item(), # And verifying X 'X/D/H/psi' : Item(contents="This is the file 'psi'.\n"), @@ -3481,6 +3480,73 @@ def switch_relative_externals(sbox): 'up', wc) +def copy_file_external_to_repo(sbox): + "explicitly copy file external to repo" + + sbox.build() + wc_dir = sbox.wc_dir + + change_external(sbox.ospath('A'), '^/A/mu ext') + sbox.simple_update() + + svntest.actions.run_and_verify_svn(None, None, [], 'cp', + '--message', 'external copy', + sbox.ospath('A/ext'), + sbox.repo_url + '/ext_copy') + + expected_output = svntest.wc.State(wc_dir, { + 'ext_copy' : Item(status='A '), + }) + expected_disk = svntest.main.greek_state.copy() + expected_disk.add({ + 'A/ext' : Item('This is the file \'mu\'.\n'), + 'ext_copy' : Item('This is the file \'mu\'.\n'), + }) + svntest.actions.run_and_verify_update(wc_dir, + expected_output, expected_disk, None) + +@Issue(4550) +def replace_tree_with_foreign_external(sbox): + "replace tree with foreign external" + + sbox.build() + wc_dir = sbox.wc_dir + repo_dir = sbox.repo_dir + + other_repo_dir, other_repo_url = sbox.add_repo_path('other') + svntest.main.copy_repos(repo_dir, other_repo_dir, 1) + + sbox.simple_propset('svn:externals', other_repo_url + '/A/B X', 'A') + sbox.simple_commit() + sbox.simple_propdel('svn:externals', 'A') + sbox.simple_mkdir('A/X') + sbox.simple_mkdir('A/X/E') + sbox.simple_commit() + sbox.simple_update() + + expected_output = svntest.wc.State(wc_dir, { + 'A/X' : Item(status='D '), + 'A' : Item(status=' U'), + 'A/X/lambda' : Item(status='A '), + 'A/X/E' : Item(status='A '), + 'A/X/E/alpha' : Item(status='A '), + 'A/X/E/beta' : Item(status='A '), + 'A/X/F' : Item(status='A '), + }) + expected_status = svntest.actions.get_virginal_state(wc_dir, 2) + expected_status.add({ + 'A/X' : Item(status=' ', wc_rev=1, prev_status='X '), + 'A/X/E' : Item(status=' ', wc_rev=1, prev_status=' '), + 'A/X/E/alpha' : Item(status=' ', wc_rev=1), + 'A/X/E/beta' : Item(status=' ', wc_rev=1), + 'A/X/F' : Item(status=' ', wc_rev=1), + 'A/X/lambda' : Item(status=' ', wc_rev=1), + }) + svntest.actions.run_and_verify_update(wc_dir, + expected_output, None, expected_status, + None, None, None, None, None, 1, + '-r', '2', wc_dir) + ######################################################################## # Run the tests @@ -3539,6 +3605,8 @@ test_list = [ None, update_external_peg_rev, update_deletes_file_external, switch_relative_externals, + copy_file_external_to_repo, + replace_tree_with_foreign_external, ] if __name__ == '__main__': Modified: subversion/branches/svn-auth-x509/subversion/tests/cmdline/lock_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/tests/cmdline/lock_tests.py?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/tests/cmdline/lock_tests.py (original) +++ subversion/branches/svn-auth-x509/subversion/tests/cmdline/lock_tests.py Fri Jan 16 14:01:35 2015 @@ -2355,6 +2355,26 @@ def lock_commit_bump(sbox): svntest.actions.run_and_verify_info(expected_infos, sbox.ospath('iota')) +def copy_dir_with_locked_file(sbox): + "copy a directory containing a locked file" + + sbox.build() + AA_url = sbox.repo_url + '/AA' + AA2_url = sbox.repo_url + '/AA2' + A_url = sbox.repo_url + '/A' + mu_url = A_url + '/mu' + + svntest.main.run_svn(None, 'lock', '-m', 'locked', mu_url) + + svntest.actions.run_and_verify_svn(None, None, [], + 'cp', A_url, AA_url, + '-m', '') + + expected_err = "svn: E160037: .*no matching lock-token available" + svntest.actions.run_and_verify_svn(None, None, expected_err, + 'mv', A_url, AA2_url, + '-m', '') + ######################################################################## # Run the tests @@ -2420,6 +2440,7 @@ test_list = [ None, dav_lock_refresh, delete_locked_file_with_percent, lock_commit_bump, + copy_dir_with_locked_file, ] if __name__ == '__main__': Modified: subversion/branches/svn-auth-x509/subversion/tests/cmdline/patch_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/tests/cmdline/patch_tests.py?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/tests/cmdline/patch_tests.py (original) +++ subversion/branches/svn-auth-x509/subversion/tests/cmdline/patch_tests.py Fri Jan 16 14:01:35 2015 @@ -4689,6 +4689,396 @@ def patch_git_rename(sbox): expected_output, expected_disk, expected_status, expected_skip) +@Issue(4533) +def patch_hunk_avoid_reorder(sbox): + """avoid reordering hunks""" + + sbox.build() + wc_dir = sbox.wc_dir + + sbox.simple_append('A/mu', + 'AA\n' 'BB\n' 'CC\n' 'DD\n' 'EE\n' 'FF\n' + 'TT\n' 'UU\n' 'VV\n' 'WW\n' 'XX\n' 'YY\n' + 'GG\n' 'HH\n' 'II\n' 'JJ\n' 'KK\n' 'LL\n' + '33333\n' '33333\n' '33333\n' + '33333\n' '33333\n' '33333\n' + '33333\n' '33333\n' '33333\n' + '33333\n' '33333\n' '33333\n' + 'MM\n' 'NN\n' 'OO\n' 'PP\n' 'QQ\n' 'RR\n' + 'SS\n' 'TT\n' 'UU\n' 'VV\n' 'WW\n' 'XX\n' + 'YY\n' 'ZZ\n', truncate=True) + sbox.simple_commit() + + # two hunks, first matches at offset +18, second matches at both -13 + # and +18 but we want the second match as it is after the first + unidiff_patch = [ + "Index: A/mu\n" + "===================================================================\n", + "--- A/mu\t(revision 1)\n", + "+++ A/mu\t(working copy)\n", + "@@ -13,6 +13,7 @@\n", + " MM\n", + " NN\n", + " OO\n", + "+11111\n", + " PP\n", + " QQ\n", + " RR\n", + "@@ -20,6 +20,7 @@\n", + " TT\n", + " UU\n", + " VV\n", + "+22222\n", + " WW\n", + " XX\n", + " YY\n", + ] + + patch_file_path = make_patch_path(sbox) + svntest.main.file_write(patch_file_path, ''.join(unidiff_patch)) + + expected_output = [ + 'U %s\n' % sbox.ospath('A/mu'), + '> applied hunk @@ -13,6 +13,7 @@ with offset 18\n', + '> applied hunk @@ -20,6 +20,7 @@ with offset 18\n' + ] + expected_disk = svntest.main.greek_state.copy() + expected_disk.tweak('A/mu', contents= + 'AA\n' 'BB\n' 'CC\n' 'DD\n' 'EE\n' 'FF\n' + 'TT\n' 'UU\n' 'VV\n' 'WW\n' 'XX\n' 'YY\n' + 'GG\n' 'HH\n' 'II\n' 'JJ\n' 'KK\n' 'LL\n' + '33333\n' '33333\n' '33333\n' + '33333\n' '33333\n' '33333\n' + '33333\n' '33333\n' '33333\n' + '33333\n' '33333\n' '33333\n' + 'MM\n' 'NN\n' 'OO\n' '11111\n' 'PP\n' 'QQ\n' 'RR\n' + 'SS\n' 'TT\n' 'UU\n' 'VV\n' '22222\n' 'WW\n' 'XX\n' + 'YY\n' 'ZZ\n') + expected_status = svntest.actions.get_virginal_state(wc_dir, 1) + expected_status.tweak('A/mu', status='M ', wc_rev=2) + expected_skip = wc.State('', { }) + svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path), + expected_output, expected_disk, + expected_status, expected_skip) + + sbox.simple_revert('A/mu') + + # change patch so second hunk matches at both -14 and +17, we still + # want the second match + unidiff_patch = [ + "Index: A/mu\n" + "===================================================================\n", + "--- A/mu\t(revision 1)\n", + "+++ A/mu\t(working copy)\n", + "@@ -13,6 +13,7 @@\n", + " MM\n", + " NN\n", + " OO\n", + "+11111\n", + " PP\n", + " QQ\n", + " RR\n", + "@@ -21,6 +21,7 @@\n", + " TT\n", + " UU\n", + " VV\n", + "+22222\n", + " WW\n", + " XX\n", + " YY\n", + ] + + patch_file_path = make_patch_path(sbox) + svntest.main.file_write(patch_file_path, ''.join(unidiff_patch)) + + expected_output = [ + 'U %s\n' % sbox.ospath('A/mu'), + '> applied hunk @@ -13,6 +13,7 @@ with offset 18\n', + '> applied hunk @@ -21,6 +21,7 @@ with offset 17\n' + ] + expected_disk = svntest.main.greek_state.copy() + expected_disk.tweak('A/mu', contents= + 'AA\n' 'BB\n' 'CC\n' 'DD\n' 'EE\n' 'FF\n' + 'TT\n' 'UU\n' 'VV\n' 'WW\n' 'XX\n' 'YY\n' + 'GG\n' 'HH\n' 'II\n' 'JJ\n' 'KK\n' 'LL\n' + '33333\n' '33333\n' '33333\n' + '33333\n' '33333\n' '33333\n' + '33333\n' '33333\n' '33333\n' + '33333\n' '33333\n' '33333\n' + 'MM\n' 'NN\n' 'OO\n' '11111\n' 'PP\n' 'QQ\n' 'RR\n' + 'SS\n' 'TT\n' 'UU\n' 'VV\n' '22222\n' 'WW\n' 'XX\n' + 'YY\n' 'ZZ\n') + expected_status = svntest.actions.get_virginal_state(wc_dir, 1) + expected_status.tweak('A/mu', status='M ', wc_rev=2) + expected_skip = wc.State('', { }) + svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path), + expected_output, expected_disk, + expected_status, expected_skip) + + sbox.simple_revert('A/mu') + +@Issue(4533) +def patch_hunk_avoid_reorder2(sbox): + """avoid reordering hunks 2""" + + sbox.build() + wc_dir = sbox.wc_dir + + sbox.simple_append('A/mu', + 'AA\n' 'BB\n' 'CC\n' 'DD\n' 'EE\n' 'FF\n' + 'TT\n' 'UU\n' 'VV\n' 'WW\n' 'XX\n' 'YY\n' + 'GG\n' 'HH\n' 'II\n' 'JJ\n' 'KK\n' 'LL\n' + '33333\n' '33333\n' '33333\n' + '33333\n' '33333\n' '33333\n' + '33333\n' '33333\n' '33333\n' + '33333\n' '33333\n' '33333\n' + 'MM\n' 'NN\n' 'OO\n' 'PP\n' 'QQ\n' 'RR\n' + 'SS\n' 'TT\n' 'UU\n' 'VV\n' 'WW\n' 'XX\n' + 'YY\n' 'ZZ\n', truncate=True) + sbox.simple_commit() + + # two hunks, first matches at offset +18, second matches at both -13 + # change patch so second hunk matches at both -12 and +19, we still + # want the second match + unidiff_patch = [ + "Index: A/mu\n" + "===================================================================\n", + "--- A/mu\t(revision 1)\n", + "+++ A/mu\t(working copy)\n", + "@@ -13,6 +13,7 @@\n", + " MM\n", + " NN\n", + " OO\n", + "+11111\n", + " PP\n", + " QQ\n", + " RR\n", + "@@ -19,6 +19,7 @@\n", + " TT\n", + " UU\n", + " VV\n", + "+22222\n", + " WW\n", + " XX\n", + " YY\n", + ] + + patch_file_path = make_patch_path(sbox) + svntest.main.file_write(patch_file_path, ''.join(unidiff_patch)) + + expected_output = [ + 'U %s\n' % sbox.ospath('A/mu'), + '> applied hunk @@ -13,6 +13,7 @@ with offset 18\n', + '> applied hunk @@ -19,6 +19,7 @@ with offset 19\n' + ] + expected_disk = svntest.main.greek_state.copy() + expected_disk.tweak('A/mu', contents= + 'AA\n' 'BB\n' 'CC\n' 'DD\n' 'EE\n' 'FF\n' + 'TT\n' 'UU\n' 'VV\n' 'WW\n' 'XX\n' 'YY\n' + 'GG\n' 'HH\n' 'II\n' 'JJ\n' 'KK\n' 'LL\n' + '33333\n' '33333\n' '33333\n' + '33333\n' '33333\n' '33333\n' + '33333\n' '33333\n' '33333\n' + '33333\n' '33333\n' '33333\n' + 'MM\n' 'NN\n' 'OO\n' '11111\n' 'PP\n' 'QQ\n' 'RR\n' + 'SS\n' 'TT\n' 'UU\n' 'VV\n' '22222\n' 'WW\n' 'XX\n' + 'YY\n' 'ZZ\n') + expected_status = svntest.actions.get_virginal_state(wc_dir, 1) + expected_status.tweak('A/mu', status='M ', wc_rev=2) + expected_skip = wc.State('', { }) + svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path), + expected_output, expected_disk, + expected_status, expected_skip) + +@Issue(4533) +def patch_hunk_reorder(sbox): + """hunks that reorder""" + + sbox.build() + wc_dir = sbox.wc_dir + + sbox.simple_append('A/mu', + 'AA\n' 'BB\n' 'CC\n' 'DD\n' 'EE\n' 'FF\n' 'GG\n' + 'HH\n' 'II\n' 'JJ\n' 'KK\n' 'LL\n' 'MM\n' 'NN\n', + truncate=True) + sbox.simple_commit() + + # Two hunks match in opposite order + unidiff_patch = [ + "Index: A/mu\n" + "===================================================================\n", + "--- A/mu\t(revision 1)\n", + "+++ A/mu\t(working copy)\n", + "@@ -2,6 +2,7 @@\n", + " II\n", + " JJ\n", + " KK\n", + "+11111\n", + " LL\n", + " MM\n", + " NN\n", + "@@ -9,6 +10,7 @@\n", + " BB\n", + " CC\n", + " DD\n", + "+22222\n", + " EE\n", + " FF\n", + " GG\n", + ] + + patch_file_path = make_patch_path(sbox) + svntest.main.file_write(patch_file_path, ''.join(unidiff_patch)) + + expected_output = [ + 'U %s\n' % sbox.ospath('A/mu'), + '> applied hunk @@ -9,6 +10,7 @@ with offset -7\n', + '> applied hunk @@ -2,6 +2,7 @@ with offset 7\n', + ] + expected_disk = svntest.main.greek_state.copy() + expected_disk.tweak('A/mu', contents= + 'AA\n' 'BB\n' 'CC\n' 'DD\n' '22222\n' 'EE\n' 'FF\n' 'GG\n' + 'HH\n' 'II\n' 'JJ\n' 'KK\n' '11111\n' 'LL\n' 'MM\n' 'NN\n') + expected_status = svntest.actions.get_virginal_state(wc_dir, 1) + expected_status.tweak('A/mu', status='M ', wc_rev=2) + expected_skip = wc.State('', { }) + svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path), + expected_output, expected_disk, + expected_status, expected_skip) + +@XFail() +def patch_hunk_overlap(sbox): + """hunks that overlap""" + + sbox.build() + wc_dir = sbox.wc_dir + + sbox.simple_append('A/mu', + 'AA\n' 'BB\n' 'CC\n' 'DD\n' 'EE\n' 'FF\n' + 'GG\n' 'HH\n' 'II\n', truncate=True) + sbox.simple_commit() + + # Two hunks that overlap when applied, GNU patch can apply both hunks. + unidiff_patch = [ + "Index: A/mu\n" + "===================================================================\n", + "--- A/mu\t(revision 1)\n", + "+++ A/mu\t(working copy)\n", + "@@ -2,6 +2,7 @@\n", + " BB\n", + " CC\n", + " DD\n", + "+11111\n", + " EE\n", + " FF\n", + " GG\n", + "@@ -9,6 +10,7 @@\n", + " DD\n", + " EE\n", + " FF\n", + "+22222\n", + " GG\n", + " HH\n", + " II\n", + ] + + patch_file_path = make_patch_path(sbox) + svntest.main.file_write(patch_file_path, ''.join(unidiff_patch)) + + expected_output = [ + 'U %s\n' % sbox.ospath('A/mu'), + '> applied hunk @@ -9,6 +10,7 @@ with offset -5\n', + ] + expected_disk = svntest.main.greek_state.copy() + expected_disk.tweak('A/mu', contents= + 'AA\n' 'BB\n' 'CC\n' 'DD\n' '11111\n' 'EE\n' 'FF\n' + '22222\n' 'GG\n' 'HH\n' 'II\n') + expected_status = svntest.actions.get_virginal_state(wc_dir, 1) + expected_status.tweak('A/mu', status='M ', wc_rev=2) + expected_skip = wc.State('', { }) + svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path), + expected_output, expected_disk, + expected_status, expected_skip) + +def patch_delete_modified(sbox): + """patch delete modified""" + + sbox.build() + wc_dir = sbox.wc_dir + + # A patch that deletes beta. + unidiff_patch = [ + "Index: A/B/E/beta\n", + "===================================================================\n", + "--- A/B/E/beta (revision 1)\n", + "+++ A/B/E/beta (working copy)\n", + "@@ -1 +0,0 @@\n", + "-This is the file 'beta'.\n", + ] + + patch_file_path = make_patch_path(sbox) + svntest.main.file_write(patch_file_path, ''.join(unidiff_patch)) + + # First application deletes beta + expected_output = [ + 'D %s\n' % sbox.ospath('A/B/E/beta'), + ] + expected_disk = svntest.main.greek_state.copy() + expected_disk.remove('A/B/E/beta') + expected_status = svntest.actions.get_virginal_state(wc_dir, 1) + expected_status.tweak('A/B/E/beta', status='D ') + expected_skip = wc.State('', { }) + svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path), + expected_output, expected_disk, + expected_status, expected_skip) + + # Second application skips + expected_output = [ + 'Skipped \'%s\'\n' % sbox.ospath('A/B/E/beta'), + ] + svntest.main.summary_of_conflicts(skipped_paths=1) + expected_skip = wc.State('', { + sbox.ospath('A/B/E/beta') : Item(verb='Skipped'), + }) + svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path), + expected_output, expected_disk, + expected_status, expected_skip) + + # Third application, with file present even though state is 'D', also skips + sbox.simple_append('A/B/E/beta', 'Modified', truncate=True) + expected_disk.add({'A/B/E/beta' : Item(contents='Modified')}) + expected_output = [ + 'Skipped \'%s\'\n' % sbox.ospath('A/B/E/beta'), + ] + svntest.main.summary_of_conflicts(skipped_paths=1) + expected_skip = wc.State('', { + sbox.ospath('A/B/E/beta') : Item(verb='Skipped'), + }) + svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path), + expected_output, expected_disk, + expected_status, expected_skip) + + # Revert and modify beta, fourth application gives a text conflict. + sbox.simple_revert('A/B/E/beta') + sbox.simple_append('A/B/E/beta', 'Modified', truncate=True) + + expected_output = [ + 'C %s\n' % sbox.ospath('A/B/E/beta'), + '> rejected hunk @@ -1,1 +0,0 @@\n', + ] + svntest.main.summary_of_conflicts(text_conflicts=1) + expected_skip = wc.State('', { }) + reject_file_contents = [ + "--- A/B/E/beta\n", + "+++ A/B/E/beta\n", + "@@ -1,1 +0,0 @@\n", + "-This is the file 'beta'.\n", + ] + expected_disk.add({'A/B/E/beta.svnpatch.rej' + : Item(contents=''.join(reject_file_contents)) + }) + expected_status.tweak('A/B/E/beta', status='M ') + svntest.actions.run_and_verify_patch(wc_dir, os.path.abspath(patch_file_path), + expected_output, expected_disk, + expected_status, expected_skip) + ######################################################################## #Run the tests @@ -4741,7 +5131,12 @@ test_list = [ None, patch_apply_no_fuz, patch_lacking_trailing_eol_on_context, patch_with_custom_keywords, - patch_git_rename + patch_git_rename, + patch_hunk_avoid_reorder, + patch_hunk_avoid_reorder2, + patch_hunk_reorder, + patch_hunk_overlap, + patch_delete_modified, ] if __name__ == '__main__': Modified: subversion/branches/svn-auth-x509/subversion/tests/cmdline/redirect_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/tests/cmdline/redirect_tests.py?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/tests/cmdline/redirect_tests.py (original) +++ subversion/branches/svn-auth-x509/subversion/tests/cmdline/redirect_tests.py Fri Jan 16 14:01:35 2015 @@ -178,6 +178,33 @@ def redirected_nonroot_update(sbox): verify_url(wc_dir, checkout_url) #---------------------------------------------------------------------- +@SkipUnless(svntest.main.is_ra_type_dav) +def redirected_externals(sbox): + "redirected externals" + + sbox.build() + + sbox.simple_propset('svn:externals', + '^/A/B/E/alpha fileX\n' + '^/A/B/F dirX', + 'A/C') + sbox.simple_commit() + sbox.simple_update() + + wc_dir = sbox.add_wc_path("my") + co_url = sbox.redirected_root_url() + exit_code, out, err = svntest.main.run_svn(None, 'co', co_url, wc_dir) + if err: + raise svntest.Failure + if not redirect_regex.match(out[0]): + raise svntest.Failure + + verify_url(wc_dir, sbox.repo_url) + verify_url(sbox.ospath('A/C/fileX'), sbox.repo_url + '/A/B/E/alpha', + wc_path_is_file=True) + verify_url(sbox.ospath('A/C/dirX'), sbox.repo_url + '/A/B/F') + +#---------------------------------------------------------------------- ######################################################################## # Run the tests @@ -188,6 +215,7 @@ test_list = [ None, redirected_checkout, redirected_update, redirected_nonroot_update, + redirected_externals, ] if __name__ == '__main__': Modified: subversion/branches/svn-auth-x509/subversion/tests/cmdline/svnadmin_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/tests/cmdline/svnadmin_tests.py?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/tests/cmdline/svnadmin_tests.py (original) +++ subversion/branches/svn-auth-x509/subversion/tests/cmdline/svnadmin_tests.py Fri Jan 16 14:01:35 2015 @@ -32,6 +32,7 @@ import shutil import sys import threading import time +import gzip logger = logging.getLogger() @@ -2938,6 +2939,35 @@ def upgrade(sbox): '-m', svntest.main.make_log_msg(), sbox.repo_url + '/dir') +def load_txdelta(sbox): + "exercising svn_txdelta_target on BDB" + + test_create(sbox) + + # This dumpfile produced a BDB repository that generated cheksum + # mismatches on read caused by the improper handling of + # svn_txdelta_target ops. The bug was fixed by r1640832. + + dumpfile_location = os.path.join(os.path.dirname(sys.argv[0]), + 'svnadmin_tests_data', + 'load_txdelta.dump.gz') + dumpfile = gzip.open(dumpfile_location).read() + + load_dumpstream(sbox, dumpfile) + + # Verify would fail with a checksum mismatch: + # * Error verifying revision 14. + # svnadmin: E200014: MD5 checksum mismatch on representation 'r': + # expected: 5182e8876ed894dc7fe28f6ff5b2fee6 + # actual: 5121f82875508863ad70daa8244e6947 + + exit_code, output, errput = svntest.main.run_svnadmin("verify", sbox.repo_dir) + if errput: + raise SVNUnexpectedStderr(errput) + if svntest.verify.verify_outputs( + "Output of 'svnadmin verify' is unexpected.", None, output, None, + ".*Verified revision *"): + raise svntest.Failure ######################################################################## # Run the tests @@ -2992,6 +3022,7 @@ test_list = [ None, fsfs_hotcopy_progress_old, freeze_same_uuid, upgrade, + load_txdelta, ] if __name__ == '__main__': Modified: subversion/branches/svn-auth-x509/subversion/tests/cmdline/svndumpfilter_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/tests/cmdline/svndumpfilter_tests.py?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/tests/cmdline/svndumpfilter_tests.py (original) +++ subversion/branches/svn-auth-x509/subversion/tests/cmdline/svndumpfilter_tests.py Fri Jan 16 14:01:35 2015 @@ -60,15 +60,10 @@ def filter_and_return_output(dump, bufsi dump = [ dump ] # Does the caller want the stderr? - try: - varargs.index('-q') + if '-q' in varargs or '--quiet' in varargs: expected_errput = None # Stderr with -q or --quiet is a real error! - except: - try: - varargs.index('--quiet') - expected_errput = None - except: - expected_errput = svntest.verify.AnyOutput + else: + expected_errput = svntest.verify.AnyOutput ## TODO: Should we handle exit_code? exit_code, output, errput = svntest.main.run_command_stdin( svntest.main.svndumpfilter_binary, expected_errput, bufsize, True, @@ -323,9 +318,9 @@ def filter_mergeinfo_revs_outside_of_dum # --skip-missing-merge-soruces which should strip out any revisions < 6. # Then we'll load the filtered result into an empty repository. This # should offset the incoming mergeinfo by -5. In addition, any mergeinfo - # revisions that are adjusted to r1 should be removed because that implies - # a merge of -r0:1, which is impossible. The resulting mergeinfo should - # look like this: + # referring to the initial revision in the dump file (r6) should be + # removed because the change it refers to (r5:6) is not wholly within the + # dumpfile. The resulting mergeinfo should look like this: # # Properties on 'branches/B1': # svn:mergeinfo Modified: subversion/branches/svn-auth-x509/subversion/tests/cmdline/svnrdump_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/tests/cmdline/svnrdump_tests.py?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/tests/cmdline/svnrdump_tests.py (original) +++ subversion/branches/svn-auth-x509/subversion/tests/cmdline/svnrdump_tests.py Fri Jan 16 14:01:35 2015 @@ -70,27 +70,28 @@ def build_repos(sbox): # Create an empty repository. svntest.main.create_repos(sbox.repo_dir) -def compare_repos_dumps(svnrdump_sbox, svnadmin_dumpfile): - """Compare two dumpfiles, one created from SVNRDUMP_SBOX, and other given - by SVNADMIN_DUMPFILE. The dumpfiles do not need to match linewise, as the - SVNADMIN_DUMPFILE contents will first be loaded into a repository and then +def compare_repos_dumps(sbox, other_dumpfile, + bypass_prop_validation=False): + """Compare two dumpfiles, one created from SBOX, and other given + by OTHER_DUMPFILE. The dumpfiles do not need to match linewise, as the + OTHER_DUMPFILE contents will first be loaded into a repository and then re-dumped to do the match, which should generate the same dumpfile as - dumping SVNRDUMP_SBOX.""" + dumping SBOX.""" - svnrdump_contents = svntest.actions.run_and_verify_dump( - svnrdump_sbox.repo_dir) - svnadmin_sbox = svnrdump_sbox.clone_dependent() - svntest.main.safe_rmtree(svnadmin_sbox.repo_dir) - svntest.main.create_repos(svnadmin_sbox.repo_dir) + sbox_dumpfile = svntest.actions.run_and_verify_dump(sbox.repo_dir) - svntest.actions.run_and_verify_load(svnadmin_sbox.repo_dir, svnadmin_dumpfile) - - svnadmin_contents = svntest.actions.run_and_verify_dump( - svnadmin_sbox.repo_dir) + # Load and dump the other dumpfile (using svnadmin) + other_sbox = sbox.clone_dependent() + svntest.main.safe_rmtree(other_sbox.repo_dir) + svntest.main.create_repos(other_sbox.repo_dir) + svntest.actions.run_and_verify_load(other_sbox.repo_dir, other_dumpfile, + bypass_prop_validation) + other_dumpfile = svntest.actions.run_and_verify_dump(other_sbox.repo_dir) + ### This call kind-of assumes EXPECTED is first and ACTUAL is second. svntest.verify.compare_dump_files( - "Dump files", "DUMP", svnadmin_contents, svnrdump_contents) + "Dump files", "DUMP", other_dumpfile, sbox_dumpfile) def run_dump_test(sbox, dumpfile_name, expected_dumpfile_name = None, subdir = None, bypass_prop_validation = False, @@ -111,11 +112,10 @@ def run_dump_test(sbox, dumpfile_name, e # Load the specified dump file into the sbox repository using # svnadmin load - svnadmin_dumpfile = open(os.path.join(svnrdump_tests_dir, + original_dumpfile = open(os.path.join(svnrdump_tests_dir, dumpfile_name), 'rb').readlines() - - svntest.actions.run_and_verify_load(sbox.repo_dir, svnadmin_dumpfile, + svntest.actions.run_and_verify_load(sbox.repo_dir, original_dumpfile, bypass_prop_validation) repo_url = sbox.repo_url @@ -129,28 +129,29 @@ def run_dump_test(sbox, dumpfile_name, e [], 0, *opts) if expected_dumpfile_name: - svnadmin_dumpfile = open(os.path.join(svnrdump_tests_dir, + expected_dumpfile = open(os.path.join(svnrdump_tests_dir, expected_dumpfile_name), 'rb').readlines() # Compare the output from stdout if ignore_base_checksums: - svnadmin_dumpfile = [l for l in svnadmin_dumpfile + expected_dumpfile = [l for l in expected_dumpfile if not l.startswith('Text-delta-base-md5')] svnrdump_dumpfile = [l for l in svnrdump_dumpfile if not l.startswith('Text-delta-base-md5')] - svnadmin_dumpfile = [l for l in svnadmin_dumpfile + expected_dumpfile = [l for l in expected_dumpfile if not mismatched_headers_re.match(l)] svnrdump_dumpfile = [l for l in svnrdump_dumpfile if not mismatched_headers_re.match(l)] - svnadmin_dumpfile = svntest.verify.UnorderedOutput(svnadmin_dumpfile) + expected_dumpfile = svntest.verify.UnorderedOutput(expected_dumpfile) svntest.verify.compare_and_display_lines( - "Dump files", "DUMP", svnadmin_dumpfile, svnrdump_dumpfile, + "Dump files", "DUMP", expected_dumpfile, svnrdump_dumpfile, None) else: - compare_repos_dumps(sbox, svnadmin_dumpfile) + # The expected dumpfile is the result of dumping SBOX. + compare_repos_dumps(sbox, svnrdump_dumpfile, bypass_prop_validation) def run_load_test(sbox, dumpfile_name, expected_dumpfile_name = None, expect_deltas = True): @@ -169,36 +170,37 @@ def run_load_test(sbox, dumpfile_name, e # Load the specified dump file into the sbox repository using # svnrdump load - svnrdump_dumpfile = open(os.path.join(svnrdump_tests_dir, + original_dumpfile = open(os.path.join(svnrdump_tests_dir, dumpfile_name), 'rb').readlines() # Set the UUID of the sbox repository to the UUID specified in the # dumpfile ### RA layer doesn't have a set_uuid functionality - uuid = svnrdump_dumpfile[2].split(' ')[1][:-1] + uuid = original_dumpfile[2].split(' ')[1][:-1] svntest.actions.run_and_verify_svnadmin2("Setting UUID", None, None, 0, 'setuuid', sbox.repo_dir, uuid) - svntest.actions.run_and_verify_svnrdump(svnrdump_dumpfile, + svntest.actions.run_and_verify_svnrdump(original_dumpfile, svntest.verify.AnyOutput, [], 0, 'load', sbox.repo_url) - # Create a dump file using svnadmin dump - svnadmin_dumpfile = svntest.actions.run_and_verify_dump(sbox.repo_dir, + # Re-dump the rdump-loaded repo using svnadmin dump + resulted_dumpfile = svntest.actions.run_and_verify_dump(sbox.repo_dir, expect_deltas) if expected_dumpfile_name: - svnrdump_dumpfile = open(os.path.join(svnrdump_tests_dir, + expected_dumpfile = open(os.path.join(svnrdump_tests_dir, expected_dumpfile_name), 'rb').readlines() # Compare the output from stdout svntest.verify.compare_and_display_lines( - "Dump files", "DUMP", svnrdump_dumpfile, svnadmin_dumpfile) + "Dump files", "DUMP", expected_dumpfile, resulted_dumpfile) else: - compare_repos_dumps(sbox, svnrdump_dumpfile) + expected_dumpfile = original_dumpfile + compare_repos_dumps(sbox, expected_dumpfile) ###################################################################### # Tests @@ -799,6 +801,105 @@ def load_prop_change_in_non_deltas_dump( [], [], 0, '-q', 'load', sbox.repo_url) +#---------------------------------------------------------------------- + +@Issue(4476) +def dump_mergeinfo_contains_r0(sbox): + "dump: mergeinfo that contains r0" + ### We pass the original dump file name as 'expected_dumpfile_name' because + ### run_dump_test is currently broken when we don't. + run_dump_test(sbox, "mergeinfo-contains-r0.dump", + bypass_prop_validation=True) + +#---------------------------------------------------------------------- + +@XFail() +@Issue(4476) +def load_mergeinfo_contains_r0(sbox): + "load: mergeinfo that contains r0" + run_load_test(sbox, "mergeinfo-contains-r0.dump", + expected_dumpfile_name="mergeinfo-contains-r0.expected.dump") + +#---------------------------------------------------------------------- + +# Regression test for issue 4551 "svnrdump load commits wrong properties, +# or fails, on a non-deltas dumpfile". In this test, the copy source does +# not exist and the failure mode is to error out. +@XFail() +@Issue(4551) +def load_non_deltas_copy_with_props(sbox): + "load non-deltas copy with props" + sbox.build() + + # Set props on a file and on a dir and on a child of the dir to be copied + sbox.simple_propset('p', 'v', 'A/mu', 'A/B', 'A/B/E') + sbox.simple_commit() + sbox.simple_update() # avoid mixed-rev + + # Case (1): Copy file/dir, not replacing anything; the copy target path + # at (new rev - 1) does not exist + sbox.simple_copy('A/mu@2', 'A/mu_COPY') + sbox.simple_copy('A/B@2', 'A/B_COPY') + # On the copy, delete a prop + sbox.simple_propdel('p', 'A/mu_COPY', 'A/B_COPY', 'A/B_COPY/E') + + sbox.simple_commit() + + # Dump with 'svnadmin' (non-deltas mode) + dumpfile = svntest.actions.run_and_verify_dump(sbox.repo_dir, deltas=False) + + # Load with 'svnrdump' + new_repo_dir, new_repo_url = sbox.add_repo_path('new_repo') + svntest.main.create_repos(new_repo_dir) + svntest.actions.enable_revprop_changes(new_repo_dir) + svntest.actions.run_and_verify_svnrdump(dumpfile, + svntest.verify.AnyOutput, + [], 0, 'load', new_repo_url) + # For regression test purposes, all we require is that the 'load' + # doesn't throw an error + +# Regression test for issue 4551 "svnrdump load commits wrong properties, +# or fails, on a non-deltas dumpfile". In this test, the copy source does +# exist and the failure mode is to fail to delete a property. +@XFail() +@Issue(4551) +def load_non_deltas_replace_copy_with_props(sbox): + "load non-deltas replace© with props" + sbox.build() + + # Set props on a file and on a dir + sbox.simple_propset('p', 'v', 'A/mu', 'A/B') + sbox.simple_commit() + sbox.simple_update() # avoid mixed-rev + + # Case (2): Copy file/dir, replacing something; the copy target path + # at (new rev - 1) exists and has no property named 'p' + sbox.simple_rm('A/D/gamma', 'A/C') + sbox.simple_copy('A/mu@2', 'A/D/gamma') + sbox.simple_copy('A/B@2', 'A/C') + # On the copy, delete a prop that isn't present on the replaced node + sbox.simple_propdel('p', 'A/D/gamma', 'A/C') + + sbox.simple_commit() + + # Dump with 'svnadmin' (non-deltas mode) + dumpfile = svntest.actions.run_and_verify_dump(sbox.repo_dir, deltas=False) + + # Load with 'svnrdump' + new_repo_dir, new_repo_url = sbox.add_repo_path('new_repo') + svntest.main.create_repos(new_repo_dir) + svntest.actions.enable_revprop_changes(new_repo_dir) + svntest.actions.run_and_verify_svnrdump(dumpfile, + svntest.verify.AnyOutput, + [], 0, 'load', new_repo_url) + + # Check that property 'p' really was deleted on each copied node + for tgt_path in ['A/D/gamma', 'A/C']: + _, out, _ = svntest.main.run_svn(None, 'proplist', + new_repo_url + '/' + tgt_path) + expected = [] + actual = out[1:] + svntest.verify.compare_and_display_lines(None, 'PROPS', expected, actual) ######################################################################## # Run the tests @@ -855,6 +956,10 @@ test_list = [ None, only_trunk_range_dump, only_trunk_A_range_dump, load_prop_change_in_non_deltas_dump, + dump_mergeinfo_contains_r0, + load_mergeinfo_contains_r0, + load_non_deltas_copy_with_props, + load_non_deltas_replace_copy_with_props, ] if __name__ == '__main__': Modified: subversion/branches/svn-auth-x509/subversion/tests/cmdline/svnsync_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/tests/cmdline/svnsync_tests.py?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/tests/cmdline/svnsync_tests.py (original) +++ subversion/branches/svn-auth-x509/subversion/tests/cmdline/svnsync_tests.py Fri Jan 16 14:01:35 2015 @@ -209,8 +209,12 @@ def setup_and_sync(sbox, dump_file_conte return dest_sbox -def verify_mirror(dest_sbox, src_sbox): - """Compare the contents of the DEST_SBOX repository with EXP_DUMP_FILE_CONTENTS.""" +def verify_mirror(dest_sbox, exp_dump_file_contents): + """Compare the contents of the mirror repository in DEST_SBOX with + EXP_DUMP_FILE_CONTENTS, by comparing the parsed dump stream content. + + First remove svnsync rev-props from the DEST_SBOX repository. + """ # Remove some SVNSync-specific housekeeping properties from the # mirror repository in preparation for the comparison dump. @@ -222,10 +226,9 @@ def verify_mirror(dest_sbox, src_sbox): # Create a dump file from the mirror repository. dest_dump = svntest.actions.run_and_verify_dump(dest_sbox.repo_dir) - src_dump = svntest.actions.run_and_verify_dump(src_sbox.repo_dir) svntest.verify.compare_dump_files( - "Dump files", "DUMP", src_dump, dest_dump) + "Dump files", "DUMP", exp_dump_file_contents, dest_dump) def run_test(sbox, dump_file_name, subdir=None, exp_dump_file_name=None, bypass_prop_validation=False, source_prop_encoding=None, @@ -251,16 +254,12 @@ or another dump file.""" # dump file (used to create the master repository) or another specified dump # file. if exp_dump_file_name: - build_repos(sbox) - svntest.actions.run_and_verify_load(sbox.repo_dir, - open(os.path.join(svnsync_tests_dir, - exp_dump_file_name), - 'rb').readlines()) - src_sbox = sbox + exp_dump_file_contents = open(os.path.join(svnsync_tests_dir, + exp_dump_file_name), 'rb').readlines() else: - src_sbox = sbox + exp_dump_file_contents = master_dumpfile_contents - verify_mirror(dest_sbox, sbox) + verify_mirror(dest_sbox, exp_dump_file_contents) @@ -564,9 +563,7 @@ def delete_revprops(sbox): run_copy_revprops(dest_sbox.repo_url, sbox.repo_url) # Does the result look as we expected? - build_repos(sbox) - svntest.actions.run_and_verify_load(sbox.repo_dir, expected_contents) - verify_mirror(dest_sbox, sbox) + verify_mirror(dest_sbox, expected_contents) @Issue(3870) @SkipUnless(svntest.main.is_posix_os) @@ -576,6 +573,15 @@ def fd_leak_sync_from_serf_to_local(sbox resource.setrlimit(resource.RLIMIT_NOFILE, (128, 128)) run_test(sbox, "largemods.dump", is_src_ra_local=None, is_dest_ra_local=True) +#---------------------------------------------------------------------- + +@Issue(4476) +def mergeinfo_contains_r0(sbox): + "mergeinfo contains r0" + run_test(sbox, "mergeinfo-contains-r0.dump", + exp_dump_file_name="mergeinfo-contains-r0.expected.dump", + bypass_prop_validation=True) + ######################################################################## # Run the tests @@ -612,6 +618,7 @@ test_list = [ None, descend_into_replace, delete_revprops, fd_leak_sync_from_serf_to_local, # calls setrlimit + mergeinfo_contains_r0, ] if __name__ == '__main__': Modified: subversion/branches/svn-auth-x509/subversion/tests/cmdline/svntest/main.py URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/tests/cmdline/svntest/main.py?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/tests/cmdline/svntest/main.py (original) +++ subversion/branches/svn-auth-x509/subversion/tests/cmdline/svntest/main.py Fri Jan 16 14:01:35 2015 @@ -544,6 +544,15 @@ def run_command_stdin(command, error_exp and not any(map(lambda arg: 'prop_tests-12' in arg, varargs)): raise Failure("Repository diskpath in %s: %r" % (name, lines)) + valgrind_diagnostic = False + # A valgrind diagnostic will raise a failure if the command is + # expected to run without error. When an error is expected any + # subsequent error pattern matching is usually lenient and will not + # detect the diagnostic so make sure a failure is raised here. + if error_expected and stderr_lines: + if any(map(lambda arg: re.match('==[0-9]+==', arg), stderr_lines)): + valgrind_diagnostic = True + stop = time.time() logger.info('<TIME = %.6f>' % (stop - start)) for x in stdout_lines: @@ -551,7 +560,8 @@ def run_command_stdin(command, error_exp for x in stderr_lines: logger.info(x.rstrip()) - if (not error_expected) and ((stderr_lines) or (exit_code != 0)): + if (((not error_expected) and ((stderr_lines) or (exit_code != 0))) + or valgrind_diagnostic): for x in stderr_lines: logger.warning(x.rstrip()) if len(varargs) <= 5: Modified: subversion/branches/svn-auth-x509/subversion/tests/cmdline/update_tests.py URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/tests/cmdline/update_tests.py?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/tests/cmdline/update_tests.py (original) +++ subversion/branches/svn-auth-x509/subversion/tests/cmdline/update_tests.py Fri Jan 16 14:01:35 2015 @@ -6517,7 +6517,6 @@ def windows_update_backslash(sbox): expected_status = svntest.actions.get_virginal_state(wc_dir, 2) svntest.actions.run_and_verify_status(wc_dir, expected_status) -@XFail() # Tries to modify unlocked part of working copy; found via r1561425 def update_moved_away(sbox): "update subtree of moved away" Modified: subversion/branches/svn-auth-x509/subversion/tests/libsvn_fs/fs-test.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/tests/libsvn_fs/fs-test.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/tests/libsvn_fs/fs-test.c (original) +++ subversion/branches/svn-auth-x509/subversion/tests/libsvn_fs/fs-test.c Fri Jan 16 14:01:35 2015 @@ -6539,6 +6539,163 @@ test_fs_merge(const svn_test_opts_t *opt return SVN_NO_ERROR; } +static svn_error_t * +test_fsfs_config_opts(const svn_test_opts_t *opts, + apr_pool_t *pool) +{ + apr_hash_t *fs_config; + svn_fs_t *fs; + const svn_fs_info_placeholder_t *fs_info; + const svn_fs_fsfs_info_t *fsfs_info; + + /* Bail (with SKIP) on known-untestable scenarios */ + if (strcmp(opts->fs_type, "fsfs") != 0) + return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL, + "this will test FSFS repositories only"); + + /* Remove the test directory from previous runs. */ + SVN_ERR(svn_io_remove_dir2("test-fsfs-config-opts", TRUE, NULL, NULL, pool)); + + /* Create the test directory and add it to the test cleanup list. */ + SVN_ERR(svn_io_dir_make("test-fsfs-config-opts", APR_OS_DEFAULT, pool)); + svn_test_add_dir_cleanup("test-fsfs-config-opts"); + + /* Create an FSFS filesystem with default config.*/ + fs_config = apr_hash_make(pool); + svn_hash_sets(fs_config, SVN_FS_CONFIG_FS_TYPE, SVN_FS_TYPE_FSFS); + SVN_ERR(svn_fs_create(&fs, "test-fsfs-config-opts/default", fs_config, pool)); + + /* Re-open FS to test the data on disk. */ + SVN_ERR(svn_fs_open2(&fs, "test-fsfs-config-opts/default", NULL, pool, pool)); + + SVN_ERR(svn_fs_info(&fs_info, fs, pool, pool)); + SVN_TEST_STRING_ASSERT(fs_info->fs_type, SVN_FS_TYPE_FSFS); + fsfs_info = (const void *) fs_info; + + /* Check FSFS specific info. Don't check the SHARD_SIZE, because it depends + * on a compile-time constant and may be overridden. */ + SVN_TEST_ASSERT(fsfs_info->log_addressing); + SVN_TEST_ASSERT(fsfs_info->min_unpacked_rev == 0); + + /* Create an FSFS filesystem with custom settings: disabled log-addressing + * and custom shard size (123). */ + fs_config = apr_hash_make(pool); + svn_hash_sets(fs_config, SVN_FS_CONFIG_FS_TYPE, SVN_FS_TYPE_FSFS); + svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_LOG_ADDRESSING, "false"); + svn_hash_sets(fs_config, SVN_FS_CONFIG_FSFS_SHARD_SIZE, "123"); + SVN_ERR(svn_fs_create(&fs, "test-fsfs-config-opts/custom", fs_config, pool)); + + /* Re-open FS to test the data on disk. */ + SVN_ERR(svn_fs_open2(&fs, "test-fsfs-config-opts/custom", NULL, pool, pool)); + + SVN_ERR(svn_fs_info(&fs_info, fs, pool, pool)); + SVN_TEST_STRING_ASSERT(fs_info->fs_type, SVN_FS_TYPE_FSFS); + fsfs_info = (const void *) fs_info; + + /* Check FSFS specific info, including the SHARD_SIZE. */ + SVN_TEST_ASSERT(fsfs_info->log_addressing == FALSE); + SVN_TEST_ASSERT(fsfs_info->shard_size == 123); + SVN_TEST_ASSERT(fsfs_info->min_unpacked_rev == 0); + + return SVN_NO_ERROR; +} + +static svn_error_t * +test_txn_pool_lifetime(const svn_test_opts_t *opts, + apr_pool_t *pool) +{ + /* Technically, the FS API makes no assumption on the lifetime of logically + * dependent objects. In particular, a txn root object may get destroyed + * after the FS object that it has been built upon. Actual data access is + * implied to be invalid without a valid svn_fs_t. + * + * This test verifies that at least the destruction order of those two + * objects is arbitrary. + */ + svn_fs_t *fs; + svn_fs_txn_t *txn; + svn_fs_root_t *txn_root; + + /* We will allocate FS in FS_POOL. Using a separate allocator makes + * sure that we actually free the memory when destroying the pool. + */ + apr_allocator_t *fs_allocator = svn_pool_create_allocator(FALSE); + apr_pool_t *fs_pool = apr_allocator_owner_get(fs_allocator); + + /* Create a new repo. */ + SVN_ERR(svn_test__create_fs(&fs, "test-repo-pool-lifetime", + opts, fs_pool)); + + /* Create a TXN_ROOT referencing FS. */ + SVN_ERR(svn_fs_begin_txn(&txn, fs, 0, pool)); + SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool)); + + /* Destroy FS. Depending on the actual allocator implementation, + * these memory pages becomes inaccessible. */ + svn_pool_destroy(fs_pool); + + /* Unclean implementations will try to access FS and may segfault here. */ + svn_fs_close_root(txn_root); + + return SVN_NO_ERROR; +} + +static svn_error_t * +test_modify_txn_being_written(const svn_test_opts_t *opts, + apr_pool_t *pool) +{ + /* FSFS has a limitation (and check) that only one file can be + * modified in TXN at time: see r861812 and svn_fs_apply_text() docstring. + * This is regression test for this behavior. */ + svn_fs_t *fs; + svn_fs_txn_t *txn; + const char *txn_name; + svn_fs_root_t *txn_root; + svn_stream_t *foo_contents; + svn_stream_t *bar_contents; + + /* Bail (with success) on known-untestable scenarios */ + if (strcmp(opts->fs_type, SVN_FS_TYPE_FSFS) != 0) + return svn_error_create(SVN_ERR_TEST_SKIPPED, NULL, + "this will test FSFS repositories only"); + + /* Create a new repo. */ + SVN_ERR(svn_test__create_fs(&fs, "test-modify-txn-being-written", + opts, pool)); + + /* Create a TXN_ROOT referencing FS. */ + SVN_ERR(svn_fs_begin_txn(&txn, fs, 0, pool)); + SVN_ERR(svn_fs_txn_name(&txn_name, txn, pool)); + SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool)); + + /* Make file /foo and open for writing.*/ + SVN_ERR(svn_fs_make_file(txn_root, "/foo", pool)); + SVN_ERR(svn_fs_apply_text(&foo_contents, txn_root, "/foo", NULL, pool)); + + /* Attempt to modify another file '/bar' -- FSFS doesn't allow this. */ + SVN_ERR(svn_fs_make_file(txn_root, "/bar", pool)); + SVN_TEST_ASSERT_ERROR( + svn_fs_apply_text(&bar_contents, txn_root, "/bar", NULL, pool), + SVN_ERR_FS_REP_BEING_WRITTEN); + + /* *Reopen TXN. */ + SVN_ERR(svn_fs_open_txn(&txn, fs, txn_name, pool)); + SVN_ERR(svn_fs_txn_root(&txn_root, txn, pool)); + + /* Check that file '/bar' still cannot be modified */ + SVN_TEST_ASSERT_ERROR( + svn_fs_apply_text(&bar_contents, txn_root, "/bar", NULL, pool), + SVN_ERR_FS_REP_BEING_WRITTEN); + + /* Close file '/foo'. */ + SVN_ERR(svn_stream_close(foo_contents)); + + /* Now file '/bar' can be modified. */ + SVN_ERR(svn_fs_apply_text(&bar_contents, txn_root, "/bar", NULL, pool)); + + return SVN_NO_ERROR; +} + /* ------------------------------------------------------------------------ */ /* The test table. */ @@ -6662,6 +6819,12 @@ static struct svn_test_descriptor_t test "get a delta stream on a file"), SVN_TEST_OPTS_PASS(test_fs_merge, "get merging txns with newer revisions"), + SVN_TEST_OPTS_PASS(test_fsfs_config_opts, + "test creating FSFS repository with different opts"), + SVN_TEST_OPTS_PASS(test_txn_pool_lifetime, + "test pool lifetime dependencies with txn roots"), + SVN_TEST_OPTS_PASS(test_modify_txn_being_written, + "test modify txn being written in FSFS"), SVN_TEST_NULL }; Propchange: subversion/branches/svn-auth-x509/subversion/tests/libsvn_fs_fs/ ------------------------------------------------------------------------------ --- svn:ignore (original) +++ svn:ignore Fri Jan 16 14:01:35 2015 @@ -4,8 +4,7 @@ Release test-repo-* upgrade_* fs-pack-test -fs-fs-fuzzy-test -fs-fs-pack-test +fs-fs-*-test test-get-set-revprop-packed-fs get_set_multiple_huge_revprops_packed_fs *.o Modified: subversion/branches/svn-auth-x509/subversion/tests/libsvn_fs_fs/fs-fs-fuzzy-test.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/tests/libsvn_fs_fs/fs-fs-fuzzy-test.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/tests/libsvn_fs_fs/fs-fs-fuzzy-test.c (original) +++ subversion/branches/svn-auth-x509/subversion/tests/libsvn_fs_fs/fs-fs-fuzzy-test.c Fri Jan 16 14:01:35 2015 @@ -133,7 +133,7 @@ fuzzing_1_byte_1_rev(const char *repo_na /* Let us know where we were too strict ... */ printf("Detected case change in checksum digest at offset 0x%" APR_UINT64_T_HEX_FMT " (%" APR_OFF_T_FMT ") in r%ld: " - "%c -> %c\n", i, i, revision, c_old, c_new); + "%c -> %c\n", (apr_uint64_t)i, i, revision, c_old, c_new); SVN_ERR(err); } @@ -143,7 +143,7 @@ fuzzing_1_byte_1_rev(const char *repo_na /* Let us know where we miss changes ... */ printf("Undetected mod at offset 0x%"APR_UINT64_T_HEX_FMT " (%"APR_OFF_T_FMT") in r%ld: 0x%02x -> 0x%02x\n", - i, i, revision, c_old, c_new); + (apr_uint64_t)i, i, revision, c_old, c_new); SVN_TEST_ASSERT(err); }
