summaryrefslogtreecommitdiff
path: root/subversion/libsvn_fs_base
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_fs_base')
-rw-r--r--subversion/libsvn_fs_base/bdb/rev-table.c3
-rw-r--r--subversion/libsvn_fs_base/fs.c44
-rw-r--r--subversion/libsvn_fs_base/fs_init.h33
-rw-r--r--subversion/libsvn_fs_base/lock.c2
-rw-r--r--subversion/libsvn_fs_base/revs-txns.c24
-rw-r--r--subversion/libsvn_fs_base/revs-txns.h8
-rw-r--r--subversion/libsvn_fs_base/tree.c80
7 files changed, 137 insertions, 57 deletions
diff --git a/subversion/libsvn_fs_base/bdb/rev-table.c b/subversion/libsvn_fs_base/bdb/rev-table.c
index b752249bfa78e..c39d2c9627619 100644
--- a/subversion/libsvn_fs_base/bdb/rev-table.c
+++ b/subversion/libsvn_fs_base/bdb/rev-table.c
@@ -79,6 +79,9 @@ svn_fs_bdb__get_rev(revision_t **revision_p,
numbers begin with one. */
db_recno_t recno = (db_recno_t) rev + 1;
+ if (!SVN_IS_VALID_REVNUM(rev))
+ return svn_fs_base__err_dangling_rev(fs, rev);
+
svn_fs_base__trail_debug(trail, "revisions", "get");
db_err = bfd->revisions->get(bfd->revisions, trail->db_txn,
svn_fs_base__set_dbt(&key, &recno,
diff --git a/subversion/libsvn_fs_base/fs.c b/subversion/libsvn_fs_base/fs.c
index 06dfbaf2f419a..903225725f06f 100644
--- a/subversion/libsvn_fs_base/fs.c
+++ b/subversion/libsvn_fs_base/fs.c
@@ -471,6 +471,13 @@ bdb_write_config(svn_fs_t *fs)
}
static svn_error_t *
+base_bdb_refresh_revision(svn_fs_t *fs,
+ apr_pool_t *scratch_pool)
+{
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
base_bdb_info_format(int *fs_format,
svn_version_t **supports_version,
svn_fs_t *fs,
@@ -545,6 +552,7 @@ base_bdb_freeze(svn_fs_t *fs,
static fs_vtable_t fs_vtable = {
svn_fs_base__youngest_rev,
+ base_bdb_refresh_revision,
svn_fs_base__revision_prop,
svn_fs_base__revision_proplist,
svn_fs_base__change_rev_prop,
@@ -572,13 +580,12 @@ static fs_vtable_t fs_vtable = {
#define FORMAT_FILE "format"
/* Depending on CREATE, create or open the environment and databases
- for filesystem FS in PATH. Use POOL for temporary allocations. */
+ for filesystem FS in PATH. */
static svn_error_t *
open_databases(svn_fs_t *fs,
svn_boolean_t create,
int format,
- const char *path,
- apr_pool_t *pool)
+ const char *path)
{
base_fs_data_t *bfd;
@@ -732,7 +739,7 @@ static svn_error_t *
base_create(svn_fs_t *fs,
const char *path,
svn_mutex__t *common_pool_lock,
- apr_pool_t *pool,
+ apr_pool_t *scratch_pool,
apr_pool_t *common_pool)
{
int format = SVN_FS_BASE__FORMAT_NUMBER;
@@ -743,7 +750,7 @@ base_create(svn_fs_t *fs,
{
svn_version_t *compatible_version;
SVN_ERR(svn_fs__compatible_version(&compatible_version, fs->config,
- pool));
+ scratch_pool));
/* select format number */
switch(compatible_version->minor)
@@ -765,7 +772,7 @@ base_create(svn_fs_t *fs,
}
/* Create the environment and databases. */
- svn_err = open_databases(fs, TRUE, format, path, pool);
+ svn_err = open_databases(fs, TRUE, format, path);
if (svn_err) goto error;
/* Initialize the DAG subsystem. */
@@ -773,14 +780,15 @@ base_create(svn_fs_t *fs,
if (svn_err) goto error;
/* This filesystem is ready. Stamp it with a format number. */
- svn_err = svn_io_write_version_file(
- svn_dirent_join(fs->path, FORMAT_FILE, pool), format, pool);
+ svn_err = svn_io_write_version_file(svn_dirent_join(fs->path, FORMAT_FILE,
+ scratch_pool),
+ format, scratch_pool);
if (svn_err) goto error;
((base_fs_data_t *) fs->fsap_data)->format = format;
- SVN_ERR(populate_opened_fs(fs, pool));
- return SVN_NO_ERROR;;
+ SVN_ERR(populate_opened_fs(fs, scratch_pool));
+ return SVN_NO_ERROR;
error:
return svn_error_compose_create(svn_err,
@@ -826,7 +834,7 @@ static svn_error_t *
base_open(svn_fs_t *fs,
const char *path,
svn_mutex__t *common_pool_lock,
- apr_pool_t *pool,
+ apr_pool_t *scratch_pool,
apr_pool_t *common_pool)
{
int format;
@@ -835,8 +843,9 @@ base_open(svn_fs_t *fs,
/* Read the FS format number. */
svn_err = svn_io_read_version_file(&format,
- svn_dirent_join(path, FORMAT_FILE, pool),
- pool);
+ svn_dirent_join(path, FORMAT_FILE,
+ scratch_pool),
+ scratch_pool);
if (svn_err && APR_STATUS_IS_ENOENT(svn_err->apr_err))
{
/* Pre-1.2 filesystems did not have a format file (you could say
@@ -852,7 +861,7 @@ base_open(svn_fs_t *fs,
goto error;
/* Create the environment and databases. */
- svn_err = open_databases(fs, FALSE, format, path, pool);
+ svn_err = open_databases(fs, FALSE, format, path);
if (svn_err) goto error;
((base_fs_data_t *) fs->fsap_data)->format = format;
@@ -862,12 +871,12 @@ base_open(svn_fs_t *fs,
if (write_format_file)
{
svn_err = svn_io_write_version_file(svn_dirent_join(path, FORMAT_FILE,
- pool),
- format, pool);
+ scratch_pool),
+ format, scratch_pool);
if (svn_err) goto error;
}
- SVN_ERR(populate_opened_fs(fs, pool));
+ SVN_ERR(populate_opened_fs(fs, scratch_pool));
return SVN_NO_ERROR;
error:
@@ -948,6 +957,7 @@ base_upgrade(svn_fs_t *fs,
err = SVN_NO_ERROR;
}
SVN_ERR(err);
+ SVN_ERR(check_format(old_format_number));
/* Bump the format file's stored version number. */
SVN_ERR(svn_io_write_version_file(version_file_path,
diff --git a/subversion/libsvn_fs_base/fs_init.h b/subversion/libsvn_fs_base/fs_init.h
new file mode 100644
index 0000000000000..012a40593e09a
--- /dev/null
+++ b/subversion/libsvn_fs_base/fs_init.h
@@ -0,0 +1,33 @@
+/*
+ * libsvn_fs_base/fs_init.h: Exported function of libsvn_fs_base
+ *
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+
+#ifndef LIBSVN_FS_LOADER_H
+#error Please include libsvn_fs/fs_loader.h instead of this file
+#else
+
+svn_error_t *svn_fs_base__init(const svn_version_t *loader_version,
+ fs_library_vtable_t **vtable,
+ apr_pool_t* common_pool);
+
+#endif
diff --git a/subversion/libsvn_fs_base/lock.c b/subversion/libsvn_fs_base/lock.c
index 1145207ea38cd..7593e9321f370 100644
--- a/subversion/libsvn_fs_base/lock.c
+++ b/subversion/libsvn_fs_base/lock.c
@@ -108,7 +108,7 @@ txn_body_lock(void *baton, trail_t *trail)
SVN_ERR(svn_fs_base__get_path_kind(&kind, args->path, trail, trail->pool));
/* Until we implement directory locks someday, we only allow locks
- on files or non-existent paths. */
+ on files. */
if (kind == svn_node_dir)
return SVN_FS__ERR_NOT_FILE(trail->fs, args->path);
diff --git a/subversion/libsvn_fs_base/revs-txns.c b/subversion/libsvn_fs_base/revs-txns.c
index f1029f4e0d0f8..2ee65455d7d5b 100644
--- a/subversion/libsvn_fs_base/revs-txns.c
+++ b/subversion/libsvn_fs_base/revs-txns.c
@@ -194,7 +194,9 @@ svn_error_t *
svn_fs_base__revision_proplist(apr_hash_t **table_p,
svn_fs_t *fs,
svn_revnum_t rev,
- apr_pool_t *pool)
+ svn_boolean_t refresh,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
struct revision_proplist_args args;
apr_hash_t *table;
@@ -204,9 +206,9 @@ svn_fs_base__revision_proplist(apr_hash_t **table_p,
args.table_p = &table;
args.rev = rev;
SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_revision_proplist, &args,
- FALSE, pool));
+ FALSE, result_pool));
- *table_p = table ? table : apr_hash_make(pool);
+ *table_p = table ? table : apr_hash_make(result_pool);
return SVN_NO_ERROR;
}
@@ -216,7 +218,9 @@ svn_fs_base__revision_prop(svn_string_t **value_p,
svn_fs_t *fs,
svn_revnum_t rev,
const char *propname,
- apr_pool_t *pool)
+ svn_boolean_t refresh,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
struct revision_proplist_args args;
apr_hash_t *table;
@@ -227,7 +231,7 @@ svn_fs_base__revision_prop(svn_string_t **value_p,
args.table_p = &table;
args.rev = rev;
SVN_ERR(svn_fs_base__retry_txn(fs, txn_body_revision_proplist, &args,
- FALSE, pool));
+ FALSE, result_pool));
/* And then the prop from that list (if there was a list). */
*value_p = svn_hash_gets(table, propname);
@@ -247,8 +251,10 @@ svn_fs_base__set_rev_prop(svn_fs_t *fs,
{
transaction_t *txn;
const char *txn_id;
+ const svn_string_t *present_value;
SVN_ERR(get_rev_txn(&txn, &txn_id, fs, rev, trail, pool));
+ present_value = svn_hash_gets(txn->proplist, name);
/* If there's no proplist, but we're just deleting a property, exit now. */
if ((! txn->proplist) && (! value))
@@ -262,7 +268,6 @@ svn_fs_base__set_rev_prop(svn_fs_t *fs,
if (old_value_p)
{
const svn_string_t *wanted_value = *old_value_p;
- const svn_string_t *present_value = svn_hash_gets(txn->proplist, name);
if ((!wanted_value != !present_value)
|| (wanted_value && present_value
&& !svn_string_compare(wanted_value, present_value)))
@@ -275,6 +280,13 @@ svn_fs_base__set_rev_prop(svn_fs_t *fs,
}
/* Fall through. */
}
+
+ /* If the prop-set is a no-op, skip the actual write. */
+ if ((!present_value && !value)
+ || (present_value && value
+ && svn_string_compare(present_value, value)))
+ return SVN_NO_ERROR;
+
svn_hash_sets(txn->proplist, name, value);
/* Overwrite the revision. */
diff --git a/subversion/libsvn_fs_base/revs-txns.h b/subversion/libsvn_fs_base/revs-txns.h
index 558a90c892667..4a2082773f6f7 100644
--- a/subversion/libsvn_fs_base/revs-txns.h
+++ b/subversion/libsvn_fs_base/revs-txns.h
@@ -172,12 +172,16 @@ svn_error_t *svn_fs_base__youngest_rev(svn_revnum_t *youngest_p, svn_fs_t *fs,
svn_error_t *svn_fs_base__revision_prop(svn_string_t **value_p, svn_fs_t *fs,
svn_revnum_t rev,
const char *propname,
- apr_pool_t *pool);
+ svn_boolean_t refresh,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
svn_error_t *svn_fs_base__revision_proplist(apr_hash_t **table_p,
svn_fs_t *fs,
svn_revnum_t rev,
- apr_pool_t *pool);
+ svn_boolean_t refresh,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
svn_error_t *svn_fs_base__change_rev_prop(svn_fs_t *fs, svn_revnum_t rev,
const char *name,
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,