From ea26c32ce1701156a3a9ac70a23987a8b0b48b75 Mon Sep 17 00:00:00 2001 From: glasser Date: Mon, 11 Feb 2008 22:38:43 +0000 Subject: [PATCH] Make FSFS require FS version 3 for mergeinfo operations. Specifically, with older filesystems, throw an error from svn_fs_get_mergeinfo; don't write the mergeinfo metadata fields to noderevs; and don't do various metadata maintenance steps. * subversion/libsvn_fs_fs/fs.h (SVN_FS_FS__MIN_MERGEINFO_FORMAT): New. * subversion/libsvn_fs_fs/fs_fs.c (svn_fs_fs__fs_supports_mergeinfo): New helper. (write_noderev_txn): New include_mergeinfo parameter controlling whether or not "minfo-count" and "minfo-here" are written. (svn_fs_fs__put_node_revision, write_final_rev): Adjust. * subversion/libsvn_fs_fs/fs_fs.h (svn_fs_fs__fs_supports_mergeinfo): Declare. * subversion/libsvn_fs_fs/structure Mention maintainance of minfo-here and minfo-count requires version 3. * subversion/libsvn_fs_fs/tree.c (fs_change_node_prop, merge, fs_delete_node, copy_helper): Only do mergeinfo bookkeeping for new repository format. (fs_get_mergeinfo): Throw error if called with old repository. git-svn-id: http://svn.collab.net/repos/svn/trunk@29280 612f8ebc-c883-4be0-9ee0-a4e9ef946e3a --- subversion/libsvn_fs_fs/fs.h | 4 ++ subversion/libsvn_fs_fs/fs_fs.c | 34 +++++++++++---- subversion/libsvn_fs_fs/fs_fs.h | 3 ++ subversion/libsvn_fs_fs/structure | 3 +- subversion/libsvn_fs_fs/tree.c | 88 ++++++++++++++++++++++++++------------- 5 files changed, 93 insertions(+), 39 deletions(-) diff --git a/subversion/libsvn_fs_fs/fs.h b/subversion/libsvn_fs_fs/fs.h index b99f3dc33..421be4123 100644 --- a/subversion/libsvn_fs_fs/fs.h +++ b/subversion/libsvn_fs_fs/fs.h @@ -87,6 +87,10 @@ extern "C" { /* The minimum format number that doesn't keep node and copy ID counters. */ #define SVN_FS_FS__MIN_NO_GLOBAL_IDS_FORMAT 3 +/* The minimum format number that maintains minfo-here and minfo-count + noderev fields. */ +#define SVN_FS_FS__MIN_MERGEINFO_FORMAT 3 + /* Maximum number of directories to cache dirents for. This *must* be a power of 2 for DIR_CACHE_ENTRIES_MASK to work. */ diff --git a/subversion/libsvn_fs_fs/fs_fs.c b/subversion/libsvn_fs_fs/fs_fs.c index 891f61481..2b1387ec8 100644 --- a/subversion/libsvn_fs_fs/fs_fs.c +++ b/subversion/libsvn_fs_fs/fs_fs.c @@ -975,6 +975,13 @@ check_format(int format) SVN_FS_FS__FORMAT_NUMBER, format); } +svn_boolean_t +svn_fs_fs__fs_supports_mergeinfo(svn_fs_t *fs) +{ + fs_fs_data_t *ffd = fs->fsap_data; + return ffd->format >= SVN_FS_FS__MIN_MERGEINFO_FORMAT; +} + static svn_error_t * get_youngest(svn_revnum_t *youngest_p, const char *fs_path, apr_pool_t *pool); @@ -1749,11 +1756,13 @@ representation_string(representation_t *rep, pool)); } -/* Write the node-revision NODEREV into the file FILE. Temporary +/* Write the node-revision NODEREV into the file FILE. Only write + mergeinfo-related metadata if INCLUDE_MERGEINFO is true. Temporary allocations are from POOL. */ static svn_error_t * write_noderev_txn(apr_file_t *file, node_revision_t *noderev, + svn_boolean_t include_mergeinfo, apr_pool_t *pool) { svn_stream_t *outfile; @@ -1807,13 +1816,16 @@ write_noderev_txn(apr_file_t *file, if (noderev->is_fresh_txn_root) SVN_ERR(svn_stream_printf(outfile, pool, HEADER_FRESHTXNRT ": y\n")); - if (noderev->mergeinfo_count > 0) - SVN_ERR(svn_stream_printf(outfile, pool, HEADER_MINFO_CNT ": %" - APR_INT64_T_FMT "\n", - noderev->mergeinfo_count)); + if (include_mergeinfo) + { + if (noderev->mergeinfo_count > 0) + SVN_ERR(svn_stream_printf(outfile, pool, HEADER_MINFO_CNT ": %" + APR_INT64_T_FMT "\n", + noderev->mergeinfo_count)); - if (noderev->has_mergeinfo) - SVN_ERR(svn_stream_printf(outfile, pool, HEADER_MINFO_HERE ": y\n")); + if (noderev->has_mergeinfo) + SVN_ERR(svn_stream_printf(outfile, pool, HEADER_MINFO_HERE ": y\n")); + } SVN_ERR(svn_stream_printf(outfile, pool, "\n")); @@ -1840,7 +1852,9 @@ svn_fs_fs__put_node_revision(svn_fs_t *fs, APR_WRITE | APR_CREATE | APR_TRUNCATE | APR_BUFFERED, APR_OS_DEFAULT, pool)); - SVN_ERR(write_noderev_txn(noderev_file, noderev, pool)); + SVN_ERR(write_noderev_txn(noderev_file, noderev, + svn_fs_fs__fs_supports_mergeinfo(fs), + pool)); SVN_ERR(svn_io_file_close(noderev_file, pool)); @@ -4758,7 +4772,9 @@ write_final_rev(const svn_fs_id_t **new_id_p, noderev->id = new_id; /* Write out our new node-revision. */ - SVN_ERR(write_noderev_txn(file, noderev, pool)); + SVN_ERR(write_noderev_txn(file, noderev, + svn_fs_fs__fs_supports_mergeinfo(fs), + pool)); /* Return our ID that references the revision file. */ *new_id_p = noderev->id; diff --git a/subversion/libsvn_fs_fs/fs_fs.h b/subversion/libsvn_fs_fs/fs_fs.h index c0b16d766..3ead46b00 100644 --- a/subversion/libsvn_fs_fs/fs_fs.h +++ b/subversion/libsvn_fs_fs/fs_fs.h @@ -184,6 +184,9 @@ svn_error_t *svn_fs_fs__change_txn_mergeinfo(svn_fs_txn_t *txn, const svn_string_t *value, apr_pool_t *pool); +/* Return whether or not the given FS supports mergeinfo metadata. */ +svn_boolean_t svn_fs_fs__fs_supports_mergeinfo(svn_fs_t *fs); + /* Store a transaction record in *TXN_P for the transaction identified by TXN_ID in filesystem FS. Allocate everything from POOL. */ svn_error_t *svn_fs_fs__get_txn(transaction_t **txn_p, diff --git a/subversion/libsvn_fs_fs/structure b/subversion/libsvn_fs_fs/structure index 9f0e6ab5e..570363e2a 100644 --- a/subversion/libsvn_fs_fs/structure +++ b/subversion/libsvn_fs_fs/structure @@ -130,7 +130,8 @@ Format 3: (understood by Subversion 1.5+) generated using the transaction sequence number stored in the txn-current file. Proto-rev and its lock are stored in txn-protorevs/.rev and txn-protorevs/.rev-lock. - Node-IDs and copy-IDs do not use the "current" file. + Node-IDs and copy-IDs do not use the "current" file. minfo-here and + minfo-count node-revision fields are maintained. Filesystem format options ------------------------- diff --git a/subversion/libsvn_fs_fs/tree.c b/subversion/libsvn_fs_fs/tree.c index 07174ef29..be8c6ee2e 100644 --- a/subversion/libsvn_fs_fs/tree.c +++ b/subversion/libsvn_fs_fs/tree.c @@ -1095,7 +1095,8 @@ fs_change_node_prop(svn_fs_root_t *root, if (! proplist) proplist = apr_hash_make(pool); - if (strcmp (name, SVN_PROP_MERGEINFO) == 0) + if (svn_fs_fs__fs_supports_mergeinfo(root->fs) + && strcmp (name, SVN_PROP_MERGEINFO) == 0) { apr_int64_t increment = 0; svn_boolean_t had_mergeinfo; @@ -1430,24 +1431,32 @@ merge(svn_stringbuf_t *conflict_p, else if (t_entry && svn_fs_fs__id_eq(a_entry->id, t_entry->id)) { dag_node_t *t_ent_node; - apr_int64_t mergeinfo_start; SVN_ERR(svn_fs_fs__dag_get_node(&t_ent_node, fs, t_entry->id, iterpool)); - SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_start, - t_ent_node, - iterpool)); - mergeinfo_increment -= mergeinfo_start; + if (svn_fs_fs__fs_supports_mergeinfo(fs)) + { + apr_int64_t mergeinfo_start; + SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_start, + t_ent_node, + iterpool)); + mergeinfo_increment -= mergeinfo_start; + } if (s_entry) { dag_node_t *s_ent_node; - apr_int64_t mergeinfo_end; SVN_ERR(svn_fs_fs__dag_get_node(&s_ent_node, fs, s_entry->id, iterpool)); - SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_end, - s_ent_node, - iterpool)); - mergeinfo_increment += mergeinfo_end; + + if (svn_fs_fs__fs_supports_mergeinfo(fs)) + { + apr_int64_t mergeinfo_end; + SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_end, + s_ent_node, + iterpool)); + mergeinfo_increment += mergeinfo_end; + } + SVN_ERR(svn_fs_fs__dag_set_entry(target, key, s_entry->id, s_entry->kind, @@ -1516,7 +1525,8 @@ merge(svn_stringbuf_t *conflict_p, txn_id, &sub_mergeinfo_increment, iterpool)); - mergeinfo_increment += sub_mergeinfo_increment; + if (svn_fs_fs__fs_supports_mergeinfo(fs)) + mergeinfo_increment += sub_mergeinfo_increment; } /* We've taken care of any possible implications E could have. @@ -1537,7 +1547,6 @@ merge(svn_stringbuf_t *conflict_p, void *val; apr_ssize_t klen; dag_node_t *s_ent_node; - apr_int64_t mergeinfo_s; svn_pool_clear(iterpool); @@ -1554,10 +1563,15 @@ merge(svn_stringbuf_t *conflict_p, SVN_ERR(svn_fs_fs__dag_get_node(&s_ent_node, fs, s_entry->id, iterpool)); - SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_s, - s_ent_node, - iterpool)); - mergeinfo_increment += mergeinfo_s; + if (svn_fs_fs__fs_supports_mergeinfo(fs)) + { + apr_int64_t mergeinfo_s; + SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_s, + s_ent_node, + iterpool)); + mergeinfo_increment += mergeinfo_s; + } + SVN_ERR(svn_fs_fs__dag_set_entry (target, s_entry->name, s_entry->id, s_entry->kind, txn_id, iterpool)); @@ -1567,8 +1581,11 @@ merge(svn_stringbuf_t *conflict_p, SVN_ERR(svn_fs_fs__dag_get_predecessor_count(&pred_count, source, pool)); SVN_ERR(update_ancestry(fs, source_id, target_id, target_path, pred_count, pool)); - SVN_ERR(svn_fs_fs__dag_increment_mergeinfo_count(target, mergeinfo_increment, - pool)); + + if (svn_fs_fs__fs_supports_mergeinfo(fs)) + SVN_ERR(svn_fs_fs__dag_increment_mergeinfo_count(target, + mergeinfo_increment, + pool)); if (mergeinfo_increment_out) *mergeinfo_increment_out = mergeinfo_increment; @@ -1930,9 +1947,10 @@ fs_delete_node(svn_fs_root_t *root, /* Make the parent directory mutable, and do the deletion. */ SVN_ERR(make_path_mutable(root, parent_path->parent, path, pool)); - SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_count, - parent_path->node, - pool)); + if (svn_fs_fs__fs_supports_mergeinfo(root->fs)) + SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_count, + parent_path->node, + pool)); SVN_ERR(svn_fs_fs__dag_delete(parent_path->parent->node, parent_path->entry, txn_id, pool)); @@ -1941,7 +1959,7 @@ fs_delete_node(svn_fs_root_t *root, dag_node_cache_invalidate(root, parent_path_path(parent_path, pool)); /* Update mergeinfo counts for parents */ - if (mergeinfo_count > 0) + if (svn_fs_fs__fs_supports_mergeinfo(root->fs) && mergeinfo_count > 0) SVN_ERR(increment_mergeinfo_up_tree(parent_path->parent, -mergeinfo_count, pool)); @@ -2046,9 +2064,10 @@ copy_helper(svn_fs_root_t *from_root, if (to_parent_path->node) { kind = svn_fs_path_change_replace; - SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_start, - to_parent_path->node, - pool)); + if (svn_fs_fs__fs_supports_mergeinfo(to_root->fs)) + SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_start, + to_parent_path->node, + pool)); } else { @@ -2056,8 +2075,9 @@ copy_helper(svn_fs_root_t *from_root, mergeinfo_start = 0; } - SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_end, - from_node, pool)); + if (svn_fs_fs__fs_supports_mergeinfo(to_root->fs)) + SVN_ERR(svn_fs_fs__dag_get_mergeinfo_count(&mergeinfo_end, + from_node, pool)); /* Make sure the target node's parents are mutable. */ SVN_ERR(make_path_mutable(to_root, to_parent_path->parent, @@ -2078,7 +2098,8 @@ copy_helper(svn_fs_root_t *from_root, dag_node_cache_invalidate(to_root, parent_path_path(to_parent_path, pool)); - if (mergeinfo_start != mergeinfo_end) + if (svn_fs_fs__fs_supports_mergeinfo(to_root->fs) + && mergeinfo_start != mergeinfo_end) SVN_ERR(increment_mergeinfo_up_tree(to_parent_path->parent, mergeinfo_end - mergeinfo_start, pool)); @@ -3671,11 +3692,20 @@ fs_get_mergeinfo(apr_hash_t **mergeinfo, int i; apr_hash_t *mergeinfo_as_hashes; apr_pool_t *subpool, *iterpool; + fs_fs_data_t *ffd = root->fs->fsap_data; /* We require a revision root. */ if (root->is_txn_root) return svn_error_create(SVN_ERR_FS_NOT_REVISION_ROOT, NULL, NULL); + /* We have to actually be able to find the mergeinfo metadata! */ + if (! svn_fs_fs__fs_supports_mergeinfo(root->fs)) + return svn_error_createf + (SVN_ERR_UNSUPPORTED_FEATURE, NULL, + _("Querying mergeinfo requries version %d of the FSFS filesystem " + "schema; filesystem '%s' uses only version %d"), + SVN_FS_FS__MIN_MERGEINFO_FORMAT, root->fs->path, ffd->format); + subpool = svn_pool_create(pool); iterpool = svn_pool_create(subpool); -- 2.11.4.GIT