You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2013/02/23 02:25:44 UTC
svn commit: r1449262 [7/25] - in /subversion/branches/ev2-export: ./ build/
build/ac-macros/ build/generator/ build/generator/swig/
build/generator/templates/ build/win32/
contrib/server-side/fsfsfixer/fixer/ contrib/server-side/svncutter/ notes/
notes...
Modified: subversion/branches/ev2-export/subversion/libsvn_diff/diff_memory.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_diff/diff_memory.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_diff/diff_memory.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_diff/diff_memory.c Sat Feb 23 01:25:38 2013
@@ -27,6 +27,8 @@
#include <apr_want.h>
#include <apr_tables.h>
+#include <assert.h>
+
#include "svn_diff.h"
#include "svn_pools.h"
#include "svn_types.h"
@@ -342,7 +344,8 @@ typedef enum unified_output_e
{
unified_output_context = 0,
unified_output_delete,
- unified_output_insert
+ unified_output_insert,
+ unified_output_skip
} unified_output_e;
/* Baton for generating unified diffs */
@@ -351,7 +354,7 @@ typedef struct unified_output_baton_t
svn_stream_t *output_stream;
const char *header_encoding;
source_tokens_t sources[2]; /* 0 == original; 1 == modified */
- apr_off_t next_token; /* next token in original source */
+ apr_off_t current_token[2]; /* current token per source */
/* Cached markers, in header_encoding,
indexed using unified_output_e */
@@ -382,31 +385,28 @@ static svn_error_t *
output_unified_token_range(output_baton_t *btn,
int tokens,
unified_output_e type,
- apr_off_t first,
- apr_off_t past_last)
+ apr_off_t until)
{
source_tokens_t *source = &btn->sources[tokens];
- apr_off_t idx;
-
- past_last = (past_last > source->tokens->nelts)
- ? source->tokens->nelts : past_last;
- if (tokens == 0)
- /* We get context from the original source, don't expect
- to be asked to output a block which starts before
- what we already have written. */
- first = (first < btn->next_token) ? btn->next_token : first;
+ if (until > source->tokens->nelts)
+ until = source->tokens->nelts;
- if (first >= past_last)
+ if (until <= btn->current_token[tokens])
return SVN_NO_ERROR;
/* Do the loop with prefix and token */
- for (idx = first; idx < past_last; idx++)
+ while (TRUE)
{
- svn_string_t *token
- = APR_ARRAY_IDX(source->tokens, idx, svn_string_t *);
- svn_stringbuf_appendcstr(btn->hunk, btn->prefix_str[type]);
- svn_stringbuf_appendbytes(btn->hunk, token->data, token->len);
+ svn_string_t *token =
+ APR_ARRAY_IDX(source->tokens, btn->current_token[tokens],
+ svn_string_t *);
+
+ if (type != unified_output_skip)
+ {
+ svn_stringbuf_appendcstr(btn->hunk, btn->prefix_str[type]);
+ svn_stringbuf_appendbytes(btn->hunk, token->data, token->len);
+ }
if (type == unified_output_context)
{
@@ -415,11 +415,18 @@ output_unified_token_range(output_baton_
}
else if (type == unified_output_delete)
btn->hunk_length[0]++;
- else
+ else if (type == unified_output_insert)
btn->hunk_length[1]++;
+ /* ### TODO: Add skip processing for -p handling? */
+
+ btn->current_token[tokens]++;
+ if (btn->current_token[tokens] == until)
+ break;
}
- if (past_last == source->tokens->nelts && source->ends_without_eol)
+
+ if (btn->current_token[tokens] == source->tokens->nelts
+ && source->ends_without_eol)
{
const char *out_str;
@@ -429,8 +436,7 @@ output_unified_token_range(output_baton_
svn_stringbuf_appendcstr(btn->hunk, out_str);
}
- if (tokens == 0)
- btn->next_token = past_last;
+
return SVN_NO_ERROR;
}
@@ -445,6 +451,8 @@ output_unified_flush_hunk(output_baton_t
{
apr_off_t target_token;
apr_size_t hunk_len;
+ apr_off_t old_start;
+ apr_off_t new_start;
if (svn_stringbuf_isempty(baton->hunk))
return SVN_NO_ERROR;
@@ -453,24 +461,28 @@ output_unified_flush_hunk(output_baton_t
/* Write the trailing context */
target_token = baton->hunk_start[0] + baton->hunk_length[0]
- + SVN_DIFF__UNIFIED_CONTEXT_SIZE;
+ + SVN_DIFF__UNIFIED_CONTEXT_SIZE;
SVN_ERR(output_unified_token_range(baton, 0 /*original*/,
unified_output_context,
- baton->next_token, target_token));
+ target_token));
if (hunk_delimiter == NULL)
hunk_delimiter = "@@";
- /* Convert our 0-based line numbers into unidiff 1-based numbers */
- if (baton->hunk_length[0] > 0)
- baton->hunk_start[0]++;
- if (baton->hunk_length[1] > 0)
- baton->hunk_start[1]++;
+ old_start = baton->hunk_start[0];
+ new_start = baton->hunk_start[1];
+
+ /* If the file is non-empty, convert the line indexes from
+ zero based to one based */
+ if (baton->hunk_length[0])
+ old_start++;
+ if (baton->hunk_length[1])
+ new_start++;
/* Write the hunk header */
SVN_ERR(svn_diff__unified_write_hunk_header(
baton->output_stream, baton->header_encoding, hunk_delimiter,
- baton->hunk_start[0], baton->hunk_length[0],
- baton->hunk_start[1], baton->hunk_length[1],
+ old_start, baton->hunk_length[0],
+ new_start, baton->hunk_length[1],
NULL /* hunk_extra_context */,
baton->pool));
@@ -478,7 +490,11 @@ output_unified_flush_hunk(output_baton_t
SVN_ERR(svn_stream_write(baton->output_stream,
baton->hunk->data, &hunk_len));
- baton->hunk_length[0] = baton->hunk_length[1] = 0;
+ /* Prepare for the next hunk */
+ baton->hunk_length[0] = 0;
+ baton->hunk_length[1] = 0;
+ baton->hunk_start[0] = 0;
+ baton->hunk_start[1] = 0;
svn_stringbuf_setempty(baton->hunk);
return SVN_NO_ERROR;
@@ -494,38 +510,91 @@ output_unified_diff_modified(void *baton
apr_off_t latest_start,
apr_off_t latest_length)
{
- output_baton_t *btn = baton;
- apr_off_t targ_orig, targ_mod;
+ output_baton_t *output_baton = baton;
+ apr_off_t context_prefix_length;
+ apr_off_t prev_context_end;
+ svn_boolean_t init_hunk = FALSE;
+
+ if (original_start > SVN_DIFF__UNIFIED_CONTEXT_SIZE)
+ context_prefix_length = SVN_DIFF__UNIFIED_CONTEXT_SIZE;
+ else
+ context_prefix_length = original_start;
- targ_orig = original_start - SVN_DIFF__UNIFIED_CONTEXT_SIZE;
- targ_orig = (targ_orig < 0) ? 0 : targ_orig;
- targ_mod = modified_start;
-
- /* If the changed ranges are far enough apart (no overlapping or
- * connecting context), flush the current hunk. */
- if (btn->next_token + SVN_DIFF__UNIFIED_CONTEXT_SIZE < targ_orig)
- SVN_ERR(output_unified_flush_hunk(btn, btn->hunk_delimiter));
- /* Adjust offset if it's not the first hunk. */
- else if (btn->hunk_length[0] != 0)
- targ_orig = btn->next_token;
+ /* Calculate where the previous hunk will end if we would write it now
+ (including the necessary context at the end) */
+ if (output_baton->hunk_length[0] > 0 || output_baton->hunk_length[1] > 0)
+ {
+ prev_context_end = output_baton->hunk_start[0]
+ + output_baton->hunk_length[0]
+ + SVN_DIFF__UNIFIED_CONTEXT_SIZE;
+ }
+ else
+ {
+ prev_context_end = -1;
+
+ if (output_baton->hunk_start[0] == 0
+ && (original_length > 0 || modified_length > 0))
+ init_hunk = TRUE;
+ }
- if (btn->hunk_length[0] == 0
- && btn->hunk_length[1] == 0)
+ /* If the changed range is far enough from the previous range, flush the current
+ hunk. */
+ {
+ apr_off_t new_hunk_start = (original_start - context_prefix_length);
+
+ if (output_baton->current_token[0] < new_hunk_start
+ && prev_context_end <= new_hunk_start)
+ {
+ SVN_ERR(output_unified_flush_hunk(output_baton,
+ output_baton->hunk_delimiter));
+ init_hunk = TRUE;
+ }
+ else if (output_baton->hunk_length[0] > 0
+ || output_baton->hunk_length[1] > 0)
+ {
+ /* We extend the current hunk */
+
+ /* Original: Output the context preceding the changed range */
+ SVN_ERR(output_unified_token_range(output_baton, 0 /* original */,
+ unified_output_context,
+ original_start));
+ }
+ }
+
+ /* Original: Skip lines until we are at the beginning of the context we want
+ to display */
+ SVN_ERR(output_unified_token_range(output_baton, 0 /* original */,
+ unified_output_skip,
+ original_start - context_prefix_length));
+
+ if (init_hunk)
{
- btn->hunk_start[0] = targ_orig;
- btn->hunk_start[1] = targ_mod + targ_orig - original_start;
+ SVN_ERR_ASSERT(output_baton->hunk_length[0] == 0
+ && output_baton->hunk_length[1] == 0);
+
+ output_baton->hunk_start[0] = original_start - context_prefix_length;
+ output_baton->hunk_start[1] = modified_start - context_prefix_length;
}
- SVN_ERR(output_unified_token_range(btn, 0/*original*/,
- unified_output_context,
- targ_orig, original_start));
- SVN_ERR(output_unified_token_range(btn, 0/*original*/,
+ /* Modified: Skip lines until we are at the start of the changed range */
+ SVN_ERR(output_unified_token_range(output_baton, 1 /* modified */,
+ unified_output_skip,
+ modified_start));
+
+ /* Original: Output the context preceding the changed range */
+ SVN_ERR(output_unified_token_range(output_baton, 0 /* original */,
+ unified_output_context,
+ original_start));
+
+ /* Both: Output the changed range */
+ SVN_ERR(output_unified_token_range(output_baton, 0 /* original */,
unified_output_delete,
- original_start,
original_start + original_length));
- return output_unified_token_range(btn, 1/*modified*/, unified_output_insert,
- modified_start,
- modified_start + modified_length);
+ SVN_ERR(output_unified_token_range(output_baton, 1 /* modified */,
+ unified_output_insert,
+ modified_start + modified_length));
+
+ return SVN_NO_ERROR;
}
static const svn_diff_output_fns_t mem_output_unified_vtable =
@@ -656,7 +725,7 @@ typedef struct merge_output_baton_t
/* Tokenized source text */
source_tokens_t sources[3];
- apr_off_t next_token;
+ apr_off_t next_token[3];
/* Markers for marking conflicted sections */
const char *markers[4]; /* 0 = original, 1 = modified,
Modified: subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.c Sat Feb 23 01:25:38 2013
@@ -483,12 +483,12 @@ svn_fs_upgrade(const char *path, apr_poo
svn_error_t *
svn_fs_verify(const char *path,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- svn_fs_progress_notify_func_t notify_func,
- void *notify_baton,
svn_revnum_t start,
svn_revnum_t end,
+ svn_fs_progress_notify_func_t notify_func,
+ void *notify_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
apr_pool_t *pool)
{
fs_library_vtable_t *vtable;
@@ -498,9 +498,10 @@ svn_fs_verify(const char *path,
fs = fs_new(NULL, pool);
SVN_MUTEX__WITH_LOCK(common_pool_lock,
- vtable->verify_fs(fs, path, cancel_func, cancel_baton,
- notify_func, notify_baton, start,
- end, pool, common_pool));
+ vtable->verify_fs(fs, path, start, end,
+ notify_func, notify_baton,
+ cancel_func, cancel_baton,
+ pool, common_pool));
return SVN_NO_ERROR;
}
Modified: subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.h?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.h Sat Feb 23 01:25:38 2013
@@ -88,11 +88,12 @@ typedef struct fs_library_vtable_t
svn_error_t *(*upgrade_fs)(svn_fs_t *fs, const char *path, apr_pool_t *pool,
apr_pool_t *common_pool);
svn_error_t *(*verify_fs)(svn_fs_t *fs, const char *path,
- svn_cancel_func_t cancel_func, void *cancel_baton,
- svn_fs_progress_notify_func_t notify_func,
- void *notify_baton,
svn_revnum_t start,
svn_revnum_t end,
+ svn_fs_progress_notify_func_t notify_func,
+ void *notify_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
apr_pool_t *pool,
apr_pool_t *common_pool);
svn_error_t *(*delete_fs)(const char *path, apr_pool_t *pool);
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_base/bdb/locks-table.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_base/bdb/locks-table.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_base/bdb/locks-table.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_base/bdb/locks-table.c Sat Feb 23 01:25:38 2013
@@ -26,6 +26,7 @@
#include "bdb_compat.h"
#include "svn_pools.h"
+#include "svn_path.h"
#include "private/svn_skel.h"
#include "dbt.h"
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_base/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_base/fs.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_base/fs.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_base/fs.c Sat Feb 23 01:25:38 2013
@@ -902,12 +902,12 @@ base_upgrade(svn_fs_t *fs, const char *p
static svn_error_t *
base_verify(svn_fs_t *fs, const char *path,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- svn_fs_progress_notify_func_t notify_func,
- void *notify_baton,
svn_revnum_t start,
svn_revnum_t end,
+ svn_fs_progress_notify_func_t notify_func,
+ void *notify_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
apr_pool_t *pool,
apr_pool_t *common_pool)
{
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_base/reps-strings.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_base/reps-strings.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_base/reps-strings.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_base/reps-strings.c Sat Feb 23 01:25:38 2013
@@ -1464,14 +1464,16 @@ svn_fs_base__rep_deltify(svn_fs_t *fs,
TRUE, trail, pool));
/* Setup a stream to convert the textdelta data into svndiff windows. */
- svn_txdelta(&txdelta_stream, source_stream, target_stream, pool);
+ svn_txdelta2(&txdelta_stream, source_stream, target_stream, TRUE, pool);
if (bfd->format >= SVN_FS_BASE__MIN_SVNDIFF1_FORMAT)
- svn_txdelta_to_svndiff2(&new_target_handler, &new_target_handler_baton,
- new_target_stream, 1, pool);
+ svn_txdelta_to_svndiff3(&new_target_handler, &new_target_handler_baton,
+ new_target_stream, 1,
+ SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, pool);
else
- svn_txdelta_to_svndiff2(&new_target_handler, &new_target_handler_baton,
- new_target_stream, 0, pool);
+ svn_txdelta_to_svndiff3(&new_target_handler, &new_target_handler_baton,
+ new_target_stream, 0,
+ SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, pool);
/* subpool for the windows */
wpool = svn_pool_create(pool);
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_base/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_base/tree.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_base/tree.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_base/tree.c Sat Feb 23 01:25:38 2013
@@ -4024,7 +4024,7 @@ base_get_file_delta_stream(svn_txdelta_s
SVN_ERR(base_file_contents(&target, target_root, target_path, pool));
/* Create a delta stream that turns the ancestor into the target. */
- svn_txdelta(&delta_stream, source, target, pool);
+ svn_txdelta2(&delta_stream, source, target, TRUE, pool);
*stream_p = delta_stream;
return SVN_NO_ERROR;
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/dag.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/dag.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/dag.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/dag.c Sat Feb 23 01:25:38 2013
@@ -1095,7 +1095,7 @@ svn_fs_fs__dag_serialize(void **data,
svn_temp_serializer__context_t *context =
svn_temp_serializer__init(node,
sizeof(*node),
- 503,
+ 1024 - SVN_TEMP_SERIALIZER__OVERHEAD,
pool);
/* for mutable nodes, we will _never_ cache the noderev */
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c Sat Feb 23 01:25:38 2013
@@ -284,12 +284,12 @@ fs_upgrade(svn_fs_t *fs, const char *pat
static svn_error_t *
fs_verify(svn_fs_t *fs, const char *path,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- svn_fs_progress_notify_func_t notify_func,
- void *notify_baton,
svn_revnum_t start,
svn_revnum_t end,
+ svn_fs_progress_notify_func_t notify_func,
+ void *notify_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
apr_pool_t *pool,
apr_pool_t *common_pool)
{
@@ -298,8 +298,8 @@ fs_verify(svn_fs_t *fs, const char *path
SVN_ERR(svn_fs_fs__open(fs, path, pool));
SVN_ERR(svn_fs_fs__initialize_caches(fs, pool));
SVN_ERR(fs_serialized_init(fs, common_pool, pool));
- return svn_fs_fs__verify(fs, cancel_func, cancel_baton, notify_func,
- notify_baton, start, end, pool);
+ return svn_fs_fs__verify(fs, start, end, notify_func, notify_baton,
+ cancel_func, cancel_baton, pool);
}
static svn_error_t *
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c Sat Feb 23 01:25:38 2013
@@ -2244,7 +2244,7 @@ get_cached_node_revision_body(node_revis
}
else
{
- pair_cache_key_t key;
+ pair_cache_key_t key = { 0 };
key.revision = svn_fs_fs__id_rev(id);
key.second = svn_fs_fs__id_offset(id);
@@ -2273,7 +2273,7 @@ set_cached_node_revision_body(node_revis
if (ffd->node_revision_cache && !svn_fs_fs__id_txn_id(id))
{
- pair_cache_key_t key;
+ pair_cache_key_t key = { 0 };
key.revision = svn_fs_fs__id_rev(id);
key.second = svn_fs_fs__id_offset(id);
@@ -3536,7 +3536,7 @@ parse_revprop(apr_hash_t **properties,
if (has_revprop_cache(fs, pool))
{
fs_fs_data_t *ffd = fs->fsap_data;
- pair_cache_key_t key;
+ pair_cache_key_t key = { 0 };
key.revision = revision;
key.second = generation;
@@ -3839,7 +3839,7 @@ get_revision_proplist(apr_hash_t **propl
if (has_revprop_cache(fs, pool))
{
svn_boolean_t is_cached;
- pair_cache_key_t key;
+ pair_cache_key_t key = { 0 };
SVN_ERR(read_revprop_generation(&generation, fs, pool));
@@ -4386,12 +4386,14 @@ create_rep_state_body(struct rep_state *
/* If the hint is
* - given,
+ * - refers to a valid revision,
* - refers to a packed revision,
* - as does the rep we want to read, and
* - refers to the same pack file as the rep
* ...
*/
if ( file_hint && rev_hint && *file_hint
+ && SVN_IS_VALID_REVNUM(*rev_hint)
&& *rev_hint < ffd->min_unpacked_rev
&& rep->revision < ffd->min_unpacked_rev
&& ( (*rev_hint / ffd->max_files_per_dir)
@@ -5192,7 +5194,7 @@ read_representation(svn_stream_t **conte
else
{
fs_fs_data_t *ffd = fs->fsap_data;
- pair_cache_key_t fulltext_cache_key;
+ pair_cache_key_t fulltext_cache_key = { 0 };
svn_filesize_t len = rep->expanded_size ? rep->expanded_size : rep->size;
struct rep_read_baton *rb;
@@ -5366,7 +5368,7 @@ svn_fs_fs__try_process_file_contents(svn
if (rep)
{
fs_fs_data_t *ffd = fs->fsap_data;
- pair_cache_key_t fulltext_cache_key;
+ pair_cache_key_t fulltext_cache_key = { 0 };
fulltext_cache_key.revision = rep->revision;
fulltext_cache_key.second = rep->offset;
@@ -5673,7 +5675,7 @@ svn_fs_fs__get_proplist(apr_hash_t **pro
{
fs_fs_data_t *ffd = fs->fsap_data;
representation_t *rep = noderev->prop_rep;
- pair_cache_key_t key;
+ pair_cache_key_t key = { 0 };
key.revision = rep->revision;
key.second = rep->offset;
@@ -10301,6 +10303,15 @@ typedef struct verify_walker_baton_t
/* number of files opened since the last clean */
int file_count;
+ /* progress notification callback to invoke periodically (may be NULL) */
+ svn_fs_progress_notify_func_t notify_func;
+
+ /* baton to use with NOTIFY_FUNC */
+ void *notify_baton;
+
+ /* remember the last revision for which we called notify_func */
+ svn_revnum_t last_notified_revision;
+
/* current file handle (or NULL) */
apr_file_t *file_hint;
@@ -10327,10 +10338,19 @@ verify_walker(representation_t *rep,
verify_walker_baton_t *walker_baton = baton;
apr_file_t * previous_file;
- /* free resources periodically */
+ /* notify and free resources periodically */
if ( walker_baton->iteration_count > 1000
|| walker_baton->file_count > 16)
{
+ if ( walker_baton->notify_func
+ && rep->revision != walker_baton->last_notified_revision)
+ {
+ walker_baton->notify_func(rep->revision,
+ walker_baton->notify_baton,
+ scratch_pool);
+ walker_baton->last_notified_revision = rep->revision;
+ }
+
svn_pool_clear(walker_baton->pool);
walker_baton->iteration_count = 0;
@@ -10362,12 +10382,12 @@ verify_walker(representation_t *rep,
svn_error_t *
svn_fs_fs__verify(svn_fs_t *fs,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- svn_fs_progress_notify_func_t notify_func,
- void *notify_baton,
svn_revnum_t start,
svn_revnum_t end,
+ svn_fs_progress_notify_func_t notify_func,
+ void *notify_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
apr_pool_t *pool)
{
fs_fs_data_t *ffd = fs->fsap_data;
@@ -10394,14 +10414,20 @@ svn_fs_fs__verify(svn_fs_t *fs,
verify_walker_baton_t *baton = apr_pcalloc(pool, sizeof(*baton));
baton->rev_hint = SVN_INVALID_REVNUM;
baton->pool = svn_pool_create(pool);
+ baton->last_notified_revision = SVN_INVALID_REVNUM;
+ baton->notify_func = notify_func;
+ baton->notify_baton = notify_baton;
+ /* tell the user that we are now read to do *something* */
+ if (notify_func)
+ notify_func(SVN_INVALID_REVNUM, notify_baton, baton->pool);
+
/* Do not attempt to walk the rep-cache database if its file does
not exist, since doing so would create it --- which may confuse
the administrator. Don't take any lock. */
- SVN_ERR(svn_fs_fs__walk_rep_reference(fs, verify_walker, baton,
+ SVN_ERR(svn_fs_fs__walk_rep_reference(fs, start, end,
+ verify_walker, baton,
cancel_func, cancel_baton,
- notify_func, notify_baton,
- start, end,
pool));
/* walker resource cleanup */
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.h?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.h Sat Feb 23 01:25:38 2013
@@ -38,17 +38,22 @@ svn_error_t *svn_fs_fs__open(svn_fs_t *f
svn_error_t *svn_fs_fs__upgrade(svn_fs_t *fs,
apr_pool_t *pool);
-/* Verify the fsfs filesystem FS. Use POOL for temporary allocations. */
+/* Verify metadata in fsfs filesystem FS. Limit the checks to revisions
+ * START to END where possible. Indicate progress via the optional
+ * NOTIFY_FUNC callback using NOTIFY_BATON. The optional CANCEL_FUNC
+ * will periodically be called with CANCEL_BATON to allow for preemption.
+ * Use POOL for temporary allocations. */
svn_error_t *svn_fs_fs__verify(svn_fs_t *fs,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- svn_fs_progress_notify_func_t notify_func,
- void *notify_baton,
svn_revnum_t start,
svn_revnum_t end,
+ svn_fs_progress_notify_func_t notify_func,
+ void *notify_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
apr_pool_t *pool);
-/* Verify REVISION in filesystem FS. Use POOL for temporary allocations. */
+/* Verify metadata of REVISION in filesystem FS.
+ * Use POOL for temporary allocations. */
svn_error_t *
svn_fs_fs__verify_rev(svn_fs_t *fs,
svn_revnum_t revision,
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache-db.sql
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache-db.sql?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache-db.sql (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache-db.sql Sat Feb 23 01:25:38 2013
@@ -22,8 +22,6 @@
*/
-- STMT_CREATE_SCHEMA
-PRAGMA AUTO_VACUUM = 1;
-
/* A table mapping representation hashes to locations in a rev file. */
CREATE TABLE rep_cache (
hash TEXT NOT NULL PRIMARY KEY,
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.c Sat Feb 23 01:25:38 2013
@@ -128,6 +128,8 @@ svn_fs_fs__exists_rep_cache(svn_boolean_
svn_error_t *
svn_fs_fs__walk_rep_reference(svn_fs_t *fs,
+ svn_revnum_t start,
+ svn_revnum_t end,
svn_error_t *(*walker)(representation_t *,
void *,
svn_fs_t *,
@@ -135,17 +137,12 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *
void *walker_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
- svn_fs_progress_notify_func_t notify_func,
- void *notify_baton,
- svn_revnum_t start,
- svn_revnum_t end,
apr_pool_t *pool)
{
fs_fs_data_t *ffd = fs->fsap_data;
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
int iterations = 0;
- svn_revnum_t last_notified_revision = SVN_INVALID_REVNUM;
apr_pool_t *iterpool = svn_pool_create(pool);
@@ -167,9 +164,6 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *
SVN_ERR(svn_sqlite__reset(stmt));
if (SVN_IS_VALID_REVNUM(max)) /* The rep-cache could be empty. */
SVN_ERR(svn_fs_fs__revision_exists(max, fs, iterpool));
-
- if (notify_func)
- notify_func(SVN_INVALID_REVNUM, notify_baton, iterpool);
}
SVN_ERR(svn_sqlite__get_statement(&stmt, ffd->rep_cache_db,
@@ -216,16 +210,6 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *
return svn_error_compose_create(err, svn_sqlite__reset(stmt));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
-
- /* Notify (occasionally, because walking is fast and we can't
- guarantee a properly ordered notification sequence anyway) */
- if ( notify_func
- && (iterations % 1024 == 0)
- && (rep->revision != last_notified_revision))
- {
- notify_func(rep->revision, notify_baton, iterpool);
- last_notified_revision = rep->revision;
- }
}
SVN_ERR(svn_sqlite__reset(stmt));
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.h?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.h Sat Feb 23 01:25:38 2013
@@ -48,6 +48,8 @@ svn_fs_fs__exists_rep_cache(svn_boolean_
/* Iterate all representations currently in FS's cache. */
svn_error_t *
svn_fs_fs__walk_rep_reference(svn_fs_t *fs,
+ svn_revnum_t start,
+ svn_revnum_t end,
svn_error_t *(*walker)(representation_t *rep,
void *walker_baton,
svn_fs_t *fs,
@@ -55,10 +57,6 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *
void *walker_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
- svn_fs_progress_notify_func_t notify_func,
- void *notify_baton,
- svn_revnum_t start,
- svn_revnum_t end,
apr_pool_t *pool);
/* Return the representation REP in FS which has fulltext CHECKSUM.
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/temp_serializer.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/temp_serializer.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/temp_serializer.c Sat Feb 23 01:25:38 2013
@@ -739,9 +739,12 @@ svn_fs_fs__serialize_node_revision(void
svn_stringbuf_t *serialized;
node_revision_t *noderev = item;
- /* create an (empty) serialization context with plenty of buffer space */
+ /* create an (empty) serialization context with plenty of (initial)
+ * buffer space. */
svn_temp_serializer__context_t *context =
- svn_temp_serializer__init(NULL, 0, 503, pool);
+ svn_temp_serializer__init(NULL, 0,
+ 1024 - SVN_TEMP_SERIALIZER__OVERHEAD,
+ pool);
/* serialize the noderev */
svn_fs_fs__noderev_serialize(context, &noderev);
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/tree.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/tree.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/tree.c Sat Feb 23 01:25:38 2013
@@ -497,6 +497,9 @@ dag_node_cache_set(svn_fs_root_t *root,
SVN_ERR_ASSERT(*path == '/');
+ /* Do *not* attempt to dup and put the node into L1.
+ * dup() is twice as expensive as an L2 lookup (which will set also L1).
+ */
locate_cache(&cache, &key, root, path, pool);
return svn_cache__set(cache, key, node, pool);
@@ -847,20 +850,28 @@ typedef enum open_path_flags_t {
directories must exist, as usual.) If the last component doesn't
exist, simply leave the `node' member of the bottom parent_path
component zero. */
- open_path_last_optional = 1
+ open_path_last_optional = 1,
+ /* When this flag is set, don't bother to lookup the DAG node in
+ our caches because we already tried this. Ignoring this flag
+ has no functional impact. */
+ open_path_uncached = 2,
+
+ /* The caller does not care about the parent node chain but only
+ the final DAG node. */
+ open_path_node_only = 4
} open_path_flags_t;
/* Open the node identified by PATH in ROOT, allocating in POOL. Set
*PARENT_PATH_P to a path from the node up to ROOT. The resulting
**PARENT_PATH_P value is guaranteed to contain at least one
- *element, for the root directory.
+ *element, for the root directory. PATH must be in canonical form.
If resulting *PARENT_PATH_P will eventually be made mutable and
modified, or if copy ID inheritance information is otherwise
needed, TXN_ID should be the ID of the mutability transaction. If
- TXN_ID is NULL, no copy ID in heritance information will be
+ TXN_ID is NULL, no copy ID inheritance information will be
calculated for the *PARENT_PATH_P chain.
If FLAGS & open_path_last_optional is zero, return the error
@@ -871,6 +882,11 @@ typedef enum open_path_flags_t {
callers that create new nodes --- we find the parent directory for
them, and tell them whether the entry exists already.
+ The remaining bits in FLAGS are hints that allow this function
+ to take shortcuts based on knowledge that the caller provides,
+ such as the caller is not actually being interested in PARENT_PATH_P,
+ but only in (*PARENT_PATH_P)->NODE.
+
NOTE: Public interfaces which only *read* from the filesystem
should not call this function directly, but should instead use
get_dag().
@@ -884,23 +900,44 @@ open_path(parent_path_t **parent_path_p,
apr_pool_t *pool)
{
svn_fs_t *fs = root->fs;
- dag_node_t *here; /* The directory we're currently looking at. */
- parent_path_t *parent_path; /* The path from HERE up to the root. */
+ dag_node_t *here = NULL; /* The directory we're currently looking at. */
+ parent_path_t *parent_path; /* The path from HERE up to the root. */
const char *rest; /* The portion of PATH we haven't traversed yet. */
- const char *canon_path = svn_fs__is_canonical_abspath(path)
- ? path
- : svn_fs__canonicalize_abspath(path, pool);
+
+ /* ensure a canonical path representation */
const char *path_so_far = "/";
apr_pool_t *iterpool = svn_pool_create(pool);
- /* Make a parent_path item for the root node, using its own current
- copy id. */
- SVN_ERR(root_node(&here, root, pool));
+ /* callers often traverse the tree in some path-based order. That means
+ a sibling of PATH has been presently accessed. Try to start the lookup
+ directly at the parent node, if the caller did not requested the full
+ parent chain. */
+ const char *directory;
+ assert(svn_fs__is_canonical_abspath(path));
+ if (flags & open_path_node_only)
+ {
+ directory = svn_dirent_dirname(path, pool);
+ if (directory[1] != 0) /* root nodes are covered anyway */
+ SVN_ERR(dag_node_cache_get(&here, root, directory, TRUE, pool));
+ }
+
+ /* did the shortcut work? */
+ if (here)
+ {
+ path_so_far = directory;
+ rest = path + strlen(directory) + 1;
+ }
+ else
+ {
+ /* Make a parent_path item for the root node, using its own current
+ copy id. */
+ SVN_ERR(root_node(&here, root, pool));
+ rest = path + 1; /* skip the leading '/', it saves in iteration */
+ }
+
parent_path = make_parent_path(here, 0, 0, pool);
parent_path->copy_inherit = copy_id_inherit_self;
- rest = canon_path + 1; /* skip the leading '/', it saves in iteration */
-
/* Whenever we are at the top of this loop:
- HERE is our current directory,
- ID is the node revision ID of HERE,
@@ -933,13 +970,16 @@ open_path(parent_path_t **parent_path_p,
copy_id_inherit_t inherit;
const char *copy_path = NULL;
svn_error_t *err = SVN_NO_ERROR;
- dag_node_t *cached_node;
+ dag_node_t *cached_node = NULL;
/* If we found a directory entry, follow it. First, we
check our node cache, and, failing that, we hit the DAG
- layer. */
- SVN_ERR(dag_node_cache_get(&cached_node, root, path_so_far, TRUE,
- pool));
+ layer. Don't bother to contact the cache for the last
+ element if we already know the lookup to fail for the
+ complete path. */
+ if (next || !(flags & open_path_uncached))
+ SVN_ERR(dag_node_cache_get(&cached_node, root, path_so_far,
+ TRUE, pool));
if (cached_node)
child = cached_node;
else
@@ -972,14 +1012,22 @@ open_path(parent_path_t **parent_path_p,
/* Other errors we return normally. */
SVN_ERR(err);
- /* Now, make a parent_path item for CHILD. */
- parent_path = make_parent_path(child, entry, parent_path, pool);
- if (txn_id)
+ if (flags & open_path_node_only)
{
- SVN_ERR(get_copy_inheritance(&inherit, ©_path,
- fs, parent_path, txn_id, iterpool));
- parent_path->copy_inherit = inherit;
- parent_path->copy_src_path = apr_pstrdup(pool, copy_path);
+ /* Shortcut: the caller only wan'ts the final DAG node. */
+ parent_path->node = child;
+ }
+ else
+ {
+ /* Now, make a parent_path item for CHILD. */
+ parent_path = make_parent_path(child, entry, parent_path, pool);
+ if (txn_id)
+ {
+ SVN_ERR(get_copy_inheritance(&inherit, ©_path, fs,
+ parent_path, txn_id, iterpool));
+ parent_path->copy_inherit = inherit;
+ parent_path->copy_src_path = apr_pstrdup(pool, copy_path);
+ }
}
/* Cache the node we found (if it wasn't already cached). */
@@ -1129,7 +1177,7 @@ get_dag(dag_node_t **dag_node_p,
if (! node)
{
/* Canonicalize the input PATH. */
- if (!svn_fs__is_canonical_abspath(path))
+ if (! svn_fs__is_canonical_abspath(path))
{
path = svn_fs__canonicalize_abspath(path, pool);
@@ -1142,7 +1190,9 @@ get_dag(dag_node_t **dag_node_p,
{
/* Call open_path with no flags, as we want this to return an
* error if the node for which we are searching doesn't exist. */
- SVN_ERR(open_path(&parent_path, root, path, 0, NULL, pool));
+ SVN_ERR(open_path(&parent_path, root, path,
+ open_path_uncached | open_path_node_only,
+ NULL, pool));
node = parent_path->node;
/* No need to cache our find -- open_path() will do that for us. */
@@ -1369,6 +1419,7 @@ fs_change_node_prop(svn_fs_root_t *root,
return SVN_FS__NOT_TXN(root);
txn_id = root->txn;
+ path = svn_fs__canonicalize_abspath(path, pool);
SVN_ERR(open_path(&parent_path, root, path, 0, txn_id, pool));
/* Check (non-recursively) to see if path is locked; if so, check
@@ -2140,6 +2191,7 @@ fs_make_dir(svn_fs_root_t *root,
dag_node_t *sub_dir;
const char *txn_id = root->txn;
+ path = svn_fs__canonicalize_abspath(path, pool);
SVN_ERR(open_path(&parent_path, root, path, open_path_last_optional,
txn_id, pool));
@@ -2191,6 +2243,7 @@ fs_delete_node(svn_fs_root_t *root,
if (! root->is_txn_root)
return SVN_FS__NOT_TXN(root);
+ path = svn_fs__canonicalize_abspath(path, pool);
SVN_ERR(open_path(&parent_path, root, path, 0, txn_id, pool));
kind = svn_fs_fs__dag_node_kind(parent_path->node);
@@ -2390,7 +2443,12 @@ fs_copy(svn_fs_root_t *from_root,
const char *to_path,
apr_pool_t *pool)
{
- return svn_error_trace(copy_helper(from_root, from_path, to_root, to_path,
+ return svn_error_trace(copy_helper(from_root,
+ svn_fs__canonicalize_abspath(from_path,
+ pool),
+ to_root,
+ svn_fs__canonicalize_abspath(to_path,
+ pool),
TRUE, pool));
}
@@ -2407,6 +2465,7 @@ fs_revision_link(svn_fs_root_t *from_roo
if (! to_root->is_txn_root)
return SVN_FS__NOT_TXN(to_root);
+ path = svn_fs__canonicalize_abspath(path, pool);
return svn_error_trace(copy_helper(from_root, path, to_root, path,
FALSE, pool));
}
@@ -2482,8 +2541,9 @@ fs_make_file(svn_fs_root_t *root,
dag_node_t *child;
const char *txn_id = root->txn;
+ path = svn_fs__canonicalize_abspath(path, pool);
SVN_ERR(open_path(&parent_path, root, path, open_path_last_optional,
- txn_id, pool));
+ txn_id, pool));
/* If there's already a file by that name, complain.
This also catches the case of trying to make a file named `/'. */
@@ -2791,7 +2851,7 @@ fs_apply_textdelta(svn_txdelta_window_ha
txdelta_baton_t *tb = apr_pcalloc(pool, sizeof(*tb));
tb->root = root;
- tb->path = path;
+ tb->path = svn_fs__canonicalize_abspath(path, pool);
tb->pool = pool;
tb->base_checksum = svn_checksum_dup(base_checksum, pool);
tb->result_checksum = svn_checksum_dup(result_checksum, pool);
@@ -2924,7 +2984,7 @@ fs_apply_text(svn_stream_t **contents_p,
struct text_baton_t *tb = apr_pcalloc(pool, sizeof(*tb));
tb->root = root;
- tb->path = path;
+ tb->path = svn_fs__canonicalize_abspath(path, pool);
tb->pool = pool;
tb->result_checksum = svn_checksum_dup(result_checksum, pool);
@@ -3144,6 +3204,7 @@ static svn_error_t *fs_closest_copy(svn_
*root_p = NULL;
*path_p = NULL;
+ path = svn_fs__canonicalize_abspath(path, pool);
SVN_ERR(open_path(&parent_path, root, path, 0, NULL, pool));
/* Find the youngest copyroot in the path of this node-rev, which
@@ -3162,7 +3223,7 @@ static svn_error_t *fs_closest_copy(svn_
if (kind == svn_node_none)
return SVN_NO_ERROR;
SVN_ERR(open_path(©_dst_parent_path, copy_dst_root, path,
- 0, NULL, pool));
+ open_path_node_only, NULL, pool));
copy_dst_node = copy_dst_parent_path->node;
if (! svn_fs_fs__id_check_related(svn_fs_fs__dag_get_id(copy_dst_node),
svn_fs_fs__dag_get_id(parent_path->node)))
@@ -3622,7 +3683,7 @@ assemble_history(svn_fs_t *fs,
{
svn_fs_history_t *history = apr_pcalloc(pool, sizeof(*history));
fs_history_data_t *fhd = apr_pcalloc(pool, sizeof(*fhd));
- fhd->path = path;
+ fhd->path = svn_fs__canonicalize_abspath(path, pool);
fhd->revision = revision;
fhd->is_interesting = is_interesting;
fhd->path_hint = path_hint;
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_util/fs-util.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_util/fs-util.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_util/fs-util.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_util/fs-util.c Sat Feb 23 01:25:38 2013
@@ -35,26 +35,19 @@
#include "private/svn_fspath.h"
#include "../libsvn_fs/fs-loader.h"
-svn_boolean_t
-svn_fs__is_canonical_abspath(const char *path)
+/* Return TRUE, if PATH of PATH_LEN > 0 chars starts with a '/' and does
+ * not end with a '/' and does not contain duplicate '/'.
+ */
+static svn_boolean_t
+is_canonical_abspath(const char *path, size_t path_len)
{
- size_t path_len;
const char *end;
- /* No PATH? No problem. */
- if (! path)
- return TRUE;
-
- /* Empty PATH? That's just "/". */
- if (! *path)
- return FALSE;
-
- /* No leading slash? Fix that. */
- if (*path != '/')
+ /* check for leading '/' */
+ if (path[0] != '/')
return FALSE;
/* check for trailing '/' */
- path_len = strlen(path);
if (path_len == 1)
return TRUE;
if (path[path_len - 1] == '/')
@@ -69,6 +62,21 @@ svn_fs__is_canonical_abspath(const char
return TRUE;
}
+svn_boolean_t
+svn_fs__is_canonical_abspath(const char *path)
+{
+ /* No PATH? No problem. */
+ if (! path)
+ return TRUE;
+
+ /* Empty PATH? That's just "/". */
+ if (! *path)
+ return FALSE;
+
+ /* detailed checks */
+ return is_canonical_abspath(path, strlen(path));
+}
+
const char *
svn_fs__canonicalize_abspath(const char *path, apr_pool_t *pool)
{
@@ -83,12 +91,16 @@ svn_fs__canonicalize_abspath(const char
/* Empty PATH? That's just "/". */
if (! *path)
- return apr_pstrdup(pool, "/");
+ return "/";
+
+ /* Non-trivial cases. Maybe, the path already is canonical after all? */
+ path_len = strlen(path);
+ if (is_canonical_abspath(path, path_len))
+ return apr_pstrmemdup(pool, path, path_len);
/* Now, the fun begins. Alloc enough room to hold PATH with an
added leading '/'. */
- path_len = strlen(path);
- newpath = apr_pcalloc(pool, path_len + 2);
+ newpath = apr_palloc(pool, path_len + 2);
/* No leading slash? Fix that. */
if (*path != '/')
@@ -123,6 +135,8 @@ svn_fs__canonicalize_abspath(const char
the root directory case)? */
if ((newpath[newpath_i - 1] == '/') && (newpath_i > 1))
newpath[newpath_i - 1] = '\0';
+ else
+ newpath[newpath_i] = '\0';
return newpath;
}
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_local/ra_plugin.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_local/ra_plugin.c Sat Feb 23 01:25:38 2013
@@ -848,10 +848,10 @@ svn_ra_local__do_switch(svn_ra_session_t
update_revision,
update_target,
switch_url,
- TRUE,
+ TRUE /* text_deltas */,
depth,
- FALSE, /* ### TODO(sussman): take new arg */
- TRUE,
+ FALSE /* send_copyfrom_args */,
+ TRUE /* ignore_ancestry */,
update_editor,
update_baton,
pool);
@@ -1513,7 +1513,10 @@ svn_ra_local__has_capability(svn_ra_sess
|| strcmp(capability, SVN_RA_CAPABILITY_PARTIAL_REPLAY) == 0
|| strcmp(capability, SVN_RA_CAPABILITY_COMMIT_REVPROPS) == 0
|| strcmp(capability, SVN_RA_CAPABILITY_ATOMIC_REVPROPS) == 0
- || strcmp(capability, SVN_RA_CAPABILITY_INHERITED_PROPS) == 0)
+ || strcmp(capability, SVN_RA_CAPABILITY_INHERITED_PROPS) == 0
+ || strcmp(capability, SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS) == 0
+ || strcmp(capability, SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE) == 0
+ )
{
*has = TRUE;
}
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/commit.c Sat Feb 23 01:25:38 2013
@@ -289,6 +289,8 @@ checkout_node(const char **working_url,
apr_pool_t *scratch_pool)
{
svn_ra_serf__handler_t handler = { 0 };
+ apr_status_t status;
+ apr_uri_t uri;
/* HANDLER_POOL is the scratch pool since we don't need to remember
anything from the handler. We just want the working resource. */
@@ -315,7 +317,17 @@ checkout_node(const char **working_url,
return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
_("No Location header received"));
- *working_url = apr_pstrdup(result_pool, handler.location);
+ /* We only want the path portion of the Location header.
+ (code.google.com sometimes returns an 'http:' scheme for an
+ 'https:' transaction ... we'll work around that by stripping the
+ scheme, host, and port here and re-adding the correct ones
+ later. */
+ status = apr_uri_parse(scratch_pool, handler.location, &uri);
+ if (status)
+ return svn_error_create(SVN_ERR_RA_DAV_MALFORMED_DATA, NULL,
+ _("Error parsing Location header value"));
+
+ *working_url = svn_urlpath__canonicalize(uri.path, result_pool);
return SVN_NO_ERROR;
}
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/options.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/options.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/options.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/options.c Sat Feb 23 01:25:38 2013
@@ -28,6 +28,7 @@
#include <serf.h>
#include "svn_dirent_uri.h"
+#include "svn_hash.h"
#include "svn_pools.h"
#include "svn_ra.h"
#include "svn_dav.h"
@@ -169,47 +170,50 @@ capabilities_headers_iterator_callback(v
if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_DEPTH, vals))
{
- apr_hash_set(session->capabilities,
- SVN_RA_CAPABILITY_DEPTH, APR_HASH_KEY_STRING,
- capability_yes);
+ svn_hash_sets(session->capabilities,
+ SVN_RA_CAPABILITY_DEPTH, capability_yes);
}
if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_MERGEINFO, vals))
{
/* The server doesn't know what repository we're referring
to, so it can't just say capability_yes. */
- apr_hash_set(session->capabilities,
- SVN_RA_CAPABILITY_MERGEINFO, APR_HASH_KEY_STRING,
- capability_server_yes);
+ if (!svn_hash_gets(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO))
+ {
+ svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO,
+ capability_server_yes);
+ }
}
if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_LOG_REVPROPS, vals))
{
- apr_hash_set(session->capabilities,
- SVN_RA_CAPABILITY_LOG_REVPROPS, APR_HASH_KEY_STRING,
- capability_yes);
+ svn_hash_sets(session->capabilities,
+ SVN_RA_CAPABILITY_LOG_REVPROPS, capability_yes);
}
if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_ATOMIC_REVPROPS, vals))
{
- apr_hash_set(session->capabilities,
- SVN_RA_CAPABILITY_ATOMIC_REVPROPS, APR_HASH_KEY_STRING,
- capability_yes);
+ svn_hash_sets(session->capabilities,
+ SVN_RA_CAPABILITY_ATOMIC_REVPROPS, capability_yes);
}
if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_PARTIAL_REPLAY, vals))
{
- apr_hash_set(session->capabilities,
- SVN_RA_CAPABILITY_PARTIAL_REPLAY, APR_HASH_KEY_STRING,
- capability_yes);
+ svn_hash_sets(session->capabilities,
+ SVN_RA_CAPABILITY_PARTIAL_REPLAY, capability_yes);
}
if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_INHERITED_PROPS, vals))
{
- apr_hash_set(session->capabilities,
- SVN_RA_CAPABILITY_INHERITED_PROPS,
- APR_HASH_KEY_STRING, capability_yes);
+ svn_hash_sets(session->capabilities,
+ SVN_RA_CAPABILITY_INHERITED_PROPS, capability_yes);
+ }
+ if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_GET_FILE_REVS_REVERSE,
+ vals))
+ {
+ svn_hash_sets(session->capabilities,
+ SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE,
+ capability_yes);
}
if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_EPHEMERAL_TXNPROPS, vals))
{
- apr_hash_set(session->capabilities,
- SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS, APR_HASH_KEY_STRING,
- capability_yes);
+ svn_hash_sets(session->capabilities,
+ SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS, capability_yes);
}
if (svn_cstring_match_list(SVN_DAV_NS_DAV_SVN_INLINE_PROPS, vals))
{
@@ -303,8 +307,20 @@ capabilities_headers_iterator_callback(v
{
const char *post_val = APR_ARRAY_IDX(vals, i, const char *);
- apr_hash_set(session->supported_posts, post_val,
- APR_HASH_KEY_STRING, (void *)1);
+ svn_hash_sets(session->supported_posts, post_val, (void *)1);
+ }
+ }
+ else if (svn_cstring_casecmp(key, SVN_DAV_REPOSITORY_MERGEINFO) == 0)
+ {
+ if (svn_cstring_casecmp(val, "yes") == 0)
+ {
+ svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO,
+ capability_yes);
+ }
+ else if (svn_cstring_casecmp(val, "no") == 0)
+ {
+ svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO,
+ capability_no);
}
}
}
@@ -331,25 +347,31 @@ options_response_handler(serf_request_t
serf_bucket_t *hdrs = serf_bucket_response_get_headers(response);
/* Start out assuming all capabilities are unsupported. */
- apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_PARTIAL_REPLAY,
- APR_HASH_KEY_STRING, capability_no);
- apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_DEPTH,
- APR_HASH_KEY_STRING, capability_no);
- apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO,
- APR_HASH_KEY_STRING, capability_no);
- apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_LOG_REVPROPS,
- APR_HASH_KEY_STRING, capability_no);
- apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
- APR_HASH_KEY_STRING, capability_no);
- apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_INHERITED_PROPS,
- APR_HASH_KEY_STRING, capability_no);
- apr_hash_set(session->capabilities, SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS,
- APR_HASH_KEY_STRING, capability_no);
+ svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_PARTIAL_REPLAY,
+ capability_no);
+ svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_DEPTH,
+ capability_no);
+ svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO,
+ NULL);
+ svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_LOG_REVPROPS,
+ capability_no);
+ svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_ATOMIC_REVPROPS,
+ capability_no);
+ svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_INHERITED_PROPS,
+ capability_no);
+ svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS,
+ capability_no);
/* Then see which ones we can discover. */
serf_bucket_headers_do(hdrs, capabilities_headers_iterator_callback,
opt_ctx);
+ /* Assume mergeinfo capability unsupported, if didn't recieve information
+ about server or repository mergeinfo capability. */
+ if (!svn_hash_gets(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO))
+ svn_hash_sets(session->capabilities, SVN_RA_CAPABILITY_MERGEINFO,
+ capability_no);
+
opt_ctx->headers_processed = TRUE;
}
@@ -548,9 +570,8 @@ svn_ra_serf__has_capability(svn_ra_sessi
else
cap_result = capability_yes;
- apr_hash_set(serf_sess->capabilities,
- SVN_RA_CAPABILITY_MERGEINFO, APR_HASH_KEY_STRING,
- cap_result);
+ svn_hash_sets(serf_sess->capabilities,
+ SVN_RA_CAPABILITY_MERGEINFO, cap_result);
}
else
{
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/property.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/property.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/property.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/property.c Sat Feb 23 01:25:38 2013
@@ -637,7 +637,7 @@ svn_ra_serf__wait_for_props(svn_ra_serf_
err2 = svn_ra_serf__error_on_status(handler->sline.code,
handler->path,
- NULL);
+ handler->location);
if (err2)
{
svn_error_clear(err);
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c Sat Feb 23 01:25:38 2013
@@ -3485,7 +3485,9 @@ try_get_wc_contents(svn_boolean_t *found
if (wc_stream)
{
- SVN_ERR(svn_stream_copy3(wc_stream, dst_stream, NULL, NULL, pool));
+ SVN_ERR(svn_stream_copy3(wc_stream,
+ svn_stream_disown(dst_stream, pool),
+ NULL, NULL, pool));
*found_p = TRUE;
}
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/util.c Sat Feb 23 01:25:38 2013
@@ -41,6 +41,7 @@
#include "svn_string.h"
#include "svn_xml.h"
#include "svn_props.h"
+#include "svn_dirent_uri.h"
#include "../libsvn_ra/ra_loader.h"
#include "private/svn_dep_compat.h"
@@ -987,27 +988,51 @@ svn_ra_serf__response_discard_handler(se
/* Return the value of the RESPONSE's Location header if any, or NULL
- otherwise. All allocations will be made in POOL. */
+ otherwise. */
static const char *
response_get_location(serf_bucket_t *response,
- apr_pool_t *pool)
+ const char *base_url,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
serf_bucket_t *headers;
const char *location;
- apr_status_t status;
- apr_uri_t uri;
headers = serf_bucket_response_get_headers(response);
location = serf_bucket_headers_get(headers, "Location");
if (location == NULL)
return NULL;
- /* Ignore the scheme/host/port. Or just return as-is if we can't parse. */
- status = apr_uri_parse(pool, location, &uri);
- if (!status)
- location = uri.path;
+ /* The RFCs say we should have received a full url in LOCATION, but
+ older apache versions and many custom web handlers just return a
+ relative path here...
+
+ And we can't trust anything because it is network data.
+ */
+ if (*location == '/')
+ {
+ apr_uri_t uri;
+ apr_status_t status;
+
+ status = apr_uri_parse(scratch_pool, base_url, &uri);
+
+ if (status != APR_SUCCESS)
+ return NULL;
+
+ /* Replace the path path with what we got */
+ uri.path = (char*)svn_urlpath__canonicalize(location, scratch_pool);
+
+ /* And make APR produce a proper full url for us */
+ location = apr_uri_unparse(scratch_pool, &uri, 0);
+
+ /* Fall through to ensure our canonicalization rules */
+ }
+ else if (!svn_path_is_url(location))
+ {
+ return NULL; /* Any other formats we should support? */
+ }
- return svn_urlpath__canonicalize(location, pool);
+ return svn_uri_canonicalize(location, result_pool);
}
@@ -1896,7 +1921,10 @@ handle_response(serf_request_t *request,
}
/* ... and set up the header fields in HANDLER. */
- handler->location = response_get_location(response, handler->handler_pool);
+ handler->location = response_get_location(response,
+ handler->session->session_url_str,
+ handler->handler_pool,
+ scratch_pool);
/* On the last request, we failed authentication. We succeeded this time,
so let's save away these credentials. */
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_svn/client.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_svn/client.c Sat Feb 23 01:25:38 2013
@@ -2589,43 +2589,46 @@ ra_svn_replay_range(svn_ra_session_t *se
}
-static svn_error_t *ra_svn_has_capability(svn_ra_session_t *session,
- svn_boolean_t *has,
- const char *capability,
- apr_pool_t *pool)
+static svn_error_t *
+ra_svn_has_capability(svn_ra_session_t *session,
+ svn_boolean_t *has,
+ const char *capability,
+ apr_pool_t *pool)
{
svn_ra_svn__session_baton_t *sess = session->priv;
+ static const char* capabilities[][2] =
+ {
+ /* { ra capability string, svn:// wire capability string} */
+ {SVN_RA_CAPABILITY_DEPTH, SVN_RA_SVN_CAP_DEPTH},
+ {SVN_RA_CAPABILITY_MERGEINFO, SVN_RA_SVN_CAP_MERGEINFO},
+ {SVN_RA_CAPABILITY_LOG_REVPROPS, SVN_RA_SVN_CAP_LOG_REVPROPS},
+ {SVN_RA_CAPABILITY_PARTIAL_REPLAY, SVN_RA_SVN_CAP_PARTIAL_REPLAY},
+ {SVN_RA_CAPABILITY_COMMIT_REVPROPS, SVN_RA_SVN_CAP_COMMIT_REVPROPS},
+ {SVN_RA_CAPABILITY_ATOMIC_REVPROPS, SVN_RA_SVN_CAP_ATOMIC_REVPROPS},
+ {SVN_RA_CAPABILITY_INHERITED_PROPS, SVN_RA_SVN_CAP_INHERITED_PROPS},
+ {SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS,
+ SVN_RA_SVN_CAP_EPHEMERAL_TXNPROPS},
+ {SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE,
+ SVN_RA_SVN_CAP_GET_FILE_REVS_REVERSE},
+
+ {NULL, NULL} /* End of list marker */
+ };
+ int i;
*has = FALSE;
- if (strcmp(capability, SVN_RA_CAPABILITY_DEPTH) == 0)
- *has = svn_ra_svn_has_capability(sess->conn, SVN_RA_SVN_CAP_DEPTH);
- else if (strcmp(capability, SVN_RA_CAPABILITY_MERGEINFO) == 0)
- *has = svn_ra_svn_has_capability(sess->conn, SVN_RA_SVN_CAP_MERGEINFO);
- else if (strcmp(capability, SVN_RA_CAPABILITY_LOG_REVPROPS) == 0)
- *has = svn_ra_svn_has_capability(sess->conn, SVN_RA_SVN_CAP_LOG_REVPROPS);
- else if (strcmp(capability, SVN_RA_CAPABILITY_PARTIAL_REPLAY) == 0)
- *has = svn_ra_svn_has_capability(sess->conn, SVN_RA_SVN_CAP_PARTIAL_REPLAY);
- else if (strcmp(capability, SVN_RA_CAPABILITY_COMMIT_REVPROPS) == 0)
- *has = svn_ra_svn_has_capability(sess->conn,
- SVN_RA_SVN_CAP_COMMIT_REVPROPS);
- else if (strcmp(capability, SVN_RA_CAPABILITY_ATOMIC_REVPROPS) == 0)
- *has = svn_ra_svn_has_capability(sess->conn,
- SVN_RA_SVN_CAP_ATOMIC_REVPROPS);
- else if (strcmp(capability, SVN_RA_CAPABILITY_INHERITED_PROPS) == 0)
- *has = svn_ra_svn_has_capability(sess->conn,
- SVN_RA_SVN_CAP_INHERITED_PROPS);
- else if (strcmp(capability, SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS) == 0)
- *has = svn_ra_svn_has_capability(sess->conn,
- SVN_RA_SVN_CAP_EPHEMERAL_TXNPROPS);
- else /* Don't know any other capabilities, so error. */
+ for (i = 0; capabilities[i][0]; i++)
{
- return svn_error_createf
- (SVN_ERR_UNKNOWN_CAPABILITY, NULL,
- _("Don't know anything about capability '%s'"), capability);
+ if (strcmp(capability, capabilities[i][0]))
+ {
+ *has = svn_ra_svn_has_capability(sess->conn, capabilities[i][1]);
+ return SVN_NO_ERROR;
+ }
}
- return SVN_NO_ERROR;
+ return svn_error_createf(SVN_ERR_UNKNOWN_CAPABILITY, NULL,
+ _("Don't know anything about capability '%s'"),
+ capability);
}
static svn_error_t *
Modified: subversion/branches/ev2-export/subversion/libsvn_repos/authz.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/authz.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/authz.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/authz.c Sat Feb 23 01:25:38 2013
@@ -771,9 +771,9 @@ authz_validate(svn_authz_t *authz, apr_p
/* Retrieve the file at DIRENT (contained in a repo) then parse it as a config
* file placing the result into CFG_P allocated in POOL.
*
- * If DIRENT is not a valid authz rule file then return SVN_AUTHZ_INVALD_CONFIG
- * as the error. The contents of CFG_P is then undefined. If MUST_EXIST is
- * TRUE, a missing authz file is also an error.
+ * If DIRENT cannot be parsed as a config file then an error is returned. The
+ * contents of CFG_P is then undefined. If MUST_EXIST is TRUE, a missing
+ * authz file is also an error.
*
* SCRATCH_POOL will be used for temporary allocations. */
static svn_error_t *
@@ -794,7 +794,7 @@ authz_retrieve_config_repo(svn_config_t
/* Search for a repository in the full path. */
repos_root_dirent = svn_repos_find_root_path(dirent, scratch_pool);
if (!repos_root_dirent)
- return svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL,
+ return svn_error_createf(SVN_ERR_RA_LOCAL_REPOS_NOT_FOUND, NULL,
"Unable to find repository at '%s'", dirent);
/* Attempt to open a repository at repos_root_dirent. */
@@ -804,7 +804,7 @@ authz_retrieve_config_repo(svn_config_t
/* Root path is always a directory so no reason to go any further */
if (*fs_path == '\0')
- return svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL,
+ return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
"'/' is not a file in repo '%s'",
repos_root_dirent);
@@ -826,19 +826,19 @@ authz_retrieve_config_repo(svn_config_t
{
if (!must_exist)
{
- SVN_ERR(svn_config_create(cfg_p, TRUE, scratch_pool));
+ SVN_ERR(svn_config_create(cfg_p, TRUE, result_pool));
return SVN_NO_ERROR;
}
else
{
- return svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL,
+ return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
"'%s' path not found in repo '%s'", fs_path,
repos_root_dirent);
}
}
else if (node_kind != svn_node_file)
{
- return svn_error_createf(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL,
+ return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
"'%s' is not a file in repo '%s'", fs_path,
repos_root_dirent);
}
@@ -849,22 +849,22 @@ authz_retrieve_config_repo(svn_config_t
/* Add the URL to the error stack since the parser doesn't have it. */
if (err != SVN_NO_ERROR)
return svn_error_createf(err->apr_err, err,
- "Error parsing config file: '%s' in repo '%s':",
+ "Error while parsing config file: '%s' in repo '%s':",
fs_path, repos_root_dirent);
return SVN_NO_ERROR;
}
-/* Given a PATH which might be a realative repo URL (^/), an absolute
+/* Given a PATH which might be a relative repo URL (^/), an absolute
* local repo URL (file://), an absolute path outside of the repo
* or a location in the Windows registry.
*
* Retrieve the configuration data that PATH points at and parse it into
* CFG_P allocated in POOL.
*
- * If PATH is not a valid authz rule file then return SVN_AUTHZ_INVALD_CONFIG
- * as the error. The contents of CFG_P is then undefined. If MUST_EXIST is
- * TRUE, a missing authz file is also an error.
+ * If PATH cannot be parsed as a config file then an error is returned. The
+ * contents of CFG_P is then undefined. If MUST_EXIST is TRUE, a missing
+ * authz file is also an error.
*
* REPOS_ROOT points at the root of the repos you are
* going to apply the authz against, can be NULL if you are sure that you
@@ -919,20 +919,81 @@ authz_retrieve_config(svn_config_t **cfg
return SVN_NO_ERROR;
}
+
+/* Callback to copy (name, value) group into the "groups" section
+ of another configuration. */
+static svn_boolean_t
+authz_copy_group(const char *name, const char *value,
+ void *baton, apr_pool_t *pool)
+{
+ svn_config_t *authz_cfg = baton;
+
+ svn_config_set(authz_cfg, SVN_CONFIG_SECTION_GROUPS, name, value);
+
+ return TRUE;
+}
+
+/* Copy group definitions from GROUPS_CFG to the resulting AUTHZ.
+ * If AUTHZ already contains any group definition, report an error.
+ * Use POOL for temporary allocations. */
+static svn_error_t *
+authz_copy_groups(svn_authz_t *authz, svn_config_t *groups_cfg,
+ apr_pool_t *pool)
+{
+ /* Easy out: we prohibit local groups in the authz file when global
+ groups are being used. */
+ if (svn_config_has_section(authz->cfg, SVN_CONFIG_SECTION_GROUPS))
+ {
+ return svn_error_create(SVN_ERR_AUTHZ_INVALID_CONFIG, NULL,
+ "Authz file cannot contain any groups "
+ "when global groups are being used.");
+ }
+
+ svn_config_enumerate2(groups_cfg, SVN_CONFIG_SECTION_GROUPS,
+ authz_copy_group, authz->cfg, pool);
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_repos__authz_read(svn_authz_t **authz_p, const char *path,
- svn_boolean_t must_exist, svn_boolean_t accept_urls,
- const char *repos_root, apr_pool_t *pool)
+ const char *groups_path, svn_boolean_t must_exist,
+ svn_boolean_t accept_urls, const char *repos_root,
+ apr_pool_t *pool)
{
svn_authz_t *authz = apr_palloc(pool, sizeof(*authz));
- /* Load the rule file */
+ /* Load the authz file */
if (accept_urls)
SVN_ERR(authz_retrieve_config(&authz->cfg, path, must_exist, repos_root,
pool));
else
SVN_ERR(svn_config_read2(&authz->cfg, path, must_exist, TRUE, pool));
+ if (groups_path)
+ {
+ svn_config_t *groups_cfg;
+ svn_error_t *err;
+
+ /* Load the groups file */
+ if (accept_urls)
+ SVN_ERR(authz_retrieve_config(&groups_cfg, groups_path, must_exist,
+ repos_root, pool));
+ else
+ SVN_ERR(svn_config_read2(&groups_cfg, groups_path, must_exist,
+ TRUE, pool));
+
+ /* Copy the groups from groups_cfg into authz. */
+ err = authz_copy_groups(authz, groups_cfg, pool);
+
+ /* Add the paths to the error stack since the authz_copy_groups
+ routine knows nothing about them. */
+ if (err != SVN_NO_ERROR)
+ return svn_error_createf(err->apr_err, err,
+ "Error reading authz file '%s' with "
+ "groups file '%s':", path, groups_path);
+ }
+
/* Make sure there are no errors in the configuration. */
SVN_ERR(authz_validate(authz, pool));
@@ -946,23 +1007,33 @@ svn_repos__authz_read(svn_authz_t **auth
svn_error_t *
svn_repos_authz_read2(svn_authz_t **authz_p, const char *path,
- svn_boolean_t must_exist, const char *repos_root,
- apr_pool_t *pool)
+ const char *groups_path, svn_boolean_t must_exist,
+ const char *repos_root, apr_pool_t *pool)
{
- return svn_repos__authz_read(authz_p, path, must_exist, TRUE, repos_root,
- pool);
+ return svn_repos__authz_read(authz_p, path, groups_path, must_exist,
+ TRUE, repos_root, pool);
}
svn_error_t *
svn_repos_authz_parse(svn_authz_t **authz_p, svn_stream_t *stream,
- apr_pool_t *pool)
+ svn_stream_t *groups_stream, apr_pool_t *pool)
{
svn_authz_t *authz = apr_palloc(pool, sizeof(*authz));
- /* Parse the stream */
+ /* Parse the authz stream */
SVN_ERR(svn_config_parse(&authz->cfg, stream, TRUE, pool));
+ if (groups_stream)
+ {
+ svn_config_t *groups_cfg;
+
+ /* Parse the groups stream */
+ SVN_ERR(svn_config_parse(&groups_cfg, groups_stream, TRUE, pool));
+
+ SVN_ERR(authz_copy_groups(authz, groups_cfg, pool));
+ }
+
/* Make sure there are no errors in the configuration. */
SVN_ERR(authz_validate(authz, pool));
Modified: subversion/branches/ev2-export/subversion/libsvn_repos/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/deprecated.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/deprecated.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/deprecated.c Sat Feb 23 01:25:38 2013
@@ -1013,5 +1013,6 @@ svn_error_t *
svn_repos_authz_read(svn_authz_t **authz_p, const char *file,
svn_boolean_t must_exist, apr_pool_t *pool)
{
- return svn_repos__authz_read(authz_p, file, must_exist, FALSE, NULL, pool);
+ return svn_repos__authz_read(authz_p, file, NULL, must_exist,
+ FALSE, NULL, pool);
}
Modified: subversion/branches/ev2-export/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/dump.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/dump.c Sat Feb 23 01:25:38 2013
@@ -1442,10 +1442,10 @@ svn_repos_verify_fs2(svn_repos_t *repos,
= svn_repos_notify_create(svn_repos_notify_verify_struc_rev, pool);
}
- /* Verify global/auxiliary data and backend-specific data first. */
- SVN_ERR(svn_fs_verify(svn_fs_path(fs, pool), cancel_func, cancel_baton,
+ /* Verify global metadata and backend-specific data first. */
+ SVN_ERR(svn_fs_verify(svn_fs_path(fs, pool), start_rev, end_rev,
verify_notify, verify_notify_baton,
- start_rev, end_rev, pool));
+ cancel_func, cancel_baton, pool));
for (rev = start_rev; rev <= end_rev; rev++)
{
Modified: subversion/branches/ev2-export/subversion/libsvn_repos/reporter.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/reporter.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/reporter.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/reporter.c Sat Feb 23 01:25:38 2013
@@ -687,18 +687,13 @@ delta_files(report_baton_t *b, void *fil
{
SVN_ERR(get_source_root(b, &s_root, s_rev));
- /* Is this delta calculation worth our time? If we are ignoring
- ancestry, then our editor implementor isn't concerned by the
- theoretical differences between "has contents which have not
- changed with respect to" and "has the same actual contents
- as". We'll do everything we can to avoid transmitting even
- an empty text-delta in that case. */
- if (b->ignore_ancestry)
- SVN_ERR(svn_repos__compare_files(&changed, b->t_root, t_path,
- s_root, s_path, pool));
- else
- SVN_ERR(svn_fs_contents_changed(&changed, b->t_root, t_path, s_root,
- s_path, pool));
+ /* We're not interested in the theoretical difference between "has
+ contents which have not changed with respect to" and "has the same
+ actual contents as" when sending text-deltas. If we know the
+ delta is an empty one, we avoiding sending it in either case. */
+ SVN_ERR(svn_repos__compare_files(&changed, b->t_root, t_path,
+ s_root, s_path, pool));
+
if (!changed)
return SVN_NO_ERROR;
Modified: subversion/branches/ev2-export/subversion/libsvn_repos/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/repos.c?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/repos.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/repos.c Sat Feb 23 01:25:38 2013
@@ -1025,6 +1025,12 @@ create_conf(svn_repos_t *repos, apr_pool
"### no path-based access control is done." NL
"### Uncomment the line below to use the default authorization file." NL
"# authz-db = " SVN_REPOS__CONF_AUTHZ NL
+"### The groups-db option controls the location of the groups file." NL
+"### Unless you specify a path starting with a /, the file's location is" NL
+"### relative to the directory containing this file. The specified path" NL
+"### may be a repository relative URL (^/) or an absolute file:// URL to a" NL
+"### text file in a Subversion repository." NL
+"# groups-db = " SVN_REPOS__CONF_GROUPS NL
"### This option specifies the authentication realm of the repository." NL
"### If two repositories have the same authentication realm, they should" NL
"### have the same password database, and vice versa. The default realm" NL
@@ -1825,6 +1831,62 @@ svn_repos_recover4(const char *path,
return SVN_NO_ERROR;
}
+struct freeze_baton_t {
+ apr_array_header_t *paths;
+ int counter;
+ svn_error_t *(*freeze_body)(void *, apr_pool_t *);
+ void *baton;
+};
+
+static svn_error_t *
+multi_freeze(void *baton,
+ apr_pool_t *pool)
+{
+ struct freeze_baton_t *fb = baton;
+
+ if (fb->counter == fb->paths->nelts)
+ {
+ SVN_ERR(fb->freeze_body(fb->baton, pool));
+ return SVN_NO_ERROR;
+ }
+ else
+ {
+ /* Using a subpool as the only way to unlock the repos lock used
+ by BDB is to clear the pool used to take the lock. */
+ apr_pool_t *subpool = svn_pool_create(pool);
+ const char *path = APR_ARRAY_IDX(fb->paths, fb->counter, const char *);
+ svn_repos_t *repos;
+
+ ++fb->counter;
+
+ SVN_ERR(get_repos(&repos, path,
+ TRUE /* exclusive (only applies to BDB) */,
+ FALSE /* non-blocking */,
+ FALSE /* open-fs */,
+ NULL, subpool));
+
+
+ if (strcmp(repos->fs_type, SVN_FS_TYPE_BDB) == 0)
+ {
+ svn_error_t *err = multi_freeze(fb, subpool);
+
+ svn_pool_destroy(subpool);
+
+ return err;
+ }
+ else
+ {
+ SVN_ERR(svn_fs_open(&repos->fs, repos->db_path, NULL, subpool));
+ SVN_ERR(svn_fs_freeze(svn_repos_fs(repos), multi_freeze, fb,
+ subpool));
+ }
+
+ svn_pool_destroy(subpool);
+ }
+
+ return SVN_NO_ERROR;
+}
+
/* For BDB we fall back on BDB's repos layer lock which means that the
repository is unreadable while frozen.
@@ -1832,36 +1894,19 @@ svn_repos_recover4(const char *path,
and an SQLite reserved lock which means the repository is readable
while frozen. */
svn_error_t *
-svn_repos_freeze(const char *path,
+svn_repos_freeze(apr_array_header_t *paths,
svn_error_t *(*freeze_body)(void *, apr_pool_t *),
void *baton,
apr_pool_t *pool)
{
- svn_repos_t *repos;
+ struct freeze_baton_t fb;
- /* Using a subpool as the only way to unlock the repos lock used by
- BDB is to clear the pool used to take the lock. */
- apr_pool_t *subpool = svn_pool_create(pool);
-
- SVN_ERR(get_repos(&repos, path,
- TRUE /* exclusive */,
- FALSE /* non-blocking */,
- FALSE /* open-fs */,
- NULL, subpool));
+ fb.paths = paths;
+ fb.counter = 0;
+ fb.freeze_body = freeze_body;
+ fb.baton = baton;
- if (strcmp(repos->fs_type, SVN_FS_TYPE_BDB) == 0)
- {
- svn_error_t *err = freeze_body(baton, subpool);
- svn_pool_destroy(subpool);
- return err;
- }
- else
- {
- SVN_ERR(svn_fs_open(&repos->fs, repos->db_path, NULL, subpool));
- SVN_ERR(svn_fs_freeze(svn_repos_fs(repos), freeze_body, baton, subpool));
- }
-
- svn_pool_destroy(subpool);
+ SVN_ERR(multi_freeze(&fb, pool));
return SVN_NO_ERROR;
}
Modified: subversion/branches/ev2-export/subversion/libsvn_repos/repos.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/repos.h?rev=1449262&r1=1449261&r2=1449262&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/repos.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/repos.h Sat Feb 23 01:25:38 2013
@@ -95,10 +95,11 @@ extern "C" {
#define SVN_REPOS__CONF_SVNSERVE_CONF "svnserve.conf"
/* In the svnserve default configuration, these are the suggested
- locations for the passwd and authz files (in the repository conf
- directory), and we put example templates there. */
+ locations for the passwd, authz and groups files (in the repository
+ conf directory), and we put example templates there. */
#define SVN_REPOS__CONF_PASSWD "passwd"
#define SVN_REPOS__CONF_AUTHZ "authz"
+#define SVN_REPOS__CONF_GROUPS "groups"
/* The Repository object, created by svn_repos_open2() and
svn_repos_create(). */
@@ -307,22 +308,24 @@ svn_repos__hooks_post_unlock(svn_repos_t
/*** Authz Functions ***/
/* Read authz configuration data from PATH into *AUTHZ_P, allocated
- in POOL.
-
- PATH may be a file or a registry path and iff ACCEPT_URLS is set
- it may also be a repos relative url or an absolute file url. When
+ in POOL. If GROUPS_PATH is set, use the global groups parsed from it.
+
+ PATH and GROUPS_PATH may be a file or a registry path and iff ACCEPT_URLS
+ is set it may also be a repos relative url or an absolute file url. When
ACCEPT_URLS is FALSE REPOS_ROOT can be NULL.
-
- If PATH is not a valid authz rule file, then return
+
+ If PATH or GROUPS_PATH is not a valid authz rule file, then return
SVN_AUTHZ_INVALID_CONFIG. The contents of *AUTHZ_P is then
- undefined. If MUST_EXIST is TRUE, a missing authz file is also
- an error.
-
+ undefined. If MUST_EXIST is TRUE, a missing authz or global groups file
+ is also an error.
+
If PATH is a repos relative URL then REPOS_ROOT must be set to
- the root of the repository the authz configuration will be used with. */
+ the root of the repository the authz configuration will be used with.
+ The same applies to GROUPS_PATH if it is being used. */
svn_error_t *
svn_repos__authz_read(svn_authz_t **authz_p,
const char *path,
+ const char *groups_path,
svn_boolean_t must_exist,
svn_boolean_t accept_urls,
const char *repos_root,