Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/cache-membuffer.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/cache-membuffer.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_subr/cache-membuffer.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/cache-membuffer.c Fri Jan 16 14:01:35 2015 @@ -31,6 +31,7 @@ #include "cache.h" #include "svn_string.h" #include "svn_sorts.h" /* get the MIN macro */ +#include "private/svn_atomic.h" #include "private/svn_dep_compat.h" #include "private/svn_mutex.h" #include "private/svn_pseudo_md5.h" @@ -364,7 +365,7 @@ typedef struct entry_t /* Number of (read) hits for this entry. Will be reset upon write. * Only valid for used entries. */ - apr_uint32_t hit_count; + svn_atomic_t hit_count; /* Reference to the next used entry in the order defined by offset. * NO_INDEX indicates the end of the list; this entry must be referenced @@ -557,19 +558,14 @@ struct svn_membuffer_t */ cache_level_t l2; + /* Number of used dictionary entries, i.e. number of cached items. - * In conjunction with hit_count, this is used calculate the average - * hit count as part of the randomized LFU algorithm. + * Purely statistical information that may be used for profiling only. + * Updates are not synchronized and values may be nonsensicle on some + * platforms. */ apr_uint32_t used_entries; - /* Sum of (read) hit counts of all used dictionary entries. - * In conjunction used_entries used_entries, this is used calculate - * the average hit count as part of the randomized LFU algorithm. - */ - apr_uint64_t hit_count; - - /* Total number of calls to membuffer_cache_get. * Purely statistical information that may be used for profiling only. * Updates are not synchronized and values may be nonsensicle on some @@ -608,12 +604,6 @@ struct svn_membuffer_t */ svn_boolean_t allow_blocking_writes; #endif - - /* All counters that have consistency requirements on thems (currently, - * that's only the hit counters) must use this mutex to serialize their - * updates. - */ - svn_mutex__t *counter_mutex; }; /* Align integer VALUE to the next ITEM_ALIGNMENT boundary. @@ -715,7 +705,7 @@ unlock_cache(svn_membuffer_t *cache, svn #if APR_HAS_THREADS # if USE_SIMPLE_MUTEX - return svn_mutex__unlock(cache->lock, SVN_NO_ERROR); + return svn_mutex__unlock(cache->lock, err); # else @@ -1027,7 +1017,6 @@ drop_entry(svn_membuffer_t *cache, entry /* update global cache usage counters */ cache->used_entries--; - cache->hit_count -= entry->hit_count; cache->data_used -= entry->size; /* extend the insertion window, if the entry happens to border it @@ -1163,7 +1152,6 @@ let_entry_age(svn_membuffer_t *cache, en if (hits_removed) { - cache->hit_count -= hits_removed; entry->hit_count -= hits_removed; } else @@ -1795,7 +1783,6 @@ svn_cache__membuffer_cache_create(svn_me c[seg].max_entry_size = max_entry_size; c[seg].used_entries = 0; - c[seg].hit_count = 0; c[seg].total_reads = 0; c[seg].total_writes = 0; c[seg].total_hits = 0; @@ -1836,11 +1823,6 @@ svn_cache__membuffer_cache_create(svn_me */ c[seg].allow_blocking_writes = allow_blocking_writes; #endif - - /* Since a simple mutex already guarantees fully serialized access, - we need this mutex only when we use multple-reader-1-writer locks. */ - SVN_ERR(svn_mutex__init(&c[seg].counter_mutex, - thread_safe && !USE_SIMPLE_MUTEX, pool)); } /* done here @@ -2067,21 +2049,17 @@ membuffer_cache_set(svn_membuffer_t *cac /* Count a hit in ENTRY within CACHE. */ -static svn_error_t * +static void increment_hit_counters(svn_membuffer_t *cache, entry_t *entry) { /* To minimize the memory footprint of the cache index, we limit local - * hit counters to 32 bits. These may overflow and we must make sure that - * the global sums are still the sum of all local counters. */ - if (++entry->hit_count == 0) - cache->hit_count -= APR_UINT32_MAX; - else - cache->hit_count++; + * hit counters to 32 bits. These may overflow but we don't really + * care because at worst, ENTRY will be dropped from cache once every + * few billion hits. */ + svn_atomic_inc(&entry->hit_count); /* That one is for stats only. */ cache->total_hits++; - - return SVN_NO_ERROR; } /* Look for the cache entry in group GROUP_INDEX of CACHE, identified @@ -2140,8 +2118,7 @@ membuffer_cache_get_internal(svn_membuff /* update hit statistics */ - SVN_MUTEX__WITH_LOCK(cache->counter_mutex, - increment_hit_counters(cache, entry)); + increment_hit_counters(cache, entry); *item_size = entry->size; return SVN_NO_ERROR; @@ -2205,9 +2182,7 @@ membuffer_cache_has_key_internal(svn_mem again. While items in L1 are well protected for a while, L2 items may get evicted soon. Thus, mark all them as "hit" to give them a higher chance of survival. */ - SVN_MUTEX__WITH_LOCK(cache->counter_mutex, - increment_hit_counters(cache, entry)); - + increment_hit_counters(cache, entry); *found = TRUE; } else @@ -2276,9 +2251,7 @@ membuffer_cache_get_partial_internal(svn else { *found = TRUE; - - SVN_MUTEX__WITH_LOCK(cache->counter_mutex, - increment_hit_counters(cache, entry)); + increment_hit_counters(cache, entry); #ifdef SVN_DEBUG_CACHE_MEMBUFFER @@ -2368,8 +2341,7 @@ membuffer_cache_set_partial_internal(svn char *orig_data = data; apr_size_t size = entry->size; - SVN_MUTEX__WITH_LOCK(cache->counter_mutex, - increment_hit_counters(cache, entry)); + increment_hit_counters(cache, entry); cache->total_writes++; #ifdef SVN_DEBUG_CACHE_MEMBUFFER @@ -2398,6 +2370,8 @@ membuffer_cache_set_partial_internal(svn * We better drop that. */ drop_entry(cache, entry); + + return err; } else {
Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/cache.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/cache.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_subr/cache.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/cache.c Fri Jan 16 14:01:35 2015 @@ -259,15 +259,15 @@ svn_cache__format_info(const svn_cache__ int i; int count = sizeof(info->histogram) / sizeof(info->histogram[0]); - for (i = 0; i < count; ++i) + for (i = count - 1; i >= 0; --i) if (info->histogram[i] > 0 || text->len > 0) text = svn_stringbuf_createf(result_pool, i == count - 1 - ? "%12" APR_UINT64_T_FMT - " buckets with >%d entries\n%s" - : "%12" APR_UINT64_T_FMT - " buckets with %d entries\n%s", - info->histogram[i], i, text->data); + ? "%s%12" APR_UINT64_T_FMT + " buckets with >%d entries\n" + : "%s%12" APR_UINT64_T_FMT + " buckets with %d entries\n", + text->data, info->histogram[i], i); histogram = text->data; } Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/cache_config.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/cache_config.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_subr/cache_config.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/cache_config.c Fri Jan 16 14:01:35 2015 @@ -27,6 +27,7 @@ #include "private/svn_cache.h" #include "svn_pools.h" +#include "svn_sorts.h" /* The cache settings as a process-wide singleton. */ @@ -80,7 +81,13 @@ initialize_cache(void *baton, apr_pool_t svn_membuffer_t **cache_p = baton; svn_membuffer_t *cache = NULL; - apr_uint64_t cache_size = cache_settings.cache_size; + /* Limit the cache size to about half the available address space + * (typ. 1G under 32 bits). + */ + apr_uint64_t cache_size = MIN(cache_settings.cache_size, + (apr_uint64_t)SVN_MAX_OBJECT_SIZE / 2); + + /* Create caches at all? */ if (cache_size) { svn_error_t *err; Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/config.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/config.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_subr/config.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/config.c Fri Jan 16 14:01:35 2015 @@ -514,14 +514,15 @@ make_string_from_option(const char **val expand_option_value(cfg, section, opt->value, &opt->x_value, tmp_pool); opt->expanded = TRUE; - if (!x_pool) + if (x_pool != cfg->x_pool) { /* Grab the fully expanded value from tmp_pool before its disappearing act. */ if (opt->x_value) opt->x_value = apr_pstrmemdup(cfg->x_pool, opt->x_value, strlen(opt->x_value)); - svn_pool_destroy(tmp_pool); + if (!x_pool) + svn_pool_destroy(tmp_pool); } } else Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/error.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/error.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_subr/error.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/error.c Fri Jan 16 14:01:35 2015 @@ -288,6 +288,8 @@ svn_error_compose(svn_error_t *chain, sv *chain = *new_err; if (chain->message) chain->message = apr_pstrdup(pool, new_err->message); + if (chain->file) + chain->file = apr_pstrdup(pool, new_err->file); chain->pool = pool; #if defined(SVN_DEBUG) if (! new_err->child) @@ -364,6 +366,8 @@ svn_error_dup(const svn_error_t *err) tmp_err->pool = pool; if (tmp_err->message) tmp_err->message = apr_pstrdup(pool, tmp_err->message); + if (tmp_err->file) + tmp_err->file = apr_pstrdup(pool, tmp_err->file); } #if defined(SVN_DEBUG) @@ -425,10 +429,8 @@ svn_error_purge_tracing(svn_error_t *err if (! err) return svn_error_create( SVN_ERR_ASSERTION_ONLY_TRACING_LINKS, - svn_error_compose_create( - svn_error__malfunction(TRUE, __FILE__, __LINE__, - NULL /* ### say something? */), - err), + svn_error__malfunction(TRUE, __FILE__, __LINE__, + NULL /* ### say something? */), NULL); /* Copy the current error except for its child error pointer Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/io.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/io.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_subr/io.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/io.c Fri Jan 16 14:01:35 2015 @@ -1170,10 +1170,10 @@ svn_io_make_dir_recursively(const char * } svn_error_t * -svn_io_file_create_binary(const char *file, - const char *contents, - apr_size_t length, - apr_pool_t *pool) +svn_io_file_create_bytes(const char *file, + const void *contents, + apr_size_t length, + apr_pool_t *pool) { apr_file_t *f; apr_size_t written; @@ -1209,18 +1209,17 @@ svn_io_file_create(const char *file, const char *contents, apr_pool_t *pool) { - return svn_error_trace(svn_io_file_create_binary(file, contents, - contents - ? strlen(contents) - : 0, - pool)); + return svn_error_trace(svn_io_file_create_bytes(file, contents, + contents ? strlen(contents) + : 0, + pool)); } svn_error_t * svn_io_file_create_empty(const char *file, apr_pool_t *pool) { - return svn_error_trace(svn_io_file_create_binary(file, "", 0, pool)); + return svn_error_trace(svn_io_file_create_bytes(file, NULL, 0, pool)); } svn_error_t * Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/mergeinfo.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/mergeinfo.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_subr/mergeinfo.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/mergeinfo.c Fri Jan 16 14:01:35 2015 @@ -99,9 +99,6 @@ parse_pathname(const char **input, if (!last_colon) return svn_error_create(SVN_ERR_MERGEINFO_PARSE_ERROR, NULL, _("Pathname not terminated by ':'")); - if (last_colon == *input) - return svn_error_create(SVN_ERR_MERGEINFO_PARSE_ERROR, NULL, - _("No pathname preceding ':'")); /* Tolerate relative repository paths, but convert them to absolute. ### Efficiency? 1 string duplication here, 2 in canonicalize. */ @@ -612,7 +609,12 @@ svn_rangelist__parse(svn_rangelist_t **r } /* Return TRUE, if all ranges in RANGELIST are in ascending order and do - * not overlap. If this returns FALSE, you probaly want to qsort() the + * not overlap and are not adjacent. + * + * ### Can yield false negatives: ranges of differing inheritance are + * allowed to be adjacent. + * + * If this returns FALSE, you probaly want to qsort() the * ranges and then call svn_rangelist__combine_adjacent_ranges(). */ static svn_boolean_t @@ -629,6 +631,20 @@ is_rangelist_normalized(svn_rangelist_t } svn_error_t * +svn_rangelist__canonicalize(svn_rangelist_t *rangelist, + apr_pool_t *scratch_pool) +{ + if (! is_rangelist_normalized(rangelist)) + { + svn_sort__array(rangelist, svn_sort_compare_ranges); + + SVN_ERR(svn_rangelist__combine_adjacent_ranges(rangelist, scratch_pool)); + } + + return SVN_NO_ERROR; +} + +svn_error_t * svn_rangelist__combine_adjacent_ranges(svn_rangelist_t *rangelist, apr_pool_t *scratch_pool) { @@ -715,14 +731,9 @@ parse_revision_line(const char **input, /* Sort the rangelist, combine adjacent ranges into single ranges, and make sure there are no overlapping ranges. Luckily, most data in - svn:mergeinfo will already be in normalized form and we can skip this. + svn:mergeinfo will already be in normalized form and this will be quick. */ - if (! is_rangelist_normalized(rangelist)) - { - svn_sort__array(rangelist, svn_sort_compare_ranges); - - SVN_ERR(svn_rangelist__combine_adjacent_ranges(rangelist, scratch_pool)); - } + SVN_ERR(svn_rangelist__canonicalize(rangelist, scratch_pool)); /* Handle any funky mergeinfo with relative merge source paths that might exist due to issue #3547. It's possible that this issue allowed @@ -1999,6 +2010,22 @@ svn_mergeinfo_sort(svn_mergeinfo_t input return SVN_NO_ERROR; } +svn_error_t * +svn_mergeinfo__canonicalize_ranges(svn_mergeinfo_t mergeinfo, + apr_pool_t *scratch_pool) +{ + apr_hash_index_t *hi; + + for (hi = apr_hash_first(scratch_pool, mergeinfo); hi; hi = apr_hash_next(hi)) + { + apr_array_header_t *rl = apr_hash_this_val(hi); + + SVN_ERR(svn_rangelist__canonicalize(rl, scratch_pool)); + } + + return SVN_NO_ERROR; +} + svn_mergeinfo_catalog_t svn_mergeinfo_catalog_dup(svn_mergeinfo_catalog_t mergeinfo_catalog, apr_pool_t *pool) Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/string.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/string.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_subr/string.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/string.c Fri Jan 16 14:01:35 2015 @@ -655,23 +655,18 @@ svn_stringbuf_insert(svn_stringbuf_t *st if (count == 0) return; + /* special case: BYTES overlaps with this string -> copy the source */ if (bytes + count > str->data && bytes < str->data + str->blocksize) - { - /* special case: BYTES overlaps with this string -> copy the source */ - const char *temp = apr_pstrndup(str->pool, bytes, count); - svn_stringbuf_insert(str, pos, temp, count); - } - else - { - if (pos > str->len) - pos = str->len; + bytes = apr_pmemdup(str->pool, bytes, count); + + if (pos > str->len) + pos = str->len; - svn_stringbuf_ensure(str, str->len + count); - memmove(str->data + pos + count, str->data + pos, str->len - pos + 1); - memcpy(str->data + pos, bytes, count); + svn_stringbuf_ensure(str, str->len + count); + memmove(str->data + pos + count, str->data + pos, str->len - pos + 1); + memcpy(str->data + pos, bytes, count); - str->len += count; - } + str->len += count; } void @@ -703,32 +698,27 @@ svn_stringbuf_replace(svn_stringbuf_t *s return; } + /* special case: BYTES overlaps with this string -> copy the source */ if (bytes + new_count > str->data && bytes < str->data + str->blocksize) + bytes = apr_pmemdup(str->pool, bytes, new_count); + + if (pos > str->len) + pos = str->len; + if (pos + old_count > str->len) + old_count = str->len - pos; + + if (old_count < new_count) { - /* special case: BYTES overlaps with this string -> copy the source */ - const char *temp = apr_pstrndup(str->pool, bytes, new_count); - svn_stringbuf_replace(str, pos, old_count, temp, new_count); + apr_size_t delta = new_count - old_count; + svn_stringbuf_ensure(str, str->len + delta); } - else - { - if (pos > str->len) - pos = str->len; - if (pos + old_count > str->len) - old_count = str->len - pos; - if (old_count < new_count) - { - apr_size_t delta = new_count - old_count; - svn_stringbuf_ensure(str, str->len + delta); - } + if (old_count != new_count) + memmove(str->data + pos + new_count, str->data + pos + old_count, + str->len - pos - old_count + 1); - if (old_count != new_count) - memmove(str->data + pos + new_count, str->data + pos + old_count, - str->len - pos - old_count + 1); - - memcpy(str->data + pos, bytes, new_count); - str->len += new_count - old_count; - } + memcpy(str->data + pos, bytes, new_count); + str->len += new_count - old_count; } @@ -879,7 +869,7 @@ char * svn_cstring_tokenize(const char *sep, char **str) { char *token; - const char * next; + char *next; char csep; /* check parameters */ @@ -909,8 +899,8 @@ svn_cstring_tokenize(const char *sep, ch } else { - *(char *)next = '\0'; - *str = (char *)next + 1; + *next = '\0'; + *str = next + 1; } return token; Modified: subversion/branches/svn-auth-x509/subversion/libsvn_subr/sysinfo.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_subr/sysinfo.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_subr/sysinfo.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_subr/sysinfo.c Fri Jan 16 14:01:35 2015 @@ -55,6 +55,10 @@ #ifdef SVN_HAVE_MACOS_PLIST #include <CoreFoundation/CoreFoundation.h> +#include <AvailabilityMacros.h> +# ifndef MAC_OS_X_VERSION_10_6 +# define MAC_OS_X_VERSION_10_6 1060 +# endif #endif #ifdef SVN_HAVE_MACHO_ITERATE @@ -927,7 +931,6 @@ system_version_plist(svn_boolean_t *serv svn_error_t *err; CFPropertyListRef plist = NULL; CFMutableDataRef resource = CFDataCreateMutable(kCFAllocatorDefault, 0); - CFStringRef errstr = NULL; /* failed getting the CFMutableDataRef, shouldn't happen */ if (!resource) @@ -940,6 +943,7 @@ system_version_plist(svn_boolean_t *serv if (!APR_STATUS_IS_ENOENT(err->apr_err)) { svn_error_clear(err); + CFRelease(resource); return NULL; } else @@ -950,6 +954,7 @@ system_version_plist(svn_boolean_t *serv if (err) { svn_error_clear(err); + CFRelease(resource); return NULL; } @@ -972,16 +977,23 @@ system_version_plist(svn_boolean_t *serv return NULL; } - /* ### CFPropertyListCreateFromXMLData is obsolete, but its - replacement CFPropertyListCreateWithData is only available - from Mac OS 10.6 onward. */ +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + /* This function is only available from Mac OS 10.6 onward. */ + plist = CFPropertyListCreateWithData(kCFAllocatorDefault, resource, + kCFPropertyListImmutable, + NULL, NULL); +#else /* Mac OS 10.5 or earlier */ + /* This function obsolete and deprecated since Mac OS 10.10. */ plist = CFPropertyListCreateFromXMLData(kCFAllocatorDefault, resource, kCFPropertyListImmutable, - &errstr); + NULL); +#endif /* MAC_OS_X_VERSION_10_6 */ + if (resource) CFRelease(resource); - if (errstr) - CFRelease(errstr); + + if (!plist) + return NULL; if (CFDictionaryGetTypeID() != CFGetTypeID(plist)) { Modified: subversion/branches/svn-auth-x509/subversion/libsvn_wc/conflicts.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_wc/conflicts.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_wc/conflicts.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_wc/conflicts.c Fri Jan 16 14:01:35 2015 @@ -2694,6 +2694,7 @@ resolve_tree_conflict_on_node(svn_boolea svn_skel_t *conflicts; svn_wc_operation_t operation; svn_boolean_t tree_conflicted; + const char *src_op_root_abspath; *did_resolve = FALSE; @@ -2708,7 +2709,8 @@ resolve_tree_conflict_on_node(svn_boolea if (!tree_conflicted) return SVN_NO_ERROR; - SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, &action, NULL, + SVN_ERR(svn_wc__conflict_read_tree_conflict(&reason, &action, + &src_op_root_abspath, db, local_abspath, conflicts, scratch_pool, scratch_pool)); @@ -2725,7 +2727,8 @@ resolve_tree_conflict_on_node(svn_boolea /* Break moves for any children moved out of this directory, * and leave this directory deleted. */ SVN_ERR(svn_wc__db_resolve_break_moved_away_children( - db, local_abspath, notify_func, notify_baton, + db, local_abspath, src_op_root_abspath, + notify_func, notify_baton, scratch_pool)); *did_resolve = TRUE; } @@ -2807,6 +2810,7 @@ resolve_tree_conflict_on_node(svn_boolea ### involving the move until ### svn_wc__db_op_mark_resolved. */ SVN_ERR(svn_wc__db_resolve_break_moved_away(db, local_abspath, + src_op_root_abspath, notify_func, notify_baton, scratch_pool)); Modified: subversion/branches/svn-auth-x509/subversion/libsvn_wc/externals.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_wc/externals.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_wc/externals.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_wc/externals.c Fri Jan 16 14:01:35 2015 @@ -159,7 +159,7 @@ find_and_remove_externals_revision(int * svn_error_t * svn_wc_parse_externals_description3(apr_array_header_t **externals_p, - const char *parent_directory, + const char *defining_directory, const char *desc, svn_boolean_t canonicalize_url, apr_pool_t *pool) @@ -167,8 +167,8 @@ svn_wc_parse_externals_description3(apr_ int i; apr_array_header_t *externals = NULL; apr_array_header_t *lines = svn_cstring_split(desc, "\n\r", TRUE, pool); - const char *parent_directory_display = svn_path_is_url(parent_directory) ? - parent_directory : svn_dirent_local_style(parent_directory, pool); + const char *defining_directory_display = svn_path_is_url(defining_directory) ? + defining_directory : svn_dirent_local_style(defining_directory, pool); /* If an error occurs halfway through parsing, *externals_p should stay * untouched. So, store the list in a local var first. */ @@ -231,7 +231,7 @@ svn_wc_parse_externals_description3(apr_ (SVN_ERR_CLIENT_INVALID_EXTERNALS_DESCRIPTION, NULL, _("Error parsing %s property on '%s': '%s'"), SVN_PROP_EXTERNALS, - parent_directory_display, + defining_directory_display, line); /* To make it easy to check for the forms, find and remove -r N @@ -242,7 +242,7 @@ svn_wc_parse_externals_description3(apr_ SVN_ERR(find_and_remove_externals_revision(&rev_idx, (const char **)line_parts, num_line_parts, item, - parent_directory_display, + defining_directory_display, line, pool)); token0 = line_parts[0]; @@ -258,7 +258,7 @@ svn_wc_parse_externals_description3(apr_ "cannot use two absolute URLs ('%s' and '%s') in an external; " "one must be a path where an absolute or relative URL is " "checked out to"), - SVN_PROP_EXTERNALS, parent_directory_display, token0, token1); + SVN_PROP_EXTERNALS, defining_directory_display, token0, token1); if (0 == rev_idx && token1_is_url) return svn_error_createf @@ -266,7 +266,7 @@ svn_wc_parse_externals_description3(apr_ _("Invalid %s property on '%s': " "cannot use a URL '%s' as the target directory for an external " "definition"), - SVN_PROP_EXTERNALS, parent_directory_display, token1); + SVN_PROP_EXTERNALS, defining_directory_display, token1); if (1 == rev_idx && token0_is_url) return svn_error_createf @@ -274,7 +274,7 @@ svn_wc_parse_externals_description3(apr_ _("Invalid %s property on '%s': " "cannot use a URL '%s' as the target directory for an external " "definition"), - SVN_PROP_EXTERNALS, parent_directory_display, token0); + SVN_PROP_EXTERNALS, defining_directory_display, token0); /* The appearance of -r N or -rN forces the type of external. If -r is at the beginning of the line or the first token is @@ -316,7 +316,7 @@ svn_wc_parse_externals_description3(apr_ _("Invalid %s property on '%s': " "target '%s' is an absolute path or involves '..'"), SVN_PROP_EXTERNALS, - parent_directory_display, + defining_directory_display, item->target_dir); if (canonicalize_url) Modified: subversion/branches/svn-auth-x509/subversion/libsvn_wc/node.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_wc/node.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_wc/node.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_wc/node.c Fri Jan 16 14:01:35 2015 @@ -636,7 +636,6 @@ svn_wc__node_get_base(svn_node_kind_t *k svn_wc_context_t *wc_ctx, const char *local_abspath, svn_boolean_t ignore_enoent, - svn_boolean_t show_hidden, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { @@ -656,9 +655,8 @@ svn_wc__node_get_base(svn_node_kind_t *k if (err && err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND) return svn_error_trace(err); else if (err - || (!err && !show_hidden - && (status != svn_wc__db_status_normal - && status != svn_wc__db_status_incomplete))) + || (status != svn_wc__db_status_normal + && status != svn_wc__db_status_incomplete)) { if (!ignore_enoent) { Modified: subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc-queries.sql URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc-queries.sql?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc-queries.sql (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc-queries.sql Fri Jan 16 14:01:35 2015 @@ -235,11 +235,11 @@ WHERE wc_id = ?1 AND IS_STRICT_DESCENDAN DELETE FROM nodes WHERE wc_id = ?1 AND IS_STRICT_DESCENDANT_OF(local_relpath, ?2) AND presence = MAP_BASE_DELETED - AND op_depth > 0 + AND op_depth > ?3 AND op_depth = (SELECT MIN(op_depth) FROM nodes n WHERE n.wc_id = ?1 AND n.local_relpath = nodes.local_relpath - AND op_depth > 0) + AND op_depth > ?3) -- STMT_DELETE_WORKING_RECURSIVE DELETE FROM nodes Modified: subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc_db.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc_db.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc_db.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc_db.c Fri Jan 16 14:01:35 2015 @@ -1561,6 +1561,7 @@ svn_wc__db_init(svn_wc__db_t *db, svn_wc__db_wcroot_t *wcroot; svn_boolean_t sqlite_exclusive = FALSE; apr_int32_t sqlite_timeout = 0; /* default timeout */ + apr_hash_index_t *hi; SVN_ERR_ASSERT(svn_dirent_is_absolute(local_abspath)); SVN_ERR_ASSERT(repos_relpath != NULL); @@ -1593,6 +1594,16 @@ svn_wc__db_init(svn_wc__db_t *db, /* The WCROOT is complete. Stash it into DB. */ svn_hash_sets(db->dir_data, wcroot->abspath, wcroot); + /* Any previously cached children now have a new WCROOT. */ + for (hi = apr_hash_first(scratch_pool, db->dir_data); + hi; + hi = apr_hash_next(hi)) + { + const char *abspath = apr_hash_this_key(hi); + if (svn_dirent_is_ancestor(wcroot->abspath, abspath)) + svn_hash_sets(db->dir_data, abspath, wcroot); + } + return SVN_NO_ERROR; } @@ -2340,7 +2351,7 @@ db_base_remove(svn_wc__db_wcroot_t *wcro { SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_DELETE_WORKING_BASE_DELETE)); - SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath)); + SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath, 0)); SVN_ERR(svn_sqlite__step_done(stmt)); } else @@ -7594,7 +7605,11 @@ delete_update_movedto(svn_wc__db_wcroot_ op_depth, new_moved_to_relpath)); SVN_ERR(svn_sqlite__update(&affected, stmt)); - assert(affected == 1); +#ifdef SVN_DEBUG + /* Not fatal in release mode. The move recording is broken, + but the rest of the working copy can handle this. */ + SVN_ERR_ASSERT(affected == 1); +#endif return SVN_NO_ERROR; } @@ -7984,7 +7999,12 @@ delete_node(void *baton, child_relpath)) child_op_depth = delete_op_depth; else - child_op_depth = relpath_depth(child_relpath); + { + /* Calculate depth of the shadowing at the new location */ + child_op_depth = child_op_depth + - relpath_depth(local_relpath) + + relpath_depth(b->moved_to_relpath); + } fixup = TRUE; } @@ -13038,6 +13058,15 @@ svn_wc__db_upgrade_get_repos_id(apr_int6 return svn_error_trace(svn_sqlite__reset(stmt)); } +svn_error_t * +svn_wc__db_wq_add_internal(svn_wc__db_wcroot_t *wcroot, + const svn_skel_t *work_item, + apr_pool_t *scratch_pool) +{ + /* Add the work item(s) to the WORK_QUEUE. */ + return svn_error_trace(add_work_items(wcroot->sdb, work_item, + scratch_pool)); +} svn_error_t * svn_wc__db_wq_add(svn_wc__db_t *db, Modified: subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc_db.h URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc_db.h?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc_db.h (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc_db.h Fri Jan 16 14:01:35 2015 @@ -3479,6 +3479,7 @@ svn_wc__db_resolve_delete_raise_moved_aw svn_error_t * svn_wc__db_resolve_break_moved_away(svn_wc__db_t *db, const char *local_abspath, + const char *src_op_root_abspath, svn_wc_notify_func2_t notify_func, void *notify_baton, apr_pool_t *scratch_pool); @@ -3491,6 +3492,7 @@ svn_wc__db_resolve_break_moved_away(svn_ svn_error_t * svn_wc__db_resolve_break_moved_away_children(svn_wc__db_t *db, const char *local_abspath, + const char *src_op_root_abspath, svn_wc_notify_func2_t notify_func, void *notify_baton, apr_pool_t *scratch_pool); Modified: subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc_db_private.h URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc_db_private.h?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc_db_private.h (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc_db_private.h Fri Jan 16 14:01:35 2015 @@ -216,6 +216,13 @@ svn_wc__db_util_open_db(svn_sqlite__db_t apr_pool_t *result_pool, apr_pool_t *scratch_pool); +/* Like svn_wc__db_wq_add() but taking WCROOT */ +svn_error_t * +svn_wc__db_wq_add_internal(svn_wc__db_wcroot_t *wcroot, + const svn_skel_t *work_item, + apr_pool_t *scratch_pool); + + /* Like svn_wc__db_read_info(), but taking WCROOT+LOCAL_RELPATH instead of DB+LOCAL_ABSPATH, and outputting repos ids instead of URL+UUID. */ svn_error_t * Modified: subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc_db_update_move.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc_db_update_move.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc_db_update_move.c (original) +++ subversion/branches/svn-auth-x509/subversion/libsvn_wc/wc_db_update_move.c Fri Jan 16 14:01:35 2015 @@ -101,6 +101,20 @@ #include "token-map.h" /* Helper functions */ +/* Return the absolute path, in local path style, of LOCAL_RELPATH + in WCROOT. */ +static const char * +path_for_error_message(const svn_wc__db_wcroot_t *wcroot, + const char *local_relpath, + apr_pool_t *result_pool) +{ + const char *local_abspath + = svn_dirent_join(wcroot->abspath, local_relpath, result_pool); + + return svn_dirent_local_style(local_abspath, result_pool); +} + +/* Ensure that there is a working copy lock for LOCAL_RELPATH in WCROOT */ static svn_error_t * verify_write_lock(svn_wc__db_wcroot_t *wcroot, const char *local_relpath, @@ -114,11 +128,8 @@ verify_write_lock(svn_wc__db_wcroot_t *w { return svn_error_createf(SVN_ERR_WC_NOT_LOCKED, NULL, _("No write-lock in '%s'"), - svn_dirent_local_style( - svn_dirent_join(wcroot->abspath, - local_relpath, - scratch_pool), - scratch_pool)); + path_for_error_message(wcroot, local_relpath, + scratch_pool)); } return SVN_NO_ERROR; @@ -308,7 +319,7 @@ mark_tree_conflict(const char *local_rel && conflict_operation != svn_wc_operation_switch) return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, _("'%s' already in conflict"), - svn_dirent_local_style(local_relpath, + path_for_error_message(wcroot, local_relpath, scratch_pool)); if (tree_conflicted) @@ -332,7 +343,8 @@ mark_tree_conflict(const char *local_rel existing_abspath)))) return svn_error_createf(SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL, _("'%s' already in conflict"), - svn_dirent_local_style(local_relpath, + path_for_error_message(wcroot, + local_relpath, scratch_pool)); /* Already a suitable tree-conflict. */ @@ -396,28 +408,33 @@ mark_tree_conflict(const char *local_rel /* Checks if a specific local path is shadowed as seen from the move root */ static svn_error_t * check_node_shadowed(svn_boolean_t *shadowed, - update_move_baton_t *b, + svn_wc__db_wcroot_t *wcroot, const char *local_relpath, + const char *move_root_dst_relpath, apr_pool_t *scratch_pool) { svn_sqlite__stmt_t *stmt; svn_boolean_t have_row; - int op_depth = -1; - *shadowed = FALSE; /* ### This should really be optimized by using something smart in the baton */ - SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb, + SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_WORKING_NODE)); - SVN_ERR(svn_sqlite__bindf(stmt, "is", b->wcroot->wc_id, local_relpath)); + SVN_ERR(svn_sqlite__bindf(stmt, "is", wcroot->wc_id, local_relpath)); + SVN_ERR(svn_sqlite__step(&have_row, stmt)); + if (have_row) - op_depth = svn_sqlite__column_int(stmt, 0); - SVN_ERR(svn_sqlite__reset(stmt)); + { + int op_depth = -1; - *shadowed = (op_depth > relpath_depth(b->move_root_dst_relpath)); + *shadowed = (op_depth > relpath_depth(move_root_dst_relpath)); + } + else + *shadowed = FALSE; + SVN_ERR(svn_sqlite__reset(stmt)); return SVN_NO_ERROR; } @@ -576,8 +593,7 @@ tc_editor_add_directory(update_move_bato SVN_ERR(svn_wc__wq_build_dir_install(&work_item, b->db, abspath, scratch_pool, scratch_pool)); - SVN_ERR(svn_wc__db_wq_add(b->db, b->wcroot->abspath, work_item, - scratch_pool)); + SVN_ERR(svn_wc__db_wq_add_internal(b->wcroot, work_item, scratch_pool)); /* Fall through */ case svn_node_dir: break; @@ -663,8 +679,7 @@ tc_editor_add_file(update_move_baton_t * TRUE /* record_file_info */, scratch_pool, scratch_pool)); - SVN_ERR(svn_wc__db_wq_add(b->db, b->wcroot->abspath, work_item, - scratch_pool)); + SVN_ERR(svn_wc__db_wq_add_internal(b->wcroot, work_item, scratch_pool)); SVN_ERR(update_move_list_add(b->wcroot, relpath, svn_wc_notify_update_add, @@ -867,8 +882,8 @@ tc_editor_alter_directory(update_move_ba SVN_ERR(svn_wc__db_mark_conflict_internal(b->wcroot, dst_relpath, conflict_skel, scratch_pool)); - SVN_ERR(svn_wc__db_wq_add(b->db, b->wcroot->abspath, work_items, - scratch_pool)); + SVN_ERR(svn_wc__db_wq_add_internal(b->wcroot, work_items, + scratch_pool)); } SVN_ERR(update_move_list_add(b->wcroot, dst_relpath, @@ -1003,8 +1018,7 @@ update_working_file(update_move_baton_t work_items = svn_wc__wq_merge(work_items, work_item, scratch_pool); } - SVN_ERR(svn_wc__db_wq_add(b->db, b->wcroot->abspath, work_items, - scratch_pool)); + SVN_ERR(svn_wc__db_wq_add_internal(b->wcroot, work_items, scratch_pool)); SVN_ERR(update_move_list_add(b->wcroot, local_relpath, svn_wc_notify_update_update, @@ -1182,8 +1196,7 @@ tc_editor_delete(update_move_baton_t *b, b->wcroot->abspath, del_abspath, iterpool, iterpool); if (!err) - err = svn_wc__db_wq_add(b->db, b->wcroot->abspath, work_item, - iterpool); + err = svn_wc__db_wq_add_internal(b->wcroot, work_item, iterpool); if (err) return svn_error_compose_create(err, svn_sqlite__reset(stmt)); @@ -1205,8 +1218,7 @@ tc_editor_delete(update_move_baton_t *b, SVN_ERR(svn_wc__wq_build_file_remove(&work_item, b->db, b->wcroot->abspath, local_abspath, iterpool, iterpool)); - SVN_ERR(svn_wc__db_wq_add(b->db, b->wcroot->abspath, work_item, - iterpool)); + SVN_ERR(svn_wc__db_wq_add_internal(b->wcroot, work_item, iterpool)); if (!is_conflicted) SVN_ERR(update_move_list_add(b->wcroot, relpath, @@ -1221,23 +1233,23 @@ tc_editor_delete(update_move_baton_t *b, /* Delete handling for both WORKING and shadowed nodes */ static svn_error_t * -delete_move_leaf(update_move_baton_t *b, - const char *relpath, +delete_move_leaf(svn_wc__db_wcroot_t *wcroot, + const char *local_relpath, + int op_depth, apr_pool_t *scratch_pool) { svn_sqlite__stmt_t *stmt; - int op_depth = relpath_depth(b->move_root_dst_relpath); - const char *parent_relpath = svn_relpath_dirname(relpath, scratch_pool); svn_boolean_t have_row; int op_depth_below; - /* Deleting the ROWS is valid so long as we update the parent before + /* Deleting the ROWS is valid as long as we update the parent before committing the transaction. The removed rows could have been replacing a lower layer in which case we need to add base-deleted rows. */ - SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb, + SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_HIGHEST_WORKING_NODE)); - SVN_ERR(svn_sqlite__bindf(stmt, "isd", b->wcroot->wc_id, parent_relpath, + SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, + svn_relpath_dirname(local_relpath, scratch_pool), op_depth)); SVN_ERR(svn_sqlite__step(&have_row, stmt)); if (have_row) @@ -1246,30 +1258,38 @@ delete_move_leaf(update_move_baton_t *b, if (have_row) { /* Remove non-shadowing nodes. */ - SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb, + SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_DELETE_NO_LOWER_LAYER)); - SVN_ERR(svn_sqlite__bindf(stmt, "isdd", b->wcroot->wc_id, relpath, + SVN_ERR(svn_sqlite__bindf(stmt, "isdd", wcroot->wc_id, local_relpath, op_depth, op_depth_below)); SVN_ERR(svn_sqlite__step_done(stmt)); /* Convert remaining shadowing nodes to presence='base-deleted'. */ - SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb, + SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_REPLACE_WITH_BASE_DELETED)); - SVN_ERR(svn_sqlite__bindf(stmt, "isd", b->wcroot->wc_id, relpath, + SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath, op_depth)); SVN_ERR(svn_sqlite__step_done(stmt)); } else { - SVN_ERR(svn_sqlite__get_statement(&stmt, b->wcroot->sdb, + SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_DELETE_WORKING_OP_DEPTH)); - SVN_ERR(svn_sqlite__bindf(stmt, "isd", b->wcroot->wc_id, relpath, + SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath, op_depth)); SVN_ERR(svn_sqlite__step_done(stmt)); } - /* Retract any base-delete. */ - SVN_ERR(svn_wc__db_retract_parent_delete(b->wcroot, relpath, op_depth, + /* Retract any base-delete for descendants. */ + { + SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, + STMT_DELETE_WORKING_BASE_DELETE)); + SVN_ERR(svn_sqlite__bindf(stmt, "isd", wcroot->wc_id, local_relpath, + op_depth)); + SVN_ERR(svn_sqlite__step_done(stmt)); + } + /* And for the node itself */ + SVN_ERR(svn_wc__db_retract_parent_delete(wcroot, local_relpath, op_depth, scratch_pool)); return SVN_NO_ERROR; @@ -1492,6 +1512,9 @@ update_moved_away_node(update_move_baton apr_array_header_t *src_children, *dst_children; int dst_op_depth = relpath_depth(move_root_dst_relpath); + SVN_ERR(verify_write_lock(wcroot, src_relpath, scratch_pool)); + SVN_ERR(verify_write_lock(wcroot, dst_relpath, scratch_pool)); + SVN_ERR(get_info(&src_props, &src_checksum, &src_children, &src_kind, src_relpath, src_op_depth, wcroot, scratch_pool, scratch_pool)); @@ -1508,7 +1531,9 @@ update_moved_away_node(update_move_baton /* And perform some work that in some ways belongs in replace_moved_layer() after creating all conflicts */ - SVN_ERR(delete_move_leaf(b, dst_relpath, scratch_pool)); + SVN_ERR(delete_move_leaf(b->wcroot, dst_relpath, + relpath_depth(b->move_root_dst_relpath), + scratch_pool)); } if (src_kind != svn_node_none && src_kind != dst_kind) @@ -1609,8 +1634,8 @@ update_moved_away_node(update_move_baton iterpool); if (!child_shadowed) - SVN_ERR(check_node_shadowed(&child_shadowed, b, dst_child_relpath, - iterpool)); + SVN_ERR(check_node_shadowed(&child_shadowed, wcroot, dst_child_relpath, + b->move_root_dst_relpath, iterpool)); SVN_ERR(update_moved_away_node(b, wcroot, src_child_relpath, dst_child_relpath, src_op_depth, @@ -1641,6 +1666,9 @@ replace_moved_layer(const char *src_relp svn_boolean_t have_row; int dst_op_depth = relpath_depth(dst_relpath); + SVN_ERR(verify_write_lock(wcroot, src_relpath, scratch_pool)); + SVN_ERR(verify_write_lock(wcroot, dst_relpath, scratch_pool)); + /* Replace entire subtree at one op-depth. */ SVN_ERR(svn_sqlite__get_statement(&stmt, wcroot->sdb, STMT_SELECT_LOCAL_RELPATH_OP_DEPTH)); @@ -1719,10 +1747,8 @@ drive_tree_conflict_editor(update_move_b operation != svn_wc_operation_switch) return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, _("Cannot auto-resolve tree-conflict on '%s'"), - svn_dirent_local_style( - svn_dirent_join(wcroot->abspath, - src_relpath, scratch_pool), - scratch_pool)); + path_for_error_message(wcroot, src_relpath, + scratch_pool)); /* We walk the move source (i.e. the post-update tree), comparing each node * with the equivalent node at the move destination and applying the update @@ -1780,22 +1806,17 @@ suitable_for_move(svn_wc__db_wcroot_t *w svn_sqlite__reset(stmt), _("Cannot apply update because move source " "%s' is a mixed-revision working copy"), - svn_dirent_local_style(svn_dirent_join( - wcroot->abspath, - local_relpath, - scratch_pool), - scratch_pool)); + path_for_error_message(wcroot, local_relpath, + scratch_pool)); if (strcmp(relpath, svn_sqlite__column_text(stmt, 1, NULL))) return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, svn_sqlite__reset(stmt), _("Cannot apply update because move source " "'%s' is a switched subtree"), - svn_dirent_local_style(svn_dirent_join( - wcroot->abspath, - local_relpath, - scratch_pool), - scratch_pool)); + path_for_error_message(wcroot, + local_relpath, + scratch_pool)); SVN_ERR(svn_sqlite__step(&have_row, stmt)); } @@ -1840,10 +1861,8 @@ update_moved_away_conflict_victim(svn_wc if (umb.move_root_dst_relpath == NULL) return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, _("The node '%s' has not been moved away"), - svn_dirent_local_style( - svn_dirent_join(wcroot->abspath, victim_relpath, - scratch_pool), - scratch_pool)); + path_for_error_message(wcroot, victim_relpath, + scratch_pool)); move_root_dst_abspath = svn_dirent_join(wcroot->abspath, umb.move_root_dst_relpath, @@ -1869,10 +1888,8 @@ update_moved_away_conflict_victim(svn_wc if (!have_row) return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL, _("'%s' is not deleted"), - svn_dirent_local_style( - svn_dirent_join(wcroot->abspath, victim_relpath, - scratch_pool), - scratch_pool)); + path_for_error_message(wcroot, victim_relpath, + scratch_pool)); if (src_op_depth == 0) SVN_ERR(suitable_for_move(wcroot, victim_relpath, scratch_pool)); @@ -2045,8 +2062,8 @@ bump_mark_tree_conflict(svn_wc__db_wcroo svn_wc_conflict_version_t *old_version; svn_wc_conflict_version_t *new_version; - SVN_ERR(verify_write_lock(wcroot, move_src_op_root_relpath, scratch_pool)); - SVN_ERR(verify_write_lock(wcroot, move_dst_op_root_relpath, scratch_pool)); + /* Verify precondition: We are allowed to set a tree conflict here. */ + SVN_ERR(verify_write_lock(wcroot, move_src_root_relpath, scratch_pool)); /* Read new (post-update) information from the new move source BASE node. */ SVN_ERR(svn_wc__db_base_get_info_internal(NULL, &new_kind, &new_rev, @@ -2058,7 +2075,14 @@ bump_mark_tree_conflict(svn_wc__db_wcroo SVN_ERR(svn_wc__db_fetch_repos_info(&repos_root_url, &repos_uuid, wcroot->sdb, repos_id, scratch_pool)); - /* Read old (pre-update) information from the move destination node. */ + /* Read old (pre-update) information from the move destination node. + + This potentially touches nodes that aren't locked by us, but that is not + a problem because we have a SQLite write lock here, and all sqlite + operations that affect move stability use a sqlite lock as well. + (And affecting the move itself requires a write lock on the node that + we do own the lock for: the move source) + */ SVN_ERR(svn_wc__db_depth_get_info(NULL, &old_kind, &old_rev, &old_repos_relpath, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -2066,6 +2090,21 @@ bump_mark_tree_conflict(svn_wc__db_wcroo relpath_depth(move_dst_op_root_relpath), scratch_pool, scratch_pool)); + if (strcmp(move_src_root_relpath, move_src_op_root_relpath)) + { + /* We have information for the op-root, but need it for the node that + we are putting the tree conflict on. Luckily we know that we have + a clean BASE */ + + const char *rpath = svn_relpath_skip_ancestor(move_src_op_root_relpath, + move_src_root_relpath); + + old_repos_relpath = svn_relpath_join(old_repos_relpath, rpath, + scratch_pool); + new_repos_relpath = svn_relpath_join(new_repos_relpath, rpath, + scratch_pool); + } + old_version = svn_wc_conflict_version_create2( repos_root_url, repos_uuid, old_repos_relpath, old_rev, old_kind, scratch_pool); @@ -2332,10 +2371,26 @@ svn_wc__db_bump_moved_away(svn_wc__db_wc { if (strcmp(move_src_root_relpath, local_relpath)) { - SVN_ERR(bump_mark_tree_conflict(wcroot, move_src_root_relpath, - move_src_op_root_relpath, - move_dst_op_root_relpath, - db, scratch_pool)); + /* An ancestor of the path that was updated is moved away. + + If we have a lock on that ancestor, we can mark a tree + conflict on it, if we don't we ignore this case. A future + update of the ancestor will handle this. */ + svn_boolean_t locked; + + SVN_ERR(svn_wc__db_wclock_owns_lock_internal( + &locked, wcroot, + move_src_root_relpath, + FALSE, scratch_pool)); + + if (locked) + { + SVN_ERR(bump_mark_tree_conflict(wcroot, + move_src_root_relpath, + move_src_op_root_relpath, + move_dst_op_root_relpath, + db, scratch_pool)); + } return SVN_NO_ERROR; } } @@ -2524,16 +2579,29 @@ break_moved_away_children_internal(svn_w const char *src_relpath = svn_sqlite__column_text(stmt, 0, NULL); const char *dst_relpath = svn_sqlite__column_text(stmt, 1, NULL); int src_op_depth = svn_sqlite__column_int(stmt, 2); + svn_error_t *err; svn_pool_clear(iterpool); - SVN_ERR(break_move(wcroot, src_relpath, src_op_depth, dst_relpath, - iterpool)); - SVN_ERR(update_move_list_add(wcroot, src_relpath, - svn_wc_notify_move_broken, - svn_node_unknown, - svn_wc_notify_state_inapplicable, - svn_wc_notify_state_inapplicable)); + err = break_move(wcroot, src_relpath, src_op_depth, dst_relpath, + iterpool); + + if (! err) + { + err = update_move_list_add(wcroot, src_relpath, + svn_wc_notify_move_broken, + svn_node_unknown, + svn_wc_notify_state_inapplicable, + svn_wc_notify_state_inapplicable); + } + + if (err) + { + return svn_error_trace( + svn_error_compose_create(err, + svn_sqlite__reset(stmt))); + } + SVN_ERR(svn_sqlite__step(&have_row, stmt)); } svn_pool_destroy(iterpool); @@ -2546,21 +2614,26 @@ break_moved_away_children_internal(svn_w svn_error_t * svn_wc__db_resolve_break_moved_away(svn_wc__db_t *db, const char *local_abspath, + const char *src_op_root_abspath, svn_wc_notify_func2_t notify_func, void *notify_baton, apr_pool_t *scratch_pool) { svn_wc__db_wcroot_t *wcroot; const char *local_relpath; + const char *src_relpath; SVN_ERR(svn_wc__db_wcroot_parse_local_abspath(&wcroot, &local_relpath, db, local_abspath, scratch_pool, scratch_pool)); VERIFY_USABLE_WCROOT(wcroot); + src_relpath = svn_dirent_skip_ancestor(wcroot->abspath, src_op_root_abspath); + SVN_ERR_ASSERT(src_relpath != NULL); + SVN_WC__DB_WITH_TXN( svn_wc__db_resolve_break_moved_away_internal(wcroot, local_relpath, - relpath_depth(local_relpath), + relpath_depth(src_relpath), scratch_pool), wcroot); @@ -2586,6 +2659,7 @@ svn_wc__db_resolve_break_moved_away(svn_ svn_error_t * svn_wc__db_resolve_break_moved_away_children(svn_wc__db_t *db, const char *local_abspath, + const char *src_op_root_abspath, svn_wc_notify_func2_t notify_func, void *notify_baton, apr_pool_t *scratch_pool) Modified: subversion/branches/svn-auth-x509/subversion/mod_authz_svn/mod_authz_svn.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/mod_authz_svn/mod_authz_svn.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/mod_authz_svn/mod_authz_svn.c (original) +++ subversion/branches/svn-auth-x509/subversion/mod_authz_svn/mod_authz_svn.c Fri Jan 16 14:01:35 2015 @@ -361,7 +361,7 @@ get_access_conf(request_rec *r, authz_sv svn_error_t *svn_err = SVN_NO_ERROR; dav_error *dav_err; - dav_err = dav_svn_get_repos_path(r, conf->base_path, &repos_path); + dav_err = dav_svn_get_repos_path2(r, conf->base_path, &repos_path, scratch_pool); if (dav_err) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "%s", dav_err->desc); Modified: subversion/branches/svn-auth-x509/subversion/mod_dav_svn/mod_dav_svn.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/mod_dav_svn/mod_dav_svn.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/mod_dav_svn/mod_dav_svn.c (original) +++ subversion/branches/svn-auth-x509/subversion/mod_dav_svn/mod_dav_svn.c Fri Jan 16 14:01:35 2015 @@ -662,9 +662,10 @@ dav_svn__get_fs_parent_path(request_rec AP_MODULE_DECLARE(dav_error *) -dav_svn_get_repos_path(request_rec *r, - const char *root_path, - const char **repos_path) +dav_svn_get_repos_path2(request_rec *r, + const char *root_path, + const char **repos_path, + apr_pool_t *pool) { const char *fs_path; @@ -692,19 +693,26 @@ dav_svn_get_repos_path(request_rec *r, /* Split the svn URI to get the name of the repository below the parent path. */ - derr = dav_svn_split_uri(r, r->uri, root_path, - &ignored_cleaned_uri, &ignored_had_slash, - &repos_name, - &ignored_relative, &ignored_path_in_repos); + derr = dav_svn_split_uri2(r, r->uri, root_path, + &ignored_cleaned_uri, &ignored_had_slash, + &repos_name, + &ignored_relative, &ignored_path_in_repos, pool); if (derr) return derr; /* Construct the full path from the parent path base directory and the repository name. */ - *repos_path = svn_dirent_join(fs_parent_path, repos_name, r->pool); + *repos_path = svn_dirent_join(fs_parent_path, repos_name, pool); return NULL; } +AP_MODULE_DECLARE(dav_error *) +dav_svn_get_repos_path(request_rec *r, + const char *root_path, + const char **repos_path) +{ + return dav_svn_get_repos_path2(r, root_path, repos_path, r->pool); +} const char * dav_svn__get_repo_name(request_rec *r) @@ -1324,8 +1332,8 @@ static const command_rec cmds[] = AP_INIT_TAKE1("SVNInMemoryCacheSize", SVNInMemoryCacheSize_cmd, NULL, RSRC_CONF, "specifies the maximum size in kB per process of Subversion's " - "in-memory object cache (default value is 16384; 0 deactivates " - "the cache)."), + "in-memory object cache (default value is 16384; 0 switches " + "to dynamically sized caches)."), /* per server */ AP_INIT_TAKE1("SVNCompressionLevel", SVNCompressionLevel_cmd, NULL, RSRC_CONF, Modified: subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/deleted-rev.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/deleted-rev.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/deleted-rev.c (original) +++ subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/deleted-rev.c Fri Jan 16 14:01:35 2015 @@ -56,6 +56,9 @@ dav_svn__get_deleted_rev_report(const da dav_error *derr = NULL; /* Sanity check. */ + if (!resource->info->repos_path) + return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0, + "The request does not specify a repository path"); ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE); if (ns == -1) return dav_svn__new_error_svn(resource->pool, HTTP_BAD_REQUEST, 0, Modified: subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/file-revs.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/file-revs.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/file-revs.c (original) +++ subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/file-revs.c Fri Jan 16 14:01:35 2015 @@ -149,7 +149,7 @@ file_rev_handler(void *baton, apr_pool_t *pool) { struct file_rev_baton *frb = baton; - apr_pool_t *subpool = svn_pool_create(pool); + apr_pool_t *iterpool = svn_pool_create(pool); apr_hash_index_t *hi; int i; @@ -169,11 +169,11 @@ file_rev_handler(void *baton, const char *pname; const svn_string_t *pval; - svn_pool_clear(subpool); + svn_pool_clear(iterpool); apr_hash_this(hi, &key, NULL, &val); pname = key; pval = val; - SVN_ERR(send_prop(frb, "rev-prop", pname, pval, subpool)); + SVN_ERR(send_prop(frb, "rev-prop", pname, pval, iterpool)); } /* Send file prop changes. */ @@ -181,17 +181,17 @@ file_rev_handler(void *baton, { const svn_prop_t *prop = &APR_ARRAY_IDX(props, i, svn_prop_t); - svn_pool_clear(subpool); + svn_pool_clear(iterpool); if (prop->value) SVN_ERR(send_prop(frb, "set-prop", prop->name, prop->value, - subpool)); + iterpool)); else { /* Property was removed. */ SVN_ERR(dav_svn__brigade_printf(frb->bb, frb->output, "<S:remove-prop name=\"%s\"/>" DEBUG_CR, - apr_xml_quote_string(subpool, + apr_xml_quote_string(iterpool, prop->name, 1))); } @@ -223,7 +223,7 @@ file_rev_handler(void *baton, SVN_ERR(dav_svn__brigade_puts(frb->bb, frb->output, "</S:file-rev>" DEBUG_CR)); - svn_pool_destroy(subpool); + svn_pool_destroy(iterpool); return SVN_NO_ERROR; } @@ -254,6 +254,9 @@ dav_svn__file_revs_report(const dav_reso arb.repos = resource->info->repos; /* Sanity check. */ + if (!resource->info->repos_path) + return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0, + "The request does not specify a repository path"); ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE); /* ### This is done on other places, but the document element is in this namespace, so is this necessary at all? */ Modified: subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/get-location-segments.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/get-location-segments.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/get-location-segments.c (original) +++ subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/get-location-segments.c Fri Jan 16 14:01:35 2015 @@ -123,6 +123,9 @@ dav_svn__get_location_segments_report(co struct location_segment_baton location_segment_baton; /* Sanity check. */ + if (!resource->info->repos_path) + return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0, + "The request does not specify a repository path"); ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE); if (ns == -1) { Modified: subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/get-locations.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/get-locations.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/get-locations.c (original) +++ subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/get-locations.c Fri Jan 16 14:01:35 2015 @@ -106,6 +106,9 @@ dav_svn__get_locations_report(const dav_ sizeof(svn_revnum_t)); /* Sanity check. */ + if (!resource->info->repos_path) + return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0, + "The request does not specify a repository path"); ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE); if (ns == -1) { Modified: subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/get-locks.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/get-locks.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/get-locks.c (original) +++ subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/get-locks.c Fri Jan 16 14:01:35 2015 @@ -66,7 +66,7 @@ send_get_lock_response(apr_hash_t *locks apr_bucket_brigade *bb, apr_pool_t *pool) { - apr_pool_t *subpool; + apr_pool_t *iterpool; apr_hash_index_t *hi; /* start sending report */ @@ -76,15 +76,13 @@ send_get_lock_response(apr_hash_t *locks "\" xmlns:D=\"DAV:\">" DEBUG_CR)); /* stream the locks */ - subpool = svn_pool_create(pool); + iterpool = svn_pool_create(pool); for (hi = apr_hash_first(pool, locks); hi; hi = apr_hash_next(hi)) { - void *val; const svn_lock_t *lock; - svn_pool_clear(subpool); - apr_hash_this(hi, NULL, NULL, &val); - lock = val; + svn_pool_clear(iterpool); + lock = apr_hash_this_val(hi); /* Begin the <S:lock> tag, transmitting the path, token, and creation date. */ @@ -93,10 +91,10 @@ send_get_lock_response(apr_hash_t *locks "<S:path>%s</S:path>" DEBUG_CR "<S:token>%s</S:token>" DEBUG_CR "<S:creationdate>%s</S:creationdate>" DEBUG_CR, - apr_xml_quote_string(subpool, lock->path, 1), - apr_xml_quote_string(subpool, lock->token, 1), + apr_xml_quote_string(iterpool, lock->path, 1), + apr_xml_quote_string(iterpool, lock->token, 1), svn_time_to_cstring(lock->creation_date, - subpool))); + iterpool))); /* Got expiration date? Tell the client. */ if (lock->expiration_date) @@ -104,7 +102,7 @@ send_get_lock_response(apr_hash_t *locks "<S:expirationdate>%s</S:expirationdate>" DEBUG_CR, svn_time_to_cstring(lock->expiration_date, - subpool))); + iterpool))); /* Transmit the lock ownership information. */ if (lock->owner) @@ -114,7 +112,7 @@ send_get_lock_response(apr_hash_t *locks if (svn_xml_is_xml_safe(lock->owner, strlen(lock->owner))) { - owner = apr_xml_quote_string(subpool, lock->owner, 1); + owner = apr_xml_quote_string(iterpool, lock->owner, 1); } else { @@ -124,7 +122,7 @@ send_get_lock_response(apr_hash_t *locks owner_string.data = lock->owner; owner_string.len = strlen(lock->owner); encoded_owner = svn_base64_encode_string2(&owner_string, TRUE, - subpool); + iterpool); owner = encoded_owner->data; owner_base64 = TRUE; } @@ -142,7 +140,7 @@ send_get_lock_response(apr_hash_t *locks if (svn_xml_is_xml_safe(lock->comment, strlen(lock->comment))) { - comment = apr_xml_quote_string(subpool, lock->comment, 1); + comment = apr_xml_quote_string(iterpool, lock->comment, 1); } else { @@ -152,7 +150,7 @@ send_get_lock_response(apr_hash_t *locks comment_string.data = lock->comment; comment_string.len = strlen(lock->comment); encoded_comment = svn_base64_encode_string2(&comment_string, - TRUE, subpool); + TRUE, iterpool); comment = encoded_comment->data; comment_base64 = TRUE; } @@ -165,7 +163,7 @@ send_get_lock_response(apr_hash_t *locks /* Okay, finish up this lock by closing the <S:lock> tag. */ SVN_APR_ERR(ap_fprintf(output, bb, "</S:lock>" DEBUG_CR)); } - svn_pool_destroy(subpool); + svn_pool_destroy(iterpool); /* Finish the report */ SVN_APR_ERR(ap_fprintf(output, bb, "</S:get-locks-report>" DEBUG_CR)); Modified: subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/inherited-props.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/inherited-props.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/inherited-props.c (original) +++ subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/inherited-props.c Fri Jan 16 14:01:35 2015 @@ -63,6 +63,9 @@ dav_svn__get_inherited_props_report(cons apr_pool_t *iterpool; /* Sanity check. */ + if (!resource->info->repos_path) + return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0, + "The request does not specify a repository path"); ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE); if (ns == -1) { Modified: subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/log.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/log.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/log.c (original) +++ subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/log.c Fri Jan 16 14:01:35 2015 @@ -315,6 +315,9 @@ dav_svn__log_report(const dav_resource * = apr_array_make(resource->pool, 1, sizeof(const char *)); /* Sanity check. */ + if (!resource->info->repos_path) + return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0, + "The request does not specify a repository path"); ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE); if (ns == -1) { Modified: subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/mergeinfo.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/mergeinfo.c?rev=1652409&r1=1652408&r2=1652409&view=diff ============================================================================== --- subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/mergeinfo.c (original) +++ subversion/branches/svn-auth-x509/subversion/mod_dav_svn/reports/mergeinfo.c Fri Jan 16 14:01:35 2015 @@ -67,6 +67,9 @@ dav_svn__get_mergeinfo_report(const dav_ = apr_array_make(resource->pool, 0, sizeof(const char *)); /* Sanity check. */ + if (!resource->info->repos_path) + return dav_svn__new_error(resource->pool, HTTP_BAD_REQUEST, 0, + "The request does not specify a repository path"); ns = dav_svn__find_ns(doc->namespaces, SVN_XML_NAMESPACE); if (ns == -1) {
