diff options
Diffstat (limited to 'subversion/libsvn_repos/reporter.c')
-rw-r--r-- | subversion/libsvn_repos/reporter.c | 95 |
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); |