summaryrefslogtreecommitdiff
path: root/subversion/libsvn_repos/rev_hunt.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_repos/rev_hunt.c')
-rw-r--r--subversion/libsvn_repos/rev_hunt.c123
1 files changed, 86 insertions, 37 deletions
diff --git a/subversion/libsvn_repos/rev_hunt.c b/subversion/libsvn_repos/rev_hunt.c
index d6cc49576d121..558d691b9bfe5 100644
--- a/subversion/libsvn_repos/rev_hunt.c
+++ b/subversion/libsvn_repos/rev_hunt.c
@@ -44,7 +44,7 @@
/* Note: this binary search assumes that the datestamp properties on
each revision are in chronological order. That is if revision A >
- revision B, then A's datestamp is younger then B's datestamp.
+ revision B, then A's datestamp is younger than B's datestamp.
If someone comes along and sets a bogus datestamp, this routine
might not work right.
@@ -65,8 +65,8 @@ get_time(apr_time_t *tm,
{
svn_string_t *date_str;
- SVN_ERR(svn_fs_revision_prop(&date_str, fs, rev, SVN_PROP_REVISION_DATE,
- pool));
+ SVN_ERR(svn_fs_revision_prop2(&date_str, fs, rev, SVN_PROP_REVISION_DATE,
+ FALSE, pool, pool));
if (! date_str)
return svn_error_createf
(SVN_ERR_FS_GENERAL, NULL,
@@ -88,6 +88,7 @@ svn_repos_dated_revision(svn_revnum_t *revision,
/* Initialize top and bottom values of binary search. */
SVN_ERR(svn_fs_youngest_rev(&rev_latest, fs, pool));
+ SVN_ERR(svn_fs_refresh_revision_props(fs, pool));
rev_bot = 0;
rev_top = rev_latest;
@@ -170,7 +171,8 @@ svn_repos_get_committed_info(svn_revnum_t *committed_rev,
SVN_ERR(svn_fs_node_created_rev(committed_rev, root, path, pool));
/* Get the revision properties of this revision. */
- SVN_ERR(svn_fs_revision_proplist(&revprops, fs, *committed_rev, pool));
+ SVN_ERR(svn_fs_revision_proplist2(&revprops, fs, *committed_rev, TRUE,
+ pool, pool));
/* Extract date and author from these revprops. */
committed_date_s = svn_hash_gets(revprops, SVN_PROP_REVISION_DATE);
@@ -669,8 +671,7 @@ svn_repos_trace_node_locations(svn_fs_t *fs,
/* First - let's sort the array of the revisions from the greatest revision
* downward, so it will be easier to search on. */
location_revisions = apr_array_copy(pool, location_revisions_orig);
- qsort(location_revisions->elts, location_revisions->nelts,
- sizeof(*revision_ptr), svn_sort_compare_revisions);
+ svn_sort__array(location_revisions, svn_sort_compare_revisions);
revision_ptr = (svn_revnum_t *)location_revisions->elts;
revision_ptr_end = revision_ptr + location_revisions->nelts;
@@ -835,27 +836,32 @@ svn_repos_node_location_segments(svn_repos_t *repos,
{
svn_fs_t *fs = svn_repos_fs(repos);
svn_stringbuf_t *current_path;
- svn_revnum_t youngest_rev = SVN_INVALID_REVNUM, current_rev;
+ svn_revnum_t youngest_rev, current_rev;
apr_pool_t *subpool;
+ SVN_ERR(svn_fs_youngest_rev(&youngest_rev, fs, pool));
+
/* No PEG_REVISION? We'll use HEAD. */
if (! SVN_IS_VALID_REVNUM(peg_revision))
- {
- SVN_ERR(svn_fs_youngest_rev(&youngest_rev, fs, pool));
- peg_revision = youngest_rev;
- }
+ peg_revision = youngest_rev;
+
+ if (peg_revision > youngest_rev)
+ return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
+ _("No such revision %ld"), peg_revision);
- /* No START_REV? We'll use HEAD (which we may have already fetched). */
+ /* No START_REV? We'll use peg rev. */
if (! SVN_IS_VALID_REVNUM(start_rev))
- {
- if (SVN_IS_VALID_REVNUM(youngest_rev))
- start_rev = youngest_rev;
- else
- SVN_ERR(svn_fs_youngest_rev(&start_rev, fs, pool));
- }
+ start_rev = peg_revision;
+ else if (start_rev > peg_revision)
+ return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
+ _("No such revision %ld"), start_rev);
/* No END_REV? We'll use 0. */
- end_rev = SVN_IS_VALID_REVNUM(end_rev) ? end_rev : 0;
+ if (! SVN_IS_VALID_REVNUM(end_rev))
+ end_rev = 0;
+ else if (end_rev > start_rev)
+ return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
+ _("No such revision %ld"), end_rev);
/* Are the revision properly ordered? They better be -- the API
demands it. */
@@ -1006,26 +1012,39 @@ get_merged_mergeinfo(apr_hash_t **merged_mergeinfo,
apr_hash_t *curr_mergeinfo, *prev_mergeinfo, *deleted, *changed;
svn_error_t *err;
svn_fs_root_t *root, *prev_root;
- apr_hash_t *changed_paths;
- const char *path = old_path_rev->path;
+ const char *start_path = old_path_rev->path;
+ const char *path = NULL;
+
+ svn_fs_path_change_iterator_t *iterator;
+ svn_fs_path_change3_t *change;
/* Getting/parsing/diffing svn:mergeinfo is expensive, so only do it
if there is a property change. */
SVN_ERR(svn_fs_revision_root(&root, repos->fs, old_path_rev->revnum,
scratch_pool));
- SVN_ERR(svn_fs_paths_changed2(&changed_paths, root, scratch_pool));
- while (1)
+ SVN_ERR(svn_fs_paths_changed3(&iterator, root, scratch_pool, scratch_pool));
+ SVN_ERR(svn_fs_path_change_get(&change, iterator));
+
+ /* Find the changed PATH closest to START_PATH which may have a mergeinfo
+ * change. */
+ while (change)
{
- svn_fs_path_change2_t *changed_path = svn_hash_gets(changed_paths, path);
- if (changed_path && changed_path->prop_mod
- && changed_path->mergeinfo_mod != svn_tristate_false)
- break;
- if (svn_fspath__is_root(path, strlen(path)))
+ if ( change->prop_mod
+ && change->mergeinfo_mod != svn_tristate_false
+ && svn_fspath__skip_ancestor(change->path.data, start_path))
{
- *merged_mergeinfo = NULL;
- return SVN_NO_ERROR;
+ if (!path || svn_fspath__skip_ancestor(path, change->path.data))
+ path = apr_pstrmemdup(scratch_pool, change->path.data,
+ change->path.len);
}
- path = svn_fspath__dirname(path, scratch_pool);
+
+ SVN_ERR(svn_fs_path_change_get(&change, iterator));
+ }
+
+ if (path == NULL)
+ {
+ *merged_mergeinfo = NULL;
+ return SVN_NO_ERROR;
}
/* First, find the mergeinfo difference for old_path_rev->revnum, and
@@ -1350,22 +1369,48 @@ send_path_revision(struct path_revision *path_rev,
void *delta_baton = NULL;
apr_pool_t *tmp_pool; /* For swapping */
svn_boolean_t contents_changed;
+ svn_boolean_t props_changed;
svn_pool_clear(sb->iterpool);
/* Get the revision properties. */
- SVN_ERR(svn_fs_revision_proplist(&rev_props, repos->fs,
- path_rev->revnum, sb->iterpool));
+ SVN_ERR(svn_fs_revision_proplist2(&rev_props, repos->fs,
+ path_rev->revnum, FALSE,
+ sb->iterpool, sb->iterpool));
/* Open the revision root. */
SVN_ERR(svn_fs_revision_root(&root, repos->fs, path_rev->revnum,
sb->iterpool));
- /* Get the file's properties for this revision and compute the diffs. */
- SVN_ERR(svn_fs_node_proplist(&props, root, path_rev->path,
+ /* Check if the props *may* have changed. */
+ if (sb->last_root)
+ {
+ /* We don't use svn_fs_props_different() because it's more
+ * expensive. */
+ SVN_ERR(svn_fs_props_changed(&props_changed,
+ sb->last_root, sb->last_path,
+ root, path_rev->path, sb->iterpool));
+ }
+ else
+ {
+ props_changed = TRUE;
+ }
+
+ /* Calculate actual difference between last and current properties. */
+ if (props_changed)
+ {
+ /* Get the file's properties for this revision and compute the diffs. */
+ SVN_ERR(svn_fs_node_proplist(&props, root, path_rev->path,
sb->iterpool));
- SVN_ERR(svn_prop_diffs(&prop_diffs, props, sb->last_props,
- sb->iterpool));
+ SVN_ERR(svn_prop_diffs(&prop_diffs, props, sb->last_props,
+ sb->iterpool));
+ }
+ else
+ {
+ /* Properties didn't change: copy LAST_PROPS to current POOL. */
+ props = svn_prop_hash_dup(sb->last_props, sb->iterpool);
+ prop_diffs = apr_array_make(sb->iterpool, 0, sizeof(svn_prop_t));
+ }
/* Check if the contents *may* have changed. */
if (! sb->last_root)
@@ -1590,6 +1635,10 @@ svn_repos_get_file_revs2(svn_repos_t *repos,
end = youngest_rev;
}
+ /* Make sure we catch up on the latest revprop changes. This is the only
+ * time we will refresh the revprop data in this query. */
+ SVN_ERR(svn_fs_refresh_revision_props(repos->fs, scratch_pool));
+
if (end < start)
{
if (include_merged_revisions)