diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-08-05 16:22:51 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-08-05 16:22:51 +0000 |
commit | cf46733632c7279a9fd0fe6ce26f9185a4ae82a9 (patch) | |
tree | da27775a2161723ef342e91af41a8b51fedef405 /subversion/libsvn_repos/log.c | |
parent | bb0ef45f7c46b0ae221b26265ef98a768c33f820 (diff) | |
download | subversion-tarball-master.tar.gz |
subversion-1.9.7HEADsubversion-1.9.7master
Diffstat (limited to 'subversion/libsvn_repos/log.c')
-rw-r--r-- | subversion/libsvn_repos/log.c | 634 |
1 files changed, 361 insertions, 273 deletions
diff --git a/subversion/libsvn_repos/log.c b/subversion/libsvn_repos/log.c index 8ca870b..82caf02 100644 --- a/subversion/libsvn_repos/log.c +++ b/subversion/libsvn_repos/log.c @@ -39,8 +39,10 @@ #include "svn_mergeinfo.h" #include "repos.h" #include "private/svn_fspath.h" +#include "private/svn_fs_private.h" #include "private/svn_mergeinfo_private.h" #include "private/svn_subr_private.h" +#include "private/svn_sorts_private.h" @@ -80,14 +82,11 @@ svn_repos_check_revision_access(svn_repos_revision_access_level_t *access_level, subpool = svn_pool_create(pool); for (hi = apr_hash_first(pool, changes); hi; hi = apr_hash_next(hi)) { - const void *key; - void *val; - svn_fs_path_change2_t *change; + const char *key = apr_hash_this_key(hi); + svn_fs_path_change2_t *change = apr_hash_this_val(hi); svn_boolean_t readable; svn_pool_clear(subpool); - apr_hash_this(hi, &key, NULL, &val); - change = val; SVN_ERR(authz_read_func(&readable, rev_root, key, authz_read_baton, subpool)); @@ -169,18 +168,23 @@ svn_repos_check_revision_access(svn_repos_revision_access_level_t *access_level, * AUTHZ_READ_BATON and FS) to check whether each changed-path (and * copyfrom_path) is readable: * + * - If absolutely every changed-path (and copyfrom_path) is + * readable, then return the full CHANGED hash, and set + * *ACCESS_LEVEL to svn_repos_revision_access_full. + * * - If some paths are readable and some are not, then silently - * omit the unreadable paths from the CHANGED hash, and return - * SVN_ERR_AUTHZ_PARTIALLY_READABLE. + * omit the unreadable paths from the CHANGED hash, and set + * *ACCESS_LEVEL to svn_repos_revision_access_partial. * * - If absolutely every changed-path (and copyfrom_path) is - * unreadable, then return an empty CHANGED hash and - * SVN_ERR_AUTHZ_UNREADABLE. (This is to distinguish a revision - * which truly has no changed paths from a revision in which all - * paths are unreadable.) + * unreadable, then return an empty CHANGED hash, and set + * *ACCESS_LEVEL to svn_repos_revision_access_none. (This is + * to distinguish a revision which truly has no changed paths + * from a revision in which all paths are unreadable.) */ static svn_error_t * -detect_changed(apr_hash_t **changed, +detect_changed(svn_repos_revision_access_level_t *access_level, + apr_hash_t **changed, svn_fs_root_t *root, svn_fs_t *fs, apr_hash_t *prefetched_changes, @@ -190,39 +194,50 @@ detect_changed(apr_hash_t **changed, { apr_hash_t *changes = prefetched_changes; apr_hash_index_t *hi; - apr_pool_t *subpool; + apr_pool_t *iterpool; svn_boolean_t found_readable = FALSE; svn_boolean_t found_unreadable = FALSE; - *changed = svn_hash__make(pool); + /* If we create the CHANGES hash ourselves, we can reuse it as the + * result hash as it contains the exact same keys - but with _all_ + * values being replaced by structs of a different type. */ if (changes == NULL) - SVN_ERR(svn_fs_paths_changed2(&changes, root, pool)); + { + SVN_ERR(svn_fs_paths_changed2(&changes, root, pool)); - if (apr_hash_count(changes) == 0) - /* No paths changed in this revision? Uh, sure, I guess the - revision is readable, then. */ - return SVN_NO_ERROR; + /* If we are going to filter the results, we won't use the exact + * same keys but put them into a new hash. */ + if (authz_read_func) + *changed = svn_hash__make(pool); + else + *changed = changes; + } + else + { + *changed = svn_hash__make(pool); + } - subpool = svn_pool_create(pool); + if (apr_hash_count(changes) == 0) + { + /* No paths changed in this revision? Uh, sure, I guess the + revision is readable, then. */ + *access_level = svn_repos_revision_access_full; + return SVN_NO_ERROR; + } + iterpool = svn_pool_create(pool); for (hi = apr_hash_first(pool, changes); hi; hi = apr_hash_next(hi)) { /* NOTE: Much of this loop is going to look quite similar to svn_repos_check_revision_access(), but we have to do more things here, so we'll live with the duplication. */ - const void *key; - void *val; - svn_fs_path_change2_t *change; - const char *path; + const char *path = apr_hash_this_key(hi); + apr_ssize_t path_len = apr_hash_this_key_len(hi); + svn_fs_path_change2_t *change = apr_hash_this_val(hi); char action; svn_log_changed_path2_t *item; - svn_pool_clear(subpool); - - /* KEY will be the path, VAL the change. */ - apr_hash_this(hi, &key, NULL, &val); - path = (const char *) key; - change = val; + svn_pool_clear(iterpool); /* Skip path if unreadable. */ if (authz_read_func) @@ -230,7 +245,7 @@ detect_changed(apr_hash_t **changed, svn_boolean_t readable; SVN_ERR(authz_read_func(&readable, root, path, - authz_read_baton, subpool)); + authz_read_baton, iterpool)); if (! readable) { found_unreadable = TRUE; @@ -288,24 +303,26 @@ detect_changed(apr_hash_t **changed, svn_revnum_t prev_rev; const char *parent_path, *name; - svn_fspath__split(&parent_path, &name, path, subpool); + svn_fspath__split(&parent_path, &name, path, iterpool); - SVN_ERR(svn_fs_node_history(&history, root, parent_path, - subpool)); + SVN_ERR(svn_fs_node_history2(&history, root, parent_path, + iterpool, iterpool)); /* Two calls because the first call returns the original revision as the deleted child means it is 'interesting' */ - SVN_ERR(svn_fs_history_prev(&history, history, TRUE, subpool)); - SVN_ERR(svn_fs_history_prev(&history, history, TRUE, subpool)); + SVN_ERR(svn_fs_history_prev2(&history, history, TRUE, iterpool, + iterpool)); + SVN_ERR(svn_fs_history_prev2(&history, history, TRUE, iterpool, + iterpool)); SVN_ERR(svn_fs_history_location(&parent_path, &prev_rev, history, - subpool)); - SVN_ERR(svn_fs_revision_root(&check_root, fs, prev_rev, subpool)); - check_path = svn_fspath__join(parent_path, name, subpool); + iterpool)); + SVN_ERR(svn_fs_revision_root(&check_root, fs, prev_rev, iterpool)); + check_path = svn_fspath__join(parent_path, name, iterpool); } SVN_ERR(svn_fs_check_path(&item->node_kind, check_root, check_path, - subpool)); + iterpool)); } @@ -318,8 +335,11 @@ detect_changed(apr_hash_t **changed, we will follow the DAG from ROOT to PATH and that requires actually reading the directories along the way. */ if (!change->copyfrom_known) - SVN_ERR(svn_fs_copied_from(©from_rev, ©from_path, - root, path, subpool)); + { + SVN_ERR(svn_fs_copied_from(©from_rev, ©from_path, + root, path, iterpool)); + copyfrom_path = apr_pstrdup(pool, copyfrom_path); + } if (copyfrom_path && SVN_IS_VALID_REVNUM(copyfrom_rev)) { @@ -330,37 +350,43 @@ detect_changed(apr_hash_t **changed, svn_fs_root_t *copyfrom_root; SVN_ERR(svn_fs_revision_root(©from_root, fs, - copyfrom_rev, subpool)); + copyfrom_rev, iterpool)); SVN_ERR(authz_read_func(&readable, copyfrom_root, copyfrom_path, - authz_read_baton, subpool)); + authz_read_baton, iterpool)); if (! readable) found_unreadable = TRUE; } if (readable) { - item->copyfrom_path = apr_pstrdup(pool, copyfrom_path); + item->copyfrom_path = copyfrom_path; item->copyfrom_rev = copyfrom_rev; } } } - svn_hash_sets(*changed, apr_pstrdup(pool, path), item); + + apr_hash_set(*changed, path, path_len, item); } - svn_pool_destroy(subpool); + svn_pool_destroy(iterpool); if (! found_readable) - /* Every changed-path was unreadable. */ - return svn_error_create(SVN_ERR_AUTHZ_UNREADABLE, - NULL, NULL); - - if (found_unreadable) - /* At least one changed-path was unreadable. */ - return svn_error_create(SVN_ERR_AUTHZ_PARTIALLY_READABLE, - NULL, NULL); + { + /* Every changed-path was unreadable. */ + *access_level = svn_repos_revision_access_none; + } + else if (found_unreadable) + { + /* At least one changed-path was unreadable. */ + *access_level = svn_repos_revision_access_partial; + } + else + { + /* Every changed-path was readable. */ + *access_level = svn_repos_revision_access_full; + } - /* Every changed-path was readable. */ return SVN_NO_ERROR; } @@ -410,7 +436,8 @@ get_history(struct path_info *info, svn_repos_authz_func_t authz_read_func, void *authz_read_baton, svn_revnum_t start, - apr_pool_t *pool) + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { svn_fs_root_t *history_root = NULL; svn_fs_history_t *hist; @@ -421,27 +448,30 @@ get_history(struct path_info *info, { subpool = info->newpool; - SVN_ERR(svn_fs_history_prev(&info->hist, info->hist, ! strict, subpool)); + SVN_ERR(svn_fs_history_prev2(&info->hist, info->hist, ! strict, + subpool, scratch_pool)); hist = info->hist; } else { - subpool = svn_pool_create(pool); + subpool = svn_pool_create(result_pool); /* Open the history located at the last rev we were at. */ SVN_ERR(svn_fs_revision_root(&history_root, fs, info->history_rev, subpool)); - SVN_ERR(svn_fs_node_history(&hist, history_root, info->path->data, - subpool)); + SVN_ERR(svn_fs_node_history2(&hist, history_root, info->path->data, + subpool, scratch_pool)); - SVN_ERR(svn_fs_history_prev(&hist, hist, ! strict, subpool)); + SVN_ERR(svn_fs_history_prev2(&hist, hist, ! strict, subpool, + scratch_pool)); if (info->first_time) info->first_time = FALSE; else - SVN_ERR(svn_fs_history_prev(&hist, hist, ! strict, subpool)); + SVN_ERR(svn_fs_history_prev2(&hist, hist, ! strict, subpool, + scratch_pool)); } if (! hist) @@ -476,11 +506,11 @@ get_history(struct path_info *info, svn_boolean_t readable; SVN_ERR(svn_fs_revision_root(&history_root, fs, info->history_rev, - subpool)); + scratch_pool)); SVN_ERR(authz_read_func(&readable, history_root, info->path->data, authz_read_baton, - subpool)); + scratch_pool)); if (! readable) info->done = TRUE; } @@ -518,7 +548,8 @@ check_history(svn_boolean_t *changed, svn_repos_authz_func_t authz_read_func, void *authz_read_baton, svn_revnum_t start, - apr_pool_t *pool) + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { /* If we're already done with histories for this path, don't try to fetch any more. */ @@ -537,7 +568,7 @@ check_history(svn_boolean_t *changed, rev where this path was changed. */ *changed = TRUE; return get_history(info, fs, strict, authz_read_func, - authz_read_baton, start, pool); + authz_read_baton, start, result_pool, scratch_pool); } /* Return the next interesting revision in our list of HISTORIES. */ @@ -562,7 +593,7 @@ next_history_rev(const apr_array_header_t *histories) /* Set *DELETED_MERGEINFO_CATALOG and *ADDED_MERGEINFO_CATALOG to catalogs describing how mergeinfo values on paths (which are the - keys of those catalogs) were changed in REV. If *PREFETCHED_CAHNGES + keys of those catalogs) were changed in REV. If *PREFETCHED_CHANGES already contains the changed paths for REV, use that. Otherwise, request that data and return it in *PREFETCHED_CHANGES. */ /* ### TODO: This would make a *great*, useful public function, @@ -575,11 +606,12 @@ fs_mergeinfo_changed(svn_mergeinfo_catalog_t *deleted_mergeinfo_catalog, svn_revnum_t rev, apr_pool_t *result_pool, apr_pool_t *scratch_pool) - { svn_fs_root_t *root; apr_pool_t *iterpool; apr_hash_index_t *hi; + svn_boolean_t any_mergeinfo = FALSE; + svn_boolean_t any_copy = FALSE; /* Initialize return variables. */ *deleted_mergeinfo_catalog = svn_hash__make(result_pool); @@ -595,8 +627,33 @@ fs_mergeinfo_changed(svn_mergeinfo_catalog_t *deleted_mergeinfo_catalog, if (*prefetched_changes == NULL) SVN_ERR(svn_fs_paths_changed2(prefetched_changes, root, scratch_pool)); - /* No changed paths? We're done. */ - if (apr_hash_count(*prefetched_changes) == 0) + /* Look for copies and (potential) mergeinfo changes. + We will use both flags to take shortcuts further down the road. */ + for (hi = apr_hash_first(scratch_pool, *prefetched_changes); + hi; + hi = apr_hash_next(hi)) + { + svn_fs_path_change2_t *change = apr_hash_this_val(hi); + + /* If there was a prop change and we are not positive that _no_ + mergeinfo change happened, we must assume that it might have. */ + if (change->mergeinfo_mod != svn_tristate_false && change->prop_mod) + any_mergeinfo = TRUE; + + switch (change->change_kind) + { + case svn_fs_path_change_add: + case svn_fs_path_change_replace: + any_copy = TRUE; + break; + + default: + break; + } + } + + /* No potential mergeinfo changes? We're done. */ + if (! any_mergeinfo) return SVN_NO_ERROR; /* Loop over changes, looking for anything that might carry an @@ -607,25 +664,27 @@ fs_mergeinfo_changed(svn_mergeinfo_catalog_t *deleted_mergeinfo_catalog, hi; hi = apr_hash_next(hi)) { - const void *key; - void *val; - svn_fs_path_change2_t *change; - const char *changed_path, *base_path = NULL; + const char *changed_path; + svn_fs_path_change2_t *change = apr_hash_this_val(hi); + const char *base_path = NULL; svn_revnum_t base_rev = SVN_INVALID_REVNUM; svn_fs_root_t *base_root = NULL; svn_string_t *prev_mergeinfo_value = NULL, *mergeinfo_value; - svn_pool_clear(iterpool); + /* Cheap pre-checks that don't require memory allocation etc. */ - /* KEY will be the path, VAL the change. */ - apr_hash_this(hi, &key, NULL, &val); - changed_path = key; - change = val; + /* No mergeinfo change? -> nothing to do here. */ + if (change->mergeinfo_mod == svn_tristate_false) + continue; /* If there was no property change on this item, ignore it. */ if (! change->prop_mod) continue; + /* Begin actual processing */ + changed_path = apr_hash_this_key(hi); + svn_pool_clear(iterpool); + switch (change->change_kind) { @@ -634,25 +693,6 @@ fs_mergeinfo_changed(svn_mergeinfo_catalog_t *deleted_mergeinfo_catalog, ### difference would be the fallback case (path/rev-1 for ### modifies, NULL otherwise). -- cmpilato */ - /* If the path was added or replaced, see if it was created via - copy. If so, that will tell us where its previous location - was. If not, there's no previous location to examine. */ - case svn_fs_path_change_add: - case svn_fs_path_change_replace: - { - const char *copyfrom_path; - svn_revnum_t copyfrom_rev; - - SVN_ERR(svn_fs_copied_from(©from_rev, ©from_path, - root, changed_path, iterpool)); - if (copyfrom_path && SVN_IS_VALID_REVNUM(copyfrom_rev)) - { - base_path = apr_pstrdup(scratch_pool, copyfrom_path); - base_rev = copyfrom_rev; - } - break; - } - /* If the path was merely modified, see if its previous location was affected by a copy which happened in this revision before assuming it holds the same path it did the @@ -661,15 +701,26 @@ fs_mergeinfo_changed(svn_mergeinfo_catalog_t *deleted_mergeinfo_catalog, { svn_revnum_t appeared_rev; - SVN_ERR(svn_repos__prev_location(&appeared_rev, &base_path, - &base_rev, fs, rev, - changed_path, iterpool)); - - /* If this path isn't the result of a copy that occurred - in this revision, we can find the previous version of - it in REV - 1 at the same path. */ - if (! (base_path && SVN_IS_VALID_REVNUM(base_rev) - && (appeared_rev == rev))) + /* If there were no copies in this revision, the path will have + existed in the previous rev. Otherwise, we might just got + copied here and need to check for that eventuality. */ + if (any_copy) + { + SVN_ERR(svn_repos__prev_location(&appeared_rev, &base_path, + &base_rev, fs, rev, + changed_path, iterpool)); + + /* If this path isn't the result of a copy that occurred + in this revision, we can find the previous version of + it in REV - 1 at the same path. */ + if (! (base_path && SVN_IS_VALID_REVNUM(base_rev) + && (appeared_rev == rev))) + { + base_path = changed_path; + base_rev = rev - 1; + } + } + else { base_path = changed_path; base_rev = rev - 1; @@ -677,6 +728,26 @@ fs_mergeinfo_changed(svn_mergeinfo_catalog_t *deleted_mergeinfo_catalog, break; } + /* If the path was added or replaced, see if it was created via + copy. If so, set BASE_REV/BASE_PATH to its previous location. + If not, there's no previous location to examine -- leave + BASE_REV/BASE_PATH = -1/NULL. */ + case svn_fs_path_change_add: + case svn_fs_path_change_replace: + { + if (change->copyfrom_known) + { + base_rev = change->copyfrom_rev; + base_path = change->copyfrom_path; + } + else + { + SVN_ERR(svn_fs_copied_from(&base_rev, &base_path, + root, changed_path, iterpool)); + } + break; + } + /* We don't care about any of the other cases. */ case svn_fs_path_change_delete: case svn_fs_path_change_reset: @@ -704,22 +775,23 @@ fs_mergeinfo_changed(svn_mergeinfo_catalog_t *deleted_mergeinfo_catalog, if (! (mergeinfo_value || prev_mergeinfo_value)) continue; + /* Mergeinfo on both sides but it did not change? Skip that too. */ + if ( mergeinfo_value && prev_mergeinfo_value + && svn_string_compare(mergeinfo_value, prev_mergeinfo_value)) + continue; + /* If mergeinfo was explicitly added or removed on this path, we need to check to see if that was a real semantic change of meaning. So, fill in the "missing" mergeinfo value with the inherited mergeinfo for that path/revision. */ if (prev_mergeinfo_value && (! mergeinfo_value)) { - apr_array_header_t *query_paths = - apr_array_make(iterpool, 1, sizeof(const char *)); svn_mergeinfo_t tmp_mergeinfo; - svn_mergeinfo_catalog_t tmp_catalog; - APR_ARRAY_PUSH(query_paths, const char *) = changed_path; - SVN_ERR(svn_fs_get_mergeinfo2(&tmp_catalog, root, - query_paths, svn_mergeinfo_inherited, - FALSE, TRUE, iterpool, iterpool)); - tmp_mergeinfo = svn_hash_gets(tmp_catalog, changed_path); + SVN_ERR(svn_fs__get_mergeinfo_for_path(&tmp_mergeinfo, + root, changed_path, + svn_mergeinfo_inherited, TRUE, + iterpool, iterpool)); if (tmp_mergeinfo) SVN_ERR(svn_mergeinfo_to_string(&mergeinfo_value, tmp_mergeinfo, @@ -728,29 +800,23 @@ fs_mergeinfo_changed(svn_mergeinfo_catalog_t *deleted_mergeinfo_catalog, else if (mergeinfo_value && (! prev_mergeinfo_value) && base_path && SVN_IS_VALID_REVNUM(base_rev)) { - apr_array_header_t *query_paths = - apr_array_make(iterpool, 1, sizeof(const char *)); svn_mergeinfo_t tmp_mergeinfo; - svn_mergeinfo_catalog_t tmp_catalog; - APR_ARRAY_PUSH(query_paths, const char *) = base_path; - SVN_ERR(svn_fs_get_mergeinfo2(&tmp_catalog, base_root, - query_paths, svn_mergeinfo_inherited, - FALSE, TRUE, iterpool, iterpool)); - tmp_mergeinfo = svn_hash_gets(tmp_catalog, base_path); + SVN_ERR(svn_fs__get_mergeinfo_for_path(&tmp_mergeinfo, + base_root, base_path, + svn_mergeinfo_inherited, TRUE, + iterpool, iterpool)); if (tmp_mergeinfo) SVN_ERR(svn_mergeinfo_to_string(&prev_mergeinfo_value, tmp_mergeinfo, iterpool)); } - /* If the old and new mergeinfo differ in any way, store the - before and after mergeinfo values in our return hashes. */ - if ((prev_mergeinfo_value && (! mergeinfo_value)) - || ((! prev_mergeinfo_value) && mergeinfo_value) - || (prev_mergeinfo_value && mergeinfo_value - && (! svn_string_compare(mergeinfo_value, - prev_mergeinfo_value)))) + /* Old and new mergeinfo probably differ in some way (we already + checked for textual equality further up). Store the before and + after mergeinfo values in our return hashes. They may still be + equal as manual intervention may have only changed the formatting + but not the relevant contents. */ { svn_mergeinfo_t prev_mergeinfo = NULL, mergeinfo = NULL; svn_mergeinfo_t deleted, added; @@ -781,10 +847,9 @@ fs_mergeinfo_changed(svn_mergeinfo_catalog_t *deleted_mergeinfo_catalog, /* Determine what (if any) mergeinfo for PATHS was modified in revision REV, returning the differences for added mergeinfo in *ADDED_MERGEINFO and deleted mergeinfo in *DELETED_MERGEINFO. - If *PREFETCHED_CAHNGES already contains the changed paths for + If *PREFETCHED_CHANGES already contains the changed paths for REV, use that. Otherwise, request that data and return it in - *PREFETCHED_CHANGES. - Use POOL for all allocations. */ + *PREFETCHED_CHANGES. */ static svn_error_t * get_combined_mergeinfo_changes(svn_mergeinfo_t *added_mergeinfo, svn_mergeinfo_t *deleted_mergeinfo, @@ -814,14 +879,12 @@ get_combined_mergeinfo_changes(svn_mergeinfo_t *added_mergeinfo, if (! paths->nelts) return SVN_NO_ERROR; - /* Create a work subpool and get a root for REV. */ - SVN_ERR(svn_fs_revision_root(&root, fs, rev, scratch_pool)); - /* Fetch the mergeinfo changes for REV. */ err = fs_mergeinfo_changed(&deleted_mergeinfo_catalog, &added_mergeinfo_catalog, prefetched_changes, - fs, rev, scratch_pool, scratch_pool); + fs, rev, + scratch_pool, scratch_pool); if (err) { if (err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR) @@ -842,7 +905,10 @@ get_combined_mergeinfo_changes(svn_mergeinfo_t *added_mergeinfo, if ( apr_hash_count(deleted_mergeinfo_catalog) == 0 && apr_hash_count(added_mergeinfo_catalog) == 0) return SVN_NO_ERROR; - + + /* Create a work subpool and get a root for REV. */ + SVN_ERR(svn_fs_revision_root(&root, fs, rev, scratch_pool)); + /* Check our PATHS for any changes to their inherited mergeinfo. (We deal with changes to mergeinfo directly *on* the paths in the following loop.) */ @@ -851,13 +917,10 @@ get_combined_mergeinfo_changes(svn_mergeinfo_t *added_mergeinfo, { const char *path = APR_ARRAY_IDX(paths, i, const char *); const char *prev_path; - apr_ssize_t klen; svn_revnum_t appeared_rev, prev_rev; svn_fs_root_t *prev_root; - svn_mergeinfo_catalog_t catalog, inherited_catalog; svn_mergeinfo_t prev_mergeinfo, mergeinfo, deleted, added, prev_inherited_mergeinfo, inherited_mergeinfo; - apr_array_header_t *query_paths; svn_pool_clear(iterpool); @@ -893,11 +956,10 @@ get_combined_mergeinfo_changes(svn_mergeinfo_t *added_mergeinfo, this path. Ignore not-found errors returned by the filesystem or invalid mergeinfo (Issue #3896).*/ SVN_ERR(svn_fs_revision_root(&prev_root, fs, prev_rev, iterpool)); - query_paths = apr_array_make(iterpool, 1, sizeof(const char *)); - APR_ARRAY_PUSH(query_paths, const char *) = prev_path; - err = svn_fs_get_mergeinfo2(&catalog, prev_root, query_paths, - svn_mergeinfo_inherited, FALSE, TRUE, - iterpool, iterpool); + err = svn_fs__get_mergeinfo_for_path(&prev_mergeinfo, + prev_root, prev_path, + svn_mergeinfo_inherited, TRUE, + iterpool, iterpool); if (err && (err->apr_err == SVN_ERR_FS_NOT_FOUND || err->apr_err == SVN_ERR_FS_NOT_DIRECTORY || err->apr_err == SVN_ERR_MERGEINFO_PARSE_ERROR)) @@ -917,31 +979,25 @@ get_combined_mergeinfo_changes(svn_mergeinfo_t *added_mergeinfo, To check for this we must fetch the "raw" previous inherited mergeinfo and the "raw" mergeinfo @REV then compare these. */ - SVN_ERR(svn_fs_get_mergeinfo2(&inherited_catalog, prev_root, query_paths, - svn_mergeinfo_nearest_ancestor, FALSE, - FALSE, /* adjust_inherited_mergeinfo */ - iterpool, iterpool)); - - klen = strlen(prev_path); - prev_mergeinfo = apr_hash_get(catalog, prev_path, klen); - prev_inherited_mergeinfo = apr_hash_get(inherited_catalog, prev_path, klen); + SVN_ERR(svn_fs__get_mergeinfo_for_path(&prev_inherited_mergeinfo, + prev_root, prev_path, + svn_mergeinfo_nearest_ancestor, + FALSE, /* adjust_inherited_mergeinfo */ + iterpool, iterpool)); /* Fetch the current mergeinfo (as of REV, and including inherited stuff) for this path. */ - APR_ARRAY_IDX(query_paths, 0, const char *) = path; - SVN_ERR(svn_fs_get_mergeinfo2(&catalog, root, query_paths, - svn_mergeinfo_inherited, FALSE, TRUE, - iterpool, iterpool)); + SVN_ERR(svn_fs__get_mergeinfo_for_path(&mergeinfo, + root, path, + svn_mergeinfo_inherited, TRUE, + iterpool, iterpool)); /* Issue #4022 again, fetch the raw inherited mergeinfo. */ - SVN_ERR(svn_fs_get_mergeinfo2(&inherited_catalog, root, query_paths, - svn_mergeinfo_nearest_ancestor, FALSE, - FALSE, /* adjust_inherited_mergeinfo */ - iterpool, iterpool)); - - klen = strlen(path); - mergeinfo = apr_hash_get(catalog, path, klen); - inherited_mergeinfo = apr_hash_get(inherited_catalog, path, klen); + SVN_ERR(svn_fs__get_mergeinfo_for_path(&inherited_mergeinfo, + root, path, + svn_mergeinfo_nearest_ancestor, + FALSE, /* adjust_inherited_mergeinfo */ + iterpool, iterpool)); if (!prev_mergeinfo && !mergeinfo) continue; @@ -965,7 +1021,7 @@ get_combined_mergeinfo_changes(svn_mergeinfo_t *added_mergeinfo, svn_boolean_t same_mergeinfo; SVN_ERR(svn_mergeinfo__equals(&same_mergeinfo, prev_inherited_mergeinfo, - FALSE, + NULL, TRUE, iterpool)); if (same_mergeinfo) continue; @@ -985,16 +1041,10 @@ get_combined_mergeinfo_changes(svn_mergeinfo_t *added_mergeinfo, for (hi = apr_hash_first(scratch_pool, added_mergeinfo_catalog); hi; hi = apr_hash_next(hi)) { - const void *key; - apr_ssize_t klen; - void *val; - const char *changed_path; - svn_mergeinfo_t added, deleted; - - /* The path is the key, the mergeinfo delta is the value. */ - apr_hash_this(hi, &key, &klen, &val); - changed_path = key; - added = val; + const char *changed_path = apr_hash_this_key(hi); + apr_ssize_t klen = apr_hash_this_key_len(hi); + svn_mergeinfo_t added = apr_hash_this_val(hi); + svn_mergeinfo_t deleted; for (i = 0; i < paths->nelts; i++) { @@ -1002,7 +1052,7 @@ get_combined_mergeinfo_changes(svn_mergeinfo_t *added_mergeinfo, if (! svn_fspath__skip_ancestor(path, changed_path)) continue; svn_pool_clear(iterpool); - deleted = apr_hash_get(deleted_mergeinfo_catalog, key, klen); + deleted = apr_hash_get(deleted_mergeinfo_catalog, changed_path, klen); SVN_ERR(svn_mergeinfo_merge2(*deleted_mergeinfo, svn_mergeinfo_dup(deleted, result_pool), result_pool, iterpool)); @@ -1033,6 +1083,7 @@ fill_log_entry(svn_log_entry_t *log_entry, { apr_hash_t *r_props, *changed_paths = NULL; svn_boolean_t get_revprops = TRUE, censor_revprops = FALSE; + svn_boolean_t want_revprops = !revprops || revprops->nelts; /* Discover changed paths if the user requested them or if we need to check that they are readable. */ @@ -1040,33 +1091,27 @@ fill_log_entry(svn_log_entry_t *log_entry, && (authz_read_func || discover_changed_paths)) { svn_fs_root_t *newroot; - svn_error_t *patherr; + svn_repos_revision_access_level_t access_level; SVN_ERR(svn_fs_revision_root(&newroot, fs, rev, pool)); - patherr = detect_changed(&changed_paths, - newroot, fs, prefetched_changes, - authz_read_func, authz_read_baton, - pool); + SVN_ERR(detect_changed(&access_level, &changed_paths, + newroot, fs, prefetched_changes, + authz_read_func, authz_read_baton, + pool)); - if (patherr - && patherr->apr_err == SVN_ERR_AUTHZ_UNREADABLE) + if (access_level == svn_repos_revision_access_none) { /* All changed-paths are unreadable, so clear all fields. */ - svn_error_clear(patherr); changed_paths = NULL; get_revprops = FALSE; } - else if (patherr - && patherr->apr_err == SVN_ERR_AUTHZ_PARTIALLY_READABLE) + else if (access_level == svn_repos_revision_access_partial) { /* At least one changed-path was unreadable, so censor all but author and date. (The unreadable paths are already missing from the hash.) */ - svn_error_clear(patherr); censor_revprops = TRUE; } - else if (patherr) - return patherr; /* It may be the case that an authz func was passed in, but the user still doesn't want to see any changed-paths. */ @@ -1074,7 +1119,7 @@ fill_log_entry(svn_log_entry_t *log_entry, changed_paths = NULL; } - if (get_revprops) + if (get_revprops && want_revprops) { /* User is allowed to see at least some revprops. */ SVN_ERR(svn_fs_revision_proplist(&r_props, fs, rev, pool)); @@ -1096,21 +1141,54 @@ fill_log_entry(svn_log_entry_t *log_entry, } else { - /* Requested only some revprops... */ int i; - for (i = 0; i < revprops->nelts; i++) + + /* Requested only some revprops... */ + + /* Make "svn:author" and "svn:date" available as svn_string_t + for efficient comparison via svn_string_compare(). Note that + we want static initialization here and must therefore emulate + strlen(x) by sizeof(x)-1. */ + static const svn_string_t svn_prop_revision_author + = {SVN_PROP_REVISION_AUTHOR, sizeof(SVN_PROP_REVISION_AUTHOR)-1}; + static const svn_string_t svn_prop_revision_date + = {SVN_PROP_REVISION_DATE, sizeof(SVN_PROP_REVISION_DATE)-1}; + + /* often only the standard revprops got requested and delivered. + In that case, we can simply pass the hash on. */ + if (revprops->nelts == apr_hash_count(r_props) && !censor_revprops) { - char *name = APR_ARRAY_IDX(revprops, i, char *); - svn_string_t *value = svn_hash_gets(r_props, name); - if (censor_revprops - && !(strcmp(name, SVN_PROP_REVISION_AUTHOR) == 0 - || strcmp(name, SVN_PROP_REVISION_DATE) == 0)) - /* ... but we can only return author/date. */ - continue; - if (log_entry->revprops == NULL) - log_entry->revprops = svn_hash__make(pool); - svn_hash_sets(log_entry->revprops, name, value); + log_entry->revprops = r_props; + for (i = 0; i < revprops->nelts; i++) + { + const svn_string_t *name + = APR_ARRAY_IDX(revprops, i, const svn_string_t *); + if (!apr_hash_get(r_props, name->data, name->len)) + { + /* hash does not match list of revprops we want */ + log_entry->revprops = NULL; + break; + } + } } + + /* slow, revprop-by-revprop filtering */ + if (log_entry->revprops == NULL) + for (i = 0; i < revprops->nelts; i++) + { + const svn_string_t *name + = APR_ARRAY_IDX(revprops, i, const svn_string_t *); + svn_string_t *value + = apr_hash_get(r_props, name->data, name->len); + if (censor_revprops + && !svn_string_compare(name, &svn_prop_revision_author) + && !svn_string_compare(name, &svn_prop_revision_date)) + /* ... but we can only return author/date. */ + continue; + if (log_entry->revprops == NULL) + log_entry->revprops = svn_hash__make(pool); + apr_hash_set(log_entry->revprops, name->data, name->len, value); + } } } @@ -1136,8 +1214,8 @@ fill_log_entry(svn_log_entry_t *log_entry, (i.e. retrieve none if the array is empty). LOG_TARGET_HISTORY_AS_MERGEINFO, HANDLING_MERGED_REVISION, and - NESTED_MERGES are as per the arguments of the same name to DO_LOGS. If - HANDLING_MERGED_REVISION is true and *all* changed paths within REV are + NESTED_MERGES are as per the arguments of the same name to DO_LOGS. + If HANDLING_MERGED_REVISION is true and *all* changed paths within REV are already represented in LOG_TARGET_HISTORY_AS_MERGEINFO, then don't send the log message for REV. If SUBTRACTIVE_MERGE is true, then REV was reverse merged. @@ -1151,7 +1229,7 @@ send_log(svn_revnum_t rev, svn_fs_t *fs, apr_hash_t *prefetched_changes, svn_mergeinfo_t log_target_history_as_mergeinfo, - apr_hash_t *nested_merges, + svn_bit_array__t *nested_merges, svn_boolean_t discover_changed_paths, svn_boolean_t subtractive_merge, svn_boolean_t handling_merged_revision, @@ -1170,8 +1248,7 @@ send_log(svn_revnum_t rev, log_entry = svn_log_entry_create(pool); SVN_ERR(fill_log_entry(log_entry, rev, fs, prefetched_changes, discover_changed_paths || handling_merged_revision, - revprops, authz_read_func, authz_read_baton, - pool)); + revprops, authz_read_func, authz_read_baton, pool)); log_entry->has_children = has_children; log_entry->subtractive_merge = subtractive_merge; @@ -1184,32 +1261,29 @@ send_log(svn_revnum_t rev, && apr_hash_count(log_target_history_as_mergeinfo)) { apr_hash_index_t *hi; - apr_pool_t *subpool = svn_pool_create(pool); + apr_pool_t *iterpool = svn_pool_create(pool); /* REV was merged in, but it might already be part of the log target's natural history, so change our starting assumption. */ found_rev_of_interest = FALSE; /* Look at each changed path in REV. */ - for (hi = apr_hash_first(subpool, log_entry->changed_paths2); + for (hi = apr_hash_first(pool, log_entry->changed_paths2); hi; hi = apr_hash_next(hi)) { svn_boolean_t path_is_in_history = FALSE; - const char *changed_path = svn__apr_hash_index_key(hi); + const char *changed_path = apr_hash_this_key(hi); apr_hash_index_t *hi2; - apr_pool_t *inner_subpool = svn_pool_create(subpool); /* Look at each path on the log target's mergeinfo. */ - for (hi2 = apr_hash_first(inner_subpool, + for (hi2 = apr_hash_first(iterpool, log_target_history_as_mergeinfo); hi2; hi2 = apr_hash_next(hi2)) { - const char *mergeinfo_path = - svn__apr_hash_index_key(hi2); - svn_rangelist_t *rangelist = - svn__apr_hash_index_val(hi2); + const char *mergeinfo_path = apr_hash_this_key(hi2); + svn_rangelist_t *rangelist = apr_hash_this_val(hi2); /* Check whether CHANGED_PATH at revision REV is a child of a (path, revision) tuple in LOG_TARGET_HISTORY_AS_MERGEINFO. */ @@ -1232,7 +1306,7 @@ send_log(svn_revnum_t rev, if (path_is_in_history) break; } - svn_pool_destroy(inner_subpool); + svn_pool_clear(iterpool); if (!path_is_in_history) { @@ -1243,7 +1317,7 @@ send_log(svn_revnum_t rev, break; } } - svn_pool_destroy(subpool); + svn_pool_destroy(iterpool); } /* If we only got changed paths the sake of detecting redundant merged @@ -1255,13 +1329,12 @@ send_log(svn_revnum_t rev, revision. */ if (found_rev_of_interest) { + apr_pool_t *scratch_pool; + /* Is REV a merged revision we've already sent? */ if (nested_merges && handling_merged_revision) { - svn_revnum_t *merged_rev = apr_hash_get(nested_merges, &rev, - sizeof(svn_revnum_t *)); - - if (merged_rev) + if (svn_bit_array__get(nested_merges, rev)) { /* We already sent REV. */ return SVN_NO_ERROR; @@ -1271,21 +1344,18 @@ send_log(svn_revnum_t rev, /* NESTED_REVS needs to last across all the send_log, do_logs, handle_merged_revisions() recursions, so use the pool it was created in at the top of the recursion. */ - apr_pool_t *hash_pool = apr_hash_pool_get(nested_merges); - svn_revnum_t *long_lived_rev = apr_palloc(hash_pool, - sizeof(svn_revnum_t)); - *long_lived_rev = rev; - apr_hash_set(nested_merges, long_lived_rev, - sizeof(svn_revnum_t *), long_lived_rev); + svn_bit_array__set(nested_merges, rev, TRUE); } } - return (*receiver)(receiver_baton, log_entry, pool); - } - else - { - return SVN_NO_ERROR; + /* Pass a scratch pool to ensure no temporary state stored + by the receiver callback persists. */ + scratch_pool = svn_pool_create(pool); + SVN_ERR(receiver(receiver_baton, log_entry, scratch_pool)); + svn_pool_destroy(scratch_pool); } + + return SVN_NO_ERROR; } /* This controls how many history objects we keep open. For any targets @@ -1334,13 +1404,11 @@ get_path_histories(apr_array_header_t **histories, const char *this_path = APR_ARRAY_IDX(paths, i, const char *); struct path_info *info = apr_palloc(pool, sizeof(struct path_info)); + svn_pool_clear(iterpool); if (authz_read_func) { svn_boolean_t readable; - - svn_pool_clear(iterpool); - SVN_ERR(authz_read_func(&readable, root, this_path, authz_read_baton, iterpool)); if (! readable) @@ -1354,7 +1422,8 @@ get_path_histories(apr_array_header_t **histories, if (i < MAX_OPEN_HISTORIES) { - err = svn_fs_node_history(&info->hist, root, this_path, pool); + err = svn_fs_node_history2(&info->hist, root, this_path, pool, + iterpool); if (err && ignore_missing_locations && (err->apr_err == SVN_ERR_FS_NOT_FOUND || @@ -1378,7 +1447,7 @@ get_path_histories(apr_array_header_t **histories, err = get_history(info, fs, strict_node_history, authz_read_func, authz_read_baton, - hist_start, pool); + hist_start, pool, iterpool); if (err && ignore_missing_locations && (err->apr_err == SVN_ERR_FS_NOT_FOUND || @@ -1486,8 +1555,9 @@ combine_mergeinfo_path_lists(apr_array_header_t **combined_list, { int i; struct rangelist_path *rp = apr_palloc(subpool, sizeof(*rp)); - apr_hash_this(hi, (void *) &rp->path, NULL, - (void *) &rp->rangelist); + + rp->path = apr_hash_this_key(hi); + rp->rangelist = apr_hash_this_val(hi); APR_ARRAY_PUSH(rangelist_paths, struct rangelist_path *) = rp; /* We need to make local copies of the rangelist, since we will be @@ -1515,8 +1585,7 @@ combine_mergeinfo_path_lists(apr_array_header_t **combined_list, /* First, sort the list such that the start revision of the first revision arrays are sorted. */ - qsort(rangelist_paths->elts, rangelist_paths->nelts, - rangelist_paths->elt_size, compare_rangelist_paths); + svn_sort__array(rangelist_paths, compare_rangelist_paths); /* Next, find the number of revision ranges which start with the same revision. */ @@ -1627,7 +1696,7 @@ do_logs(svn_fs_t *fs, const apr_array_header_t *paths, svn_mergeinfo_t log_target_history_as_mergeinfo, svn_mergeinfo_t processed, - apr_hash_t *nested_merges, + svn_bit_array__t *nested_merges, svn_revnum_t hist_start, svn_revnum_t hist_end, int limit, @@ -1680,7 +1749,7 @@ static svn_error_t * handle_merged_revisions(svn_revnum_t rev, svn_fs_t *fs, svn_mergeinfo_t log_target_history_as_mergeinfo, - apr_hash_t *nested_merges, + svn_bit_array__t *nested_merges, svn_mergeinfo_t processed, svn_mergeinfo_t added_mergeinfo, svn_mergeinfo_t deleted_mergeinfo, @@ -1711,8 +1780,7 @@ handle_merged_revisions(svn_revnum_t rev, TRUE, pool)); SVN_ERR_ASSERT(combined_list != NULL); - qsort(combined_list->elts, combined_list->nelts, - combined_list->elt_size, compare_path_list_range); + svn_sort__array(combined_list, compare_path_list_range); /* Because the combined_lists are ordered youngest to oldest, iterate over them in reverse. */ @@ -1889,7 +1957,7 @@ do_logs(svn_fs_t *fs, const apr_array_header_t *paths, svn_mergeinfo_t log_target_history_as_mergeinfo, svn_mergeinfo_t processed, - apr_hash_t *nested_merges, + svn_bit_array__t *nested_merges, svn_revnum_t hist_start, svn_revnum_t hist_end, int limit, @@ -1907,7 +1975,7 @@ do_logs(svn_fs_t *fs, void *authz_read_baton, apr_pool_t *pool) { - apr_pool_t *iterpool; + apr_pool_t *iterpool, *iterpool2; apr_pool_t *subpool = NULL; apr_array_header_t *revs = NULL; apr_hash_t *rev_mergeinfo = NULL; @@ -1943,6 +2011,7 @@ do_logs(svn_fs_t *fs, where a path was changed to the array, or if they wanted history in reverse order just send it to them right away. */ iterpool = svn_pool_create(pool); + iterpool2 = svn_pool_create(pool); for (current = hist_end; any_histories_left; current = next_history_rev(histories)) @@ -1956,14 +2025,19 @@ do_logs(svn_fs_t *fs, struct path_info *info = APR_ARRAY_IDX(histories, i, struct path_info *); + svn_pool_clear(iterpool2); + /* Check history for this path in current rev. */ SVN_ERR(check_history(&changed, info, fs, current, strict_node_history, authz_read_func, - authz_read_baton, hist_start, pool)); + authz_read_baton, hist_start, pool, + iterpool2)); if (! info->done) any_histories_left = TRUE; } + svn_pool_clear(iterpool2); + /* If any of the paths changed in this rev then add or send it. */ if (changed) { @@ -1993,8 +2067,8 @@ do_logs(svn_fs_t *fs, &deleted_mergeinfo, &changes, fs, cur_paths, - current, iterpool, - iterpool)); + current, + iterpool, iterpool)); has_children = (apr_hash_count(added_mergeinfo) > 0 || apr_hash_count(deleted_mergeinfo) > 0); } @@ -2020,7 +2094,7 @@ do_logs(svn_fs_t *fs, single hash to be shared across all of the merged recursions so we can track and squelch duplicates. */ subpool = svn_pool_create(pool); - nested_merges = svn_hash__make(subpool); + nested_merges = svn_bit_array__create(hist_end, subpool); processed = svn_hash__make(subpool); } @@ -2052,19 +2126,18 @@ do_logs(svn_fs_t *fs, if (added_mergeinfo || deleted_mergeinfo) { - svn_revnum_t *cur_rev = apr_pcalloc(pool, sizeof(*cur_rev)); + svn_revnum_t *cur_rev = + apr_pmemdup(pool, ¤t, sizeof(*cur_rev)); struct added_deleted_mergeinfo *add_and_del_mergeinfo = apr_palloc(pool, sizeof(*add_and_del_mergeinfo)); - if (added_mergeinfo) - add_and_del_mergeinfo->added_mergeinfo = - svn_mergeinfo_dup(added_mergeinfo, pool); - - if (deleted_mergeinfo) - add_and_del_mergeinfo->deleted_mergeinfo = - svn_mergeinfo_dup(deleted_mergeinfo, pool); + /* If we have added or deleted mergeinfo, both are non-null */ + SVN_ERR_ASSERT(added_mergeinfo && deleted_mergeinfo); + add_and_del_mergeinfo->added_mergeinfo = + svn_mergeinfo_dup(added_mergeinfo, pool); + add_and_del_mergeinfo->deleted_mergeinfo = + svn_mergeinfo_dup(deleted_mergeinfo, pool); - *cur_rev = current; if (! rev_mergeinfo) rev_mergeinfo = svn_hash__make(pool); apr_hash_set(rev_mergeinfo, cur_rev, sizeof(*cur_rev), @@ -2073,6 +2146,7 @@ do_logs(svn_fs_t *fs, } } } + svn_pool_destroy(iterpool2); svn_pool_destroy(iterpool); if (subpool) @@ -2112,7 +2186,8 @@ do_logs(svn_fs_t *fs, SVN_ERR(send_log(current, fs, NULL, log_target_history_as_mergeinfo, nested_merges, discover_changed_paths, subtractive_merge, - handling_merged_revisions, revprops, has_children, + handling_merged_revisions, + revprops, has_children, receiver, receiver_baton, authz_read_func, authz_read_baton, iterpool)); if (has_children) @@ -2120,7 +2195,7 @@ do_logs(svn_fs_t *fs, if (!nested_merges) { subpool = svn_pool_create(pool); - nested_merges = svn_hash__make(subpool); + nested_merges = svn_bit_array__create(current, subpool); } SVN_ERR(handle_merged_revisions(current, fs, @@ -2130,7 +2205,8 @@ do_logs(svn_fs_t *fs, added_mergeinfo, deleted_mergeinfo, discover_changed_paths, - strict_node_history, revprops, + strict_node_history, + revprops, receiver, receiver_baton, authz_read_func, authz_read_baton, @@ -2252,6 +2328,19 @@ svn_repos_get_logs4(svn_repos_t *repos, svn_boolean_t descending_order; svn_mergeinfo_t paths_history_mergeinfo = NULL; + if (revprops) + { + int i; + apr_array_header_t *new_revprops + = apr_array_make(pool, revprops->nelts, sizeof(svn_string_t *)); + + for (i = 0; i < revprops->nelts; ++i) + APR_ARRAY_PUSH(new_revprops, svn_string_t *) + = svn_string_create(APR_ARRAY_IDX(revprops, i, const char *), pool); + + revprops = new_revprops; + } + /* Setup log range. */ SVN_ERR(svn_fs_youngest_rev(&head, fs, pool)); @@ -2321,7 +2410,7 @@ svn_repos_get_logs4(svn_repos_t *repos, } send_count = end - start + 1; - if (limit && send_count > limit) + if (limit > 0 && send_count > limit) send_count = limit; for (i = 0; i < send_count; ++i) { @@ -2335,9 +2424,8 @@ svn_repos_get_logs4(svn_repos_t *repos, rev = start + i; SVN_ERR(send_log(rev, fs, NULL, NULL, NULL, discover_changed_paths, FALSE, - FALSE, revprops, FALSE, receiver, - receiver_baton, authz_read_func, - authz_read_baton, iterpool)); + FALSE, revprops, FALSE, receiver, receiver_baton, + authz_read_func, authz_read_baton, iterpool)); } svn_pool_destroy(iterpool); @@ -2363,7 +2451,7 @@ svn_repos_get_logs4(svn_repos_t *repos, return do_logs(repos->fs, paths, paths_history_mergeinfo, NULL, NULL, start, end, limit, discover_changed_paths, strict_node_history, - include_merged_revisions, FALSE, FALSE, FALSE, revprops, - descending_order, receiver, receiver_baton, + include_merged_revisions, FALSE, FALSE, FALSE, + revprops, descending_order, receiver, receiver_baton, authz_read_func, authz_read_baton, pool); } |