You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2015/11/30 11:24:23 UTC
svn commit: r1717223 [30/50] - in /subversion/branches/ra-git: ./ build/
build/ac-macros/ build/generator/ build/generator/templates/
contrib/hook-scripts/ notes/ notes/api-errata/1.9/ notes/move-tracking/
subversion/ subversion/bindings/ctypes-python/...
Modified: subversion/branches/ra-git/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_repos/dump.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_repos/dump.c Mon Nov 30 10:24:16 2015
@@ -1164,13 +1164,13 @@ dump_node(struct edit_baton *eb,
svn_fs_root_fs(eb->fs_root),
compare_rev, pool));
- SVN_ERR(svn_fs_props_different(&must_dump_props,
- compare_root, compare_path,
- eb->fs_root, path, pool));
+ SVN_ERR(svn_fs_props_changed(&must_dump_props,
+ compare_root, compare_path,
+ eb->fs_root, path, pool));
if (kind == svn_node_file)
- SVN_ERR(svn_fs_contents_different(&must_dump_text,
- compare_root, compare_path,
- eb->fs_root, path, pool));
+ SVN_ERR(svn_fs_contents_changed(&must_dump_text,
+ compare_root, compare_path,
+ eb->fs_root, path, pool));
break;
case svn_node_action_delete:
@@ -1293,16 +1293,16 @@ dump_node(struct edit_baton *eb,
/* Need to decide if the copied node had any extra textual or
property mods as well. */
- SVN_ERR(svn_fs_props_different(&must_dump_props,
- compare_root, compare_path,
- eb->fs_root, path, pool));
+ SVN_ERR(svn_fs_props_changed(&must_dump_props,
+ compare_root, compare_path,
+ eb->fs_root, path, pool));
if (kind == svn_node_file)
{
svn_checksum_t *checksum;
const char *hex_digest;
- SVN_ERR(svn_fs_contents_different(&must_dump_text,
- compare_root, compare_path,
- eb->fs_root, path, pool));
+ SVN_ERR(svn_fs_contents_changed(&must_dump_text,
+ compare_root, compare_path,
+ eb->fs_root, path, pool));
SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_md5,
compare_root, compare_path,
@@ -1919,33 +1919,44 @@ get_dump_editor(const svn_delta_editor_t
/* Helper for svn_repos_dump_fs.
Write a revision record of REV in FS to writable STREAM, using POOL.
+ Dump revision properties as well if INCLUDE_REVPROPS has been set.
*/
static svn_error_t *
write_revision_record(svn_stream_t *stream,
svn_fs_t *fs,
svn_revnum_t rev,
+ svn_boolean_t include_revprops,
apr_pool_t *pool)
{
apr_hash_t *props;
apr_time_t timetemp;
svn_string_t *datevalue;
- SVN_ERR(svn_fs_revision_proplist(&props, fs, rev, pool));
+ if (include_revprops)
+ {
+ SVN_ERR(svn_fs_revision_proplist2(&props, fs, rev, FALSE, pool, pool));
- /* Run revision date properties through the time conversion to
- canonicalize them. */
- /* ### Remove this when it is no longer needed for sure. */
- datevalue = svn_hash_gets(props, SVN_PROP_REVISION_DATE);
- if (datevalue)
- {
- SVN_ERR(svn_time_from_cstring(&timetemp, datevalue->data, pool));
- datevalue = svn_string_create(svn_time_to_cstring(timetemp, pool),
- pool);
- svn_hash_sets(props, SVN_PROP_REVISION_DATE, datevalue);
+ /* Run revision date properties through the time conversion to
+ canonicalize them. */
+ /* ### Remove this when it is no longer needed for sure. */
+ datevalue = svn_hash_gets(props, SVN_PROP_REVISION_DATE);
+ if (datevalue)
+ {
+ SVN_ERR(svn_time_from_cstring(&timetemp, datevalue->data, pool));
+ datevalue = svn_string_create(svn_time_to_cstring(timetemp, pool),
+ pool);
+ svn_hash_sets(props, SVN_PROP_REVISION_DATE, datevalue);
+ }
+ }
+ else
+ {
+ /* Although we won't use it, we still need this container for the
+ call below. */
+ props = apr_hash_make(pool);
}
SVN_ERR(svn_repos__dump_revision_record(stream, rev, NULL, props,
- TRUE /*props_section_always*/,
+ include_revprops,
pool));
return SVN_NO_ERROR;
}
@@ -1954,12 +1965,14 @@ write_revision_record(svn_stream_t *stre
/* The main dumper. */
svn_error_t *
-svn_repos_dump_fs3(svn_repos_t *repos,
+svn_repos_dump_fs4(svn_repos_t *repos,
svn_stream_t *stream,
svn_revnum_t start_rev,
svn_revnum_t end_rev,
svn_boolean_t incremental,
svn_boolean_t use_deltas,
+ svn_boolean_t include_revprops,
+ svn_boolean_t include_changes,
svn_repos_notify_func_t notify_func,
void *notify_baton,
svn_cancel_func_t cancel_func,
@@ -1970,7 +1983,7 @@ svn_repos_dump_fs3(svn_repos_t *repos,
void *dump_edit_baton = NULL;
svn_revnum_t rev;
svn_fs_t *fs = svn_repos_fs(repos);
- apr_pool_t *subpool = svn_pool_create(pool);
+ apr_pool_t *iterpool = svn_pool_create(pool);
svn_revnum_t youngest;
const char *uuid;
int version;
@@ -1978,6 +1991,10 @@ svn_repos_dump_fs3(svn_repos_t *repos,
svn_boolean_t found_old_mergeinfo = FALSE;
svn_repos_notify_t *notify;
+ /* Make sure we catch up on the latest revprop changes. This is the only
+ * time we will refresh the revprop data in this query. */
+ SVN_ERR(svn_fs_refresh_revision_props(fs, pool));
+
/* Determine the current youngest revision of the filesystem. */
SVN_ERR(svn_fs_youngest_rev(&youngest, fs, pool));
@@ -2029,18 +2046,20 @@ svn_repos_dump_fs3(svn_repos_t *repos,
svn_fs_root_t *to_root;
svn_boolean_t use_deltas_for_rev;
- svn_pool_clear(subpool);
+ svn_pool_clear(iterpool);
/* Check for cancellation. */
if (cancel_func)
SVN_ERR(cancel_func(cancel_baton));
/* Write the revision record. */
- SVN_ERR(write_revision_record(stream, fs, rev, subpool));
+ SVN_ERR(write_revision_record(stream, fs, rev, include_revprops,
+ iterpool));
/* When dumping revision 0, we just write out the revision record.
- The parser might want to use its properties. */
- if (rev == 0)
+ The parser might want to use its properties.
+ If we don't want revision changes at all, skip in any case. */
+ if (rev == 0 || !include_changes)
goto loop_end;
/* Fetch the editor which dumps nodes to a file. Regardless of
@@ -2052,10 +2071,10 @@ svn_repos_dump_fs3(svn_repos_t *repos,
&found_old_mergeinfo, NULL,
notify_func, notify_baton,
start_rev, use_deltas_for_rev, FALSE, FALSE,
- subpool));
+ iterpool));
/* Drive the editor in one way or another. */
- SVN_ERR(svn_fs_revision_root(&to_root, fs, rev, subpool));
+ SVN_ERR(svn_fs_revision_root(&to_root, fs, rev, iterpool));
/* If this is the first revision of a non-incremental dump,
we're in for a full tree dump. Otherwise, we want to simply
@@ -2064,7 +2083,7 @@ svn_repos_dump_fs3(svn_repos_t *repos,
{
/* Compare against revision 0, so everything appears to be added. */
svn_fs_root_t *from_root;
- SVN_ERR(svn_fs_revision_root(&from_root, fs, 0, subpool));
+ SVN_ERR(svn_fs_revision_root(&from_root, fs, 0, iterpool));
SVN_ERR(svn_repos_dir_delta2(from_root, "", "",
to_root, "",
dump_editor, dump_edit_baton,
@@ -2074,25 +2093,25 @@ svn_repos_dump_fs3(svn_repos_t *repos,
svn_depth_infinity,
FALSE, /* don't send entry props */
FALSE, /* don't ignore ancestry */
- subpool));
+ iterpool));
}
else
{
/* The normal case: compare consecutive revs. */
SVN_ERR(svn_repos_replay2(to_root, "", SVN_INVALID_REVNUM, FALSE,
dump_editor, dump_edit_baton,
- NULL, NULL, subpool));
+ NULL, NULL, iterpool));
/* While our editor close_edit implementation is a no-op, we still
do this for completeness. */
- SVN_ERR(dump_editor->close_edit(dump_edit_baton, subpool));
+ SVN_ERR(dump_editor->close_edit(dump_edit_baton, iterpool));
}
loop_end:
if (notify_func)
{
notify->revision = rev;
- notify_func(notify_baton, notify, subpool);
+ notify_func(notify_baton, notify, iterpool);
}
}
@@ -2103,12 +2122,12 @@ svn_repos_dump_fs3(svn_repos_t *repos,
warning, since the inline warnings already issued might easily be
missed. */
- notify = svn_repos_notify_create(svn_repos_notify_dump_end, subpool);
- notify_func(notify_baton, notify, subpool);
+ notify = svn_repos_notify_create(svn_repos_notify_dump_end, iterpool);
+ notify_func(notify_baton, notify, iterpool);
if (found_old_reference)
{
- notify_warning(subpool, notify_func, notify_baton,
+ notify_warning(iterpool, notify_func, notify_baton,
svn_repos_notify_warning_found_old_reference,
_("The range of revisions dumped "
"contained references to "
@@ -2120,7 +2139,7 @@ svn_repos_dump_fs3(svn_repos_t *repos,
in dumped mergeinfo. */
if (found_old_mergeinfo)
{
- notify_warning(subpool, notify_func, notify_baton,
+ notify_warning(iterpool, notify_func, notify_baton,
svn_repos_notify_warning_found_old_mergeinfo,
_("The range of revisions dumped "
"contained mergeinfo "
@@ -2129,7 +2148,7 @@ svn_repos_dump_fs3(svn_repos_t *repos,
}
}
- svn_pool_destroy(subpool);
+ svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
@@ -2265,24 +2284,6 @@ verify_close_directory(void *dir_baton,
return close_directory(dir_baton, pool);
}
-static void
-notify_verification_error(svn_revnum_t rev,
- svn_error_t *err,
- svn_repos_notify_func_t notify_func,
- void *notify_baton,
- apr_pool_t *pool)
-{
- svn_repos_notify_t *notify_failure;
-
- if (notify_func == NULL)
- return;
-
- notify_failure = svn_repos_notify_create(svn_repos_notify_failure, pool);
- notify_failure->err = err;
- notify_failure->revision = rev;
- notify_func(notify_baton, notify_failure, pool);
-}
-
/* Verify revision REV in file system FS. */
static svn_error_t *
verify_one_revision(svn_fs_t *fs,
@@ -2328,13 +2329,14 @@ verify_one_revision(svn_fs_t *fs,
do this for completeness. */
SVN_ERR(cancel_editor->close_edit(cancel_edit_baton, scratch_pool));
- SVN_ERR(svn_fs_revision_proplist(&props, fs, rev, scratch_pool));
+ SVN_ERR(svn_fs_revision_proplist2(&props, fs, rev, FALSE, scratch_pool,
+ scratch_pool));
return SVN_NO_ERROR;
}
/* Baton type used for forwarding notifications from FS API to REPOS API. */
-struct verify_fs2_notify_func_baton_t
+struct verify_fs_notify_func_baton_t
{
/* notification function to call (must not be NULL) */
svn_repos_notify_func_t notify_func;
@@ -2348,26 +2350,53 @@ struct verify_fs2_notify_func_baton_t
/* Forward the notification to BATON. */
static void
-verify_fs2_notify_func(svn_revnum_t revision,
+verify_fs_notify_func(svn_revnum_t revision,
void *baton,
apr_pool_t *pool)
{
- struct verify_fs2_notify_func_baton_t *notify_baton = baton;
+ struct verify_fs_notify_func_baton_t *notify_baton = baton;
notify_baton->notify->revision = revision;
notify_baton->notify_func(notify_baton->notify_baton,
notify_baton->notify, pool);
}
+static svn_error_t *
+report_error(svn_revnum_t revision,
+ svn_error_t *verify_err,
+ svn_repos_verify_callback_t verify_callback,
+ void *verify_baton,
+ apr_pool_t *pool)
+{
+ if (verify_callback)
+ {
+ svn_error_t *cb_err;
+
+ /* The caller provided us with a callback, so make him responsible
+ for what's going to happen with the error. */
+ cb_err = verify_callback(verify_baton, revision, verify_err, pool);
+ svn_error_clear(verify_err);
+ SVN_ERR(cb_err);
+
+ return SVN_NO_ERROR;
+ }
+ else
+ {
+ /* No callback -- no second guessing. Just return the error. */
+ return svn_error_trace(verify_err);
+ }
+}
+
svn_error_t *
svn_repos_verify_fs3(svn_repos_t *repos,
svn_revnum_t start_rev,
svn_revnum_t end_rev,
- svn_boolean_t keep_going,
svn_boolean_t check_normalization,
svn_boolean_t metadata_only,
svn_repos_notify_func_t notify_func,
void *notify_baton,
+ svn_repos_verify_callback_t verify_callback,
+ void *verify_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *pool)
@@ -2378,9 +2407,12 @@ svn_repos_verify_fs3(svn_repos_t *repos,
apr_pool_t *iterpool = svn_pool_create(pool);
svn_repos_notify_t *notify;
svn_fs_progress_notify_func_t verify_notify = NULL;
- struct verify_fs2_notify_func_baton_t *verify_notify_baton = NULL;
+ struct verify_fs_notify_func_baton_t *verify_notify_baton = NULL;
svn_error_t *err;
- svn_boolean_t found_corruption = FALSE;
+
+ /* Make sure we catch up on the latest revprop changes. This is the only
+ * time we will refresh the revprop data in this query. */
+ SVN_ERR(svn_fs_refresh_revision_props(fs, pool));
/* Determine the current youngest revision of the filesystem. */
SVN_ERR(svn_fs_youngest_rev(&youngest, fs, pool));
@@ -2409,7 +2441,7 @@ svn_repos_verify_fs3(svn_repos_t *repos,
{
notify = svn_repos_notify_create(svn_repos_notify_verify_rev_end, pool);
- verify_notify = verify_fs2_notify_func;
+ verify_notify = verify_fs_notify_func;
verify_notify_baton = apr_palloc(pool, sizeof(*verify_notify_baton));
verify_notify_baton->notify_func = notify_func;
verify_notify_baton->notify_baton = notify_baton;
@@ -2423,34 +2455,14 @@ svn_repos_verify_fs3(svn_repos_t *repos,
verify_notify, verify_notify_baton,
cancel_func, cancel_baton, pool);
- if (err)
+ if (err && err->apr_err == SVN_ERR_CANCELLED)
{
- if (err->apr_err == SVN_ERR_CANCELLED)
- return svn_error_trace(err);
-
- found_corruption = TRUE;
- notify_verification_error(SVN_INVALID_REVNUM, err, notify_func,
- notify_baton, iterpool);
-
- /* If we already reported the error, reset it. */
- if (notify_func)
- {
- svn_error_clear(err);
- err = NULL;
- }
-
- /* If we abort the verification now, combine yet unreported error
- info with the generic one we return. */
- if (!keep_going)
- /* ### Jump to "We're done" and so send the final notification,
- for consistency? */
- return svn_error_createf(SVN_ERR_REPOS_CORRUPTED, err,
- _("Repository '%s' failed to verify"),
- svn_dirent_local_style(svn_repos_path(repos,
- pool),
- pool));
-
- svn_error_clear(err);
+ return svn_error_trace(err);
+ }
+ else if (err)
+ {
+ SVN_ERR(report_error(SVN_INVALID_REVNUM, err, verify_callback,
+ verify_baton, iterpool));
}
if (!metadata_only)
@@ -2464,24 +2476,18 @@ svn_repos_verify_fs3(svn_repos_t *repos,
cancel_func, cancel_baton,
iterpool);
- if (err)
+ if (err && err->apr_err == SVN_ERR_CANCELLED)
{
- if (err->apr_err == SVN_ERR_CANCELLED)
- return svn_error_trace(err);
-
- found_corruption = TRUE;
- notify_verification_error(rev, err, notify_func, notify_baton,
- iterpool);
- svn_error_clear(err);
-
- if (keep_going)
- continue;
- else
- break;
+ return svn_error_trace(err);
}
-
- if (notify_func)
+ else if (err)
{
+ SVN_ERR(report_error(rev, err, verify_callback, verify_baton,
+ iterpool));
+ }
+ else if (notify_func)
+ {
+ /* Tell the caller that we're done with this revision. */
notify->revision = rev;
notify_func(notify_baton, notify, iterpool);
}
@@ -2496,12 +2502,5 @@ svn_repos_verify_fs3(svn_repos_t *repos,
svn_pool_destroy(iterpool);
- if (found_corruption)
- return svn_error_createf(SVN_ERR_REPOS_CORRUPTED, NULL,
- _("Repository '%s' failed to verify"),
- svn_dirent_local_style(svn_repos_path(repos,
- pool),
- pool));
-
return SVN_NO_ERROR;
}
Modified: subversion/branches/ra-git/subversion/libsvn_repos/fs-wrap.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_repos/fs-wrap.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_repos/fs-wrap.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_repos/fs-wrap.c Mon Nov 30 10:24:16 2015
@@ -58,6 +58,8 @@ svn_repos_fs_commit_txn(const char **con
apr_hash_t *hooks_env;
*new_rev = SVN_INVALID_REVNUM;
+ if (conflict_p)
+ *conflict_p = NULL;
/* Parse the hooks-env file (if any). */
SVN_ERR(svn_repos__parse_hooks_env(&hooks_env, repos->hooks_env_path,
@@ -378,7 +380,8 @@ svn_repos_fs_change_rev_prop4(svn_repos_
* to the hooks to be accurate. */
svn_string_t *old_value2;
- SVN_ERR(svn_fs_revision_prop(&old_value2, repos->fs, rev, name, pool));
+ SVN_ERR(svn_fs_revision_prop2(&old_value2, repos->fs, rev, name,
+ TRUE, pool, pool));
old_value = old_value2;
}
@@ -448,12 +451,13 @@ svn_repos_fs_revision_prop(svn_string_t
*value_p = NULL;
else
- SVN_ERR(svn_fs_revision_prop(value_p, repos->fs,
- rev, propname, pool));
+ SVN_ERR(svn_fs_revision_prop2(value_p, repos->fs,
+ rev, propname, TRUE, pool, pool));
}
else /* wholly readable revision */
{
- SVN_ERR(svn_fs_revision_prop(value_p, repos->fs, rev, propname, pool));
+ SVN_ERR(svn_fs_revision_prop2(value_p, repos->fs, rev, propname, TRUE,
+ pool, pool));
}
return SVN_NO_ERROR;
@@ -486,7 +490,8 @@ svn_repos_fs_revision_proplist(apr_hash_
svn_string_t *value;
/* Produce two property hashtables, both in POOL. */
- SVN_ERR(svn_fs_revision_proplist(&tmphash, repos->fs, rev, pool));
+ SVN_ERR(svn_fs_revision_proplist2(&tmphash, repos->fs, rev, TRUE,
+ pool, pool));
*table_p = apr_hash_make(pool);
/* If they exist, we only copy svn:author and svn:date into the
@@ -501,7 +506,8 @@ svn_repos_fs_revision_proplist(apr_hash_
}
else /* wholly readable revision */
{
- SVN_ERR(svn_fs_revision_proplist(table_p, repos->fs, rev, pool));
+ SVN_ERR(svn_fs_revision_proplist2(table_p, repos->fs, rev, TRUE,
+ pool, pool));
}
return SVN_NO_ERROR;
@@ -975,15 +981,18 @@ pack_notify_func(void *baton,
{
struct pack_notify_baton *pnb = baton;
svn_repos_notify_t *notify;
+ svn_repos_notify_action_t repos_action;
/* Simple conversion works for these values. */
SVN_ERR_ASSERT(pack_action >= svn_fs_pack_notify_start
- && pack_action <= svn_fs_pack_notify_end_revprop);
+ && pack_action <= svn_fs_pack_notify_noop);
- notify = svn_repos_notify_create(pack_action
- + svn_repos_notify_pack_shard_start
- - svn_fs_pack_notify_start,
- pool);
+ repos_action = pack_action == svn_fs_pack_notify_noop
+ ? svn_repos_notify_pack_noop
+ : pack_action + svn_repos_notify_pack_shard_start
+ - svn_fs_pack_notify_start;
+
+ notify = svn_repos_notify_create(repos_action, pool);
notify->shard = shard;
pnb->notify_func(pnb->notify_baton, notify, pool);
Modified: subversion/branches/ra-git/subversion/libsvn_repos/load-fs-vtable.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_repos/load-fs-vtable.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_repos/load-fs-vtable.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_repos/load-fs-vtable.c Mon Nov 30 10:24:16 2015
@@ -624,14 +624,6 @@ maybe_add_with_history(struct node_baton
}
static svn_error_t *
-magic_header_record(int version,
- void *parse_baton,
- apr_pool_t *pool)
-{
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
uuid_record(const char *uuid,
void *parse_baton,
apr_pool_t *pool)
@@ -1022,7 +1014,8 @@ close_revision(void *baton)
apr_array_header_t *diff;
int i;
- SVN_ERR(svn_fs_revision_proplist(&orig_props, pb->fs, 0, rb->pool));
+ SVN_ERR(svn_fs_revision_proplist2(&orig_props, pb->fs, 0, TRUE,
+ rb->pool, rb->pool));
new_props = svn_prop_array_to_hash(rb->revprops, rb->pool);
SVN_ERR(svn_prop_diffs(&diff, new_props, orig_props, rb->pool));
@@ -1194,7 +1187,7 @@ svn_repos_get_fs_build_parser5(const svn
if (SVN_IS_VALID_REVNUM(start_rev))
SVN_ERR_ASSERT(start_rev <= end_rev);
- parser->magic_header_record = magic_header_record;
+ parser->magic_header_record = NULL;
parser->uuid_record = uuid_record;
parser->new_revision_record = new_revision_record;
parser->new_node_record = new_node_record;
@@ -1271,3 +1264,216 @@ svn_repos_load_fs5(svn_repos_t *repos,
return svn_repos_parse_dumpstream3(dumpstream, parser, parse_baton, FALSE,
cancel_func, cancel_baton, pool);
}
+
+/*----------------------------------------------------------------------*/
+
+/** The same functionality for revprops only **/
+
+/* Implement svn_repos_parse_fns3_t.new_revision_record.
+ *
+ * Because the revision is supposed to already exist, we don't need to
+ * start transactions etc. */
+static svn_error_t *
+revprops_new_revision_record(void **revision_baton,
+ apr_hash_t *headers,
+ void *parse_baton,
+ apr_pool_t *pool)
+{
+ struct parse_baton *pb = parse_baton;
+ struct revision_baton *rb;
+
+ rb = make_revision_baton(headers, pb, pool);
+
+ /* If we're skipping this revision, try to notify someone. */
+ if (rb->skipped && pb->notify_func)
+ {
+ /* ### TODO: Use proper scratch pool instead of pb->notify_pool */
+ svn_repos_notify_t *notify = svn_repos_notify_create(
+ svn_repos_notify_load_skipped_rev,
+ pb->notify_pool);
+
+ notify->old_revision = rb->rev;
+ pb->notify_func(pb->notify_baton, notify, pb->notify_pool);
+ svn_pool_clear(pb->notify_pool);
+ }
+
+ /* If we're parsing revision 0, only the revision props are (possibly)
+ interesting to us: when loading the stream into an empty
+ filesystem, then we want new filesystem's revision 0 to have the
+ same props. Otherwise, we just ignore revision 0 in the stream. */
+
+ *revision_baton = rb;
+ return SVN_NO_ERROR;
+}
+
+/* Implement svn_repos_parse_fns3_t.close_revision.
+ *
+ * Simply set the revprops we previously parsed and send notifications.
+ * This is the place where we will detect missing revisions. */
+static svn_error_t *
+revprops_close_revision(void *baton)
+{
+ struct revision_baton *rb = baton;
+ struct parse_baton *pb = rb->pb;
+ apr_hash_t *orig_props;
+ apr_hash_t *new_props;
+ apr_array_header_t *diff;
+ int i;
+
+ /* If we're skipping this revision we're done here. */
+ if (rb->skipped)
+ return SVN_NO_ERROR;
+
+ /* If the dumpstream doesn't have an 'svn:date' property and we
+ aren't ignoring the dates in the dumpstream altogether, remove
+ any 'svn:date' revision property that was set by FS layer when
+ the TXN was created. */
+ if (! (pb->ignore_dates || rb->datestamp))
+ {
+ svn_prop_t *prop = &APR_ARRAY_PUSH(rb->revprops, svn_prop_t);
+ prop->name = SVN_PROP_REVISION_DATE;
+ prop->value = NULL;
+ }
+
+ SVN_ERR(svn_fs_revision_proplist2(&orig_props, pb->fs, rb->rev, TRUE,
+ rb->pool, rb->pool));
+ new_props = svn_prop_array_to_hash(rb->revprops, rb->pool);
+ SVN_ERR(svn_prop_diffs(&diff, new_props, orig_props, rb->pool));
+
+ for (i = 0; i < diff->nelts; i++)
+ {
+ const svn_prop_t *prop = &APR_ARRAY_IDX(diff, i, svn_prop_t);
+
+ SVN_ERR(change_rev_prop(pb->repos, rb->rev, prop->name, prop->value,
+ pb->validate_props, rb->pool));
+ }
+
+ if (pb->notify_func)
+ {
+ /* ### TODO: Use proper scratch pool instead of pb->notify_pool */
+ svn_repos_notify_t *notify = svn_repos_notify_create(
+ svn_repos_notify_load_revprop_set,
+ pb->notify_pool);
+
+ notify->new_revision = rb->rev;
+ notify->old_revision = SVN_INVALID_REVNUM;
+ pb->notify_func(pb->notify_baton, notify, pb->notify_pool);
+ svn_pool_clear(pb->notify_pool);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/* Set *CALLBACKS and *PARSE_BATON to a vtable parser which commits new
+ * revisions to the fs in REPOS. Allocate the objects in RESULT_POOL.
+ *
+ * START_REV and END_REV act as filters, the lower and upper (inclusive)
+ * range values of revisions in DUMPSTREAM which will be loaded. Either
+ * both of these values are #SVN_INVALID_REVNUM (in which case no
+ * revision-based filtering occurs at all), or both are valid revisions
+ * (where START_REV is older than or equivalent to END_REV).
+ *
+ * START_REV and END_REV act as filters, the lower and upper (inclusive)
+ * range values of revisions which will
+ * be loaded. Either both of these values are #SVN_INVALID_REVNUM (in
+ * which case no revision-based filtering occurs at all), or both are
+ * valid revisions (where START_REV is older than or equivalent to
+ * END_REV). They refer to dump stream revision numbers rather than
+ * committed revision numbers.
+ *
+ * If VALIDATE_PROPS is set, then validate Subversion revision properties
+ * (those in the svn: namespace) against established rules for those things.
+ *
+ * If IGNORE_DATES is set, ignore any revision datestamps found in
+ * DUMPSTREAM, keeping whatever timestamps the revisions currently have.
+ */
+static svn_error_t *
+build_revprop_parser(const svn_repos_parse_fns3_t **callbacks,
+ void **parse_baton,
+ svn_repos_t *repos,
+ svn_revnum_t start_rev,
+ svn_revnum_t end_rev,
+ svn_boolean_t validate_props,
+ svn_boolean_t ignore_dates,
+ svn_repos_notify_func_t notify_func,
+ void *notify_baton,
+ apr_pool_t *result_pool)
+{
+ svn_repos_parse_fns3_t *parser = apr_pcalloc(result_pool, sizeof(*parser));
+ struct parse_baton *pb = apr_pcalloc(result_pool, sizeof(*pb));
+
+ SVN_ERR_ASSERT((SVN_IS_VALID_REVNUM(start_rev) &&
+ SVN_IS_VALID_REVNUM(end_rev))
+ || ((! SVN_IS_VALID_REVNUM(start_rev)) &&
+ (! SVN_IS_VALID_REVNUM(end_rev))));
+ if (SVN_IS_VALID_REVNUM(start_rev))
+ SVN_ERR_ASSERT(start_rev <= end_rev);
+
+ parser->magic_header_record = NULL;
+ parser->uuid_record = uuid_record;
+ parser->new_revision_record = revprops_new_revision_record;
+ parser->new_node_record = NULL;
+ parser->set_revision_property = set_revision_property;
+ parser->set_node_property = NULL;
+ parser->remove_node_props = NULL;
+ parser->set_fulltext = NULL;
+ parser->close_node = NULL;
+ parser->close_revision = revprops_close_revision;
+ parser->delete_node_property = NULL;
+ parser->apply_textdelta = NULL;
+
+ pb->repos = repos;
+ pb->fs = svn_repos_fs(repos);
+ pb->use_history = FALSE;
+ pb->validate_props = validate_props;
+ pb->notify_func = notify_func;
+ pb->notify_baton = notify_baton;
+ pb->uuid_action = svn_repos_load_uuid_ignore; /* Never touch the UUID. */
+ pb->parent_dir = NULL;
+ pb->pool = result_pool;
+ pb->notify_pool = svn_pool_create(result_pool);
+ pb->rev_map = NULL;
+ pb->oldest_dumpstream_rev = SVN_INVALID_REVNUM;
+ pb->last_rev_mapped = SVN_INVALID_REVNUM;
+ pb->start_rev = start_rev;
+ pb->end_rev = end_rev;
+ pb->use_pre_commit_hook = FALSE;
+ pb->use_post_commit_hook = FALSE;
+ pb->ignore_dates = ignore_dates;
+
+ *callbacks = parser;
+ *parse_baton = pb;
+ return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
+svn_repos_load_fs_revprops(svn_repos_t *repos,
+ svn_stream_t *dumpstream,
+ svn_revnum_t start_rev,
+ svn_revnum_t end_rev,
+ svn_boolean_t validate_props,
+ svn_boolean_t ignore_dates,
+ svn_repos_notify_func_t notify_func,
+ void *notify_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *scratch_pool)
+{
+ const svn_repos_parse_fns3_t *parser;
+ void *parse_baton;
+
+ /* This is really simple. */
+
+ SVN_ERR(build_revprop_parser(&parser, &parse_baton,
+ repos,
+ start_rev, end_rev,
+ validate_props,
+ ignore_dates,
+ notify_func,
+ notify_baton,
+ scratch_pool));
+
+ return svn_repos_parse_dumpstream3(dumpstream, parser, parse_baton, FALSE,
+ cancel_func, cancel_baton, scratch_pool);
+}
Modified: subversion/branches/ra-git/subversion/libsvn_repos/load.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_repos/load.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_repos/load.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_repos/load.c Mon Nov 30 10:24:16 2015
@@ -385,7 +385,135 @@ parse_format_version(int *version,
return SVN_NO_ERROR;
}
+/*----------------------------------------------------------------------*/
+
+/** Dummy callback implementations for functions not provided by the user **/
+
+static svn_error_t *
+dummy_handler_magic_header_record(int version,
+ void *parse_baton,
+ apr_pool_t *pool)
+{
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+dummy_handler_uuid_record(const char *uuid,
+ void *parse_baton,
+ apr_pool_t *pool)
+{
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+dummy_handler_new_revision_record(void **revision_baton,
+ apr_hash_t *headers,
+ void *parse_baton,
+ apr_pool_t *pool)
+{
+ *revision_baton = NULL;
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+dummy_handler_new_node_record(void **node_baton,
+ apr_hash_t *headers,
+ void *revision_baton,
+ apr_pool_t *pool)
+{
+ *node_baton = NULL;
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+dummy_handler_set_revision_property(void *revision_baton,
+ const char *name,
+ const svn_string_t *value)
+{
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+dummy_handler_set_node_property(void *node_baton,
+ const char *name,
+ const svn_string_t *value)
+{
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+dummy_handler_delete_node_property(void *node_baton,
+ const char *name)
+{
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+dummy_handler_remove_node_props(void *node_baton)
+{
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+dummy_handler_set_fulltext(svn_stream_t **stream,
+ void *node_baton)
+{
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+dummy_handler_apply_textdelta(svn_txdelta_window_handler_t *handler,
+ void **handler_baton,
+ void *node_baton)
+{
+ /* Only called by parse_text_block() and that tests for NULL handlers. */
+ *handler = NULL;
+ *handler_baton = NULL;
+ return SVN_NO_ERROR;
+}
+static svn_error_t *
+dummy_handler_close_node(void *node_baton)
+{
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+dummy_handler_close_revision(void *revision_baton)
+{
+ return SVN_NO_ERROR;
+}
+
+/* Helper macro to copy the function pointer SOURCE->NAME to DEST->NAME.
+ * If the source pointer is NULL, pick the corresponding dummy handler
+ * instead. */
+#define SET_VTABLE_ENTRY(dest, source, name) \
+ dest->name = provided->name ? provided->name : dummy_handler_##name
+
+/* Return a copy of PROVIDED with all NULL callbacks replaced by a dummy
+ * handler. Allocate the result in RESULT_POOL. */
+static const svn_repos_parse_fns3_t *
+complete_vtable(const svn_repos_parse_fns3_t *provided,
+ apr_pool_t *result_pool)
+{
+ svn_repos_parse_fns3_t *completed = apr_pcalloc(result_pool,
+ sizeof(*completed));
+
+ SET_VTABLE_ENTRY(completed, provided, magic_header_record);
+ SET_VTABLE_ENTRY(completed, provided, uuid_record);
+ SET_VTABLE_ENTRY(completed, provided, new_revision_record);
+ SET_VTABLE_ENTRY(completed, provided, new_node_record);
+ SET_VTABLE_ENTRY(completed, provided, set_revision_property);
+ SET_VTABLE_ENTRY(completed, provided, set_node_property);
+ SET_VTABLE_ENTRY(completed, provided, delete_node_property);
+ SET_VTABLE_ENTRY(completed, provided, remove_node_props);
+ SET_VTABLE_ENTRY(completed, provided, set_fulltext);
+ SET_VTABLE_ENTRY(completed, provided, apply_textdelta);
+ SET_VTABLE_ENTRY(completed, provided, close_node);
+ SET_VTABLE_ENTRY(completed, provided, close_revision);
+
+ return completed;
+}
/*----------------------------------------------------------------------*/
@@ -410,6 +538,10 @@ svn_repos_parse_dumpstream3(svn_stream_t
apr_pool_t *nodepool = svn_pool_create(pool);
int version;
+ /* Make sure we can blindly invoke callbacks. */
+ parse_fns = complete_vtable(parse_fns, pool);
+
+ /* Start parsing process. */
SVN_ERR(svn_stream_readline(stream, &linebuf, "\n", &eof, linepool));
if (eof)
return stream_ran_dry();
Modified: subversion/branches/ra-git/subversion/libsvn_repos/log.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_repos/log.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_repos/log.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_repos/log.c Mon Nov 30 10:24:16 2015
@@ -43,6 +43,7 @@
#include "private/svn_mergeinfo_private.h"
#include "private/svn_subr_private.h"
#include "private/svn_sorts_private.h"
+#include "private/svn_string_private.h"
@@ -1122,7 +1123,8 @@ fill_log_entry(svn_log_entry_t *log_entr
if (get_revprops && want_revprops)
{
/* User is allowed to see at least some revprops. */
- SVN_ERR(svn_fs_revision_proplist(&r_props, fs, rev, pool));
+ SVN_ERR(svn_fs_revision_proplist2(&r_props, fs, rev, FALSE, pool,
+ pool));
if (revprops == NULL)
{
/* Requested all revprops... */
@@ -1150,9 +1152,9 @@ fill_log_entry(svn_log_entry_t *log_entr
we want static initialization here and must therefore emulate
strlen(x) by sizeof(x)-1. */
static const svn_string_t svn_prop_revision_author
- = {SVN_PROP_REVISION_AUTHOR, sizeof(SVN_PROP_REVISION_AUTHOR)-1};
+ = SVN__STATIC_STRING(SVN_PROP_REVISION_AUTHOR);
static const svn_string_t svn_prop_revision_date
- = {SVN_PROP_REVISION_DATE, sizeof(SVN_PROP_REVISION_DATE)-1};
+ = SVN__STATIC_STRING(SVN_PROP_REVISION_DATE);
/* often only the standard revprops got requested and delivered.
In that case, we can simply pass the hash on. */
@@ -1907,8 +1909,7 @@ store_search(svn_mergeinfo_t processed,
const char *path = APR_ARRAY_IDX(paths, i, const char *);
svn_rangelist_t *ranges = apr_array_make(processed_pool, 1,
sizeof(svn_merge_range_t*));
- svn_merge_range_t *range = apr_palloc(processed_pool,
- sizeof(svn_merge_range_t));
+ svn_merge_range_t *range = apr_palloc(processed_pool, sizeof(*range));
range->start = start;
range->end = end;
@@ -2176,7 +2177,7 @@ do_logs(svn_fs_t *fs,
if (rev_mergeinfo)
{
struct added_deleted_mergeinfo *add_and_del_mergeinfo =
- apr_hash_get(rev_mergeinfo, ¤t, sizeof(svn_revnum_t));
+ apr_hash_get(rev_mergeinfo, ¤t, sizeof(current));
added_mergeinfo = add_and_del_mergeinfo->added_mergeinfo;
deleted_mergeinfo = add_and_del_mergeinfo->deleted_mergeinfo;
has_children = (apr_hash_count(added_mergeinfo) > 0
@@ -2341,6 +2342,10 @@ svn_repos_get_logs4(svn_repos_t *repos,
revprops = new_revprops;
}
+ /* Make sure we catch up on the latest revprop changes. This is the only
+ * time we will refresh the revprop data in this query. */
+ SVN_ERR(svn_fs_refresh_revision_props(fs, pool));
+
/* Setup log range. */
SVN_ERR(svn_fs_youngest_rev(&head, fs, pool));
Modified: subversion/branches/ra-git/subversion/libsvn_repos/replay.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_repos/replay.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_repos/replay.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_repos/replay.c Mon Nov 30 10:24:16 2015
@@ -555,10 +555,6 @@ path_driver_cb_func(void **dir_baton,
return svn_error_create(SVN_ERR_FS_ALREADY_EXISTS, NULL,
_("Root directory already exists."));
- /* A NULL parent_baton will cause a segfault. It should never be
- NULL for non-root paths. */
- SVN_ERR_ASSERT(parent_baton);
-
/* Was this node copied? */
SVN_ERR(fill_copyfrom(©from_root, ©from_path, ©from_rev,
&src_readable, root, change,
@@ -971,6 +967,11 @@ svn_repos_replay2(svn_fs_root_t *root,
const char *repos_root = "";
void *unlock_baton;
+ /* If we were not given a low water mark, assume that everything is there,
+ all the way back to revision 0. */
+ if (! SVN_IS_VALID_REVNUM(low_water_mark))
+ low_water_mark = 0;
+
/* Special-case r0, which we know is an empty revision; if we don't
special-case it we might end up trying to compare it to "r-1". */
if (svn_fs_is_revision_root(root)
@@ -1493,7 +1494,7 @@ svn_repos__replay_ev2(svn_fs_root_t *roo
svn_error_t *err = SVN_NO_ERROR;
int i;
- SVN_ERR_ASSERT(!svn_dirent_is_absolute(base_repos_relpath));
+ SVN_ERR_ASSERT(svn_relpath_is_canonical(base_repos_relpath));
/* Special-case r0, which we know is an empty revision; if we don't
special-case it we might end up trying to compare it to "r-1". */
Modified: subversion/branches/ra-git/subversion/libsvn_repos/reporter.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_repos/reporter.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_repos/reporter.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_repos/reporter.c Mon Nov 30 10:24:16 2015
@@ -481,10 +481,12 @@ get_revision_info(report_baton_t *b,
{
/* Info is not available, yet.
Get all revprops. */
- SVN_ERR(svn_fs_revision_proplist(&r_props,
- b->repos->fs,
- rev,
- scratch_pool));
+ SVN_ERR(svn_fs_revision_proplist2(&r_props,
+ b->repos->fs,
+ rev,
+ FALSE,
+ scratch_pool,
+ scratch_pool));
/* Extract the committed-date. */
cdate = svn_hash_gets(r_props, SVN_PROP_REVISION_DATE);
@@ -1282,7 +1284,7 @@ delta_dirs(report_baton_t *b, svn_revnum
/* Loop over the dirents in the target. */
SVN_ERR(svn_fs_dir_optimal_order(&t_ordered_entries, b->t_root,
- t_entries, subpool));
+ t_entries, subpool, iterpool));
for (i = 0; i < t_ordered_entries->nelts; ++i)
{
const svn_fs_dirent_t *t_entry
@@ -1548,6 +1550,7 @@ svn_repos_finish_report(void *baton, apr
{
report_baton_t *b = baton;
+ SVN_ERR(svn_fs_refresh_revision_props(svn_repos_fs(b->repos), pool));
return svn_error_trace(finish_report(b, pool));
}
Modified: subversion/branches/ra-git/subversion/libsvn_repos/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_repos/repos.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_repos/repos.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_repos/repos.c Mon Nov 30 10:24:16 2015
@@ -393,15 +393,15 @@ create_hooks(svn_repos_t *repos, apr_poo
"# e.g.: \"" SVN_RA_CAPABILITY_MERGEINFO ":some-other-capability\" " \
"(the order is undefined)." NL
"#" NL
+"# The list is self-reported by the client. Therefore, you should not" NL
+"# make security assumptions based on the capabilities list, nor should" NL
+"# you assume that clients reliably report every capability they have." NL
+"#" NL
"# Note: The TXN-NAME parameter is new in Subversion 1.8. Prior to version" NL
"# 1.8, the start-commit hook was invoked before the commit txn was even" NL
"# created, so the ability to inspect the commit txn and its metadata from" NL
"# within the start-commit hook was not possible." NL
"# " NL
-"# The list is self-reported by the client. Therefore, you should not" NL
-"# make security assumptions based on the capabilities list, nor should" NL
-"# you assume that clients reliably report every capability they have." NL
-"#" NL
"# If the hook program exits with success, the commit continues; but" NL
"# if it exits with failure (non-zero), the commit is stopped before" NL
"# a Subversion txn is created, and STDERR is returned to the client." NL;
@@ -1175,8 +1175,8 @@ svn_repos_create(svn_repos_t **repos_p,
SVN_ERR(lock_repos(repos, FALSE, FALSE, scratch_pool));
/* Create an environment for the filesystem. */
- if ((err = svn_fs_create(&repos->fs, repos->db_path, fs_config,
- result_pool)))
+ if ((err = svn_fs_create2(&repos->fs, repos->db_path, fs_config,
+ result_pool, scratch_pool)))
{
/* If there was an error making the filesytem, e.g. unknown/supported
* filesystem type. Clean up after ourselves. Yes this is safe because
@@ -1635,9 +1635,10 @@ svn_repos_fs(svn_repos_t *repos)
}
const char *
-svn_repos_fs_type(svn_repos_t *repos, apr_pool_t *pool)
+svn_repos_fs_type(svn_repos_t *repos,
+ apr_pool_t *result_pool)
{
- return apr_pstrdup(pool, repos->fs_type);
+ return apr_pstrdup(result_pool, repos->fs_type);
}
/* For historical reasons, for the Berkeley DB backend, this code uses
@@ -1957,7 +1958,7 @@ svn_repos_hotcopy3(const char *src_path,
void *notify_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
- apr_pool_t *pool)
+ apr_pool_t *scratch_pool)
{
svn_fs_hotcopy_notify_t fs_notify_func;
struct fs_hotcopy_notify_baton_t fs_notify_baton;
@@ -1968,8 +1969,8 @@ svn_repos_hotcopy3(const char *src_path,
svn_repos_t *dst_repos;
svn_error_t *err;
- SVN_ERR(svn_dirent_get_absolute(&src_abspath, src_path, pool));
- SVN_ERR(svn_dirent_get_absolute(&dst_abspath, dst_path, pool));
+ SVN_ERR(svn_dirent_get_absolute(&src_abspath, src_path, scratch_pool));
+ SVN_ERR(svn_dirent_get_absolute(&dst_abspath, dst_path, scratch_pool));
if (strcmp(src_abspath, dst_abspath) == 0)
return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL,
_("Hotcopy source and destination are equal"));
@@ -1979,7 +1980,7 @@ svn_repos_hotcopy3(const char *src_path,
FALSE, FALSE,
FALSE, /* don't try to open the db yet. */
NULL,
- pool, pool));
+ scratch_pool, scratch_pool));
/* If we are going to clean logs, then get an exclusive lock on
db-logs.lock, to ensure that no one else will work with logs.
@@ -1987,7 +1988,7 @@ svn_repos_hotcopy3(const char *src_path,
If we are just copying, then get a shared lock to ensure that
no one else will clean logs while we copying them */
- SVN_ERR(lock_db_logs_file(src_repos, clean_logs, pool));
+ SVN_ERR(lock_db_logs_file(src_repos, clean_logs, scratch_pool));
/* Copy the repository to a new path, with exception of
specially handled directories */
@@ -2001,16 +2002,16 @@ svn_repos_hotcopy3(const char *src_path,
0,
hotcopy_structure,
&hotcopy_context,
- pool));
+ scratch_pool));
/* Prepare dst_repos object so that we may create locks,
so that we may open repository */
- dst_repos = create_svn_repos_t(dst_abspath, pool);
+ dst_repos = create_svn_repos_t(dst_abspath, scratch_pool);
dst_repos->fs_type = src_repos->fs_type;
dst_repos->format = src_repos->format;
- err = create_locks(dst_repos, pool);
+ err = create_locks(dst_repos, scratch_pool);
if (err)
{
if (incremental && err->apr_err == SVN_ERR_DIR_NOT_EMPTY)
@@ -2019,7 +2020,8 @@ svn_repos_hotcopy3(const char *src_path,
return svn_error_trace(err);
}
- err = svn_io_dir_make_sgid(dst_repos->db_path, APR_OS_DEFAULT, pool);
+ err = svn_io_dir_make_sgid(dst_repos->db_path, APR_OS_DEFAULT,
+ scratch_pool);
if (err)
{
if (incremental && APR_STATUS_IS_EEXIST(err->apr_err))
@@ -2030,7 +2032,7 @@ svn_repos_hotcopy3(const char *src_path,
/* Exclusively lock the new repository.
No one should be accessing it at the moment */
- SVN_ERR(lock_repos(dst_repos, TRUE, FALSE, pool));
+ SVN_ERR(lock_repos(dst_repos, TRUE, FALSE, scratch_pool));
fs_notify_func = notify_func ? fs_hotcopy_notify : NULL;
fs_notify_baton.notify_func = notify_func;
@@ -2039,12 +2041,12 @@ svn_repos_hotcopy3(const char *src_path,
SVN_ERR(svn_fs_hotcopy3(src_repos->db_path, dst_repos->db_path,
clean_logs, incremental,
fs_notify_func, &fs_notify_baton,
- cancel_func, cancel_baton, pool));
+ cancel_func, cancel_baton, scratch_pool));
/* Destination repository is ready. Stamp it with a format number. */
return svn_io_write_version_file
- (svn_dirent_join(dst_repos->path, SVN_REPOS__FORMAT, pool),
- dst_repos->format, pool);
+ (svn_dirent_join(dst_repos->path, SVN_REPOS__FORMAT, scratch_pool),
+ dst_repos->format, scratch_pool);
}
/* Return the library version number. */
@@ -2065,7 +2067,6 @@ svn_repos_stat(svn_dirent_t **dirent,
svn_node_kind_t kind;
svn_dirent_t *ent;
const char *datestring;
- apr_hash_t *prophash;
SVN_ERR(svn_fs_check_path(&kind, root, path, pool));
@@ -2081,9 +2082,7 @@ svn_repos_stat(svn_dirent_t **dirent,
if (kind == svn_node_file)
SVN_ERR(svn_fs_file_length(&(ent->size), root, path, pool));
- SVN_ERR(svn_fs_node_proplist(&prophash, root, path, pool));
- if (apr_hash_count(prophash) > 0)
- ent->has_props = TRUE;
+ SVN_ERR(svn_fs_node_has_props(&ent->has_props, root, path, pool));
SVN_ERR(svn_repos_get_committed_info(&(ent->created_rev),
&datestring,
Modified: subversion/branches/ra-git/subversion/libsvn_repos/rev_hunt.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_repos/rev_hunt.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_repos/rev_hunt.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_repos/rev_hunt.c Mon Nov 30 10:24:16 2015
@@ -44,7 +44,7 @@
/* Note: this binary search assumes that the datestamp properties on
each revision are in chronological order. That is if revision A >
- revision B, then A's datestamp is younger then B's datestamp.
+ revision B, then A's datestamp is younger than B's datestamp.
If someone comes along and sets a bogus datestamp, this routine
might not work right.
@@ -65,8 +65,8 @@ get_time(apr_time_t *tm,
{
svn_string_t *date_str;
- SVN_ERR(svn_fs_revision_prop(&date_str, fs, rev, SVN_PROP_REVISION_DATE,
- pool));
+ SVN_ERR(svn_fs_revision_prop2(&date_str, fs, rev, SVN_PROP_REVISION_DATE,
+ FALSE, pool, pool));
if (! date_str)
return svn_error_createf
(SVN_ERR_FS_GENERAL, NULL,
@@ -88,6 +88,7 @@ svn_repos_dated_revision(svn_revnum_t *r
/* Initialize top and bottom values of binary search. */
SVN_ERR(svn_fs_youngest_rev(&rev_latest, fs, pool));
+ SVN_ERR(svn_fs_refresh_revision_props(fs, pool));
rev_bot = 0;
rev_top = rev_latest;
@@ -170,7 +171,8 @@ svn_repos_get_committed_info(svn_revnum_
SVN_ERR(svn_fs_node_created_rev(committed_rev, root, path, pool));
/* Get the revision properties of this revision. */
- SVN_ERR(svn_fs_revision_proplist(&revprops, fs, *committed_rev, pool));
+ SVN_ERR(svn_fs_revision_proplist2(&revprops, fs, *committed_rev, TRUE,
+ pool, pool));
/* Extract date and author from these revprops. */
committed_date_s = svn_hash_gets(revprops, SVN_PROP_REVISION_DATE);
@@ -310,9 +312,8 @@ svn_repos_deleted_rev(svn_fs_t *fs,
svn_revnum_t *deleted,
apr_pool_t *pool)
{
- apr_pool_t *subpool;
- svn_fs_root_t *start_root, *root, *copy_root;
- const char *copy_path;
+ apr_pool_t *iterpool;
+ svn_fs_root_t *start_root, *root;
svn_revnum_t mid_rev;
svn_node_kind_t kind;
svn_fs_node_relation_t node_relation;
@@ -379,6 +380,8 @@ svn_repos_deleted_rev(svn_fs_t *fs,
root, path, pool));
if (node_relation != svn_fs_node_unrelated)
{
+ svn_fs_root_t *copy_root;
+ const char *copy_path;
SVN_ERR(svn_fs_closest_copy(©_root, ©_path, root,
path, pool));
if (!copy_root ||
@@ -432,15 +435,15 @@ svn_repos_deleted_rev(svn_fs_t *fs,
*/
mid_rev = (start + end) / 2;
- subpool = svn_pool_create(pool);
+ iterpool = svn_pool_create(pool);
while (1)
{
- svn_pool_clear(subpool);
+ svn_pool_clear(iterpool);
/* Get revision root and node id for mid_rev at that revision. */
- SVN_ERR(svn_fs_revision_root(&root, fs, mid_rev, subpool));
- SVN_ERR(svn_fs_check_path(&kind, root, path, pool));
+ SVN_ERR(svn_fs_revision_root(&root, fs, mid_rev, iterpool));
+ SVN_ERR(svn_fs_check_path(&kind, root, path, iterpool));
if (kind == svn_node_none)
{
/* Case D: Look lower in the range. */
@@ -449,13 +452,15 @@ svn_repos_deleted_rev(svn_fs_t *fs,
}
else
{
+ svn_fs_root_t *copy_root;
+ const char *copy_path;
/* Determine the relationship between the start node
and the current node. */
SVN_ERR(svn_fs_node_relation(&node_relation, start_root, path,
- root, path, pool));
+ root, path, iterpool));
if (node_relation != svn_fs_node_unrelated)
- SVN_ERR(svn_fs_closest_copy(©_root, ©_path, root,
- path, subpool));
+ SVN_ERR(svn_fs_closest_copy(©_root, ©_path, root,
+ path, iterpool));
if (node_relation == svn_fs_node_unrelated ||
(copy_root &&
(svn_fs_revision_root_revision(copy_root) > start)))
@@ -479,7 +484,7 @@ svn_repos_deleted_rev(svn_fs_t *fs,
}
}
- svn_pool_destroy(subpool);
+ svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
@@ -666,8 +671,7 @@ svn_repos_trace_node_locations(svn_fs_t
/* First - let's sort the array of the revisions from the greatest revision
* downward, so it will be easier to search on. */
location_revisions = apr_array_copy(pool, location_revisions_orig);
- qsort(location_revisions->elts, location_revisions->nelts,
- sizeof(*revision_ptr), svn_sort_compare_revisions);
+ svn_sort__array(location_revisions, svn_sort_compare_revisions);
revision_ptr = (svn_revnum_t *)location_revisions->elts;
revision_ptr_end = revision_ptr + location_revisions->nelts;
@@ -708,23 +712,6 @@ svn_repos_trace_node_locations(svn_fs_t
if (! prev_path)
break;
- if (authz_read_func)
- {
- svn_boolean_t readable;
- svn_fs_root_t *tmp_root;
-
- SVN_ERR(svn_fs_revision_root(&tmp_root, fs, revision, currpool));
- SVN_ERR(authz_read_func(&readable, tmp_root, path,
- authz_read_baton, currpool));
- if (! readable)
- {
- svn_pool_destroy(lastpool);
- svn_pool_destroy(currpool);
-
- return SVN_NO_ERROR;
- }
- }
-
/* Assign the current path to all younger revisions until we reach
the copy target rev. */
while ((revision_ptr < revision_ptr_end)
@@ -747,6 +734,20 @@ svn_repos_trace_node_locations(svn_fs_t
path = prev_path;
revision = prev_rev;
+ if (authz_read_func)
+ {
+ svn_boolean_t readable;
+ SVN_ERR(svn_fs_revision_root(&root, fs, revision, currpool));
+ SVN_ERR(authz_read_func(&readable, root, path,
+ authz_read_baton, currpool));
+ if (!readable)
+ {
+ svn_pool_destroy(lastpool);
+ svn_pool_destroy(currpool);
+ return SVN_NO_ERROR;
+ }
+ }
+
/* Clear last pool and switch. */
svn_pool_clear(lastpool);
tmppool = lastpool;
@@ -835,27 +836,32 @@ svn_repos_node_location_segments(svn_rep
{
svn_fs_t *fs = svn_repos_fs(repos);
svn_stringbuf_t *current_path;
- svn_revnum_t youngest_rev = SVN_INVALID_REVNUM, current_rev;
+ svn_revnum_t youngest_rev, current_rev;
apr_pool_t *subpool;
+ SVN_ERR(svn_fs_youngest_rev(&youngest_rev, fs, pool));
+
/* No PEG_REVISION? We'll use HEAD. */
if (! SVN_IS_VALID_REVNUM(peg_revision))
- {
- SVN_ERR(svn_fs_youngest_rev(&youngest_rev, fs, pool));
- peg_revision = youngest_rev;
- }
+ peg_revision = youngest_rev;
+
+ if (peg_revision > youngest_rev)
+ return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
+ _("No such revision %ld"), peg_revision);
- /* No START_REV? We'll use HEAD (which we may have already fetched). */
+ /* No START_REV? We'll use peg rev. */
if (! SVN_IS_VALID_REVNUM(start_rev))
- {
- if (SVN_IS_VALID_REVNUM(youngest_rev))
- start_rev = youngest_rev;
- else
- SVN_ERR(svn_fs_youngest_rev(&start_rev, fs, pool));
- }
+ start_rev = peg_revision;
+ else if (start_rev > peg_revision)
+ return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
+ _("No such revision %ld"), start_rev);
/* No END_REV? We'll use 0. */
- end_rev = SVN_IS_VALID_REVNUM(end_rev) ? end_rev : 0;
+ if (! SVN_IS_VALID_REVNUM(end_rev))
+ end_rev = 0;
+ else if (end_rev > start_rev)
+ return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
+ _("No such revision %ld"), end_rev);
/* Are the revision properly ordered? They better be -- the API
demands it. */
@@ -1329,6 +1335,7 @@ struct send_baton
apr_hash_t *last_props;
const char *last_path;
svn_fs_root_t *last_root;
+ svn_boolean_t include_merged_revisions;
};
/* Send PATH_REV to HANDLER and HANDLER_BATON, using information provided by
@@ -1349,32 +1356,75 @@ send_path_revision(struct path_revision
void *delta_baton = NULL;
apr_pool_t *tmp_pool; /* For swapping */
svn_boolean_t contents_changed;
+ svn_boolean_t props_changed;
svn_pool_clear(sb->iterpool);
/* Get the revision properties. */
- SVN_ERR(svn_fs_revision_proplist(&rev_props, repos->fs,
- path_rev->revnum, sb->iterpool));
+ SVN_ERR(svn_fs_revision_proplist2(&rev_props, repos->fs,
+ path_rev->revnum, FALSE,
+ sb->iterpool, sb->iterpool));
/* Open the revision root. */
SVN_ERR(svn_fs_revision_root(&root, repos->fs, path_rev->revnum,
sb->iterpool));
- /* Get the file's properties for this revision and compute the diffs. */
- SVN_ERR(svn_fs_node_proplist(&props, root, path_rev->path,
- sb->iterpool));
- SVN_ERR(svn_prop_diffs(&prop_diffs, props, sb->last_props,
- sb->iterpool));
-
- /* Check if the contents *may* have changed. (Allow false positives,
- for now, as the blame implementation currently depends on them.) */
- /* Special case: In the first revision, we always provide a delta. */
+ /* Check if the props *may* have changed. */
if (sb->last_root)
- SVN_ERR(svn_fs_contents_different(&contents_changed, sb->last_root,
- sb->last_path, root, path_rev->path,
- sb->iterpool));
+ {
+ /* We don't use svn_fs_props_different() because it's more
+ * expensive. */
+ SVN_ERR(svn_fs_props_changed(&props_changed,
+ sb->last_root, sb->last_path,
+ root, path_rev->path, sb->iterpool));
+ }
else
- contents_changed = TRUE;
+ {
+ props_changed = TRUE;
+ }
+
+ /* Calculate actual difference between last and current properties. */
+ if (props_changed)
+ {
+ /* Get the file's properties for this revision and compute the diffs. */
+ SVN_ERR(svn_fs_node_proplist(&props, root, path_rev->path,
+ sb->iterpool));
+ SVN_ERR(svn_prop_diffs(&prop_diffs, props, sb->last_props,
+ sb->iterpool));
+ }
+ else
+ {
+ /* Properties didn't change: copy LAST_PROPS to current POOL. */
+ props = svn_prop_hash_dup(sb->last_props, sb->iterpool);
+ prop_diffs = apr_array_make(sb->iterpool, 0, sizeof(svn_prop_t));
+ }
+
+ /* Check if the contents *may* have changed. */
+ if (! sb->last_root)
+ {
+ /* Special case: In the first revision, we always provide a delta. */
+ contents_changed = TRUE;
+ }
+ else if (sb->include_merged_revisions
+ && strcmp(sb->last_path, path_rev->path))
+ {
+ /* ### This is a HACK!!!
+ * Blame -g, in older clients anyways, relies on getting a notification
+ * whenever the path changes - even if there was no content change.
+ *
+ * TODO: A future release should take an extra parameter and depending
+ * on that either always send a text delta or only send it if there
+ * is a difference. */
+ contents_changed = TRUE;
+ }
+ else
+ {
+ /* Did the file contents actually change?
+ * It could e.g. be a property-only change. */
+ SVN_ERR(svn_fs_contents_different(&contents_changed, sb->last_root,
+ sb->last_path, root, path_rev->path,
+ sb->iterpool));
+ }
/* We have all we need, give to the handler. */
SVN_ERR(handler(handler_baton, path_rev->path, path_rev->revnum,
@@ -1443,6 +1493,7 @@ get_file_revs_backwards(svn_repos_t *rep
last_pool = svn_pool_create(scratch_pool);
sb.iterpool = svn_pool_create(scratch_pool);
sb.last_pool = svn_pool_create(scratch_pool);
+ sb.include_merged_revisions = FALSE;
/* We want the first txdelta to be against the empty file. */
sb.last_root = NULL;
@@ -1571,6 +1622,10 @@ svn_repos_get_file_revs2(svn_repos_t *re
end = youngest_rev;
}
+ /* Make sure we catch up on the latest revprop changes. This is the only
+ * time we will refresh the revprop data in this query. */
+ SVN_ERR(svn_fs_refresh_revision_props(repos->fs, scratch_pool));
+
if (end < start)
{
if (include_merged_revisions)
@@ -1598,6 +1653,9 @@ svn_repos_get_file_revs2(svn_repos_t *re
/* Create an empty hash table for the first property diff. */
sb.last_props = apr_hash_make(sb.last_pool);
+ /* Inform send_path_revision() whether workarounds / special behavior
+ * may be needed. */
+ sb.include_merged_revisions = include_merged_revisions;
/* Get the revisions we are interested in. */
duplicate_path_revs = apr_hash_make(scratch_pool);
Propchange: subversion/branches/ra-git/subversion/libsvn_subr/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Mon Nov 30 10:24:16 2015
@@ -12,3 +12,4 @@ internal_statements.h
errorcode.inc
libsvn_subr.pc.in
libsvn_subr.pc
+config_keys.inc
Modified: subversion/branches/ra-git/subversion/libsvn_subr/atomic.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/atomic.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/atomic.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/atomic.c Mon Nov 30 10:24:16 2015
@@ -20,8 +20,13 @@
* ====================================================================
*/
+#include <assert.h>
#include <apr_time.h>
+
+#include "svn_pools.h"
+
#include "private/svn_atomic.h"
+#include "private/svn_mutex.h"
/* Magic values for atomic initialization */
#define SVN_ATOMIC_UNINITIALIZED 0
@@ -29,11 +34,21 @@
#define SVN_ATOMIC_INIT_FAILED 2
#define SVN_ATOMIC_INITIALIZED 3
-svn_error_t*
-svn_atomic__init_once(volatile svn_atomic_t *global_status,
- svn_error_t *(*init_func)(void*,apr_pool_t*),
- void *baton,
- apr_pool_t* pool)
+
+/* Baton used by init_funct_t and init_once(). */
+typedef struct init_baton_t init_baton_t;
+
+/* Initialization function wrapper. Hides API details from init_once().
+ The implementation must return FALSE on failure. */
+typedef svn_boolean_t (*init_func_t)(init_baton_t *init_baton);
+
+/*
+ * This is the actual atomic initialization driver.
+ * Returns FALSE on failure.
+ */
+static svn_boolean_t
+init_once(volatile svn_atomic_t *global_status,
+ init_func_t init_func, init_baton_t *init_baton)
{
/* !! Don't use localizable strings in this function, because these
!! might cause deadlocks. This function can be used to initialize
@@ -42,44 +57,162 @@ svn_atomic__init_once(volatile svn_atomi
/* We have to call init_func exactly once. Because APR
doesn't have statically-initialized mutexes, we implement a poor
man's spinlock using svn_atomic_cas. */
+
svn_atomic_t status = svn_atomic_cas(global_status,
SVN_ATOMIC_START_INIT,
SVN_ATOMIC_UNINITIALIZED);
- if (status == SVN_ATOMIC_UNINITIALIZED)
+ for (;;)
{
- svn_error_t *err = init_func(baton, pool);
- if (err)
+ switch (status)
{
-#if APR_HAS_THREADS
- /* Tell other threads that the initialization failed. */
- svn_atomic_cas(global_status,
- SVN_ATOMIC_INIT_FAILED,
- SVN_ATOMIC_START_INIT);
-#endif
- return svn_error_create(SVN_ERR_ATOMIC_INIT_FAILURE, err,
- "Couldn't perform atomic initialization");
+ case SVN_ATOMIC_UNINITIALIZED:
+ {
+ const svn_boolean_t result = init_func(init_baton);
+ const svn_atomic_t init_state = (result
+ ? SVN_ATOMIC_INITIALIZED
+ : SVN_ATOMIC_INIT_FAILED);
+
+ svn_atomic_cas(global_status, init_state,
+ SVN_ATOMIC_START_INIT);
+ return result;
+ }
+
+ case SVN_ATOMIC_START_INIT:
+ /* Wait for the init function to complete. */
+ apr_sleep(APR_USEC_PER_SEC / 1000);
+ status = svn_atomic_cas(global_status,
+ SVN_ATOMIC_UNINITIALIZED,
+ SVN_ATOMIC_UNINITIALIZED);
+ continue;
+
+ case SVN_ATOMIC_INIT_FAILED:
+ return FALSE;
+
+ case SVN_ATOMIC_INITIALIZED:
+ return TRUE;
+
+ default:
+ /* Something went seriously wrong with the atomic operations. */
+ abort();
}
- svn_atomic_cas(global_status,
- SVN_ATOMIC_INITIALIZED,
- SVN_ATOMIC_START_INIT);
- }
-#if APR_HAS_THREADS
- /* Wait for whichever thread is performing initialization to finish. */
- /* XXX FIXME: Should we have a maximum wait here, like we have in
- the Windows file IO spinner? */
- else while (status != SVN_ATOMIC_INITIALIZED)
- {
- if (status == SVN_ATOMIC_INIT_FAILED)
- return svn_error_create(SVN_ERR_ATOMIC_INIT_FAILURE, NULL,
- "Couldn't perform atomic initialization");
-
- apr_sleep(APR_USEC_PER_SEC / 1000);
- status = svn_atomic_cas(global_status,
- SVN_ATOMIC_UNINITIALIZED,
- SVN_ATOMIC_UNINITIALIZED);
}
-#endif /* APR_HAS_THREADS */
+}
+
+
+/* This baton structure is used by the two flavours of init-once APIs
+ to hide their differences from the init_once() driver. Each private
+ API uses only selected parts of the baton.
+
+ No part of this structure changes unless a wrapped init function is
+ actually invoked by init_once().
+*/
+struct init_baton_t
+{
+ /* Used only by svn_atomic__init_once()/err_init_func_wrapper() */
+ svn_atomic__err_init_func_t err_init_func;
+ svn_error_t *err;
+ apr_pool_t *pool;
+
+ /* Used only by svn_atomic__init_no_error()/str_init_func_wrapper() */
+ svn_atomic__str_init_func_t str_init_func;
+ const char *errstr;
+
+ /* Used by both pairs of functions */
+ void *baton;
+};
+
+/* Wrapper for the svn_atomic__init_once init function. */
+static svn_boolean_t err_init_func_wrapper(init_baton_t *init_baton)
+{
+ init_baton->err = init_baton->err_init_func(init_baton->baton,
+ init_baton->pool);
+ return (init_baton->err == SVN_NO_ERROR);
+}
+
+svn_error_t *
+svn_atomic__init_once(volatile svn_atomic_t *global_status,
+ svn_atomic__err_init_func_t err_init_func,
+ void *baton,
+ apr_pool_t* pool)
+{
+ init_baton_t init_baton;
+ init_baton.err_init_func = err_init_func;
+ init_baton.err = NULL;
+ init_baton.pool = pool;
+ init_baton.baton = baton;
+
+ if (init_once(global_status, err_init_func_wrapper, &init_baton))
+ return SVN_NO_ERROR;
+
+ return svn_error_create(SVN_ERR_ATOMIC_INIT_FAILURE, init_baton.err,
+ "Couldn't perform atomic initialization");
+}
+
+/* Wrapper for the svn_atomic__init_no_error init function. */
+static svn_boolean_t str_init_func_wrapper(init_baton_t *init_baton)
+{
+ init_baton->errstr = init_baton->str_init_func(init_baton->baton);
+ return (init_baton->errstr == NULL);
+}
+
+const char *
+svn_atomic__init_once_no_error(volatile svn_atomic_t *global_status,
+ svn_atomic__str_init_func_t str_init_func,
+ void *baton)
+{
+ init_baton_t init_baton;
+ init_baton.str_init_func = str_init_func;
+ init_baton.errstr = NULL;
+ init_baton.baton = baton;
+
+ if (init_once(global_status, str_init_func_wrapper, &init_baton))
+ return NULL;
+
+ /* Our init function wrapper may not have been called; make sure
+ that we return generic error message in that case. */
+ if (!init_baton.errstr)
+ return "Couldn't perform atomic initialization";
+ else
+ return init_baton.errstr;
+}
+
+/* The process-global counter that we use to produce process-wide unique
+ * values. Since APR has no 64 bit atomics, all access to this will be
+ * serialized through COUNTER_MUTEX. */
+static apr_uint64_t uniqiue_counter = 0;
+
+/* The corresponding mutex and initialization state. */
+static volatile svn_atomic_t counter_status = SVN_ATOMIC_UNINITIALIZED;
+static svn_mutex__t *counter_mutex = NULL;
+
+/* svn_atomic__err_init_func_t implementation that initializes COUNTER_MUTEX.
+ * Note that neither argument will be used and should be NULL. */
+static svn_error_t *
+init_unique_counter(void *null_baton,
+ apr_pool_t *null_pool)
+{
+ /* COUNTER_MUTEX is global, so it needs to live in a global pool.
+ * APR also makes those thread-safe by default. */
+ SVN_ERR(svn_mutex__init(&counter_mutex, TRUE, svn_pool_create(NULL)));
+ return SVN_NO_ERROR;
+}
+
+/* Read and increment UNIQIUE_COUNTER. Return the new value in *VALUE.
+ * Call this function only while having acquired the COUNTER_MUTEX. */
+static svn_error_t *
+read_unique_counter(apr_uint64_t *value)
+{
+ *value = ++uniqiue_counter;
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_atomic__unique_counter(apr_uint64_t *value)
+{
+ SVN_ERR(svn_atomic__init_once(&counter_status, init_unique_counter, NULL,
+ NULL));
+ SVN_MUTEX__WITH_LOCK(counter_mutex, read_unique_counter(value));
return SVN_NO_ERROR;
}
Modified: subversion/branches/ra-git/subversion/libsvn_subr/auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/auth.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/auth.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/auth.c Mon Nov 30 10:24:16 2015
@@ -109,10 +109,10 @@ struct svn_auth_baton_t
/* run-time parameters needed by providers. */
apr_hash_t *parameters;
+ apr_hash_t *slave_parameters;
/* run-time credentials cache. */
apr_hash_t *creds_cache;
-
};
/* Abstracted iteration baton */
@@ -125,6 +125,7 @@ struct svn_auth_iterstate_t
const char *realmstring; /* The original realmstring passed in */
const char *cache_key; /* key to use in auth_baton's creds_cache */
svn_auth_baton_t *auth_baton; /* the original auth_baton. */
+ apr_hash_t *parameters;
};
@@ -142,6 +143,7 @@ svn_auth_open(svn_auth_baton_t **auth_ba
ab = apr_pcalloc(pool, sizeof(*ab));
ab->tables = apr_hash_make(pool);
ab->parameters = apr_hash_make(pool);
+ /* ab->slave_parameters = NULL; */
ab->creds_cache = apr_hash_make(pool);
ab->pool = pool;
@@ -170,7 +172,8 @@ svn_auth_open(svn_auth_baton_t **auth_ba
*auth_baton = ab;
}
-
+/* Magic pointer value to allow storing 'NULL' in an apr_hash_t */
+static const void *auth_NULL = NULL;
void
svn_auth_set_parameter(svn_auth_baton_t *auth_baton,
@@ -178,17 +181,35 @@ svn_auth_set_parameter(svn_auth_baton_t
const void *value)
{
if (auth_baton)
- svn_hash_sets(auth_baton->parameters, name, value);
+ {
+ if (auth_baton->slave_parameters)
+ {
+ if (!value)
+ value = &auth_NULL;
+
+ svn_hash_sets(auth_baton->slave_parameters, name, value);
+ }
+ else
+ svn_hash_sets(auth_baton->parameters, name, value);
+ }
}
const void *
svn_auth_get_parameter(svn_auth_baton_t *auth_baton,
const char *name)
{
- if (auth_baton)
- return svn_hash_gets(auth_baton->parameters, name);
- else
+ const void *value;
+ if (!auth_baton)
return NULL;
+ else if (!auth_baton->slave_parameters)
+ return svn_hash_gets(auth_baton->parameters, name);
+
+ value = svn_hash_gets(auth_baton->slave_parameters, name);
+
+ if (value)
+ return (value == &auth_NULL ? NULL : value);
+
+ return svn_hash_gets(auth_baton->parameters, name);
}
@@ -218,6 +239,7 @@ svn_auth_first_credentials(void **creden
svn_boolean_t got_first = FALSE;
svn_auth_iterstate_t *iterstate;
const char *cache_key;
+ apr_hash_t *parameters;
if (! auth_baton)
return svn_error_create(SVN_ERR_AUTHN_NO_PROVIDER, NULL,
@@ -230,6 +252,26 @@ svn_auth_first_credentials(void **creden
_("No provider registered for '%s' credentials"),
cred_kind);
+ if (auth_baton->slave_parameters)
+ {
+ apr_hash_index_t *hi;
+ parameters = apr_hash_copy(pool, auth_baton->parameters);
+
+ for (hi = apr_hash_first(pool, auth_baton->slave_parameters);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const void *value = apr_hash_this_val(hi);
+
+ if (value == &auth_NULL)
+ value = NULL;
+
+ svn_hash_sets(parameters, apr_hash_this_key(hi), value);
+ }
+ }
+ else
+ parameters = auth_baton->parameters;
+
/* First, see if we have cached creds in the auth_baton. */
cache_key = make_cache_key(cred_kind, realmstring, pool);
creds = svn_hash_gets(auth_baton->creds_cache, cache_key);
@@ -247,7 +289,7 @@ svn_auth_first_credentials(void **creden
svn_auth_provider_object_t *);
SVN_ERR(provider->vtable->first_credentials(&creds, &iter_baton,
provider->provider_baton,
- auth_baton->parameters,
+ parameters,
realmstring,
auth_baton->pool));
@@ -274,6 +316,7 @@ svn_auth_first_credentials(void **creden
iterstate->realmstring = apr_pstrdup(pool, realmstring);
iterstate->cache_key = cache_key;
iterstate->auth_baton = auth_baton;
+ iterstate->parameters = parameters;
*state = iterstate;
/* Put the creds in the cache */
@@ -310,7 +353,7 @@ svn_auth_next_credentials(void **credent
{
SVN_ERR(provider->vtable->first_credentials(
&creds, &(state->provider_iter_baton),
- provider->provider_baton, auth_baton->parameters,
+ provider->provider_baton, state->parameters,
state->realmstring, auth_baton->pool));
state->got_first = TRUE;
}
@@ -319,7 +362,7 @@ svn_auth_next_credentials(void **credent
SVN_ERR(provider->vtable->next_credentials(&creds,
state->provider_iter_baton,
provider->provider_baton,
- auth_baton->parameters,
+ state->parameters,
state->realmstring,
auth_baton->pool));
}
@@ -327,7 +370,9 @@ svn_auth_next_credentials(void **credent
if (creds != NULL)
{
/* Put the creds in the cache */
- svn_hash_sets(auth_baton->creds_cache, state->cache_key, creds);
+ svn_hash_sets(auth_baton->creds_cache,
+ apr_pstrdup(auth_baton->pool, state->cache_key),
+ creds);
break;
}
@@ -348,19 +393,17 @@ svn_auth_save_credentials(svn_auth_iters
svn_auth_provider_object_t *provider;
svn_boolean_t save_succeeded = FALSE;
const char *no_auth_cache;
- svn_auth_baton_t *auth_baton;
void *creds;
if (! state || state->table->providers->nelts <= state->provider_idx)
return SVN_NO_ERROR;
- auth_baton = state->auth_baton;
creds = svn_hash_gets(state->auth_baton->creds_cache, state->cache_key);
if (! creds)
return SVN_NO_ERROR;
/* Do not save the creds if SVN_AUTH_PARAM_NO_AUTH_CACHE is set */
- no_auth_cache = svn_hash_gets(auth_baton->parameters,
+ no_auth_cache = svn_hash_gets(state->parameters,
SVN_AUTH_PARAM_NO_AUTH_CACHE);
if (no_auth_cache)
return SVN_NO_ERROR;
@@ -373,7 +416,7 @@ svn_auth_save_credentials(svn_auth_iters
SVN_ERR(provider->vtable->save_credentials(&save_succeeded,
creds,
provider->provider_baton,
- auth_baton->parameters,
+ state->parameters,
state->realmstring,
pool));
if (save_succeeded)
@@ -389,7 +432,7 @@ svn_auth_save_credentials(svn_auth_iters
if (provider->vtable->save_credentials)
SVN_ERR(provider->vtable->save_credentials(&save_succeeded, creds,
provider->provider_baton,
- auth_baton->parameters,
+ state->parameters,
state->realmstring,
pool));
@@ -687,10 +730,12 @@ svn_auth_get_platform_specific_client_pr
}
svn_error_t *
-svn_auth__apply_config_for_server(svn_auth_baton_t *auth_baton,
- apr_hash_t *config,
- const char *server_name,
- apr_pool_t *scratch_pool)
+svn_auth__make_session_auth(svn_auth_baton_t **session_auth_baton,
+ const svn_auth_baton_t *auth_baton,
+ apr_hash_t *config,
+ const char *server_name,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
svn_boolean_t store_passwords = SVN_CONFIG_DEFAULT_OPTION_STORE_PASSWORDS;
svn_boolean_t store_auth_creds = SVN_CONFIG_DEFAULT_OPTION_STORE_AUTH_CREDS;
@@ -702,6 +747,12 @@ svn_auth__apply_config_for_server(svn_au
svn_config_t *servers = NULL;
const char *server_group = NULL;
+ struct svn_auth_baton_t *ab;
+
+ ab = apr_pmemdup(result_pool, auth_baton, sizeof(*ab));
+
+ ab->slave_parameters = apr_hash_make(result_pool);
+
/* The 'store-passwords' and 'store-auth-creds' parameters used to
* live in SVN_CONFIG_CATEGORY_CONFIG. For backward compatibility,
* if values for these parameters have already been set by our
@@ -716,12 +767,10 @@ svn_auth__apply_config_for_server(svn_au
* "store-auth-creds = yes" -- they'll get the expected behaviour.
*/
- if (svn_auth_get_parameter(auth_baton,
- SVN_AUTH_PARAM_DONT_STORE_PASSWORDS) != NULL)
+ if (svn_auth_get_parameter(ab, SVN_AUTH_PARAM_DONT_STORE_PASSWORDS) != NULL)
store_passwords = FALSE;
- if (svn_auth_get_parameter(auth_baton,
- SVN_AUTH_PARAM_NO_AUTH_CACHE) != NULL)
+ if (svn_auth_get_parameter(ab, SVN_AUTH_PARAM_NO_AUTH_CACHE) != NULL)
store_auth_creds = FALSE;
/* All the svn_auth_set_parameter() calls below this not only affect the
@@ -806,46 +855,60 @@ svn_auth__apply_config_for_server(svn_au
/* Save auth caching parameters in the auth parameter hash. */
if (! store_passwords)
- svn_auth_set_parameter(auth_baton,
- SVN_AUTH_PARAM_DONT_STORE_PASSWORDS, "");
+ svn_auth_set_parameter(ab, SVN_AUTH_PARAM_DONT_STORE_PASSWORDS, "");
- svn_auth_set_parameter(auth_baton,
+ svn_auth_set_parameter(ab,
SVN_AUTH_PARAM_STORE_PLAINTEXT_PASSWORDS,
store_plaintext_passwords);
if (! store_pp)
- svn_auth_set_parameter(auth_baton,
+ svn_auth_set_parameter(ab,
SVN_AUTH_PARAM_DONT_STORE_SSL_CLIENT_CERT_PP,
"");
- svn_auth_set_parameter(auth_baton,
+ svn_auth_set_parameter(ab,
SVN_AUTH_PARAM_STORE_SSL_CLIENT_CERT_PP_PLAINTEXT,
store_pp_plaintext);
if (! store_auth_creds)
- svn_auth_set_parameter(auth_baton,
- SVN_AUTH_PARAM_NO_AUTH_CACHE, "");
+ svn_auth_set_parameter(ab, SVN_AUTH_PARAM_NO_AUTH_CACHE, "");
- /* ### This setting may have huge side-effects when the auth baton is shared
- ### between different ra sessions, as it will change which server settings
- ### will be used for all future auth requests.
- ###
- ### E.g. when you connect using a ssl client cert that is specified in the
- ### config file, you might have it when you first connect... but if you
- ### then connect to another repository, you might not see the same
- ### settings when the SSL connection is built up again later on.
- ###
- ### Most current usages should probably have been keyed on the realm
- ### string instead of this magic flag that changes when multiple repositories
- ### are used.
- ###
- ### This especially affects long living ra sessions, such as those on the
- ### reuse-ra-session branch.
- */
if (server_group)
- svn_auth_set_parameter(auth_baton,
+ svn_auth_set_parameter(ab,
SVN_AUTH_PARAM_SERVER_GROUP,
- apr_pstrdup(auth_baton->pool, server_group));
+ apr_pstrdup(ab->pool, server_group));
+
+ *session_auth_baton = ab;
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+dummy_first_creds(void **credentials,
+ void **iter_baton,
+ void *provider_baton,
+ apr_hash_t *parameters,
+ const char *realmstring,
+ apr_pool_t *pool)
+{
+ *credentials = NULL;
+ *iter_baton = NULL;
return SVN_NO_ERROR;
}
+
+void
+svn_auth__get_dummmy_simple_provider(svn_auth_provider_object_t **provider,
+ apr_pool_t *pool)
+{
+ static const svn_auth_provider_t vtable = {
+ SVN_AUTH_CRED_SIMPLE,
+ dummy_first_creds,
+ NULL, NULL
+ };
+
+ svn_auth_provider_object_t *po = apr_pcalloc(pool, sizeof(*po));
+
+ po->vtable = &vtable;
+ *provider = po;
+}
Modified: subversion/branches/ra-git/subversion/libsvn_subr/auth.h
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/auth.h?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/auth.h (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/auth.h Mon Nov 30 10:24:16 2015
@@ -157,6 +157,15 @@ svn_auth__get_gpg_agent_simple_provider
apr_pool_t *pool);
#endif /* !defined(WIN32) || defined(DOXYGEN) */
+/**
+ * Set @a *provider to a dummy provider of type @c
+ * svn_auth_cred_simple_t that never returns or stores any
+ * credentials.
+ */
+void
+svn_auth__get_dummmy_simple_provider(svn_auth_provider_object_t **provider,
+ apr_pool_t *pool);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */