diff options
Diffstat (limited to 'subversion/libsvn_fs_base')
-rw-r--r-- | subversion/libsvn_fs_base/bdb/rev-table.c | 3 | ||||
-rw-r--r-- | subversion/libsvn_fs_base/fs.c | 44 | ||||
-rw-r--r-- | subversion/libsvn_fs_base/fs_init.h | 33 | ||||
-rw-r--r-- | subversion/libsvn_fs_base/lock.c | 2 | ||||
-rw-r--r-- | subversion/libsvn_fs_base/revs-txns.c | 24 | ||||
-rw-r--r-- | subversion/libsvn_fs_base/revs-txns.h | 8 | ||||
-rw-r--r-- | subversion/libsvn_fs_base/tree.c | 80 |
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, |