summaryrefslogtreecommitdiff
path: root/subversion/libsvn_repos/reporter.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_repos/reporter.c')
-rw-r--r--subversion/libsvn_repos/reporter.c95
1 files changed, 58 insertions, 37 deletions
diff --git a/subversion/libsvn_repos/reporter.c b/subversion/libsvn_repos/reporter.c
index de46858..76c7201 100644
--- a/subversion/libsvn_repos/reporter.c
+++ b/subversion/libsvn_repos/reporter.c
@@ -495,11 +495,11 @@ get_revision_info(report_baton_t *b,
/* Create a result object */
info = apr_palloc(b->pool, sizeof(*info));
info->rev = rev;
- info->date = cdate ? svn_string_dup(cdate, b->pool) : NULL;
- info->author = author ? svn_string_dup(author, b->pool) : NULL;
+ info->date = svn_string_dup(cdate, b->pool);
+ info->author = svn_string_dup(author, b->pool);
/* Cache it */
- apr_hash_set(b->revision_infos, &info->rev, sizeof(rev), info);
+ apr_hash_set(b->revision_infos, &info->rev, sizeof(info->rev), info);
}
*revision_info = info;
@@ -576,8 +576,8 @@ delta_proplists(report_baton_t *b, svn_revnum_t s_rev, const char *s_path,
SVN_ERR(get_source_root(b, &s_root, s_rev));
/* Is this deltification worth our time? */
- SVN_ERR(svn_fs_props_changed(&changed, b->t_root, t_path, s_root,
- s_path, pool));
+ SVN_ERR(svn_fs_props_different(&changed, b->t_root, t_path, s_root,
+ s_path, pool));
if (! changed)
return SVN_NO_ERROR;
@@ -603,10 +603,9 @@ delta_proplists(report_baton_t *b, svn_revnum_t s_rev, const char *s_path,
/* So source, i.e. all new. Transmit all target props. */
for (hi = apr_hash_first(pool, t_props); hi; hi = apr_hash_next(hi))
{
- const void *key;
- void *val;
+ const char *key = apr_hash_this_key(hi);
+ svn_string_t *val = apr_hash_this_val(hi);
- apr_hash_this(hi, &key, NULL, &val);
SVN_ERR(change_fn(b, object, key, val, pool));
}
}
@@ -842,7 +841,7 @@ add_file_smartly(report_baton_t *b,
starting with '/', so make sure o_path always starts with a '/'
too. */
if (*o_path != '/')
- o_path = apr_pstrcat(pool, "/", o_path, (char *)NULL);
+ o_path = apr_pstrcat(pool, "/", o_path, SVN_VA_NULL);
SVN_ERR(svn_fs_closest_copy(&closest_copy_root, &closest_copy_path,
b->t_root, o_path, pool));
@@ -917,7 +916,7 @@ update_entry(report_baton_t *b, svn_revnum_t s_rev, const char *s_path,
const char *e_path, path_info_t *info, svn_depth_t wc_depth,
svn_depth_t requested_depth, apr_pool_t *pool)
{
- svn_fs_root_t *s_root;
+ svn_fs_root_t *s_root = NULL;
svn_boolean_t allowed, related;
void *new_baton;
svn_checksum_t *checksum;
@@ -960,7 +959,26 @@ update_entry(report_baton_t *b, svn_revnum_t s_rev, const char *s_path,
if (s_entry && t_entry && s_entry->kind == t_entry->kind)
{
int distance = svn_fs_compare_ids(s_entry->id, t_entry->id);
- if (distance == 0 && !any_path_info(b, e_path)
+ svn_boolean_t changed = TRUE;
+
+ /* Check related files for content changes to avoid reporting
+ * unchanged copies of files to the client as an open_file() call
+ * and change_file_prop()/apply_textdelta() calls with no-op changes.
+ * The client will otherwise raise unnecessary tree conflicts. */
+ if (!b->ignore_ancestry && t_entry->kind == svn_node_file &&
+ distance == 1)
+ {
+ if (s_root == NULL)
+ SVN_ERR(get_source_root(b, &s_root, s_rev));
+
+ SVN_ERR(svn_fs_props_different(&changed, s_root, s_path,
+ b->t_root, t_path, pool));
+ if (!changed)
+ SVN_ERR(svn_fs_contents_different(&changed, s_root, s_path,
+ b->t_root, t_path, pool));
+ }
+
+ if ((distance == 0 || !changed) && !any_path_info(b, e_path)
&& (requested_depth <= wc_depth || t_entry->kind == svn_node_file))
{
if (!info)
@@ -1140,13 +1158,11 @@ delta_dirs(report_baton_t *b, svn_revnum_t s_rev, const char *s_path,
svn_boolean_t start_empty, svn_depth_t wc_depth,
svn_depth_t requested_depth, apr_pool_t *pool)
{
- svn_fs_root_t *s_root;
apr_hash_t *s_entries = NULL, *t_entries;
apr_hash_index_t *hi;
apr_pool_t *subpool = svn_pool_create(pool);
- apr_pool_t *iterpool;
- const char *name, *s_fullpath, *t_fullpath, *e_fullpath;
- path_info_t *info;
+ apr_array_header_t *t_ordered_entries = NULL;
+ int i;
/* Compare the property lists. If we're starting empty, pass a NULL
source path so that we add all the properties.
@@ -1159,19 +1175,25 @@ delta_dirs(report_baton_t *b, svn_revnum_t s_rev, const char *s_path,
if (requested_depth > svn_depth_empty
|| requested_depth == svn_depth_unknown)
{
+ apr_pool_t *iterpool;
+
/* Get the list of entries in each of source and target. */
if (s_path && !start_empty)
{
+ svn_fs_root_t *s_root;
+
SVN_ERR(get_source_root(b, &s_root, s_rev));
SVN_ERR(svn_fs_dir_entries(&s_entries, s_root, s_path, subpool));
}
SVN_ERR(svn_fs_dir_entries(&t_entries, b->t_root, t_path, subpool));
/* Iterate over the report information for this directory. */
- iterpool = svn_pool_create(pool);
+ iterpool = svn_pool_create(subpool);
while (1)
{
+ path_info_t *info;
+ const char *name, *s_fullpath, *t_fullpath, *e_fullpath;
const svn_fs_dirent_t *s_entry, *t_entry;
svn_pool_clear(iterpool);
@@ -1192,6 +1214,8 @@ delta_dirs(report_baton_t *b, svn_revnum_t s_rev, const char *s_path,
but don't update the entry yet. */
if (s_entries)
svn_hash_sets(s_entries, name, NULL);
+
+ svn_pool_destroy(info->pool);
continue;
}
@@ -1199,10 +1223,9 @@ delta_dirs(report_baton_t *b, svn_revnum_t s_rev, const char *s_path,
t_fullpath = svn_fspath__join(t_path, name, iterpool);
t_entry = svn_hash_gets(t_entries, name);
s_fullpath = s_path ? svn_fspath__join(s_path, name, iterpool) : NULL;
- s_entry = s_entries ?
- svn_hash_gets(s_entries, name) : NULL;
+ s_entry = s_entries ? svn_hash_gets(s_entries, name) : NULL;
- /* The only special cases here are
+ /* The only special cases where we don't process the entry are
- When requested_depth is files but the reported path is
a directory. This is technically a client error, but we
@@ -1210,10 +1233,10 @@ delta_dirs(report_baton_t *b, svn_revnum_t s_rev, const char *s_path,
- When the reported depth is svn_depth_exclude.
*/
- if ((! info || info->depth != svn_depth_exclude)
- && (requested_depth != svn_depth_files
- || ((! t_entry || t_entry->kind != svn_node_dir)
- && (! s_entry || s_entry->kind != svn_node_dir))))
+ if (! ((requested_depth == svn_depth_files
+ && ((t_entry && t_entry->kind == svn_node_dir)
+ || (s_entry && s_entry->kind == svn_node_dir)))
+ || (info && info->depth == svn_depth_exclude)))
SVN_ERR(update_entry(b, s_rev, s_fullpath, s_entry, t_fullpath,
t_entry, dir_baton, e_fullpath, info,
info ? info->depth
@@ -1242,13 +1265,13 @@ delta_dirs(report_baton_t *b, svn_revnum_t s_rev, const char *s_path,
hi;
hi = apr_hash_next(hi))
{
- const svn_fs_dirent_t *s_entry;
+ const svn_fs_dirent_t *s_entry = apr_hash_this_val(hi);
svn_pool_clear(iterpool);
- s_entry = svn__apr_hash_index_val(hi);
if (svn_hash_gets(t_entries, s_entry->name) == NULL)
{
+ const char *e_fullpath;
svn_revnum_t deleted_rev;
if (s_entry->kind == svn_node_file
@@ -1277,14 +1300,16 @@ delta_dirs(report_baton_t *b, svn_revnum_t s_rev, const char *s_path,
}
/* Loop over the dirents in the target. */
- for (hi = apr_hash_first(subpool, t_entries);
- hi;
- hi = apr_hash_next(hi))
+ SVN_ERR(svn_fs_dir_optimal_order(&t_ordered_entries, b->t_root,
+ t_entries, subpool, iterpool));
+ for (i = 0; i < t_ordered_entries->nelts; ++i)
{
- const svn_fs_dirent_t *s_entry, *t_entry;
+ const svn_fs_dirent_t *t_entry
+ = APR_ARRAY_IDX(t_ordered_entries, i, svn_fs_dirent_t *);
+ const svn_fs_dirent_t *s_entry;
+ const char *s_fullpath, *t_fullpath, *e_fullpath;
svn_pool_clear(iterpool);
- t_entry = svn__apr_hash_index_val(hi);
if (is_depth_upgrade(wc_depth, requested_depth, t_entry->kind))
{
@@ -1305,11 +1330,9 @@ delta_dirs(report_baton_t *b, svn_revnum_t s_rev, const char *s_path,
|| requested_depth == svn_depth_files))
continue;
- /* Look for an entry with the same name
- in the source dirents. */
+ /* Look for an entry with the same name in the source dirents. */
s_entry = s_entries ?
- svn_hash_gets(s_entries, t_entry->name)
- : NULL;
+ svn_hash_gets(s_entries, t_entry->name) : NULL;
s_fullpath = s_entry ?
svn_fspath__join(s_path, t_entry->name, iterpool) : NULL;
}
@@ -1325,9 +1348,7 @@ delta_dirs(report_baton_t *b, svn_revnum_t s_rev, const char *s_path,
iterpool));
}
-
- /* Destroy iteration subpool. */
- svn_pool_destroy(iterpool);
+ /* iterpool is destroyed by destroying its parent (subpool) below */
}
svn_pool_destroy(subpool);