You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2015/10/06 10:46:44 UTC
svn commit: r1706963 [3/6] - in /subversion/branches/move-tracking-2: ./
build/ subversion/ subversion/bindings/javahl/native/ subversion/include/
subversion/include/private/ subversion/libsvn_client/
subversion/libsvn_diff/ subversion/libsvn_fs_base/ ...
Modified: subversion/branches/move-tracking-2/subversion/libsvn_client/upgrade.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_client/upgrade.c?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_client/upgrade.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_client/upgrade.c Tue Oct 6 08:46:43 2015
@@ -179,6 +179,122 @@ svn_client_upgrade(const char *path,
return SVN_NO_ERROR;
}
+/* Helper for upgrade_externals_from_properties: upgrades one external ITEM
+ in EXTERNALS_PARENT. Uses SCRATCH_POOL for temporary allocations. */
+static svn_error_t *
+upgrade_external_item(svn_client_ctx_t *ctx,
+ const char *externals_parent_abspath,
+ const char *externals_parent_url,
+ const char *externals_parent_repos_root_url,
+ svn_wc_external_item2_t *item,
+ struct repos_info_baton *info_baton,
+ apr_pool_t *scratch_pool)
+{
+ const char *resolved_url;
+ const char *external_abspath;
+ const char *repos_relpath;
+ const char *repos_root_url;
+ const char *repos_uuid;
+ svn_node_kind_t external_kind;
+ svn_revnum_t peg_revision;
+ svn_revnum_t revision;
+ svn_error_t *err;
+
+ external_abspath = svn_dirent_join(externals_parent_abspath,
+ item->target_dir,
+ scratch_pool);
+
+ SVN_ERR(svn_wc__resolve_relative_external_url(
+ &resolved_url,
+ item,
+ externals_parent_repos_root_url,
+ externals_parent_url,
+ scratch_pool, scratch_pool));
+
+ /* This is a hack. We only need to call svn_wc_upgrade() on external
+ * dirs, as file externals are upgraded along with their defining
+ * WC. Reading the kind will throw an exception on an external dir,
+ * saying that the wc must be upgraded. If it's a file, the lookup
+ * is done in an adm_dir belonging to the defining wc (which has
+ * already been upgraded) and no error is returned. If it doesn't
+ * exist (external that isn't checked out yet), we'll just get
+ * svn_node_none. */
+ err = svn_wc_read_kind2(&external_kind, ctx->wc_ctx,
+ external_abspath, TRUE, FALSE, scratch_pool);
+ if (err && err->apr_err == SVN_ERR_WC_UPGRADE_REQUIRED)
+ {
+ svn_error_clear(err);
+
+ SVN_ERR(svn_client_upgrade(external_abspath, ctx, scratch_pool));
+ }
+ else if (err)
+ return svn_error_trace(err);
+
+ /* The upgrade of any dir should be done now, get the now reliable
+ * kind. */
+ SVN_ERR(svn_wc_read_kind2(&external_kind, ctx->wc_ctx, external_abspath,
+ TRUE, FALSE, scratch_pool));
+
+ /* Update the EXTERNALS table according to the root URL,
+ * relpath and uuid known in the upgraded external WC. */
+
+ /* We should probably have a function that provides all three
+ * of root URL, repos relpath and uuid at once, but here goes... */
+
+ /* First get the relpath, as that returns SVN_ERR_WC_PATH_NOT_FOUND
+ * when the node is not present in the file system.
+ * svn_wc__node_get_repos_info() would try to derive the URL. */
+ SVN_ERR(svn_wc__node_get_repos_info(NULL,
+ &repos_relpath,
+ &repos_root_url,
+ &repos_uuid,
+ ctx->wc_ctx,
+ external_abspath,
+ scratch_pool, scratch_pool));
+
+ /* If we haven't got any information from the checked out external,
+ * or if the URL information mismatches the external's definition,
+ * ask fetch_repos_info() to find out the repos root. */
+ if (0 != strcmp(resolved_url,
+ svn_path_url_add_component2(repos_root_url,
+ repos_relpath,
+ scratch_pool)))
+ {
+ SVN_ERR(fetch_repos_info(&repos_root_url, &repos_uuid, info_baton,
+ resolved_url, scratch_pool, scratch_pool));
+
+ repos_relpath = svn_uri_skip_ancestor(repos_root_url,
+ resolved_url,
+ scratch_pool);
+
+ /* There's just the URL, no idea what kind the external is.
+ * That's fine, as the external isn't even checked out yet.
+ * The kind will be set during the next 'update'. */
+ external_kind = svn_node_unknown;
+ }
+
+ peg_revision = (item->peg_revision.kind == svn_opt_revision_number
+ ? item->peg_revision.value.number
+ : SVN_INVALID_REVNUM);
+
+ revision = (item->revision.kind == svn_opt_revision_number
+ ? item->revision.value.number
+ : SVN_INVALID_REVNUM);
+
+ SVN_ERR(svn_wc__upgrade_add_external_info(ctx->wc_ctx,
+ external_abspath,
+ external_kind,
+ externals_parent_abspath,
+ repos_relpath,
+ repos_root_url,
+ repos_uuid,
+ peg_revision,
+ revision,
+ scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
static svn_error_t *
upgrade_externals_from_properties(svn_client_ctx_t *ctx,
const char *local_abspath,
@@ -207,34 +323,32 @@ upgrade_externals_from_properties(svn_cl
hi = apr_hash_next(hi))
{
int i;
- const char *externals_parent_abspath;
const char *externals_parent_url;
const char *externals_parent_repos_root_url;
const char *externals_parent_repos_relpath;
- const char *externals_parent = apr_hash_this_key(hi);
+ const char *externals_parent_abspath = apr_hash_this_key(hi);
svn_string_t *external_desc = apr_hash_this_val(hi);
apr_array_header_t *externals_p;
svn_error_t *err;
svn_pool_clear(iterpool);
+
+ /* svn_client_propget5() has API promise to return absolute paths. */
+ SVN_ERR_ASSERT(svn_dirent_is_absolute(externals_parent_abspath));
+
externals_p = apr_array_make(iterpool, 1,
sizeof(svn_wc_external_item2_t*));
/* In this loop, an error causes the respective externals definition, or
* the external (inner loop), to be skipped, so that upgrade carries on
* with the other externals. */
-
- err = svn_dirent_get_absolute(&externals_parent_abspath,
- externals_parent, iterpool);
-
- if (!err)
- err = svn_wc__node_get_repos_info(NULL,
- &externals_parent_repos_relpath,
- &externals_parent_repos_root_url,
- NULL,
- ctx->wc_ctx,
- externals_parent_abspath,
- iterpool, iterpool);
+ err = svn_wc__node_get_repos_info(NULL,
+ &externals_parent_repos_relpath,
+ &externals_parent_repos_root_url,
+ NULL,
+ ctx->wc_ctx,
+ externals_parent_abspath,
+ iterpool, iterpool);
if (!err)
externals_parent_url = svn_path_url_add_component2(
@@ -248,7 +362,7 @@ upgrade_externals_from_properties(svn_cl
if (err)
{
svn_wc_notify_t *notify =
- svn_wc_create_notify(externals_parent,
+ svn_wc_create_notify(externals_parent_abspath,
svn_wc_notify_failed_external,
scratch_pool);
notify->err = err;
@@ -265,130 +379,21 @@ upgrade_externals_from_properties(svn_cl
for (i = 0; i < externals_p->nelts; i++)
{
svn_wc_external_item2_t *item;
- const char *resolved_url;
- const char *external_abspath;
- const char *repos_relpath;
- const char *repos_root_url;
- const char *repos_uuid;
- svn_node_kind_t external_kind;
- svn_revnum_t peg_revision;
- svn_revnum_t revision;
item = APR_ARRAY_IDX(externals_p, i, svn_wc_external_item2_t*);
svn_pool_clear(iterpool2);
- external_abspath = svn_dirent_join(externals_parent_abspath,
- item->target_dir,
- iterpool2);
-
- err = svn_wc__resolve_relative_external_url(
- &resolved_url,
- item,
- externals_parent_repos_root_url,
- externals_parent_url,
- scratch_pool, scratch_pool);
- if (err)
- goto handle_error;
-
- /* This is a hack. We only need to call svn_wc_upgrade() on external
- * dirs, as file externals are upgraded along with their defining
- * WC. Reading the kind will throw an exception on an external dir,
- * saying that the wc must be upgraded. If it's a file, the lookup
- * is done in an adm_dir belonging to the defining wc (which has
- * already been upgraded) and no error is returned. If it doesn't
- * exist (external that isn't checked out yet), we'll just get
- * svn_node_none. */
- err = svn_wc_read_kind2(&external_kind, ctx->wc_ctx,
- external_abspath, TRUE, FALSE, iterpool2);
- if (err && err->apr_err == SVN_ERR_WC_UPGRADE_REQUIRED)
- {
- svn_error_clear(err);
-
- err = svn_client_upgrade(external_abspath, ctx, iterpool2);
- if (err)
- goto handle_error;
- }
- else if (err)
- goto handle_error;
-
- /* The upgrade of any dir should be done now, get the now reliable
- * kind. */
- err = svn_wc_read_kind2(&external_kind, ctx->wc_ctx, external_abspath,
- TRUE, FALSE, iterpool2);
- if (err)
- goto handle_error;
-
- /* Update the EXTERNALS table according to the root URL,
- * relpath and uuid known in the upgraded external WC. */
-
- /* We should probably have a function that provides all three
- * of root URL, repos relpath and uuid at once, but here goes... */
-
- /* First get the relpath, as that returns SVN_ERR_WC_PATH_NOT_FOUND
- * when the node is not present in the file system.
- * svn_wc__node_get_repos_info() would try to derive the URL. */
- err = svn_wc__node_get_repos_info(NULL,
- &repos_relpath,
- &repos_root_url,
- &repos_uuid,
- ctx->wc_ctx,
- external_abspath,
- iterpool2, iterpool2);
- if (err)
- goto handle_error;
-
- /* If we haven't got any information from the checked out external,
- * or if the URL information mismatches the external's definition,
- * ask fetch_repos_info() to find out the repos root. */
- if (0 != strcmp(resolved_url,
- svn_path_url_add_component2(repos_root_url,
- repos_relpath,
- scratch_pool)))
- {
- err = fetch_repos_info(&repos_root_url,
- &repos_uuid,
- info_baton,
- resolved_url,
- scratch_pool, scratch_pool);
- if (err)
- goto handle_error;
-
- repos_relpath = svn_uri_skip_ancestor(repos_root_url,
- resolved_url,
- iterpool2);
-
- /* There's just the URL, no idea what kind the external is.
- * That's fine, as the external isn't even checked out yet.
- * The kind will be set during the next 'update'. */
- external_kind = svn_node_unknown;
- }
-
- if (err)
- goto handle_error;
+ err = upgrade_external_item(ctx, externals_parent_abspath,
+ externals_parent_url,
+ externals_parent_repos_root_url,
+ item, info_baton, iterpool2);
- peg_revision = (item->peg_revision.kind == svn_opt_revision_number
- ? item->peg_revision.value.number
- : SVN_INVALID_REVNUM);
-
- revision = (item->revision.kind == svn_opt_revision_number
- ? item->revision.value.number
- : SVN_INVALID_REVNUM);
-
- err = svn_wc__upgrade_add_external_info(ctx->wc_ctx,
- external_abspath,
- external_kind,
- externals_parent,
- repos_relpath,
- repos_root_url,
- repos_uuid,
- peg_revision,
- revision,
- iterpool2);
-handle_error:
if (err)
{
svn_wc_notify_t *notify =
- svn_wc_create_notify(external_abspath,
+ svn_wc_create_notify(svn_dirent_join(externals_parent_abspath,
+ item->target_dir,
+ iterpool2),
svn_wc_notify_failed_external,
scratch_pool);
notify->err = err;
Modified: subversion/branches/move-tracking-2/subversion/libsvn_diff/diff_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_diff/diff_file.c?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_diff/diff_file.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_diff/diff_file.c Tue Oct 6 08:46:43 2015
@@ -1242,17 +1242,20 @@ svn_diff_file_options_parse(svn_diff_fil
{
apr_getopt_t *os;
struct opt_parsing_error_baton_t opt_parsing_error_baton;
- /* Make room for each option (starting at index 1) plus trailing NULL. */
- const char **argv = apr_palloc(pool, sizeof(char*) * (args->nelts + 2));
+ apr_array_header_t *argv;
opt_parsing_error_baton.err = NULL;
opt_parsing_error_baton.pool = pool;
- argv[0] = "";
- memcpy(argv + 1, args->elts, sizeof(char*) * args->nelts);
- argv[args->nelts + 1] = NULL;
-
- apr_getopt_init(&os, pool, args->nelts + 1, argv);
+ /* Make room for each option (starting at index 1) plus trailing NULL. */
+ argv = apr_array_make(pool, args->nelts + 2, sizeof(char*));
+ APR_ARRAY_PUSH(argv, const char *) = "";
+ apr_array_cat(argv, args);
+ APR_ARRAY_PUSH(argv, const char *) = NULL;
+
+ apr_getopt_init(&os, pool,
+ argv->nelts - 1 /* Exclude trailing NULL */,
+ (const char *const *) argv->elts);
/* Capture any error message from apr_getopt_long(). This will typically
* say which option is wrong, which we would not otherwise know. */
@@ -1416,6 +1419,10 @@ typedef struct svn_diff__file_output_bat
int context_size;
+ /* Cancel handler */
+ svn_cancel_func_t cancel_func;
+ void *cancel_baton;
+
apr_pool_t *pool;
} svn_diff__file_output_baton_t;
@@ -1597,10 +1604,15 @@ static APR_INLINE svn_error_t *
output_unified_diff_range(svn_diff__file_output_baton_t *output_baton,
int source,
svn_diff__file_output_unified_type_e type,
- apr_off_t until)
+ apr_off_t until,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton)
{
while (output_baton->current_line[source] < until)
{
+ if (cancel_func)
+ SVN_ERR(cancel_func(cancel_baton));
+
SVN_ERR(output_unified_line(output_baton, type, source));
}
return SVN_NO_ERROR;
@@ -1626,7 +1638,8 @@ output_unified_flush_hunk(svn_diff__file
/* Add trailing context to the hunk */
SVN_ERR(output_unified_diff_range(baton, 0 /* original */,
svn_diff__file_output_unified_context,
- target_line));
+ target_line,
+ baton->cancel_func, baton->cancel_baton));
old_start = baton->hunk_start[0];
new_start = baton->hunk_start[1];
@@ -1714,7 +1727,9 @@ output_unified_diff_modified(void *baton
/* Original: Output the context preceding the changed range */
SVN_ERR(output_unified_diff_range(output_baton, 0 /* original */,
svn_diff__file_output_unified_context,
- original_start));
+ original_start,
+ output_baton->cancel_func,
+ output_baton->cancel_baton));
}
}
@@ -1722,7 +1737,9 @@ output_unified_diff_modified(void *baton
to display */
SVN_ERR(output_unified_diff_range(output_baton, 0 /* original */,
svn_diff__file_output_unified_skip,
- original_start - context_prefix_length));
+ original_start - context_prefix_length,
+ output_baton->cancel_func,
+ output_baton->cancel_baton));
/* Note that the above skip stores data for the show_c_function support below */
@@ -1768,20 +1785,28 @@ output_unified_diff_modified(void *baton
/* Modified: Skip lines until we are at the start of the changed range */
SVN_ERR(output_unified_diff_range(output_baton, 1 /* modified */,
svn_diff__file_output_unified_skip,
- modified_start));
+ modified_start,
+ output_baton->cancel_func,
+ output_baton->cancel_baton));
/* Original: Output the context preceding the changed range */
SVN_ERR(output_unified_diff_range(output_baton, 0 /* original */,
svn_diff__file_output_unified_context,
- original_start));
+ original_start,
+ output_baton->cancel_func,
+ output_baton->cancel_baton));
/* Both: Output the changed range */
SVN_ERR(output_unified_diff_range(output_baton, 0 /* original */,
svn_diff__file_output_unified_delete,
- original_start + original_length));
+ original_start + original_length,
+ output_baton->cancel_func,
+ output_baton->cancel_baton));
SVN_ERR(output_unified_diff_range(output_baton, 1 /* modified */,
svn_diff__file_output_unified_insert,
- modified_start + modified_length));
+ modified_start + modified_length,
+ output_baton->cancel_func,
+ output_baton->cancel_baton));
return SVN_NO_ERROR;
}
@@ -1842,6 +1867,8 @@ svn_diff_file_output_unified4(svn_stream
memset(&baton, 0, sizeof(baton));
baton.output_stream = output_stream;
+ baton.cancel_func = cancel_func;
+ baton.cancel_baton = cancel_baton;
baton.pool = pool;
baton.header_encoding = header_encoding;
baton.path[0] = original_path;
Modified: subversion/branches/move-tracking-2/subversion/libsvn_diff/parse-diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_diff/parse-diff.c?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_diff/parse-diff.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_diff/parse-diff.c Tue Oct 6 08:46:43 2015
@@ -64,7 +64,7 @@ struct svn_diff__hunk_range {
struct svn_diff_hunk_t {
/* The patch this hunk belongs to. */
- svn_patch_t *patch;
+ const svn_patch_t *patch;
/* APR file handle to the patch file this hunk came from. */
apr_file_t *apr_file;
@@ -93,7 +93,7 @@ struct svn_diff_hunk_t {
struct svn_diff_binary_patch_t {
/* The patch this hunk belongs to. */
- svn_patch_t *patch;
+ const svn_patch_t *patch;
/* APR file handle to the patch file this hunk came from. */
apr_file_t *apr_file;
@@ -117,7 +117,7 @@ struct svn_diff_binary_patch_t {
static svn_error_t *
add_or_delete_single_line(svn_diff_hunk_t **hunk_out,
const char *line,
- svn_patch_t *patch,
+ const svn_patch_t *patch,
svn_boolean_t add,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
@@ -202,11 +202,12 @@ add_or_delete_single_line(svn_diff_hunk_
svn_error_t *
svn_diff_hunk__create_adds_single_line(svn_diff_hunk_t **hunk_out,
const char *line,
- svn_patch_t *patch,
+ const svn_patch_t *patch,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- SVN_ERR(add_or_delete_single_line(hunk_out, line, patch, TRUE,
+ SVN_ERR(add_or_delete_single_line(hunk_out, line, patch,
+ (!patch->reverse),
result_pool, scratch_pool));
return SVN_NO_ERROR;
}
@@ -214,11 +215,12 @@ svn_diff_hunk__create_adds_single_line(s
svn_error_t *
svn_diff_hunk__create_deletes_single_line(svn_diff_hunk_t **hunk_out,
const char *line,
- svn_patch_t *patch,
+ const svn_patch_t *patch,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
- SVN_ERR(add_or_delete_single_line(hunk_out, line, patch, FALSE,
+ SVN_ERR(add_or_delete_single_line(hunk_out, line, patch,
+ patch->reverse,
result_pool, scratch_pool));
return SVN_NO_ERROR;
}
@@ -653,6 +655,7 @@ hunk_readline_original_or_modified(apr_f
apr_off_t pos;
svn_stringbuf_t *str;
const char *eol_p;
+ apr_pool_t *last_pool;
if (!eol)
eol = &eol_p;
@@ -669,13 +672,19 @@ hunk_readline_original_or_modified(apr_f
pos = 0;
SVN_ERR(svn_io_file_seek(file, APR_CUR, &pos, scratch_pool));
SVN_ERR(svn_io_file_seek(file, APR_SET, &range->current, scratch_pool));
+
+ /* It's not ITERPOOL because we use data allocated in LAST_POOL out
+ of the loop. */
+ last_pool = svn_pool_create(scratch_pool);
do
{
+ svn_pool_clear(last_pool);
+
max_len = range->end - range->current;
SVN_ERR(svn_io_file_readline(file, &str, eol, eof, max_len,
- result_pool, scratch_pool));
+ last_pool, last_pool));
range->current = 0;
- SVN_ERR(svn_io_file_seek(file, APR_CUR, &range->current, scratch_pool));
+ SVN_ERR(svn_io_file_seek(file, APR_CUR, &range->current, last_pool));
filtered = (str->data[0] == verboten || str->data[0] == '\\');
}
while (filtered && ! *eof);
@@ -697,7 +706,7 @@ hunk_readline_original_or_modified(apr_f
*stringbuf = svn_stringbuf_dup(str, result_pool);
}
- if (!filtered && *eof && !*eol && !no_final_eol && *str->data)
+ if (!filtered && *eof && !*eol && *str->data)
{
/* Ok, we miss a final EOL in the patch file, but didn't see a
no eol marker line.
@@ -705,7 +714,7 @@ hunk_readline_original_or_modified(apr_f
We should report that we had an EOL or the patch code will
misbehave (and it knows nothing about no eol markers) */
- if (eol != &eol_p)
+ if (!no_final_eol && eol != &eol_p)
{
apr_off_t start = 0;
@@ -723,6 +732,7 @@ hunk_readline_original_or_modified(apr_f
}
SVN_ERR(svn_io_file_seek(file, APR_SET, &pos, scratch_pool));
+ svn_pool_destroy(last_pool);
return SVN_NO_ERROR;
}
@@ -1139,12 +1149,12 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
}
SVN_ERR(svn_io_file_seek(apr_file, APR_SET, &pos, iterpool));
+ /* Set for the type and context by using != the other type */
+ if (last_line_type != modified_line)
+ original_no_final_eol = TRUE;
+ if (last_line_type != original_line)
+ modified_no_final_eol = TRUE;
}
- /* Set for the type and context by using != the other type */
- if (last_line_type != modified_line)
- original_no_final_eol = TRUE;
- if (last_line_type != original_line)
- modified_no_final_eol = TRUE;
continue;
}
@@ -1157,7 +1167,13 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
SVN_ERR(parse_mergeinfo(&found_mergeinfo, line, *hunk, patch,
result_pool, iterpool));
if (found_mergeinfo)
- continue; /* Proceed to the next line in the patch. */
+ continue; /* Proceed to the next line in the svn:mergeinfo hunk. */
+ else
+ {
+ /* Perhaps we can also use original_lines/modified_lines here */
+
+ in_hunk = FALSE; /* On to next property */
+ }
}
if (in_hunk)
@@ -1590,10 +1606,11 @@ git_plus(enum parse_state *new_state, ch
}
/* Helper for git_old_mode() and git_new_mode(). Translate the git
- * file mode MODE_STR into a binary "executable?" notion EXECUTABLE_P. */
+ * file mode MODE_STR into a binary "executable?" and "symlink?" state. */
static svn_error_t *
-parse_bits_into_executability(svn_tristate_t *executable_p,
- const char *mode_str)
+parse_git_mode_bits(svn_tristate_t *executable_p,
+ svn_tristate_t *symlink_p,
+ const char *mode_str)
{
apr_uint64_t mode;
SVN_ERR(svn_cstring_strtoui64(&mode, mode_str,
@@ -1629,6 +1646,24 @@ parse_bits_into_executability(svn_trista
break;
}
+ switch (mode & 0170000 /* S_IFMT */)
+ {
+ case 0120000: /* S_IFLNK */
+ *symlink_p = svn_tristate_true;
+ break;
+
+ case 0100000: /* S_IFREG */
+ case 0040000: /* S_IFDIR */
+ *symlink_p = svn_tristate_false;
+ break;
+
+ default:
+ /* Ignore unknown values.
+ (Including those generated by Subversion <= 1.9) */
+ *symlink_p = svn_tristate_unknown;
+ break;
+ }
+
return SVN_NO_ERROR;
}
@@ -1637,12 +1672,13 @@ static svn_error_t *
git_old_mode(enum parse_state *new_state, char *line, svn_patch_t *patch,
apr_pool_t *result_pool, apr_pool_t *scratch_pool)
{
- SVN_ERR(parse_bits_into_executability(&patch->old_executable_p,
- line + STRLEN_LITERAL("old mode ")));
+ SVN_ERR(parse_git_mode_bits(&patch->old_executable_bit,
+ &patch->old_symlink_bit,
+ line + STRLEN_LITERAL("old mode ")));
#ifdef SVN_DEBUG
/* If this assert trips, the "old mode" is neither ...644 nor ...755 . */
- SVN_ERR_ASSERT(patch->old_executable_p != svn_tristate_unknown);
+ SVN_ERR_ASSERT(patch->old_executable_bit != svn_tristate_unknown);
#endif
*new_state = state_old_mode_seen;
@@ -1654,12 +1690,13 @@ static svn_error_t *
git_new_mode(enum parse_state *new_state, char *line, svn_patch_t *patch,
apr_pool_t *result_pool, apr_pool_t *scratch_pool)
{
- SVN_ERR(parse_bits_into_executability(&patch->new_executable_p,
- line + STRLEN_LITERAL("new mode ")));
+ SVN_ERR(parse_git_mode_bits(&patch->new_executable_bit,
+ &patch->new_symlink_bit,
+ line + STRLEN_LITERAL("new mode ")));
#ifdef SVN_DEBUG
/* If this assert trips, the "old mode" is neither ...644 nor ...755 . */
- SVN_ERR_ASSERT(patch->new_executable_p != svn_tristate_unknown);
+ SVN_ERR_ASSERT(patch->new_executable_bit != svn_tristate_unknown);
#endif
/* Don't touch patch->operation. */
@@ -1668,6 +1705,39 @@ git_new_mode(enum parse_state *new_state
return SVN_NO_ERROR;
}
+static svn_error_t *
+git_index(enum parse_state *new_state, char *line, svn_patch_t *patch,
+ apr_pool_t *result_pool, apr_pool_t *scratch_pool)
+{
+ /* We either have something like "index 33e5b38..0000000" (which we just
+ ignore as we are not interested in git specific shas) or something like
+ "index 33e5b38..0000000 120000" which tells us the mode, that isn't
+ changed by applying this patch.
+
+ If the mode would have changed then we would see 'old mode' and 'new mode'
+ lines.
+ */
+ line = strchr(line + STRLEN_LITERAL("index "), ' ');
+
+ if (line && patch->new_executable_bit == svn_tristate_unknown
+ && patch->new_symlink_bit == svn_tristate_unknown
+ && patch->operation != svn_diff_op_added
+ && patch->operation != svn_diff_op_deleted)
+ {
+ SVN_ERR(parse_git_mode_bits(&patch->new_executable_bit,
+ &patch->new_symlink_bit,
+ line + 1));
+
+ /* There is no change.. so set the old values to the new values */
+ patch->old_executable_bit = patch->new_executable_bit;
+ patch->old_symlink_bit = patch->new_symlink_bit;
+ }
+
+ /* This function doesn't change the state! */
+ /* *new_state = *new_state */
+ return SVN_NO_ERROR;
+}
+
/* Parse the 'rename from ' line of a git extended unidiff. */
static svn_error_t *
git_move_from(enum parse_state *new_state, char *line, svn_patch_t *patch,
@@ -1728,9 +1798,9 @@ static svn_error_t *
git_new_file(enum parse_state *new_state, char *line, svn_patch_t *patch,
apr_pool_t *result_pool, apr_pool_t *scratch_pool)
{
- SVN_ERR(
- parse_bits_into_executability(&patch->new_executable_p,
- line + STRLEN_LITERAL("new file mode ")));
+ SVN_ERR(parse_git_mode_bits(&patch->new_executable_bit,
+ &patch->new_symlink_bit,
+ line + STRLEN_LITERAL("new file mode ")));
patch->operation = svn_diff_op_added;
@@ -1745,9 +1815,9 @@ static svn_error_t *
git_deleted_file(enum parse_state *new_state, char *line, svn_patch_t *patch,
apr_pool_t *result_pool, apr_pool_t *scratch_pool)
{
- SVN_ERR(
- parse_bits_into_executability(&patch->old_executable_p,
- line + STRLEN_LITERAL("deleted file mode ")));
+ SVN_ERR(parse_git_mode_bits(&patch->old_executable_bit,
+ &patch->old_symlink_bit,
+ line + STRLEN_LITERAL("deleted file mode ")));
patch->operation = svn_diff_op_deleted;
@@ -1762,8 +1832,6 @@ static svn_error_t *
binary_patch_start(enum parse_state *new_state, char *line, svn_patch_t *patch,
apr_pool_t *result_pool, apr_pool_t *scratch_pool)
{
- patch->operation = svn_diff_op_modified;
-
*new_state = state_binary_patch_found;
return SVN_NO_ERROR;
}
@@ -1896,7 +1964,6 @@ parse_binary_patch(svn_patch_t *patch, a
bpatch->apr_file = apr_file;
- patch->operation = svn_diff_op_modified;
patch->prop_patches = apr_hash_make(result_pool);
pos = 0;
@@ -2034,8 +2101,13 @@ static struct transition transitions[] =
{"deleted file ", state_git_diff_seen, git_deleted_file},
+ {"index ", state_git_diff_seen, git_index},
+ {"index ", state_git_tree_seen, git_index},
+ {"index ", state_git_mode_seen, git_index},
+
{"GIT binary patch", state_git_diff_seen, binary_patch_start},
{"GIT binary patch", state_git_tree_seen, binary_patch_start},
+ {"GIT binary patch", state_git_mode_seen, binary_patch_start},
};
svn_error_t *
@@ -2061,8 +2133,10 @@ svn_diff_parse_next_patch(svn_patch_t **
}
patch = apr_pcalloc(result_pool, sizeof(*patch));
- patch->old_executable_p = svn_tristate_unknown;
- patch->new_executable_p = svn_tristate_unknown;
+ patch->old_executable_bit = svn_tristate_unknown;
+ patch->new_executable_bit = svn_tristate_unknown;
+ patch->old_symlink_bit = svn_tristate_unknown;
+ patch->new_symlink_bit = svn_tristate_unknown;
pos = patch_file->next_patch_offset;
SVN_ERR(svn_io_file_seek(patch_file->apr_file, APR_SET, &pos, scratch_pool));
@@ -2113,17 +2187,13 @@ svn_diff_parse_next_patch(svn_patch_t **
&& line_after_tree_header_read
&& !valid_header_line)
{
- /* git patches can contain an index line after the file mode line */
- if (!starts_with(line->data, "index "))
- {
- /* We have a valid diff header for a patch with only tree changes.
- * Rewind to the start of the line just read, so subsequent calls
- * to this function don't end up skipping the line -- it may
- * contain a patch. */
- SVN_ERR(svn_io_file_seek(patch_file->apr_file, APR_SET, &last_line,
- scratch_pool));
- break;
- }
+ /* We have a valid diff header for a patch with only tree changes.
+ * Rewind to the start of the line just read, so subsequent calls
+ * to this function don't end up skipping the line -- it may
+ * contain a patch. */
+ SVN_ERR(svn_io_file_seek(patch_file->apr_file, APR_SET, &last_line,
+ scratch_pool));
+ break;
}
else if (state == state_git_tree_seen
|| state == state_git_mode_seen)
@@ -2131,8 +2201,7 @@ svn_diff_parse_next_patch(svn_patch_t **
line_after_tree_header_read = TRUE;
}
else if (! valid_header_line && state != state_start
- && state != state_git_diff_seen
- && !starts_with(line->data, "index "))
+ && state != state_git_diff_seen)
{
/* We've encountered an invalid diff header.
*
@@ -2172,9 +2241,13 @@ svn_diff_parse_next_patch(svn_patch_t **
break; /* Stays modify */
}
- ts_tmp = patch->old_executable_p;
- patch->old_executable_p = patch->new_executable_p;
- patch->new_executable_p = ts_tmp;
+ ts_tmp = patch->old_executable_bit;
+ patch->old_executable_bit = patch->new_executable_bit;
+ patch->new_executable_bit = ts_tmp;
+
+ ts_tmp = patch->old_symlink_bit;
+ patch->old_symlink_bit = patch->new_symlink_bit;
+ patch->new_symlink_bit = ts_tmp;
}
if (patch->old_filename == NULL || patch->new_filename == NULL)
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_base/tree.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_base/tree.c?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_base/tree.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_base/tree.c Tue Oct 6 08:46:43 2015
@@ -68,6 +68,7 @@
#include "private/svn_fspath.h"
#include "private/svn_fs_util.h"
#include "private/svn_mergeinfo_private.h"
+#include "private/svn_sorts_private.h"
/* ### I believe this constant will become internal to reps-strings.c.
@@ -2580,8 +2581,7 @@ verify_locks(const char *txn_name,
apr_hash_this(hi, &key, NULL, NULL);
APR_ARRAY_PUSH(changed_paths, const char *) = key;
}
- qsort(changed_paths->elts, changed_paths->nelts,
- changed_paths->elt_size, svn_sort_compare_paths);
+ svn_sort__array(changed_paths, svn_sort_compare_paths);
/* Now, traverse the array of changed paths, verify locks. Note
that if we need to do a recursive verification a path, we'll skip
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/cached_data.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/cached_data.c?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/cached_data.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/cached_data.c Tue Oct 6 08:46:43 2015
@@ -2636,27 +2636,27 @@ locate_dir_cache(svn_fs_t *fs,
apr_pool_t *pool)
{
fs_fs_data_t *ffd = fs->fsap_data;
- if (svn_fs_fs__id_is_txn(noderev->id))
+ if (!noderev->data_rep)
+ {
+ /* no data rep -> empty directory.
+ A NULL key causes a cache miss. */
+ *key = NULL;
+ return ffd->dir_cache;
+ }
+
+ if (svn_fs_fs__id_txn_used(&noderev->data_rep->txn_id))
{
/* data in txns requires the expensive fs_id-based addressing mode */
*key = svn_fs_fs__id_unparse(noderev->id, pool)->data;
+
return ffd->txn_dir_cache;
}
else
{
/* committed data can use simple rev,item pairs */
- if (noderev->data_rep)
- {
- pair_key->revision = noderev->data_rep->revision;
- pair_key->second = noderev->data_rep->item_index;
- *key = pair_key;
- }
- else
- {
- /* no data rep -> empty directory.
- A NULL key causes a cache miss. */
- *key = NULL;
- }
+ pair_key->revision = noderev->data_rep->revision;
+ pair_key->second = noderev->data_rep->item_index;
+ *key = pair_key;
return ffd->dir_cache;
}
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/pack.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/pack.c?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/pack.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/pack.c Tue Oct 6 08:46:43 2015
@@ -108,8 +108,8 @@ typedef struct path_order_t
/* noderev predecessor count */
int predecessor_count;
- /* this is a directory node */
- svn_boolean_t is_dir;
+ /* this is a node is the latest for this PATH in this rev / pack file */
+ svn_boolean_t is_head;
/* length of the expanded representation content */
apr_int64_t expanded_size;
@@ -746,7 +746,6 @@ copy_node_to_temp(pack_context_t *contex
path_order->node_id = *svn_fs_fs__id_node_id(noderev->id);
path_order->revision = svn_fs_fs__id_rev(noderev->id);
path_order->predecessor_count = noderev->predecessor_count;
- path_order->is_dir = noderev->kind == svn_node_dir;
path_order->noderev_id = *svn_fs_fs__id_rev_item(noderev->id);
APR_ARRAY_PUSH(context->path_order, path_order_t *) = path_order;
@@ -763,13 +762,8 @@ compare_path_order(const path_order_t *
const path_order_t * lhs = *lhs_p;
const path_order_t * rhs = *rhs_p;
- /* cluster all directories */
- int diff = rhs->is_dir - lhs->is_dir;
- if (diff)
- return diff;
-
/* lexicographic order on path and node (i.e. latest first) */
- diff = svn_prefix_string__compare(lhs->path, rhs->path);
+ int diff = svn_prefix_string__compare(lhs->path, rhs->path);
if (diff)
return diff;
@@ -816,6 +810,41 @@ roundness(int value)
return value ? value - (value & (value - 1)) : INT_MAX;
}
+/* For all paths in first COUNT entries in PATH_ORDER, mark their latest
+ * node as "HEAD". PATH_ORDER must be ordered by path, revision.
+ */
+static void
+classify_nodes(path_order_t **path_order,
+ int count)
+{
+ const svn_prefix_string__t *path;
+ int i;
+
+ /* The logic below would fail for empty ranges. */
+ if (count == 0)
+ return;
+
+ /* All entries are sorted by path, followed by revision.
+ * So, the first index is also HEAD for the first path.
+ */
+ path = path_order[0]->path;
+ path_order[0]->is_head = TRUE;
+
+ /* Since the sorting implicitly groups all entries by path and then sorts
+ * by descending revision within the group, whenever we encounter a new
+ * path, the first entry is "HEAD" for that path.
+ */
+ for (i = 1; i < count; ++i)
+ {
+ /* New path? */
+ if (svn_prefix_string__compare(path, path_order[i]->path))
+ {
+ path = path_order[i]->path;
+ path_order[i]->is_head = TRUE;
+ }
+ }
+}
+
/* Order a range of data collected in CONTEXT such that we can place them
* in the desired order. The input is taken from *PATH_ORDER, offsets FIRST
* to LAST and then written in the final order to the same range in *TEMP.
@@ -953,7 +982,7 @@ static void
sort_reps(pack_context_t *context)
{
apr_pool_t *temp_pool;
- const path_order_t **temp, **path_order;
+ path_order_t **temp, **path_order;
int i, count;
/* We will later assume that there is at least one node / path.
@@ -979,7 +1008,10 @@ sort_reps(pack_context_t *context)
temp = apr_pcalloc(temp_pool, count * sizeof(*temp));
path_order = (void *)context->path_order->elts;
- /* Sort those sub-sections separately. */
+ /* Mark nodes depending on what other nodes exist for the same path etc. */
+ classify_nodes(path_order, count);
+
+ /* Rearrange those sub-sections separately. */
sort_reps_range(context, path_order, temp, 0, count);
/* We now know the final ordering. */
@@ -1147,7 +1179,7 @@ copy_reps_from_temp(pack_context_t *cont
apr_array_header_t *path_order = context->path_order;
int i;
- /* copy items in path order. */
+ /* copy items in path order. Exclude the non-HEAD noderevs. */
for (i = 0; i < path_order->nelts; ++i)
{
path_order_t *current_path;
@@ -1157,13 +1189,30 @@ copy_reps_from_temp(pack_context_t *cont
svn_pool_clear(iterpool);
current_path = APR_ARRAY_IDX(path_order, i, path_order_t *);
- node_part = get_item(context, ¤t_path->noderev_id, TRUE);
+ if (current_path->is_head)
+ {
+ node_part = get_item(context, ¤t_path->noderev_id, TRUE);
+ if (node_part)
+ SVN_ERR(store_item(context, temp_file, node_part, iterpool));
+ }
+
rep_part = get_item(context, ¤t_path->rep_id, TRUE);
+ if (rep_part)
+ SVN_ERR(store_item(context, temp_file, rep_part, iterpool));
+ }
+ /* copy the remaining non-head noderevs. */
+ for (i = 0; i < path_order->nelts; ++i)
+ {
+ path_order_t *current_path;
+ svn_fs_fs__p2l_entry_t *node_part;
+
+ svn_pool_clear(iterpool);
+
+ current_path = APR_ARRAY_IDX(path_order, i, path_order_t *);
+ node_part = get_item(context, ¤t_path->noderev_id, TRUE);
if (node_part)
SVN_ERR(store_item(context, temp_file, node_part, iterpool));
- if (rep_part)
- SVN_ERR(store_item(context, temp_file, rep_part, iterpool));
}
svn_pool_destroy(iterpool);
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/stats.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/stats.c?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/stats.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/stats.c Tue Oct 6 08:46:43 2015
@@ -70,8 +70,9 @@ typedef enum rep_kind_t
*/
typedef struct rep_stats_t
{
- /* absolute offset in the file */
- apr_off_t offset;
+ /* offset in the revision file (phys. addressing) /
+ * item index within REVISION (log. addressing) */
+ apr_uint64_t item_index;
/* item length in bytes */
apr_uint64_t size;
@@ -92,8 +93,36 @@ typedef struct rep_stats_t
/* classification of the representation. values of rep_kind_t */
char kind;
+ /* length of the delta chain, including this representation,
+ * saturated to 255 - if need be */
+ apr_byte_t chain_length;
} rep_stats_t;
+/* Represents a link in the rep delta chain. REVISION + ITEM_INDEX points
+ * to BASE_REVISION + BASE_ITEM_INDEX. We collect this info while scanning
+ * a f7 repo in a single pass and resolve it afterwards. */
+typedef struct rep_ref_t
+{
+ /* Revision that contains this representation. */
+ svn_revnum_t revision;
+
+ /* Item index of this rep within REVISION. */
+ apr_uint64_t item_index;
+
+ /* Revision of the representation we deltified against.
+ * -1 if this representation is either PLAIN or a self-delta. */
+ svn_revnum_t base_revision;
+
+ /* Item index of that rep within BASE_REVISION. */
+ apr_uint64_t base_item_index;
+
+ /* Length of the PLAIN / DELTA line in the source file in bytes.
+ * We use this to update the info in the rep stats after scanning the
+ * whole file. */
+ apr_uint16_t header_size;
+
+} rep_ref_t;
+
/* Represents a single revision.
* There will be only one instance per revision. */
typedef struct revision_info_t
@@ -328,13 +357,13 @@ add_change(svn_fs_fs__stats_t *stats,
/* Comparator used for binary search comparing the absolute file offset
* of a representation to some other offset. DATA is a *rep_stats_t,
- * KEY is a pointer to an apr_off_t.
+ * KEY is a pointer to an apr_uint64_t.
*/
static int
-compare_representation_offsets(const void *data, const void *key)
+compare_representation_item_index(const void *data, const void *key)
{
- apr_off_t lhs = (*(const rep_stats_t *const *)data)->offset;
- apr_off_t rhs = *(const apr_off_t *)key;
+ apr_uint64_t lhs = (*(const rep_stats_t *const *)data)->item_index;
+ apr_uint64_t rhs = *(const apr_uint64_t *)key;
if (lhs < rhs)
return -1;
@@ -345,7 +374,7 @@ compare_representation_offsets(const voi
* return it in *REVISION_INFO. For performance reasons, we skip the
* lookup if the info is already provided.
*
- * In that revision, look for the rep_stats_t object for offset OFFSET.
+ * In that revision, look for the rep_stats_t object for item ITEM_INDEX.
* If it already exists, set *IDX to its index in *REVISION_INFO's
* representations list and return the representation object. Otherwise,
* set the index to where it must be inserted and return NULL.
@@ -355,7 +384,7 @@ find_representation(int *idx,
query_t *query,
revision_info_t **revision_info,
svn_revnum_t revision,
- apr_off_t offset)
+ apr_uint64_t item_index)
{
revision_info_t *info;
*idx = -1;
@@ -375,14 +404,14 @@ find_representation(int *idx,
/* look for the representation */
*idx = svn_sort__bsearch_lower_bound(info->representations,
- &offset,
- compare_representation_offsets);
+ &item_index,
+ compare_representation_item_index);
if (*idx < info->representations->nelts)
{
/* return the representation, if this is the one we were looking for */
rep_stats_t *result
= APR_ARRAY_IDX(info->representations, *idx, rep_stats_t *);
- if (result->offset == offset)
+ if (result->item_index == item_index)
return result;
}
@@ -411,7 +440,7 @@ parse_representation(rep_stats_t **repre
/* look it up */
result = find_representation(&idx, query, &revision_info, rep->revision,
- (apr_off_t)rep->item_index);
+ rep->item_index);
if (!result)
{
/* not parsed, yet (probably a rep in the same revision).
@@ -420,7 +449,7 @@ parse_representation(rep_stats_t **repre
result = apr_pcalloc(result_pool, sizeof(*result));
result->revision = rep->revision;
result->expanded_size = rep->expanded_size;
- result->offset = (apr_off_t)rep->item_index;
+ result->item_index = rep->item_index;
result->size = rep->size;
/* In phys. addressing mode, follow link to the actual representation.
@@ -429,7 +458,8 @@ parse_representation(rep_stats_t **repre
if (!svn_fs_fs__use_log_addressing(query->fs))
{
svn_fs_fs__rep_header_t *header;
- apr_off_t offset = revision_info->offset + result->offset;
+ apr_off_t offset = revision_info->offset
+ + (apr_off_t)rep->item_index;
SVN_ERR_ASSERT(revision_info->rev_file);
SVN_ERR(svn_io_file_seek(revision_info->rev_file->file, APR_SET,
@@ -439,6 +469,23 @@ parse_representation(rep_stats_t **repre
scratch_pool, scratch_pool));
result->header_size = header->header_size;
+
+ /* Determine length of the delta chain. */
+ if (header->type == svn_fs_fs__rep_delta)
+ {
+ int base_idx;
+ rep_stats_t *base_rep
+ = find_representation(&base_idx, query, NULL,
+ header->base_revision,
+ header->base_item_index);
+
+ result->chain_length = 1 + MIN(base_rep->chain_length,
+ (apr_byte_t)0xfe);
+ }
+ else
+ {
+ result->chain_length = 1;
+ }
}
svn_sort__array_insert(revision_info->representations, &result, idx);
@@ -867,6 +914,70 @@ read_item(svn_stringbuf_t **contents,
return SVN_NO_ERROR;
}
+/* Predicate comparing the two rep_ref_t** LHS and RHS by the respective
+ * representation's revision.
+ */
+static int
+compare_representation_refs(const void *lhs, const void *rhs)
+{
+ svn_revnum_t lhs_rev = (*(const rep_ref_t *const *)lhs)->revision;
+ svn_revnum_t rhs_rev = (*(const rep_ref_t *const *)rhs)->revision;
+
+ if (lhs_rev < rhs_rev)
+ return -1;
+ return (lhs_rev > rhs_rev ? 1 : 0);
+}
+
+/* Given all the presentations found in a single rev / pack file as
+ * rep_ref_t * in REP_REFS, update the delta chain lengths in QUERY.
+ * REP_REFS and its contents can then be discarded.
+ */
+static svn_error_t *
+resolve_representation_refs(query_t *query,
+ apr_array_header_t *rep_refs)
+{
+ int i;
+
+ /* Because delta chains can only point to previous revs, after sorting
+ * REP_REFS, all base refs have already been updated. */
+ svn_sort__array(rep_refs, compare_representation_refs);
+
+ /* Build up the CHAIN_LENGTH values. */
+ for (i = 0; i < rep_refs->nelts; ++i)
+ {
+ int idx;
+ rep_ref_t *ref = APR_ARRAY_IDX(rep_refs, i, rep_ref_t *);
+ rep_stats_t *rep = find_representation(&idx, query, NULL,
+ ref->revision, ref->item_index);
+
+ /* No dangling pointers and all base reps have been processed. */
+ SVN_ERR_ASSERT(rep);
+ SVN_ERR_ASSERT(!rep->chain_length);
+
+ /* Set the HEADER_SIZE as we found it during the scan. */
+ rep->header_size = ref->header_size;
+
+ /* The delta chain got 1 element longer. */
+ if (ref->base_revision == SVN_INVALID_REVNUM)
+ {
+ rep->chain_length = 1;
+ }
+ else
+ {
+ rep_stats_t *base;
+
+ base = find_representation(&idx, query, NULL, ref->base_revision,
+ ref->base_item_index);
+ SVN_ERR_ASSERT(base);
+ SVN_ERR_ASSERT(base->chain_length);
+
+ rep->chain_length = 1 + MIN(base->chain_length, (apr_byte_t)0xfe);
+ }
+ }
+
+ return SVN_NO_ERROR;
+}
+
/* Process the logically addressed revision contents of revisions BASE to
* BASE + COUNT - 1 in QUERY.
*
@@ -887,6 +998,12 @@ read_log_rev_or_packfile(query_t *query,
int i;
svn_fs_fs__revision_file_t *rev_file;
+ /* We collect the delta chain links as we scan the file. Afterwards,
+ * we determine the lengths of those delta chains and throw this
+ * temporary container away. */
+ apr_array_header_t *rep_refs = apr_array_make(scratch_pool, 64,
+ sizeof(rep_ref_t *));
+
/* we will process every revision in the rev / pack file */
for (i = 0; i < count; ++i)
{
@@ -929,6 +1046,8 @@ read_log_rev_or_packfile(query_t *query,
/* process all entries (and later continue with the next block) */
for (i = 0; i < entries->nelts; ++i)
{
+ svn_stringbuf_t *item;
+ revision_info_t *info;
svn_fs_fs__p2l_entry_t *entry
= &APR_ARRAY_IDX(entries, i, svn_fs_fs__p2l_entry_t);
@@ -941,32 +1060,64 @@ read_log_rev_or_packfile(query_t *query,
continue;
/* read and process interesting items */
+ info = APR_ARRAY_IDX(query->revisions, entry->item.revision,
+ revision_info_t*);
+
if (entry->type == SVN_FS_FS__ITEM_TYPE_NODEREV)
{
- svn_stringbuf_t *item;
- revision_info_t *info = APR_ARRAY_IDX(query->revisions,
- entry->item.revision,
- revision_info_t*);
SVN_ERR(read_item(&item, rev_file, entry, iterpool, iterpool));
SVN_ERR(read_noderev(query, item, info, result_pool, iterpool));
}
else if (entry->type == SVN_FS_FS__ITEM_TYPE_CHANGES)
{
- svn_stringbuf_t *item;
- revision_info_t *info = APR_ARRAY_IDX(query->revisions,
- entry->item.revision,
- revision_info_t*);
SVN_ERR(read_item(&item, rev_file, entry, iterpool, iterpool));
info->change_count
= get_log_change_count(item->data + 0, item->len);
info->changes_len += entry->size;
}
+ else if ( (entry->type == SVN_FS_FS__ITEM_TYPE_FILE_REP)
+ || (entry->type == SVN_FS_FS__ITEM_TYPE_DIR_REP)
+ || (entry->type == SVN_FS_FS__ITEM_TYPE_FILE_PROPS)
+ || (entry->type == SVN_FS_FS__ITEM_TYPE_DIR_PROPS))
+ {
+ /* Collect the delta chain link. */
+ svn_fs_fs__rep_header_t *header;
+ rep_ref_t *ref = apr_pcalloc(scratch_pool, sizeof(*ref));
+
+ SVN_ERR(svn_io_file_aligned_seek(rev_file->file,
+ rev_file->block_size,
+ NULL, entry->offset,
+ iterpool));
+ SVN_ERR(svn_fs_fs__read_rep_header(&header,
+ rev_file->stream,
+ iterpool, iterpool));
+
+ ref->header_size = header->header_size;
+ ref->revision = entry->item.revision;
+ ref->item_index = entry->item.number;
+
+ if (header->type == svn_fs_fs__rep_delta)
+ {
+ ref->base_item_index = header->base_item_index;
+ ref->base_revision = header->base_revision;
+ }
+ else
+ {
+ ref->base_item_index = SVN_FS_FS__ITEM_INDEX_UNUSED;
+ ref->base_revision = SVN_INVALID_REVNUM;
+ }
+
+ APR_ARRAY_PUSH(rep_refs, rep_ref_t *) = ref;
+ }
/* advance offset */
offset += entry->size;
}
}
+ /* Resolve the delta chain links. */
+ SVN_ERR(resolve_representation_refs(query, rep_refs));
+
/* clean up and close file handles */
svn_pool_destroy(iterpool);
@@ -1093,6 +1244,7 @@ add_rep_stats(svn_fs_fs__representation_
stats->references += rep->ref_count;
stats->expanded_size += rep->ref_count * rep->expanded_size;
+ stats->chain_len += rep->chain_length;
}
/* Aggregate the info the in revision_info_t * array REVISIONS into the
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/temp_serializer.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/temp_serializer.c?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/temp_serializer.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/temp_serializer.c Tue Oct 6 08:46:43 2015
@@ -1076,6 +1076,18 @@ svn_fs_fs__replace_dir_entry(void **data
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_fs_fs__reset_txn_filesize(void **data,
+ apr_size_t *data_len,
+ void *baton,
+ apr_pool_t *pool)
+{
+ dir_data_t *dir_data = (dir_data_t *)*data;
+ dir_data->txn_filesize = SVN_INVALID_FILESIZE;
+
+ return SVN_NO_ERROR;
+}
+
svn_error_t *
svn_fs_fs__serialize_rep_header(void **data,
apr_size_t *data_len,
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/temp_serializer.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/temp_serializer.h?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/temp_serializer.h (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/temp_serializer.h Tue Oct 6 08:46:43 2015
@@ -295,6 +295,17 @@ svn_fs_fs__replace_dir_entry(void **data
apr_pool_t *pool);
/**
+ * Implements #svn_cache__partial_setter_func_t for a #svn_fs_fs__dir_data_t
+ * at @a *data, resetting its txn_filesize field to SVN_INVALID_FILESIZE.
+ * &a baton should be NULL.
+ */
+svn_error_t *
+svn_fs_fs__reset_txn_filesize(void **data,
+ apr_size_t *data_len,
+ void *baton,
+ apr_pool_t *pool);
+
+/**
* Implements #svn_cache__serialize_func_t for a #svn_fs_fs__rep_header_t.
*/
svn_error_t *
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/transaction.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/transaction.c?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/transaction.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/transaction.c Tue Oct 6 08:46:43 2015
@@ -576,16 +576,62 @@ unparse_dir_entry(svn_fs_dirent_t *diren
svn_stream_t *stream,
apr_pool_t *pool)
{
- const char *val
- = apr_psprintf(pool, "%s %s",
- (dirent->kind == svn_node_file) ? SVN_FS_FS__KIND_FILE
- : SVN_FS_FS__KIND_DIR,
- svn_fs_fs__id_unparse(dirent->id, pool)->data);
-
- SVN_ERR(svn_stream_printf(stream, pool, "K %" APR_SIZE_T_FMT "\n%s\n"
- "V %" APR_SIZE_T_FMT "\n%s\n",
- strlen(dirent->name), dirent->name,
- strlen(val), val));
+ apr_size_t to_write;
+ svn_string_t *id_str = svn_fs_fs__id_unparse(dirent->id, pool);
+ apr_size_t name_len = strlen(dirent->name);
+
+ /* Note that sizeof == len + 1, i.e. accounts for the space between
+ * type and ID. */
+ apr_size_t type_len = (dirent->kind == svn_node_file)
+ ? sizeof(SVN_FS_FS__KIND_FILE)
+ : sizeof(SVN_FS_FS__KIND_DIR);
+ apr_size_t value_len = type_len + id_str->len;
+
+ /* A buffer with sufficient space for
+ * - both string lines
+ * - 4 newlines
+ * - 2 lines K/V lines containing a number each
+ */
+ char *buffer = apr_palloc(pool, name_len + value_len
+ + 4
+ + 2 * (2 + SVN_INT64_BUFFER_SIZE));
+
+ /* Now construct the value. */
+ char *p = buffer;
+
+ /* The "K length(name)\n" line. */
+ p[0] = 'K';
+ p[1] = ' ';
+ p += 2;
+ p += svn__i64toa(p, name_len);
+ *(p++) = '\n';
+
+ /* The line with the key, i.e. dir entry name. */
+ memcpy(p, dirent->name, name_len);
+ p += name_len;
+ *(p++) = '\n';
+
+ /* The "V length(type+id)\n" line. */
+ p[0] = 'V';
+ p[1] = ' ';
+ p += 2;
+ p += svn__i64toa(p, value_len);
+ *(p++) = '\n';
+
+ /* The line with the type and ID. */
+ memcpy(p,
+ (dirent->kind == svn_node_file) ? SVN_FS_FS__KIND_FILE
+ : SVN_FS_FS__KIND_DIR,
+ type_len - 1);
+ p += type_len - 1;
+ *(p++) = ' ';
+ memcpy(p, id_str->data, id_str->len);
+ p+=id_str->len;
+ *(p++) = '\n';
+
+ /* Add the entry to the output stream. */
+ to_write = p - buffer;
+ SVN_ERR(svn_stream_write(stream, buffer, &to_write));
return SVN_NO_ERROR;
}
@@ -1503,8 +1549,6 @@ svn_fs_fs__set_entry(svn_fs_t *fs,
out = svn_stream_from_aprfile2(file, TRUE, pool);
SVN_ERR(unparse_dir_entries(entries, out, subpool));
- svn_pool_clear(subpool);
-
/* Mark the node-rev's data rep as mutable. */
rep = apr_pcalloc(pool, sizeof(*rep));
rep->revision = SVN_INVALID_REVNUM;
@@ -1513,6 +1557,30 @@ svn_fs_fs__set_entry(svn_fs_t *fs,
parent_noderev->data_rep = rep;
SVN_ERR(svn_fs_fs__put_node_revision(fs, parent_noderev->id,
parent_noderev, FALSE, pool));
+
+ /* Immediately populate the txn dir cache to avoid re-reading
+ * the file we just wrote. */
+ if (ffd->txn_dir_cache)
+ {
+ const char *key
+ = svn_fs_fs__id_unparse(parent_noderev->id, subpool)->data;
+ svn_fs_fs__dir_data_t dir_data;
+ svn_filesize_t filesize;
+
+ /* Flush APR buffers. */
+ SVN_ERR(svn_io_file_flush(file, subpool));
+
+ /* Obtain final file size to update txn_dir_cache. */
+ SVN_ERR(svn_io_file_size_get(&filesize, file, subpool));
+
+ /* Store in the cache. */
+ dir_data.entries = entries;
+ dir_data.txn_filesize = filesize;
+ SVN_ERR(svn_cache__set(ffd->txn_dir_cache, key, &dir_data,
+ subpool));
+ }
+
+ svn_pool_clear(subpool);
}
else
{
@@ -2180,6 +2248,10 @@ get_shared_rep(representation_t **old_re
if (!ffd->rep_sharing_allowed)
return SVN_NO_ERROR;
+ /* Can't look up if we don't know the key (happens for directories). */
+ if (!rep->has_sha1)
+ return SVN_NO_ERROR;
+
/* Check and see if we already have a representation somewhere that's
identical to the one we just wrote out. Start with the hash lookup
because it is cheapest. */
@@ -2296,6 +2368,7 @@ get_shared_rep(representation_t **old_re
}
/* Copy the hash sum calculation results from MD5_CTX, SHA1_CTX into REP.
+ * SHA1 results are only be set if SHA1_CTX is not NULL.
* Use POOL for allocations.
*/
static svn_error_t *
@@ -2308,10 +2381,12 @@ digests_final(representation_t *rep,
SVN_ERR(svn_checksum_final(&checksum, md5_ctx, pool));
memcpy(rep->md5_digest, checksum->digest, svn_checksum_size(checksum));
- SVN_ERR(svn_checksum_final(&checksum, sha1_ctx, pool));
- rep->has_sha1 = checksum != NULL;
+ rep->has_sha1 = sha1_ctx != NULL;
if (rep->has_sha1)
- memcpy(rep->sha1_digest, checksum->digest, svn_checksum_size(checksum));
+ {
+ SVN_ERR(svn_checksum_final(&checksum, sha1_ctx, pool));
+ memcpy(rep->sha1_digest, checksum->digest, svn_checksum_size(checksum));
+ }
return SVN_NO_ERROR;
}
@@ -2516,6 +2591,8 @@ struct write_container_baton
apr_size_t size;
svn_checksum_ctx_t *md5_ctx;
+
+ /* SHA1 calculation is optional. If not needed, this will be NULL. */
svn_checksum_ctx_t *sha1_ctx;
};
@@ -2530,7 +2607,8 @@ write_container_handler(void *baton,
struct write_container_baton *whb = baton;
SVN_ERR(svn_checksum_update(whb->md5_ctx, data, *len));
- SVN_ERR(svn_checksum_update(whb->sha1_ctx, data, *len));
+ if (whb->sha1_ctx)
+ SVN_ERR(svn_checksum_update(whb->sha1_ctx, data, *len));
SVN_ERR(svn_stream_write(whb->stream, data, len));
whb->size += *len;
@@ -2602,7 +2680,8 @@ write_container_rep(representation_t *re
scratch_pool);
whb->size = 0;
whb->md5_ctx = svn_checksum_ctx_create(svn_checksum_md5, scratch_pool);
- whb->sha1_ctx = svn_checksum_ctx_create(svn_checksum_sha1, scratch_pool);
+ if (item_type != SVN_FS_FS__ITEM_TYPE_DIR_REP)
+ whb->sha1_ctx = svn_checksum_ctx_create(svn_checksum_sha1, scratch_pool);
stream = svn_stream_create(whb, scratch_pool);
svn_stream_set_write(stream, write_container_handler);
@@ -2741,7 +2820,8 @@ write_container_delta_rep(representation
scratch_pool);
whb->size = 0;
whb->md5_ctx = svn_checksum_ctx_create(svn_checksum_md5, scratch_pool);
- whb->sha1_ctx = svn_checksum_ctx_create(svn_checksum_sha1, scratch_pool);
+ if (item_type != SVN_FS_FS__ITEM_TYPE_DIR_REP)
+ whb->sha1_ctx = svn_checksum_ctx_create(svn_checksum_sha1, scratch_pool);
/* serialize the hash */
stream = svn_stream_create(whb, scratch_pool);
@@ -2895,6 +2975,9 @@ get_final_id(svn_fs_fs__id_part_t *part,
INITIAL_OFFSET is the offset of the proto-rev-file on entry to
commit_body.
+ Collect the pair_cache_key_t of all directories written to the
+ committed cache in DIRECTORY_IDS.
+
If REPS_TO_CACHE is not NULL, append to it a copy (allocated in
REPS_POOL) of each data rep that is new in this revision.
@@ -2916,6 +2999,7 @@ write_final_rev(const svn_fs_id_t **new_
apr_uint64_t start_node_id,
apr_uint64_t start_copy_id,
apr_off_t initial_offset,
+ apr_array_header_t *directory_ids,
apr_array_header_t *reps_to_cache,
apr_hash_t *reps_hash,
apr_pool_t *reps_pool,
@@ -2958,14 +3042,17 @@ write_final_rev(const svn_fs_id_t **new_
svn_pool_clear(subpool);
SVN_ERR(write_final_rev(&new_id, file, rev, fs, dirent->id,
start_node_id, start_copy_id, initial_offset,
- reps_to_cache, reps_hash, reps_pool, FALSE,
- subpool));
+ directory_ids, reps_to_cache, reps_hash,
+ reps_pool, FALSE, subpool));
if (new_id && (svn_fs_fs__id_rev(new_id) == rev))
dirent->id = svn_fs_fs__id_copy(new_id, pool);
}
if (noderev->data_rep && is_txn_rep(noderev->data_rep))
{
+ pair_cache_key_t *key;
+ svn_fs_fs__dir_data_t dir_data;
+
/* Write out the contents of this directory as a text rep. */
noderev->data_rep->revision = rev;
if (ffd->deltify_directories)
@@ -2981,6 +3068,23 @@ write_final_rev(const svn_fs_id_t **new_
SVN_FS_FS__ITEM_TYPE_DIR_REP, pool));
reset_txn_in_rep(noderev->data_rep);
+
+ /* Cache the new directory contents. Otherwise, subsequent reads
+ * or commits will likely have to reconstruct, verify and parse
+ * it again. */
+ key = apr_array_push(directory_ids);
+ key->revision = noderev->data_rep->revision;
+ key->second = noderev->data_rep->item_index;
+
+ /* Store directory contents under the new revision number but mark
+ * it as "stale" by setting the file length to 0. Committed dirs
+ * will report -1, in-txn dirs will report > 0, so that this can
+ * never match. We reset that to -1 after the commit is complete.
+ */
+ dir_data.entries = entries;
+ dir_data.txn_filesize = 0;
+
+ SVN_ERR(svn_cache__set(ffd->dir_cache, key, &dir_data, subpool));
}
}
else
@@ -3423,6 +3527,41 @@ svn_fs_fs__add_index_data(svn_fs_t *fs,
return SVN_NO_ERROR;
}
+/* Mark the directories cached in FS with the keys from DIRECTORY_IDS
+ * as "valid" now. Use SCRATCH_POOL for temporaries. */
+static svn_error_t *
+promote_cached_directories(svn_fs_t *fs,
+ apr_array_header_t *directory_ids,
+ apr_pool_t *scratch_pool)
+{
+ fs_fs_data_t *ffd = fs->fsap_data;
+ apr_pool_t *iterpool;
+ int i;
+
+ if (!ffd->dir_cache)
+ return SVN_NO_ERROR;
+
+ iterpool = svn_pool_create(scratch_pool);
+ for (i = 0; i < directory_ids->nelts; ++i)
+ {
+ const pair_cache_key_t *key
+ = &APR_ARRAY_IDX(directory_ids, i, pair_cache_key_t);
+
+ svn_pool_clear(iterpool);
+
+ /* Currently, the entry for KEY - if it still exists - is marked
+ * as "stale" and would not be used. Mark it as current for in-
+ * revison data. */
+ SVN_ERR(svn_cache__set_partial(ffd->dir_cache, key,
+ svn_fs_fs__reset_txn_filesize, NULL,
+ iterpool));
+ }
+
+ svn_pool_destroy(iterpool);
+
+ return SVN_NO_ERROR;
+}
+
/* Baton used for commit_body below. */
struct commit_baton {
svn_revnum_t *new_rev_p;
@@ -3452,6 +3591,8 @@ commit_body(void *baton, apr_pool_t *poo
apr_off_t initial_offset, changed_path_offset;
const svn_fs_fs__id_part_t *txn_id = svn_fs_fs__txn_get_id(cb->txn);
apr_hash_t *changed_paths;
+ apr_array_header_t *directory_ids = apr_array_make(pool, 4,
+ sizeof(pair_cache_key_t));
/* Re-Read the current repository format. All our repo upgrade and
config evaluation strategies are such that existing information in
@@ -3505,8 +3646,8 @@ commit_body(void *baton, apr_pool_t *poo
root_id = svn_fs_fs__id_txn_create_root(txn_id, pool);
SVN_ERR(write_final_rev(&new_root_id, proto_file, new_rev, cb->fs, root_id,
start_node_id, start_copy_id, initial_offset,
- cb->reps_to_cache, cb->reps_hash, cb->reps_pool,
- TRUE, pool));
+ directory_ids, cb->reps_to_cache, cb->reps_hash,
+ cb->reps_pool, TRUE, pool));
/* Write the changed-path information. */
SVN_ERR(write_final_changed_path_info(&changed_path_offset, proto_file,
@@ -3615,6 +3756,10 @@ commit_body(void *baton, apr_pool_t *poo
ffd->youngest_rev_cache = new_rev;
+ /* Make the directory contents alreday cached for the new revision
+ * visible. */
+ SVN_ERR(promote_cached_directories(cb->fs, directory_ids, pool));
+
/* Remove this transaction directory. */
SVN_ERR(svn_fs_fs__purge_txn(cb->fs, cb->txn->id, pool));
Modified: subversion/branches/move-tracking-2/subversion/libsvn_ra_serf/multistatus.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_ra_serf/multistatus.c?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_ra_serf/multistatus.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_ra_serf/multistatus.c Tue Oct 6 08:46:43 2015
@@ -315,7 +315,7 @@ multistatus_closed(svn_ra_serf__xml_esta
svn_ra_serf__xml_note(xes, MS_RESPONSE, "errcode", errcode);
break;
case MS_RESPONSE:
- if ((status = svn_hash_gets(attrs, "status")) != NULL)
+ if ((status = svn_hash__get_cstring(attrs, "status", NULL)) != NULL)
{
error_item_t *item;
@@ -369,7 +369,7 @@ multistatus_closed(svn_ra_serf__xml_esta
break;
case MS_PROPSTAT:
- if ((status = svn_hash_gets(attrs, "status")) != NULL)
+ if ((status = svn_hash__get_cstring(attrs, "status", NULL)) != NULL)
{
apr_hash_t *response_attrs;
error_item_t *item;
@@ -428,7 +428,8 @@ multistatus_closed(svn_ra_serf__xml_esta
item->http_status = server_error->handler->sline.code;
/* Do we have a mod_dav specific message? */
- item->message = svn_hash_gets(attrs, "human-readable");
+ item->message = svn_hash__get_cstring(attrs, "human-readable",
+ NULL);
if (item->message)
{
@@ -442,9 +443,6 @@ multistatus_closed(svn_ra_serf__xml_esta
item->message = apr_pstrdup(server_error->pool, item->message);
}
- else
- item->message = apr_pstrdup(server_error->pool,
- svn_hash_gets(attrs, "description"));
APR_ARRAY_PUSH(server_error->items, error_item_t *) = item;
Modified: subversion/branches/move-tracking-2/subversion/libsvn_subr/config.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_subr/config.c?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_subr/config.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_subr/config.c Tue Oct 6 08:46:43 2015
@@ -359,22 +359,14 @@ for_each_option(svn_config_t *cfg, void
sec_ndx != NULL;
sec_ndx = apr_hash_next(sec_ndx))
{
- void *sec_ptr;
- cfg_section_t *sec;
+ cfg_section_t *sec = apr_hash_this_val(sec_ndx);
apr_hash_index_t *opt_ndx;
- apr_hash_this(sec_ndx, NULL, NULL, &sec_ptr);
- sec = sec_ptr;
-
for (opt_ndx = apr_hash_first(pool, sec->options);
opt_ndx != NULL;
opt_ndx = apr_hash_next(opt_ndx))
{
- void *opt_ptr;
- cfg_option_t *opt;
-
- apr_hash_this(opt_ndx, NULL, NULL, &opt_ptr);
- opt = opt_ptr;
+ cfg_option_t *opt = apr_hash_this_val(opt_ndx);
if (callback(baton, sec, opt))
return;
@@ -1030,11 +1022,8 @@ svn_config_enumerate_sections2(svn_confi
sec_ndx != NULL;
sec_ndx = apr_hash_next(sec_ndx))
{
- void *sec_ptr;
- cfg_section_t *sec;
+ cfg_section_t *sec = apr_hash_this_val(sec_ndx);
- apr_hash_this(sec_ndx, NULL, NULL, &sec_ptr);
- sec = sec_ptr;
++count;
svn_pool_clear(iteration_pool);
if (!callback(sec->name, baton, iteration_pool))
@@ -1066,13 +1055,9 @@ svn_config_enumerate(svn_config_t *cfg,
opt_ndx != NULL;
opt_ndx = apr_hash_next(opt_ndx))
{
- void *opt_ptr;
- cfg_option_t *opt;
+ cfg_option_t *opt = apr_hash_this_val(opt_ndx);
const char *temp_value;
- apr_hash_this(opt_ndx, NULL, NULL, &opt_ptr);
- opt = opt_ptr;
-
++count;
make_string_from_option(&temp_value, cfg, sec, opt, NULL);
if (!callback(opt->name, temp_value, baton))
@@ -1104,13 +1089,9 @@ svn_config_enumerate2(svn_config_t *cfg,
opt_ndx != NULL;
opt_ndx = apr_hash_next(opt_ndx))
{
- void *opt_ptr;
- cfg_option_t *opt;
+ cfg_option_t *opt = apr_hash_this_val(opt_ndx);
const char *temp_value;
- apr_hash_this(opt_ndx, NULL, NULL, &opt_ptr);
- opt = opt_ptr;
-
++count;
make_string_from_option(&temp_value, cfg, sec, opt, NULL);
svn_pool_clear(iteration_pool);
Modified: subversion/branches/move-tracking-2/subversion/libsvn_subr/opt.c
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_subr/opt.c?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_subr/opt.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_subr/opt.c Tue Oct 6 08:46:43 2015
@@ -350,41 +350,50 @@ print_command_info2(const svn_opt_subcom
return SVN_NO_ERROR;
}
-void
-svn_opt_print_generic_help2(const char *header,
- const svn_opt_subcommand_desc2_t *cmd_table,
- const apr_getopt_option_t *opt_table,
- const char *footer,
- apr_pool_t *pool, FILE *stream)
+/* The body for svn_opt_print_generic_help2() function with standard error
+ * handling semantic. Handling of errors implemented at caller side. */
+static svn_error_t *
+print_generic_help_body(const char *header,
+ const svn_opt_subcommand_desc2_t *cmd_table,
+ const apr_getopt_option_t *opt_table,
+ const char *footer,
+ apr_pool_t *pool, FILE *stream)
{
int i = 0;
- svn_error_t *err;
if (header)
- if ((err = svn_cmdline_fputs(header, stream, pool)))
- goto print_error;
+ SVN_ERR(svn_cmdline_fputs(header, stream, pool));
while (cmd_table[i].name)
{
- if ((err = svn_cmdline_fputs(" ", stream, pool))
- || (err = print_command_info2(cmd_table + i, opt_table,
- NULL, FALSE,
- pool, stream))
- || (err = svn_cmdline_fputs("\n", stream, pool)))
- goto print_error;
+ SVN_ERR(svn_cmdline_fputs(" ", stream, pool));
+ SVN_ERR(print_command_info2(cmd_table + i, opt_table,
+ NULL, FALSE,
+ pool, stream));
+ SVN_ERR(svn_cmdline_fputs("\n", stream, pool));
i++;
}
- if ((err = svn_cmdline_fputs("\n", stream, pool)))
- goto print_error;
+ SVN_ERR(svn_cmdline_fputs("\n", stream, pool));
if (footer)
- if ((err = svn_cmdline_fputs(footer, stream, pool)))
- goto print_error;
+ SVN_ERR(svn_cmdline_fputs(footer, stream, pool));
+
+ return SVN_NO_ERROR;
+}
+
+void
+svn_opt_print_generic_help2(const char *header,
+ const svn_opt_subcommand_desc2_t *cmd_table,
+ const apr_getopt_option_t *opt_table,
+ const char *footer,
+ apr_pool_t *pool, FILE *stream)
+{
+ svn_error_t *err;
- return;
+ err = print_generic_help_body(header, cmd_table, opt_table, footer, pool,
+ stream);
- print_error:
/* Issue #3014:
* Don't print anything on broken pipes. The pipe was likely
* closed by the process at the other end. We expect that
@@ -392,7 +401,7 @@ svn_opt_print_generic_help2(const char *
*
* ### This assumes that there is only one error in a chain for
* ### SVN_ERR_IO_PIPE_WRITE_ERROR. See svn_cmdline_fputs(). */
- if (err->apr_err != SVN_ERR_IO_PIPE_WRITE_ERROR)
+ if (err && err->apr_err != SVN_ERR_IO_PIPE_WRITE_ERROR)
svn_handle_error2(err, stderr, FALSE, "svn: ");
svn_error_clear(err);
}
Modified: subversion/branches/move-tracking-2/subversion/libsvn_wc/diff.h
URL: http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_wc/diff.h?rev=1706963&r1=1706962&r2=1706963&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_wc/diff.h (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_wc/diff.h Tue Oct 6 08:46:43 2015
@@ -52,6 +52,7 @@ svn_error_t *
svn_wc__diff_local_only_file(svn_wc__db_t *db,
const char *local_abspath,
const char *relpath,
+ const char *moved_from_relpath,
const svn_diff_tree_processor_t *processor,
void *processor_parent_baton,
svn_boolean_t diff_pristine,
@@ -75,6 +76,7 @@ svn_wc__diff_local_only_dir(svn_wc__db_t
const char *local_abspath,
const char *relpath,
svn_depth_t depth,
+ const char *moved_from_relpath,
const svn_diff_tree_processor_t *processor,
void *processor_parent_baton,
svn_boolean_t diff_pristine,