summaryrefslogtreecommitdiff
path: root/subversion/libsvn_fs_base/tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_fs_base/tree.c')
-rw-r--r--subversion/libsvn_fs_base/tree.c80
1 files changed, 49 insertions, 31 deletions
diff --git a/subversion/libsvn_fs_base/tree.c b/subversion/libsvn_fs_base/tree.c
index 924e7c94a2a06..ba5debbd970b6 100644
--- a/subversion/libsvn_fs_base/tree.c
+++ b/subversion/libsvn_fs_base/tree.c
@@ -68,6 +68,7 @@
#include "private/svn_fspath.h"
#include "private/svn_fs_util.h"
#include "private/svn_mergeinfo_private.h"
+#include "private/svn_sorts_private.h"
/* ### I believe this constant will become internal to reps-strings.c.
@@ -2580,8 +2581,7 @@ verify_locks(const char *txn_name,
apr_hash_this(hi, &key, NULL, NULL);
APR_ARRAY_PUSH(changed_paths, const char *) = key;
}
- qsort(changed_paths->elts, changed_paths->nelts,
- changed_paths->elt_size, svn_sort_compare_paths);
+ svn_sort__array(changed_paths, svn_sort_compare_paths);
/* Now, traverse the array of changed paths, verify locks. Note
that if we need to do a recursive verification a path, we'll skip
@@ -2661,7 +2661,7 @@ txn_body_commit(void *baton, trail_t *trail)
svn_revnum_t youngest_rev;
const svn_fs_id_t *y_rev_root_id;
- dag_node_t *txn_base_root_node;
+ dag_node_t *txn_base_root_node, *txn_root_node;
/* Getting the youngest revision locks the revisions table until
this trail is done. */
@@ -2694,6 +2694,19 @@ txn_body_commit(void *baton, trail_t *trail)
discovered locks. */
SVN_ERR(verify_locks(txn_name, trail, trail->pool));
+ /* Ensure every txn has a mutable root as then the new revision will
+ have a distinct root node-revision-id. This is necessary as
+ future transactions use the root node-revision-id as a proxy for
+ the transaction base revision. */
+ SVN_ERR(svn_fs_base__dag_txn_root(&txn_root_node, fs, txn_name,
+ trail, trail->pool));
+ if (!svn_fs_base__dag_check_mutable(txn_root_node, txn->id))
+ {
+ dag_node_t *clone;
+ SVN_ERR(svn_fs_base__dag_clone_root(&clone, fs, txn->id,
+ trail, trail->pool));
+ }
+
/* Else, commit the txn. */
return svn_fs_base__dag_commit_txn(&(args->new_rev), txn, trail,
trail->pool);
@@ -5061,8 +5074,8 @@ base_node_origin_rev(svn_revnum_t *revision,
/* Examine directory NODE's immediately children for mergeinfo.
- For those which have explicit mergeinfo, add their mergeinfo to
- RESULT_CATALOG (allocated in RESULT_CATALOG's pool).
+ For those which have explicit mergeinfo, invoke RECEIVER with
+ RECEIVER_BATON.
For those which don't, but sit atop trees which contain mergeinfo
somewhere deeper, add them to *CHILDREN_ATOP_MERGEINFO_TREES, a
@@ -5076,10 +5089,11 @@ base_node_origin_rev(svn_revnum_t *revision,
struct get_mergeinfo_data_and_entries_baton
{
- svn_mergeinfo_catalog_t result_catalog;
apr_hash_t *children_atop_mergeinfo_trees;
dag_node_t *node;
const char *node_path;
+ svn_fs_mergeinfo_receiver_t receiver;
+ void *receiver_baton;
};
static svn_error_t *
@@ -5090,7 +5104,6 @@ txn_body_get_mergeinfo_data_and_entries(void *baton, trail_t *trail)
apr_hash_t *entries;
apr_hash_index_t *hi;
apr_pool_t *iterpool = svn_pool_create(trail->pool);
- apr_pool_t *result_pool = apr_hash_pool_get(args->result_catalog);
apr_pool_t *children_pool =
apr_hash_pool_get(args->children_atop_mergeinfo_trees);
@@ -5144,7 +5157,7 @@ txn_body_get_mergeinfo_data_and_entries(void *baton, trail_t *trail)
CHILD_NODE then treat it as if no mergeinfo is present rather
than raising a parse error. */
err = svn_mergeinfo_parse(&child_mergeinfo, pval->data,
- result_pool);
+ iterpool);
if (err)
{
if (err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR)
@@ -5154,10 +5167,12 @@ txn_body_get_mergeinfo_data_and_entries(void *baton, trail_t *trail)
}
else
{
- svn_hash_sets(args->result_catalog,
- svn_fspath__join(args->node_path, dirent->name,
- result_pool),
- child_mergeinfo);
+ SVN_ERR(args->receiver(svn_fspath__join(args->node_path,
+ dirent->name,
+ iterpool),
+ child_mergeinfo,
+ args->receiver_baton,
+ iterpool));
}
}
@@ -5191,7 +5206,8 @@ static svn_error_t *
crawl_directory_for_mergeinfo(svn_fs_t *fs,
dag_node_t *node,
const char *node_path,
- svn_mergeinfo_catalog_t result_catalog,
+ svn_fs_mergeinfo_receiver_t receiver,
+ void *baton,
apr_pool_t *pool)
{
struct get_mergeinfo_data_and_entries_baton gmdae_args;
@@ -5201,10 +5217,11 @@ crawl_directory_for_mergeinfo(svn_fs_t *fs,
/* Add mergeinfo for immediate children that have it, and fetch
immediate children that *don't* have it but sit atop trees that do. */
- gmdae_args.result_catalog = result_catalog;
gmdae_args.children_atop_mergeinfo_trees = children_atop_mergeinfo_trees;
gmdae_args.node = node;
gmdae_args.node_path = node_path;
+ gmdae_args.receiver = receiver;
+ gmdae_args.receiver_baton = baton;
SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_get_mergeinfo_data_and_entries,
&gmdae_args, FALSE, pool));
@@ -5226,7 +5243,7 @@ crawl_directory_for_mergeinfo(svn_fs_t *fs,
SVN_ERR(crawl_directory_for_mergeinfo(fs, val,
svn_fspath__join(node_path, key,
iterpool),
- result_catalog, iterpool));
+ receiver, baton, iterpool));
}
svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
@@ -5384,20 +5401,21 @@ txn_body_get_node_mergeinfo_stats(void *baton, trail_t *trail)
}
-/* Get the mergeinfo for a set of paths, returned in
- *MERGEINFO_CATALOG. Returned values are allocated in POOL, while
- temporary values are allocated in a sub-pool. */
+/* Find all the mergeinfo for a set of PATHS under ROOT and report it
+ through RECEIVER with BATON. INHERITED, INCLUDE_DESCENDANTS and
+ ADJUST_INHERITED_MERGEINFO are the same as in the FS API.
+
+ Allocate temporary values are allocated in SCRATCH_POOL. */
static svn_error_t *
get_mergeinfos_for_paths(svn_fs_root_t *root,
- svn_mergeinfo_catalog_t *mergeinfo_catalog,
const apr_array_header_t *paths,
svn_mergeinfo_inheritance_t inherit,
svn_boolean_t include_descendants,
svn_boolean_t adjust_inherited_mergeinfo,
- apr_pool_t *result_pool,
+ svn_fs_mergeinfo_receiver_t receiver,
+ void *baton,
apr_pool_t *scratch_pool)
{
- svn_mergeinfo_catalog_t result_catalog = apr_hash_make(result_pool);
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
int i;
@@ -5416,14 +5434,13 @@ get_mergeinfos_for_paths(svn_fs_root_t *root,
gmfp_args.root = root;
gmfp_args.path = path;
gmfp_args.inherit = inherit;
- gmfp_args.pool = result_pool;
+ gmfp_args.pool = iterpool;
gmfp_args.adjust_inherited_mergeinfo = adjust_inherited_mergeinfo;
SVN_ERR(svn_fs_base__retry_txn(root->fs,
txn_body_get_mergeinfo_for_path,
&gmfp_args, FALSE, iterpool));
if (path_mergeinfo)
- svn_hash_sets(result_catalog, apr_pstrdup(result_pool, path),
- path_mergeinfo);
+ SVN_ERR(receiver(path, path_mergeinfo, baton, iterpool));
/* If we're including descendants, do so. */
if (include_descendants)
@@ -5449,26 +5466,25 @@ get_mergeinfos_for_paths(svn_fs_root_t *root,
/* If it's worth crawling, crawl. */
if (do_crawl)
SVN_ERR(crawl_directory_for_mergeinfo(root->fs, gnms_args.node,
- path, result_catalog,
+ path, receiver, baton,
iterpool));
}
}
svn_pool_destroy(iterpool);
- *mergeinfo_catalog = result_catalog;
return SVN_NO_ERROR;
}
/* Implements svn_fs_get_mergeinfo. */
static svn_error_t *
-base_get_mergeinfo(svn_mergeinfo_catalog_t *catalog,
- svn_fs_root_t *root,
+base_get_mergeinfo(svn_fs_root_t *root,
const apr_array_header_t *paths,
svn_mergeinfo_inheritance_t inherit,
svn_boolean_t include_descendants,
svn_boolean_t adjust_inherited_mergeinfo,
- apr_pool_t *result_pool,
+ svn_fs_mergeinfo_receiver_t receiver,
+ void *baton,
apr_pool_t *scratch_pool)
{
/* Verify that our filesystem version supports mergeinfo stuff. */
@@ -5480,10 +5496,11 @@ base_get_mergeinfo(svn_mergeinfo_catalog_t *catalog,
return svn_error_create(SVN_ERR_FS_NOT_REVISION_ROOT, NULL, NULL);
/* Retrieve a path -> mergeinfo mapping. */
- return get_mergeinfos_for_paths(root, catalog, paths,
+ return get_mergeinfos_for_paths(root, paths,
inherit, include_descendants,
adjust_inherited_mergeinfo,
- result_pool, scratch_pool);
+ receiver, baton,
+ scratch_pool);
}
@@ -5493,6 +5510,7 @@ base_get_mergeinfo(svn_mergeinfo_catalog_t *catalog,
static root_vtable_t root_vtable = {
base_paths_changed,
+ NULL,
base_check_path,
base_node_history,
base_node_id,