summaryrefslogtreecommitdiff
path: root/subversion/libsvn_fs
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>2018-05-08 03:44:38 +0000
committerPeter Wemm <peter@FreeBSD.org>2018-05-08 03:44:38 +0000
commit3faf8d6bffc5d0fb2525ba37bb504c53366caf9d (patch)
tree7e47911263e75034b767fe34b2f8d3d17e91f66d /subversion/libsvn_fs
parenta55fb3c0d5eca7d887798125d5b95942b1f01d4b (diff)
Diffstat (limited to 'subversion/libsvn_fs')
-rw-r--r--subversion/libsvn_fs/deprecated.c157
-rw-r--r--subversion/libsvn_fs/editor.c18
-rw-r--r--subversion/libsvn_fs/fs-loader.c460
-rw-r--r--subversion/libsvn_fs/fs-loader.h67
4 files changed, 547 insertions, 155 deletions
diff --git a/subversion/libsvn_fs/deprecated.c b/subversion/libsvn_fs/deprecated.c
index 03045773f5201..0e741c273c587 100644
--- a/subversion/libsvn_fs/deprecated.c
+++ b/subversion/libsvn_fs/deprecated.c
@@ -26,7 +26,9 @@
deprecated functions in this file. */
#define SVN_DEPRECATED
+#include <apr_md5.h>
#include "svn_fs.h"
+#include "private/svn_subr_private.h"
/*** From fs-loader.c ***/
@@ -64,6 +66,28 @@ svn_fs_begin_txn(svn_fs_txn_t **txn_p, svn_fs_t *fs, svn_revnum_t rev,
}
svn_error_t *
+svn_fs_revision_prop(svn_string_t **value_p,
+ svn_fs_t *fs,
+ svn_revnum_t rev,
+ const char *propname,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(
+ svn_fs_revision_prop2(value_p, fs, rev, propname, TRUE, pool,
+ pool));
+}
+
+svn_error_t *
+svn_fs_revision_proplist(apr_hash_t **table_p,
+ svn_fs_t *fs,
+ svn_revnum_t rev,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(
+ svn_fs_revision_proplist2(table_p, fs, rev, TRUE, pool, pool));
+}
+
+svn_error_t *
svn_fs_change_rev_prop(svn_fs_t *fs, svn_revnum_t rev, const char *name,
const svn_string_t *value, apr_pool_t *pool)
{
@@ -81,6 +105,139 @@ svn_fs_get_locks(svn_fs_t *fs, const char *path,
pool));
}
+svn_error_t *
+svn_fs_create(svn_fs_t **fs_p,
+ const char *path,
+ apr_hash_t *fs_config,
+ apr_pool_t *pool)
+{
+ return svn_fs_create2(fs_p, path, fs_config, pool, pool);
+}
+
+svn_error_t *
+svn_fs_open(svn_fs_t **fs_p,
+ const char *path,
+ apr_hash_t *fs_config,
+ apr_pool_t *pool)
+{
+ return svn_fs_open2(fs_p, path, fs_config, pool, pool);
+}
+
+svn_error_t *
+svn_fs_node_history(svn_fs_history_t **history_p, svn_fs_root_t *root,
+ const char *path, apr_pool_t *pool)
+{
+ return svn_error_trace(svn_fs_node_history2(history_p, root, path,
+ pool, pool));
+}
+
+static svn_error_t *
+mergeinfo_receiver(const char *path,
+ svn_mergeinfo_t mergeinfo,
+ void *baton,
+ apr_pool_t *scratch_pool)
+{
+ svn_mergeinfo_catalog_t catalog = baton;
+ apr_pool_t *result_pool = apr_hash_pool_get(catalog);
+ apr_size_t len = strlen(path);
+
+ apr_hash_set(catalog,
+ apr_pstrmemdup(result_pool, path, len),
+ len,
+ svn_mergeinfo_dup(mergeinfo, result_pool));
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_get_mergeinfo2(svn_mergeinfo_catalog_t *catalog,
+ 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,
+ apr_pool_t *scratch_pool)
+{
+ svn_mergeinfo_catalog_t result_catalog = svn_hash__make(result_pool);
+ SVN_ERR(svn_fs_get_mergeinfo3(root, paths, inherit,
+ include_descendants,
+ adjust_inherited_mergeinfo,
+ mergeinfo_receiver, result_catalog,
+ scratch_pool));
+ *catalog = result_catalog;
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_get_mergeinfo(svn_mergeinfo_catalog_t *catalog,
+ svn_fs_root_t *root,
+ const apr_array_header_t *paths,
+ svn_mergeinfo_inheritance_t inherit,
+ svn_boolean_t include_descendants,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(svn_fs_get_mergeinfo2(catalog, root, paths,
+ inherit,
+ include_descendants,
+ TRUE, pool, pool));
+}
+
+svn_error_t *
+svn_fs_paths_changed(apr_hash_t **changed_paths_p, svn_fs_root_t *root,
+ apr_pool_t *pool)
+{
+ apr_hash_t *changed_paths_new_structs;
+ apr_hash_index_t *hi;
+
+ SVN_ERR(svn_fs_paths_changed2(&changed_paths_new_structs, root, pool));
+ *changed_paths_p = apr_hash_make(pool);
+ for (hi = apr_hash_first(pool, changed_paths_new_structs);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ const void *vkey;
+ apr_ssize_t klen;
+ void *vval;
+ svn_fs_path_change2_t *val;
+ svn_fs_path_change_t *change;
+ apr_hash_this(hi, &vkey, &klen, &vval);
+ val = vval;
+ change = apr_palloc(pool, sizeof(*change));
+ change->node_rev_id = val->node_rev_id;
+ change->change_kind = val->change_kind;
+ change->text_mod = val->text_mod;
+ change->prop_mod = val->prop_mod;
+ apr_hash_set(*changed_paths_p, vkey, klen, change);
+ }
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_file_md5_checksum(unsigned char digest[],
+ svn_fs_root_t *root,
+ const char *path,
+ apr_pool_t *pool)
+{
+ svn_checksum_t *md5sum;
+
+ SVN_ERR(svn_fs_file_checksum(&md5sum, svn_checksum_md5, root, path, TRUE,
+ pool));
+ memcpy(digest, md5sum->digest, APR_MD5_DIGESTSIZE);
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_history_prev(svn_fs_history_t **prev_history_p,
+ svn_fs_history_t *history, svn_boolean_t cross_copies,
+ apr_pool_t *pool)
+{
+ return svn_error_trace(svn_fs_history_prev2(prev_history_p, history,
+ cross_copies, pool, pool));
+}
+
/*** From access.c ***/
svn_error_t *
svn_fs_access_add_lock_token(svn_fs_access_t *access_ctx,
diff --git a/subversion/libsvn_fs/editor.c b/subversion/libsvn_fs/editor.c
index b4cd3bca3f3e3..c24c154e59cfa 100644
--- a/subversion/libsvn_fs/editor.c
+++ b/subversion/libsvn_fs/editor.c
@@ -777,16 +777,24 @@ svn_fs__editor_commit(svn_revnum_t *revision,
/* Clean up internal resources (eg. eb->root). This also allows the
editor infrastructure to know this editor is "complete". */
err = svn_editor_complete(editor);
+ if (err)
+ {
+ svn_fs_txn_t *txn = eb->txn;
+
+ eb->txn = NULL;
+ return svn_error_trace(svn_error_compose_create(
+ err,
+ svn_fs_abort_txn(txn, scratch_pool)));
+ }
/* Note: docco for svn_fs_commit_txn() states that CONFLICT_PATH will
be allocated in the txn's pool. But it lies. Regardless, we want
it placed into RESULT_POOL. */
- if (!err)
- err = svn_fs_commit_txn(&inner_conflict_path,
- revision,
- eb->txn,
- scratch_pool);
+ err = svn_fs_commit_txn(&inner_conflict_path,
+ revision,
+ eb->txn,
+ scratch_pool);
if (SVN_IS_VALID_REVNUM(*revision))
{
if (err)
diff --git a/subversion/libsvn_fs/fs-loader.c b/subversion/libsvn_fs/fs-loader.c
index ba90554fa263e..f898d8a56a6a7 100644
--- a/subversion/libsvn_fs/fs-loader.c
+++ b/subversion/libsvn_fs/fs-loader.c
@@ -26,8 +26,6 @@
#include <apr.h>
#include <apr_atomic.h>
#include <apr_hash.h>
-#include <apr_md5.h>
-#include <apr_thread_mutex.h>
#include <apr_uuid.h>
#include <apr_strings.h>
@@ -47,6 +45,7 @@
#include "private/svn_atomic.h"
#include "private/svn_fs_private.h"
#include "private/svn_fs_util.h"
+#include "private/svn_fspath.h"
#include "private/svn_utf_private.h"
#include "private/svn_mutex.h"
#include "private/svn_subr_private.h"
@@ -61,6 +60,22 @@
#define FS_TYPE_FILENAME "fs-type"
+/* If a FS backend does not implement the PATHS_CHANGED vtable function,
+ it will get emulated. However, if this macro is defined to non-null
+ then the API will always be emulated when feasible, i.e. the calls
+ get "re-directed" to the new API implementation. */
+#ifndef SVN_FS_EMULATE_PATHS_CHANGED
+#define SVN_FS_EMULATE_PATHS_CHANGED FALSE
+#endif
+
+/* If a FS backend does not implement the REPORT_CHANGES vtable function,
+ it will get emulated. However, if this macro is defined to non-null
+ then the API will always be emulated when feasible, i.e. the calls
+ get "re-directed" to the old API implementation. */
+#ifndef SVN_FS_EMULATE_REPORT_CHANGES
+#define SVN_FS_EMULATE_REPORT_CHANGES FALSE
+#endif
+
/* A pool common to all FS objects. See the documentation on the
open/create functions in fs-loader.h and for svn_fs_initialize(). */
static apr_pool_t *common_pool = NULL;
@@ -74,7 +89,7 @@ struct fs_type_defn {
const char *fs_type;
const char *fsap_name;
fs_init_func_t initfunc;
- fs_library_vtable_t *vtable;
+ void * volatile vtable; /* fs_library_vtable_t */
struct fs_type_defn *next;
};
@@ -140,7 +155,7 @@ load_module(fs_init_func_t *initfunc, const char *name, apr_pool_t *pool)
_("Invalid name for FS type '%s'"),
name);
- libname = apr_psprintf(pool, "libsvn_fs_%s-%d.so.%d",
+ libname = apr_psprintf(pool, "libsvn_fs_%s-" SVN_DSO_SUFFIX_FMT,
name, SVN_VER_MAJOR, SVN_SOVERSION);
funcname = apr_psprintf(pool, "svn_fs_%s__init", name);
@@ -175,7 +190,7 @@ get_library_vtable_direct(fs_library_vtable_t **vtable,
const svn_version_t *fs_version;
/* most times, we get lucky */
- *vtable = apr_atomic_casptr((volatile void **)&fst->vtable, NULL, NULL);
+ *vtable = svn_atomic_casptr(&fst->vtable, NULL, NULL);
if (*vtable)
return SVN_NO_ERROR;
@@ -218,7 +233,7 @@ get_library_vtable_direct(fs_library_vtable_t **vtable,
fs_version->patch, fs_version->tag);
/* the vtable will not change. Remember it */
- apr_atomic_casptr((volatile void **)&fst->vtable, *vtable, NULL);
+ svn_atomic_casptr(&fst->vtable, *vtable, NULL);
return SVN_NO_ERROR;
}
@@ -507,24 +522,28 @@ svn_fs_set_warning_func(svn_fs_t *fs, svn_fs_warning_callback_t warning,
}
svn_error_t *
-svn_fs_create(svn_fs_t **fs_p, const char *path, apr_hash_t *fs_config,
- apr_pool_t *pool)
+svn_fs_create2(svn_fs_t **fs_p,
+ const char *path,
+ apr_hash_t *fs_config,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
fs_library_vtable_t *vtable;
const char *fs_type = svn_hash__get_cstring(fs_config,
SVN_FS_CONFIG_FS_TYPE,
DEFAULT_FS_TYPE);
- SVN_ERR(get_library_vtable(&vtable, fs_type, pool));
+ SVN_ERR(get_library_vtable(&vtable, fs_type, scratch_pool));
/* Create the FS directory and write out the fsap-name file. */
- SVN_ERR(svn_io_dir_make_sgid(path, APR_OS_DEFAULT, pool));
- SVN_ERR(write_fs_type(path, fs_type, pool));
+ SVN_ERR(svn_io_dir_make_sgid(path, APR_OS_DEFAULT, scratch_pool));
+ SVN_ERR(write_fs_type(path, fs_type, scratch_pool));
/* Perform the actual creation. */
- *fs_p = fs_new(fs_config, pool);
+ *fs_p = fs_new(fs_config, result_pool);
- SVN_ERR(vtable->create(*fs_p, path, common_pool_lock, pool, common_pool));
+ SVN_ERR(vtable->create(*fs_p, path, common_pool_lock, scratch_pool,
+ common_pool));
SVN_ERR(vtable->set_svn_fs_open(*fs_p, svn_fs_open2));
return SVN_NO_ERROR;
@@ -547,15 +566,6 @@ svn_fs_open2(svn_fs_t **fs_p, const char *path, apr_hash_t *fs_config,
}
svn_error_t *
-svn_fs_open(svn_fs_t **fs_p,
- const char *path,
- apr_hash_t *fs_config,
- apr_pool_t *pool)
-{
- return svn_fs_open2(fs_p, path, fs_config, pool, pool);
-}
-
-svn_error_t *
svn_fs_upgrade2(const char *path,
svn_fs_upgrade_notify_t notify_func,
void *notify_baton,
@@ -1046,40 +1056,163 @@ svn_fs_revision_root_revision(svn_fs_root_t *root)
}
svn_error_t *
+svn_fs_path_change_get(svn_fs_path_change3_t **change,
+ svn_fs_path_change_iterator_t *iterator)
+{
+ return iterator->vtable->get(change, iterator);
+}
+
+svn_error_t *
svn_fs_paths_changed2(apr_hash_t **changed_paths_p,
svn_fs_root_t *root,
apr_pool_t *pool)
{
- return root->vtable->paths_changed(changed_paths_p, root, pool);
+ svn_boolean_t emulate = !root->vtable->paths_changed
+ || SVN_FS_EMULATE_PATHS_CHANGED;
+
+ if (emulate)
+ {
+ apr_pool_t *scratch_pool = svn_pool_create(pool);
+ apr_hash_t *changes = svn_hash__make(pool);
+
+ svn_fs_path_change_iterator_t *iterator;
+ svn_fs_path_change3_t *change;
+
+ SVN_ERR(svn_fs_paths_changed3(&iterator, root, scratch_pool,
+ scratch_pool));
+
+ SVN_ERR(svn_fs_path_change_get(&change, iterator));
+ while (change)
+ {
+ svn_fs_path_change2_t *copy;
+ const svn_fs_id_t *id_copy;
+ const char *change_path = change->path.data;
+ svn_fs_root_t *change_root = root;
+
+ /* Copy CHANGE to old API struct. */
+ if (change->change_kind == svn_fs_path_change_delete)
+ SVN_ERR(svn_fs__get_deleted_node(&change_root, &change_path,
+ change_root, change_path,
+ scratch_pool, scratch_pool));
+
+ SVN_ERR(svn_fs_node_id(&id_copy, change_root, change_path, pool));
+
+ copy = svn_fs_path_change2_create(id_copy, change->change_kind,
+ pool);
+ copy->copyfrom_known = change->copyfrom_known;
+ if ( copy->copyfrom_known
+ && SVN_IS_VALID_REVNUM(change->copyfrom_rev))
+ {
+ copy->copyfrom_rev = change->copyfrom_rev;
+ copy->copyfrom_path = apr_pstrdup(pool, change->copyfrom_path);
+ }
+ copy->mergeinfo_mod = change->mergeinfo_mod;
+ copy->node_kind = change->node_kind;
+ copy->prop_mod = change->prop_mod;
+ copy->text_mod = change->text_mod;
+
+ svn_hash_sets(changes, apr_pstrmemdup(pool, change->path.data,
+ change->path.len), copy);
+
+ /* Next change. */
+ SVN_ERR(svn_fs_path_change_get(&change, iterator));
+ }
+ svn_pool_destroy(scratch_pool);
+
+ *changed_paths_p = changes;
+ }
+ else
+ {
+ SVN_ERR(root->vtable->paths_changed(changed_paths_p, root, pool));
+ }
+
+ return SVN_NO_ERROR;
}
-svn_error_t *
-svn_fs_paths_changed(apr_hash_t **changed_paths_p, svn_fs_root_t *root,
- apr_pool_t *pool)
+/* Implement svn_fs_path_change_iterator_t on top of svn_fs_paths_changed2. */
+
+/* The iterator builds upon a hash iterator, which in turn operates on the
+ full prefetched changes list. */
+typedef struct fsap_iterator_data_t
{
- apr_hash_t *changed_paths_new_structs;
apr_hash_index_t *hi;
- SVN_ERR(svn_fs_paths_changed2(&changed_paths_new_structs, root, pool));
- *changed_paths_p = apr_hash_make(pool);
- for (hi = apr_hash_first(pool, changed_paths_new_structs);
- hi;
- hi = apr_hash_next(hi))
+ /* For efficicency such that we don't need to dynamically allocate
+ yet another copy of that data. */
+ svn_fs_path_change3_t change;
+} fsap_iterator_data_t;
+
+static svn_error_t *
+changes_iterator_get(svn_fs_path_change3_t **change,
+ svn_fs_path_change_iterator_t *iterator)
+{
+ fsap_iterator_data_t *data = iterator->fsap_data;
+
+ if (data->hi)
{
- const void *vkey;
- apr_ssize_t klen;
- void *vval;
- svn_fs_path_change2_t *val;
- svn_fs_path_change_t *change;
- apr_hash_this(hi, &vkey, &klen, &vval);
- val = vval;
- change = apr_palloc(pool, sizeof(*change));
- change->node_rev_id = val->node_rev_id;
- change->change_kind = val->change_kind;
- change->text_mod = val->text_mod;
- change->prop_mod = val->prop_mod;
- apr_hash_set(*changed_paths_p, vkey, klen, change);
+ const char *path = apr_hash_this_key(data->hi);
+ svn_fs_path_change2_t *entry = apr_hash_this_val(data->hi);
+
+ data->change.path.data = path;
+ data->change.path.len = apr_hash_this_key_len(data->hi);
+ data->change.change_kind = entry->change_kind;
+ data->change.node_kind = entry->node_kind;
+ data->change.text_mod = entry->text_mod;
+ data->change.prop_mod = entry->prop_mod;
+ data->change.mergeinfo_mod = entry->mergeinfo_mod;
+ data->change.copyfrom_known = entry->copyfrom_known;
+ data->change.copyfrom_rev = entry->copyfrom_rev;
+ data->change.copyfrom_path = entry->copyfrom_path;
+
+ *change = &data->change;
+ data->hi = apr_hash_next(data->hi);
}
+ else
+ {
+ *change = NULL;
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static changes_iterator_vtable_t iterator_vtable =
+{
+ changes_iterator_get
+};
+
+svn_error_t *
+svn_fs_paths_changed3(svn_fs_path_change_iterator_t **iterator,
+ svn_fs_root_t *root,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_boolean_t emulate = !root->vtable->report_changes
+ || ( SVN_FS_EMULATE_REPORT_CHANGES
+ && root->vtable->paths_changed);
+
+ if (emulate)
+ {
+ svn_fs_path_change_iterator_t *result;
+ fsap_iterator_data_t *data;
+
+ apr_hash_t *changes;
+ SVN_ERR(root->vtable->paths_changed(&changes, root, result_pool));
+
+ data = apr_pcalloc(result_pool, sizeof(*data));
+ data->hi = apr_hash_first(result_pool, changes);
+
+ result = apr_pcalloc(result_pool, sizeof(*result));
+ result->fsap_data = data;
+ result->vtable = &iterator_vtable;
+
+ *iterator = result;
+ }
+ else
+ {
+ SVN_ERR(root->vtable->report_changes(iterator, root, result_pool,
+ scratch_pool));
+ }
+
return SVN_NO_ERROR;
}
@@ -1101,14 +1234,6 @@ svn_fs_node_history2(svn_fs_history_t **history_p, svn_fs_root_t *root,
}
svn_error_t *
-svn_fs_node_history(svn_fs_history_t **history_p, svn_fs_root_t *root,
- const char *path, apr_pool_t *pool)
-{
- return svn_error_trace(root->vtable->node_history(history_p, root, path,
- pool, pool));
-}
-
-svn_error_t *
svn_fs_is_dir(svn_boolean_t *is_dir, svn_fs_root_t *root, const char *path,
apr_pool_t *pool)
{
@@ -1254,32 +1379,38 @@ svn_fs_closest_copy(svn_fs_root_t **root_p, const char **path_p,
}
svn_error_t *
-svn_fs_get_mergeinfo2(svn_mergeinfo_catalog_t *catalog,
- svn_fs_root_t *root,
+svn_fs_get_mergeinfo3(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)
{
return svn_error_trace(root->vtable->get_mergeinfo(
- catalog, root, paths, inherit, include_descendants,
- adjust_inherited_mergeinfo, result_pool, scratch_pool));
+ root, paths, inherit, include_descendants, adjust_inherited_mergeinfo,
+ receiver, baton, scratch_pool));
}
-svn_error_t *
-svn_fs_get_mergeinfo(svn_mergeinfo_catalog_t *catalog,
- svn_fs_root_t *root,
- const apr_array_header_t *paths,
- svn_mergeinfo_inheritance_t inherit,
- svn_boolean_t include_descendants,
- apr_pool_t *pool)
+/* Baton type to be used with mergeinfo_receiver(). It provides some of
+ * the parameters passed to svn_fs__get_mergeinfo_for_path. */
+typedef struct mergeinfo_receiver_baton_t
+{
+ svn_mergeinfo_t *mergeinfo;
+ apr_pool_t *result_pool;
+} mergeinfo_receiver_baton_t;
+
+static svn_error_t *
+mergeinfo_receiver(const char *path,
+ svn_mergeinfo_t mergeinfo,
+ void *baton,
+ apr_pool_t *scratch_pool)
{
- return svn_error_trace(root->vtable->get_mergeinfo(catalog, root, paths,
- inherit,
- include_descendants,
- TRUE, pool, pool));
+ mergeinfo_receiver_baton_t *b = baton;
+ *b->mergeinfo = svn_mergeinfo_dup(mergeinfo, b->result_pool);
+
+ return SVN_NO_ERROR;
}
svn_error_t *
@@ -1293,15 +1424,19 @@ svn_fs__get_mergeinfo_for_path(svn_mergeinfo_t *mergeinfo,
{
apr_array_header_t *paths
= apr_array_make(scratch_pool, 1, sizeof(const char *));
- svn_mergeinfo_catalog_t catalog;
+
+ mergeinfo_receiver_baton_t baton;
+ baton.mergeinfo = mergeinfo;
+ baton.result_pool = result_pool;
APR_ARRAY_PUSH(paths, const char *) = path;
- SVN_ERR(svn_fs_get_mergeinfo2(&catalog, root, paths,
+ *mergeinfo = NULL;
+ SVN_ERR(svn_fs_get_mergeinfo3(root, paths,
inherit, FALSE /*include_descendants*/,
adjust_inherited_mergeinfo,
- result_pool, scratch_pool));
- *mergeinfo = svn_hash_gets(catalog, path);
+ mergeinfo_receiver, &baton,
+ scratch_pool));
return SVN_NO_ERROR;
}
@@ -1390,36 +1525,17 @@ svn_fs_file_checksum(svn_checksum_t **checksum,
if (force && (*checksum == NULL || (*checksum)->kind != kind))
{
- svn_stream_t *contents, *checksum_contents;
+ svn_stream_t *contents;
SVN_ERR(svn_fs_file_contents(&contents, root, path, pool));
- checksum_contents = svn_stream_checksummed2(contents, checksum, NULL,
- kind, TRUE, pool);
-
- /* This will force a read of any remaining data (which is all of it in
- this case) and dump the checksum into checksum->digest. */
- SVN_ERR(svn_stream_close(checksum_contents));
+ SVN_ERR(svn_stream_contents_checksum(checksum, contents, kind,
+ pool, pool));
}
return SVN_NO_ERROR;
}
svn_error_t *
-svn_fs_file_md5_checksum(unsigned char digest[],
- svn_fs_root_t *root,
- const char *path,
- apr_pool_t *pool)
-{
- svn_checksum_t *md5sum;
-
- SVN_ERR(svn_fs_file_checksum(&md5sum, svn_checksum_md5, root, path, TRUE,
- pool));
- memcpy(digest, md5sum->digest, APR_MD5_DIGESTSIZE);
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
svn_fs_file_contents(svn_stream_t **contents, svn_fs_root_t *root,
const char *path, apr_pool_t *pool)
{
@@ -1554,19 +1670,39 @@ svn_fs_deltify_revision(svn_fs_t *fs, svn_revnum_t revision, apr_pool_t *pool)
}
svn_error_t *
-svn_fs_revision_prop(svn_string_t **value_p, svn_fs_t *fs, svn_revnum_t rev,
- const char *propname, apr_pool_t *pool)
+svn_fs_refresh_revision_props(svn_fs_t *fs,
+ apr_pool_t *scratch_pool)
+{
+ return svn_error_trace(fs->vtable->refresh_revprops(fs, scratch_pool));
+}
+
+svn_error_t *
+svn_fs_revision_prop2(svn_string_t **value_p,
+ svn_fs_t *fs,
+ svn_revnum_t rev,
+ const char *propname,
+ svn_boolean_t refresh,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
return svn_error_trace(fs->vtable->revision_prop(value_p, fs, rev,
- propname, pool));
+ propname, refresh,
+ result_pool,
+ scratch_pool));
}
svn_error_t *
-svn_fs_revision_proplist(apr_hash_t **table_p, svn_fs_t *fs, svn_revnum_t rev,
- apr_pool_t *pool)
+svn_fs_revision_proplist2(apr_hash_t **table_p,
+ svn_fs_t *fs,
+ svn_revnum_t rev,
+ svn_boolean_t refresh,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
return svn_error_trace(fs->vtable->revision_proplist(table_p, fs, rev,
- pool));
+ refresh,
+ result_pool,
+ scratch_pool));
}
svn_error_t *
@@ -1593,6 +1729,64 @@ svn_fs_get_file_delta_stream(svn_txdelta_stream_t **stream_p,
}
svn_error_t *
+svn_fs__get_deleted_node(svn_fs_root_t **node_root,
+ const char **node_path,
+ svn_fs_root_t *root,
+ const char *path,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ const char *parent_path, *name;
+ svn_fs_root_t *copy_root;
+ const char *copy_path;
+
+ /* History traversal does not work with transaction roots.
+ * Therefore, do it "by hand". */
+
+ /* If the parent got copied in ROOT, PATH got copied with it.
+ * Otherwise, we will find the node at PATH in the revision prior to ROOT.
+ */
+ svn_fspath__split(&parent_path, &name, path, scratch_pool);
+ SVN_ERR(svn_fs_closest_copy(&copy_root, &copy_path, root, parent_path,
+ scratch_pool));
+
+ /* Copied in ROOT? */
+ if ( copy_root
+ && ( svn_fs_revision_root_revision(copy_root)
+ == svn_fs_revision_root_revision(root)))
+ {
+ svn_revnum_t copyfrom_rev;
+ const char *copyfrom_path;
+ const char *rel_path;
+ SVN_ERR(svn_fs_copied_from(&copyfrom_rev, &copyfrom_path,
+ copy_root, copy_path, scratch_pool));
+
+ SVN_ERR(svn_fs_revision_root(node_root, svn_fs_root_fs(root),
+ copyfrom_rev, result_pool));
+ rel_path = svn_fspath__skip_ancestor(copy_path, path);
+ *node_path = svn_fspath__join(copyfrom_path, rel_path, result_pool);
+ }
+ else
+ {
+ svn_revnum_t revision;
+ svn_revnum_t previous_rev;
+
+ /* Determine the latest revision before ROOT. */
+ revision = svn_fs_revision_root_revision(root);
+ if (SVN_IS_VALID_REVNUM(revision))
+ previous_rev = revision - 1;
+ else
+ previous_rev = svn_fs_txn_root_base_revision(root);
+
+ SVN_ERR(svn_fs_revision_root(node_root, svn_fs_root_fs(root),
+ previous_rev, result_pool));
+ *node_path = apr_pstrdup(result_pool, path);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
svn_fs_get_uuid(svn_fs_t *fs, const char **uuid, apr_pool_t *pool)
{
/* If you change this, consider changing svn_fs__identifier(). */
@@ -1662,20 +1856,24 @@ svn_fs_lock_many(svn_fs_t *fs,
target->token, "opaquelocktoken");
if (!err)
- for (c = target->token; *c && !err; c++)
- if (! svn_ctype_isascii(*c) || svn_ctype_iscntrl(*c))
+ {
+ for (c = target->token; *c && !err; c++)
+ if (! svn_ctype_isascii(*c) || svn_ctype_iscntrl(*c))
+ err = svn_error_createf(
+ SVN_ERR_FS_BAD_LOCK_TOKEN, NULL,
+ _("Lock token '%s' is not ASCII or is a "
+ "control character at byte %u"),
+ target->token,
+ (unsigned)(c - target->token));
+
+ /* strlen(token) == c - token. */
+ if (!err && !svn_xml_is_xml_safe(target->token,
+ c - target->token))
err = svn_error_createf(
- SVN_ERR_FS_BAD_LOCK_TOKEN, NULL,
- _("Lock token '%s' is not ASCII or is a "
- "control character at byte %u"),
- target->token,
- (unsigned)(c - target->token));
-
- /* strlen(token) == c - token. */
- if (!err && !svn_xml_is_xml_safe(target->token, c - target->token))
- err = svn_error_createf(SVN_ERR_FS_BAD_LOCK_TOKEN, NULL,
- _("Lock token URI '%s' is not XML-safe"),
- target->token);
+ SVN_ERR_FS_BAD_LOCK_TOKEN, NULL,
+ _("Lock token URI '%s' is not XML-safe"),
+ target->token);
+ }
}
if (err)
@@ -1770,8 +1968,7 @@ svn_fs_lock_target_create(const char *token,
svn_revnum_t current_rev,
apr_pool_t *result_pool)
{
- svn_fs_lock_target_t *target = apr_palloc(result_pool,
- sizeof(svn_fs_lock_target_t));
+ svn_fs_lock_target_t *target = apr_palloc(result_pool, sizeof(*target));
target->token = token;
target->current_rev = current_rev;
@@ -1858,15 +2055,6 @@ svn_fs_history_prev2(svn_fs_history_t **prev_history_p,
}
svn_error_t *
-svn_fs_history_prev(svn_fs_history_t **prev_history_p,
- svn_fs_history_t *history, svn_boolean_t cross_copies,
- apr_pool_t *pool)
-{
- return svn_error_trace(history->vtable->prev(prev_history_p, history,
- cross_copies, pool, pool));
-}
-
-svn_error_t *
svn_fs_history_location(const char **path, svn_revnum_t *revision,
svn_fs_history_t *history, apr_pool_t *pool)
{
@@ -1965,6 +2153,28 @@ svn_fs_path_change2_create(const svn_fs_id_t *node_rev_id,
return svn_fs__path_change_create_internal(node_rev_id, change_kind, pool);
}
+svn_fs_path_change3_t *
+svn_fs_path_change3_create(svn_fs_path_change_kind_t change_kind,
+ apr_pool_t *result_pool)
+{
+ return svn_fs__path_change_create_internal2(change_kind, result_pool);
+}
+
+svn_fs_path_change3_t *
+svn_fs_path_change3_dup(svn_fs_path_change3_t *change,
+ apr_pool_t *result_pool)
+{
+ svn_fs_path_change3_t *copy = apr_pmemdup(result_pool, change,
+ sizeof(*copy));
+
+ copy->path.data = apr_pstrmemdup(result_pool, copy->path.data,
+ copy->path.len);
+ if (copy->copyfrom_path)
+ copy->copyfrom_path = apr_pstrdup(result_pool, change->copyfrom_path);
+
+ return copy;
+}
+
/* Return the library version number. */
const svn_version_t *
svn_fs_version(void)
diff --git a/subversion/libsvn_fs/fs-loader.h b/subversion/libsvn_fs/fs-loader.h
index db83744257491..0712c23307d9d 100644
--- a/subversion/libsvn_fs/fs-loader.h
+++ b/subversion/libsvn_fs/fs-loader.h
@@ -22,8 +22,8 @@
*/
-#ifndef LIBSVN_FS_FS_H
-#define LIBSVN_FS_FS_H
+#ifndef LIBSVN_FS_LOADER_H
+#define LIBSVN_FS_LOADER_H
#include "svn_types.h"
#include "svn_fs.h"
@@ -79,11 +79,11 @@ typedef struct fs_library_vtable_t
parameter for allocating fs-global objects such as an env cache. */
svn_error_t *(*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);
svn_error_t *(*open_fs)(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);
/* open_for_recovery() is like open(), but used to fill in an fs pointer
that will be passed to recover(). We assume that the open() method
@@ -184,15 +184,9 @@ typedef svn_error_t *(*fs_init_func_t)(const svn_version_t *loader_version,
to the create and open functions and these init functions (as well
as the open and create functions) are globally serialized so that
they have exclusive access to the common_pool. */
-svn_error_t *svn_fs_base__init(const svn_version_t *loader_version,
- fs_library_vtable_t **vtable,
- apr_pool_t* common_pool);
-svn_error_t *svn_fs_fs__init(const svn_version_t *loader_version,
- fs_library_vtable_t **vtable,
- apr_pool_t* common_pool);
-svn_error_t *svn_fs_x__init(const svn_version_t *loader_version,
- fs_library_vtable_t **vtable,
- apr_pool_t* common_pool);
+#include "../libsvn_fs_base/fs_init.h"
+#include "../libsvn_fs_fs/fs_init.h"
+#include "../libsvn_fs_x/fs_init.h"
@@ -202,11 +196,17 @@ typedef struct fs_vtable_t
{
svn_error_t *(*youngest_rev)(svn_revnum_t *youngest_p, svn_fs_t *fs,
apr_pool_t *pool);
+ svn_error_t *(*refresh_revprops)(svn_fs_t *fs, apr_pool_t *scratch_pool);
svn_error_t *(*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 *(*revision_proplist)(apr_hash_t **table_p, svn_fs_t *fs,
- svn_revnum_t rev, apr_pool_t *pool);
+ svn_revnum_t rev,
+ svn_boolean_t refresh,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
svn_error_t *(*change_rev_prop)(svn_fs_t *fs, svn_revnum_t rev,
const char *name,
const svn_string_t *const *old_value_p,
@@ -301,6 +301,10 @@ typedef struct root_vtable_t
svn_error_t *(*paths_changed)(apr_hash_t **changed_paths_p,
svn_fs_root_t *root,
apr_pool_t *pool);
+ svn_error_t *(*report_changes)(svn_fs_path_change_iterator_t **iterator,
+ svn_fs_root_t *root,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
/* Generic node operations */
svn_error_t *(*check_path)(svn_node_kind_t *kind_p, svn_fs_root_t *root,
@@ -415,17 +419,24 @@ typedef struct root_vtable_t
const char *ancestor_path,
apr_pool_t *pool);
/* Mergeinfo. */
- svn_error_t *(*get_mergeinfo)(svn_mergeinfo_catalog_t *catalog,
- svn_fs_root_t *root,
+ svn_error_t *(*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);
} root_vtable_t;
+typedef struct changes_iterator_vtable_t
+{
+ svn_error_t *(*get)(svn_fs_path_change3_t **change,
+ svn_fs_path_change_iterator_t *iterator);
+} changes_iterator_vtable_t;
+
+
typedef struct history_vtable_t
{
svn_error_t *(*prev)(svn_fs_history_t **prev_history_p,
@@ -449,7 +460,7 @@ typedef struct id_vtable_t
/*** Definitions of the abstract FS object types ***/
/* These are transaction properties that correspond to the bitfields
- in the 'flags' argument to svn_fs_lock(). */
+ in the 'flags' argument to svn_fs_begin_txn2(). */
#define SVN_FS__PROP_TXN_CHECK_LOCKS SVN_PROP_PREFIX "check-locks"
#define SVN_FS__PROP_TXN_CHECK_OOD SVN_PROP_PREFIX "check-ood"
/* Set to "0" at the start of the txn, to "1" when svn:date changes. */
@@ -474,7 +485,7 @@ struct svn_fs_t
svn_fs_access_t *access_ctx;
/* FSAP-specific vtable and private data */
- fs_vtable_t *vtable;
+ const fs_vtable_t *vtable;
void *fsap_data;
/* UUID, stored by open(), create(), and set_uuid(). */
@@ -496,7 +507,7 @@ struct svn_fs_txn_t
const char *id;
/* FSAP-specific vtable and private data */
- txn_vtable_t *vtable;
+ const txn_vtable_t *vtable;
void *fsap_data;
};
@@ -524,15 +535,21 @@ struct svn_fs_root_t
svn_revnum_t rev;
/* FSAP-specific vtable and private data */
- root_vtable_t *vtable;
+ const root_vtable_t *vtable;
void *fsap_data;
};
+struct svn_fs_path_change_iterator_t
+{
+ /* FSAP-specific vtable and private data */
+ const changes_iterator_vtable_t *vtable;
+ void *fsap_data;
+};
struct svn_fs_history_t
{
/* FSAP-specific vtable and private data */
- history_vtable_t *vtable;
+ const history_vtable_t *vtable;
void *fsap_data;
};
@@ -540,7 +557,7 @@ struct svn_fs_history_t
struct svn_fs_id_t
{
/* FSAP-specific vtable and private data */
- id_vtable_t *vtable;
+ const id_vtable_t *vtable;
void *fsap_data;
};
@@ -569,4 +586,4 @@ struct svn_fs_lock_target_t
}
#endif /* __cplusplus */
-#endif
+#endif /* LIBSVN_FS_LOADER_H */