You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by hw...@apache.org on 2013/01/22 00:37:04 UTC
svn commit: r1436688 [4/12] - in /subversion/branches/ev2-export: ./
contrib/client-side/emacs/ notes/commit-access-templates/
subversion/bindings/javahl/native/ subversion/bindings/swig/perl/native/t/
subversion/bindings/swig/ruby/test/ subversion/inc...
Modified: subversion/branches/ev2-export/subversion/libsvn_client/patch.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/patch.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/patch.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/patch.c Mon Jan 21 23:37:01 2013
@@ -175,6 +175,9 @@ typedef struct patch_target_t {
* CONTENT->existed). */
apr_file_t *file;
+ /* The target file is a symlink */
+ svn_boolean_t is_symlink;
+
/* The patched file.
* This is equivalent to the target, except that in appropriate
* places it contains the modified text as it appears in the patch file.
@@ -437,48 +440,37 @@ resolve_target_path(patch_target_t *targ
result_pool, scratch_pool);
if (err)
{
- if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
- svn_error_clear(err);
- else
+ if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND)
return svn_error_trace(err);
+
+ svn_error_clear(err);
+
+ target->locally_deleted = TRUE;
+ target->db_kind = svn_node_none;
+ status = NULL;
}
else if (status->node_status == svn_wc_status_ignored ||
status->node_status == svn_wc_status_unversioned ||
status->node_status == svn_wc_status_missing ||
- status->node_status == svn_wc_status_obstructed)
+ status->node_status == svn_wc_status_obstructed ||
+ status->conflicted)
{
target->skipped = TRUE;
return SVN_NO_ERROR;
}
-
- SVN_ERR(svn_io_check_path(target->local_abspath,
- &target->kind_on_disk, scratch_pool));
- err = svn_wc__node_is_status_deleted(&target->locally_deleted,
- wc_ctx, target->local_abspath,
- scratch_pool);
- if (err)
+ else if (status->node_status == svn_wc_status_deleted)
{
- if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND)
- {
- svn_error_clear(err);
- target->locally_deleted = FALSE;
- }
- else
- return svn_error_trace(err);
+ target->locally_deleted = TRUE;
}
- SVN_ERR(svn_wc_read_kind(&target->db_kind, wc_ctx, target->local_abspath,
- FALSE, scratch_pool));
- /* If the target is a versioned directory present on disk,
- * and there are only property changes in the patch, we accept
- * a directory target. Else, we skip directories. */
- if (target->db_kind == svn_node_dir && ! prop_changes_only)
- {
- /* ### We cannot yet replace a locally deleted dir with a file,
- * ### but some day we might want to allow it. */
- target->skipped = TRUE;
- return SVN_NO_ERROR;
- }
+ if (status && (status->kind != svn_node_unknown))
+ target->db_kind = status->kind;
+ else
+ target->db_kind = svn_node_none;
+
+ SVN_ERR(svn_io_check_special_path(target->local_abspath,
+ &target->kind_on_disk, &target->is_symlink,
+ scratch_pool));
if (target->locally_deleted)
{
@@ -498,8 +490,10 @@ resolve_target_path(patch_target_t *targ
/* As far as we are concerned this target is not locally deleted. */
target->locally_deleted = FALSE;
- SVN_ERR(svn_io_check_path(target->local_abspath,
- &target->kind_on_disk, scratch_pool));
+ SVN_ERR(svn_io_check_special_path(target->local_abspath,
+ &target->kind_on_disk,
+ &target->is_symlink,
+ scratch_pool));
}
else if (target->kind_on_disk != svn_node_none)
{
@@ -523,6 +517,8 @@ typedef struct prop_read_baton_t {
* the property value runs out in which case *EOF is set to TRUE.
* The line-terminator is not stored in *STRINGBUF.
*
+ * If the line is empty or could not be read, *line is set to NULL.
+ *
* The line-terminator is detected automatically and stored in *EOL
* if EOL is not NULL. If the end of the property value is reached
* and does not end with a newline character, and EOL is not NULL,
@@ -536,17 +532,15 @@ readline_prop(void *baton, svn_stringbuf
apr_pool_t *scratch_pool)
{
prop_read_baton_t *b = (prop_read_baton_t *)baton;
- svn_stringbuf_t *str;
+ svn_stringbuf_t *str = NULL;
const char *c;
svn_boolean_t found_eof;
- str = svn_stringbuf_create_ensure(80, result_pool);
-
if ((apr_uint64_t)b->offset >= (apr_uint64_t)b->value->len)
{
*eol_str = NULL;
*eof = TRUE;
- *line = str;
+ *line = NULL;
return SVN_NO_ERROR;
}
@@ -578,7 +572,11 @@ readline_prop(void *baton, svn_stringbuf
}
}
else
- svn_stringbuf_appendbyte(str, *c);
+ {
+ if (str == NULL)
+ str = svn_stringbuf_create_ensure(80, result_pool);
+ svn_stringbuf_appendbyte(str, *c);
+ }
if (*eol_str)
break;
@@ -652,7 +650,7 @@ init_prop_target(prop_patch_target_t **p
content->hunks = apr_array_make(result_pool, 0, sizeof(hunk_info_t *));
content->keywords = apr_hash_make(result_pool);
- new_prop_target = apr_palloc(result_pool, sizeof(*new_prop_target));
+ new_prop_target = apr_pcalloc(result_pool, sizeof(*new_prop_target));
new_prop_target->name = apr_pstrdup(result_pool, prop_name);
new_prop_target->operation = operation;
new_prop_target->content = content;
@@ -675,7 +673,7 @@ init_prop_target(prop_patch_target_t **p
/* Wire up the read and write callbacks. */
- prop_read_baton = apr_palloc(result_pool, sizeof(*prop_read_baton));
+ prop_read_baton = apr_pcalloc(result_pool, sizeof(*prop_read_baton));
prop_read_baton->value = value;
prop_read_baton->offset = 0;
content->readline = readline_prop;
@@ -696,6 +694,8 @@ init_prop_target(prop_patch_target_t **p
* or if EOF is reached in which case *EOF is set to TRUE.
* The line-terminator is not stored in *STRINGBUF.
*
+ * If the line is empty or could not be read, *line is set to NULL.
+ *
* The line-terminator is detected automatically and stored in *EOL
* if EOL is not NULL. If EOF is reached and FILE does not end
* with a newline character, and EOL is not NULL, *EOL is set to NULL.
@@ -708,13 +708,11 @@ readline_file(void *baton, svn_stringbuf
apr_pool_t *scratch_pool)
{
apr_file_t *file = (apr_file_t *)baton;
- svn_stringbuf_t *str;
+ svn_stringbuf_t *str = NULL;
apr_size_t numbytes;
char c;
svn_boolean_t found_eof;
- str = svn_stringbuf_create_ensure(80, result_pool);
-
/* Read bytes into STR up to and including, but not storing,
* the next EOL sequence. */
*eol_str = NULL;
@@ -761,7 +759,11 @@ readline_file(void *baton, svn_stringbuf
}
}
else
- svn_stringbuf_appendbyte(str, c);
+ {
+ if (str == NULL)
+ str = svn_stringbuf_create_ensure(80, result_pool);
+ svn_stringbuf_appendbyte(str, c);
+ }
if (*eol_str)
break;
@@ -807,6 +809,118 @@ write_file(void *baton, const char *buf,
return SVN_NO_ERROR;
}
+/* Handling symbolic links:
+ *
+ * In Subversion, symlinks can be represented on disk in two distinct ways.
+ * On systems which support symlinks, a symlink is created on disk.
+ * On systems which do not support symlink, a file is created on disk
+ * which contains the "normal form" of the symlink, which looks like:
+ * link TARGET
+ * where TARGET is the file the symlink points to.
+ *
+ * When reading symlinks (i.e. the link itself, not the file the symlink
+ * is pointing to) through the svn_subst_create_specialfile() function
+ * into a buffer, the buffer always contains the "normal form" of the symlink.
+ * Due to this representation symlinks always contain a single line of text.
+ *
+ * The functions below are needed to deal with the case where a patch
+ * wants to change the TARGET that a symlink points to.
+ */
+
+/* Baton for the (readline|tell|seek|write)_symlink functions. */
+struct symlink_baton_t
+{
+ /* The path to the symlink on disk (not the path to the target of the link) */
+ const char *local_abspath;
+
+ /* Indicates whether the "normal form" of the symlink has been read. */
+ svn_boolean_t at_eof;
+};
+
+/* Allocate *STRINGBUF in RESULT_POOL, and store into it the "normal form"
+ * of the symlink accessed via BATON.
+ *
+ * Otherwise behaves like readline_file(), which see.
+ */
+static svn_error_t *
+readline_symlink(void *baton, svn_stringbuf_t **line, const char **eol_str,
+ svn_boolean_t *eof, apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ struct symlink_baton_t *sb = baton;
+
+ if (eof)
+ *eof = TRUE;
+ if (eol_str)
+ *eol_str = NULL;
+
+ if (sb->at_eof)
+ {
+ *line = NULL;
+ }
+ else
+ {
+ svn_string_t *dest;
+
+ SVN_ERR(svn_io_read_link(&dest, sb->local_abspath, scratch_pool));
+ *line = svn_stringbuf_createf(result_pool, "link %s", dest->data);
+ sb->at_eof = TRUE;
+ }
+
+ return SVN_NO_ERROR;
+}
+
+/* Set *OFFSET to 1 or 0 depending on whether the "normal form" of
+ * the symlink has already been read. */
+static svn_error_t *
+tell_symlink(void *baton, apr_off_t *offset, apr_pool_t *scratch_pool)
+{
+ struct symlink_baton_t *sb = baton;
+
+ *offset = sb->at_eof ? 1 : 0;
+ return SVN_NO_ERROR;
+}
+
+/* If offset is non-zero, mark the symlink as having been read in its
+ * "normal form". Else, mark the symlink as not having been read yet. */
+static svn_error_t *
+seek_symlink(void *baton, apr_off_t offset, apr_pool_t *scratch_pool)
+{
+ struct symlink_baton_t *sb = baton;
+
+ sb->at_eof = (offset != 0);
+ return SVN_NO_ERROR;
+}
+
+
+/* Set the target of the symlink accessed via BATON.
+ * The contents of BUF must be a valid "normal form" of a symlink. */
+static svn_error_t *
+write_symlink(void *baton, const char *buf, apr_size_t len,
+ apr_pool_t *scratch_pool)
+{
+ const char *target_abspath = baton;
+ const char *new_name;
+ const char *link = apr_pstrndup(scratch_pool, buf, len);
+
+ if (strncmp(link, "link ", 5) != 0)
+ return svn_error_create(SVN_ERR_IO_WRITE_ERROR, NULL,
+ _("Invalid link representation"));
+
+ link += 5; /* Skip "link " */
+
+ /* We assume the entire symlink is written at once, as the patch
+ format is line based */
+
+ SVN_ERR(svn_io_create_unique_link(&new_name, target_abspath, link,
+ ".tmp", scratch_pool));
+
+ SVN_ERR(svn_io_file_rename(new_name, target_abspath, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+
/* Return a suitable filename for the target of PATCH.
* Examine the ``old'' and ``new'' file names, and choose the file name
* with the fewest path components, the shortest basename, and the shortest
@@ -912,7 +1026,21 @@ init_patch_target(patch_target_t **patch
/* Create a temporary file to write the patched result to.
* Also grab various bits of information about the file. */
- if (target->kind_on_disk == svn_node_file)
+ if (target->is_symlink)
+ {
+ struct symlink_baton_t *sb = apr_pcalloc(result_pool, sizeof(*sb));
+ content->existed = TRUE;
+
+ sb->local_abspath = target->local_abspath;
+
+ /* Wire up the read callbacks. */
+ content->read_baton = sb;
+
+ content->readline = readline_symlink;
+ content->seek = seek_symlink;
+ content->tell = tell_symlink;
+ }
+ else if (target->kind_on_disk == svn_node_file)
{
SVN_ERR(svn_io_file_open(&target->file, target->local_abspath,
APR_READ | APR_BUFFERED,
@@ -950,17 +1078,34 @@ init_patch_target(patch_target_t **patch
else if (patch->operation == svn_diff_op_deleted)
target->deleted = TRUE;
- /* Open a temporary file to write the patched result to. */
- SVN_ERR(svn_io_open_unique_file3(&target->patched_file,
- &target->patched_path, NULL,
- remove_tempfiles ?
- svn_io_file_del_on_pool_cleanup :
- svn_io_file_del_none,
- result_pool, scratch_pool));
+ if (! target->is_symlink)
+ {
+ /* Open a temporary file to write the patched result to. */
+ SVN_ERR(svn_io_open_unique_file3(&target->patched_file,
+ &target->patched_path, NULL,
+ remove_tempfiles ?
+ svn_io_file_del_on_pool_cleanup :
+ svn_io_file_del_none,
+ result_pool, scratch_pool));
+
+ /* Put the write callback in place. */
+ content->write = write_file;
+ content->write_baton = target->patched_file;
+ }
+ else
+ {
+ /* Put the write callback in place. */
+ SVN_ERR(svn_io_open_unique_file3(NULL,
+ &target->patched_path, NULL,
+ remove_tempfiles ?
+ svn_io_file_del_on_pool_cleanup :
+ svn_io_file_del_none,
+ result_pool, scratch_pool));
- /* Put the write callback in place. */
- content->write = write_file;
- content->write_baton = target->patched_file;
+ content->write_baton = (void*)target->patched_path;
+
+ content->write = write_symlink;
+ }
/* Open a temporary file to write rejected hunks to. */
SVN_ERR(svn_io_open_unique_file3(&target->reject_file,
@@ -1009,7 +1154,9 @@ init_patch_target(patch_target_t **patch
}
/* Read a *LINE from CONTENT. If the line has not been read before
- * mark the line in CONTENT->LINES. Allocate *LINE in RESULT_POOL.
+ * mark the line in CONTENT->LINES.
+ * If a line could be read successfully, increase CONTENT->CURRENT_LINE,
+ * and allocate *LINE in RESULT_POOL.
* Do temporary allocations in SCRATCH_POOL.
*/
static svn_error_t *
@@ -1044,14 +1191,22 @@ readline(target_content_t *content,
if (content->eol_style == svn_subst_eol_style_none)
content->eol_str = eol_str;
- /* Contract keywords. */
- SVN_ERR(svn_subst_translate_cstring2(line_raw->data, line,
- NULL, FALSE,
- content->keywords, FALSE,
- result_pool));
- if (! content->eof)
+ if (line_raw)
+ {
+ /* Contract keywords. */
+ SVN_ERR(svn_subst_translate_cstring2(line_raw->data, line,
+ NULL, FALSE,
+ content->keywords, FALSE,
+ result_pool));
+ }
+ else
+ *line = "";
+
+ if ((line_raw && line_raw->len > 0) || eol_str)
content->current_line++;
+ SVN_ERR_ASSERT(content->current_line > 0);
+
return SVN_NO_ERROR;
}
@@ -1383,26 +1538,45 @@ get_hunk_info(hunk_info_t **hi, patch_ta
* the hunk applies at line 1. If the file already exists, the hunk
* is rejected, unless the file is versioned and its content matches
* the file the patch wants to create. */
- if (original_start == 0 && ! is_prop_hunk)
+ if (original_start == 0 && fuzz > 0)
+ {
+ matched_line = 0; /* reject any fuzz for new files */
+ }
+ else if (original_start == 0 && ! is_prop_hunk)
{
if (target->kind_on_disk == svn_node_file)
{
- if (target->db_kind == svn_node_file)
+ const svn_io_dirent2_t *dirent;
+ SVN_ERR(svn_io_stat_dirent2(&dirent, target->local_abspath, FALSE,
+ TRUE, scratch_pool, scratch_pool));
+
+ if (dirent->kind == svn_node_file
+ && !dirent->special
+ && dirent->filesize == 0)
+ {
+ matched_line = 1; /* Matched an on-disk empty file */
+ }
+ else
{
- svn_boolean_t file_matches;
+ if (target->db_kind == svn_node_file)
+ {
+ svn_boolean_t file_matches;
- SVN_ERR(match_existing_target(&file_matches, content, hunk,
+ /* ### I can't reproduce anything but a no-match here.
+ The content is already at eof, so any hunk fails */
+ SVN_ERR(match_existing_target(&file_matches, content, hunk,
scratch_pool));
- if (file_matches)
- {
- matched_line = 1;
- already_applied = TRUE;
+ if (file_matches)
+ {
+ matched_line = 1;
+ already_applied = TRUE;
+ }
+ else
+ matched_line = 0; /* reject */
}
else
matched_line = 0; /* reject */
}
- else
- matched_line = 0; /* reject */
}
else
matched_line = 1;
@@ -1518,7 +1692,7 @@ get_hunk_info(hunk_info_t **hi, patch_ta
matched_line = 0;
}
- (*hi) = apr_palloc(result_pool, sizeof(hunk_info_t));
+ (*hi) = apr_pcalloc(result_pool, sizeof(hunk_info_t));
(*hi)->hunk = hunk;
(*hi)->matched_line = matched_line;
(*hi)->rejected = (matched_line == 0);
@@ -2094,13 +2268,17 @@ apply_one_patch(patch_target_t **patch_t
svn_pool_destroy(iterpool);
- /* Now close files we don't need any longer to get their contents
- * flushed to disk.
- * But we're not closing the reject file -- it still needed and
- * will be closed later in write_out_rejected_hunks(). */
- if (target->kind_on_disk == svn_node_file)
- SVN_ERR(svn_io_file_close(target->file, scratch_pool));
- SVN_ERR(svn_io_file_close(target->patched_file, scratch_pool));
+ if (!target->is_symlink)
+ {
+ /* Now close files we don't need any longer to get their contents
+ * flushed to disk.
+ * But we're not closing the reject file -- it still needed and
+ * will be closed later in write_out_rejected_hunks(). */
+ if (target->kind_on_disk == svn_node_file)
+ SVN_ERR(svn_io_file_close(target->file, scratch_pool));
+
+ SVN_ERR(svn_io_file_close(target->patched_file, scratch_pool));
+ }
if (! target->skipped)
{
@@ -2111,10 +2289,10 @@ apply_one_patch(patch_target_t **patch_t
* We'll need those to figure out whether we should delete the
* patched file. */
SVN_ERR(svn_io_stat(&patched_file, target->patched_path,
- APR_FINFO_SIZE, scratch_pool));
+ APR_FINFO_SIZE | APR_FINFO_LINK, scratch_pool));
if (target->kind_on_disk == svn_node_file)
SVN_ERR(svn_io_stat(&working_file, target->local_abspath,
- APR_FINFO_SIZE, scratch_pool));
+ APR_FINFO_SIZE | APR_FINFO_LINK, scratch_pool));
else
working_file.size = 0;
@@ -2574,265 +2752,129 @@ install_patched_prop_targets(patch_targe
return SVN_NO_ERROR;
}
-/* Baton for find_existing_children() */
-struct status_baton
+/* Baton for can_delete_callback */
+struct can_delete_baton_t
{
- apr_array_header_t *existing_targets;
- const char *parent_path;
- apr_pool_t *result_pool;
+ svn_boolean_t must_keep;
+ const apr_array_header_t *targets_info;
+ const char *local_abspath;
};
/* Implements svn_wc_status_func4_t. */
static svn_error_t *
-find_existing_children(void *baton,
- const char *abspath,
- const svn_wc_status3_t *status,
- apr_pool_t *pool)
+can_delete_callback(void *baton,
+ const char *abspath,
+ const svn_wc_status3_t *status,
+ apr_pool_t *pool)
{
- struct status_baton *btn = baton;
+ struct can_delete_baton_t *cb = baton;
+ int i;
- if (status->node_status != svn_wc_status_none
- && status->node_status != svn_wc_status_deleted
- && strcmp(abspath, btn->parent_path))
+ switch(status->node_status)
{
- APR_ARRAY_PUSH(btn->existing_targets,
- const char *) = apr_pstrdup(btn->result_pool,
- abspath);
- }
+ case svn_wc_status_none:
+ case svn_wc_status_deleted:
+ return SVN_NO_ERROR;
- return SVN_NO_ERROR;
-}
+ default:
+ if (! strcmp(cb->local_abspath, abspath))
+ return SVN_NO_ERROR; /* Only interested in descendants */
-/* Indicate in *EMPTY whether the directory at LOCAL_ABSPATH has any
- * versioned or unversioned children. Consider any DELETED_TARGETS,
- * as well as paths occuring as keys of DELETED_ABSPATHS_HASH (which may
- * be NULL) as already deleted. Use WC_CTX as the working copy context.
- * Do temporary allocations in SCRATCH_POOL. */
-static svn_error_t *
-check_dir_empty(svn_boolean_t *empty, const char *local_abspath,
- svn_wc_context_t *wc_ctx,
- apr_array_header_t *deleted_targets,
- apr_hash_t *deleted_abspath_hash,
- apr_pool_t *scratch_pool)
-{
- struct status_baton btn;
- svn_boolean_t is_wc_root;
- int i;
+ for (i = 0; i < cb->targets_info->nelts; i++)
+ {
+ const patch_target_info_t *target_info =
+ APR_ARRAY_IDX(cb->targets_info, i, const patch_target_info_t *);
- /* Working copy root cannot be deleted, so never consider it empty. */
- SVN_ERR(svn_wc__is_wcroot(&is_wc_root, wc_ctx, local_abspath,
- scratch_pool));
- if (is_wc_root)
- {
- *empty = FALSE;
- return SVN_NO_ERROR;
- }
+ if (! strcmp(target_info->local_abspath, abspath))
+ {
+ if (target_info->deleted)
+ return SVN_NO_ERROR;
- /* Find existing children of the directory. */
- btn.existing_targets = apr_array_make(scratch_pool, 0,
- sizeof(patch_target_t *));
- btn.parent_path = local_abspath;
- btn.result_pool = scratch_pool;
- SVN_ERR(svn_wc_walk_status(wc_ctx, local_abspath, svn_depth_immediates,
- TRUE, TRUE, FALSE, NULL, find_existing_children,
- &btn, NULL, NULL, scratch_pool));
- *empty = TRUE;
-
- /* Do we delete all children? */
- for (i = 0; i < btn.existing_targets->nelts; i++)
- {
- int j;
- const char *found;
- svn_boolean_t deleted;
-
- deleted = FALSE;
- found = APR_ARRAY_IDX(btn.existing_targets, i, const char *);
-
- for (j = 0; j < deleted_targets->nelts; j++)
- {
- patch_target_info_t *target_info;
-
- target_info = APR_ARRAY_IDX(deleted_targets, j,
- patch_target_info_t *);
- if (! svn_path_compare_paths(found, target_info->local_abspath))
- {
- deleted = TRUE;
- break;
- }
- }
- if (! deleted && deleted_abspath_hash)
- {
- apr_hash_index_t *hi;
+ break; /* Cease invocation; must keep */
+ }
+ }
- for (hi = apr_hash_first(scratch_pool, deleted_abspath_hash);
- hi;
- hi = apr_hash_next(hi))
- {
- const char *abspath;
+ cb->must_keep = TRUE;
- abspath = svn__apr_hash_index_key(hi);
- if (! svn_path_compare_paths(found, abspath))
- {
- deleted = TRUE;
- break;
- }
- }
- }
- if (! deleted)
- {
- *empty = FALSE;
- break;
- }
+ return svn_error_create(SVN_ERR_CEASE_INVOCATION, NULL, NULL);
}
-
- return SVN_NO_ERROR;
}
-/* Delete all directories from the working copy which are left empty
- * by deleted TARGETS. Use client context CTX.
- * If DRY_RUN is TRUE, do not modify the working copy.
- * Do temporary allocations in SCRATCH_POOL. */
static svn_error_t *
-delete_empty_dirs(apr_array_header_t *targets_info, svn_client_ctx_t *ctx,
- svn_boolean_t dry_run, apr_pool_t *scratch_pool)
+check_ancestor_delete(const char *deleted_target,
+ apr_array_header_t *targets_info,
+ const char *apply_root,
+ svn_boolean_t dry_run,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
- apr_hash_t *empty_dirs;
- apr_hash_t *non_empty_dirs;
- apr_array_header_t *deleted_targets;
- apr_pool_t *iterpool;
- svn_boolean_t again;
- int i;
- apr_hash_index_t *hi;
-
- /* Get a list of all deleted targets. */
- deleted_targets = apr_array_make(scratch_pool, 0, sizeof(patch_target_t *));
- for (i = 0; i < targets_info->nelts; i++)
- {
- patch_target_info_t *target_info;
-
- target_info = APR_ARRAY_IDX(targets_info, i, patch_target_info_t *);
- if (target_info->deleted)
- APR_ARRAY_PUSH(deleted_targets, patch_target_info_t *) = target_info;
- }
-
- /* We have nothing to do if there aren't any deleted targets. */
- if (deleted_targets->nelts == 0)
- return SVN_NO_ERROR;
-
- /* Look for empty parent directories of deleted targets. */
- empty_dirs = apr_hash_make(scratch_pool);
- non_empty_dirs = apr_hash_make(scratch_pool);
- iterpool = svn_pool_create(scratch_pool);
- for (i = 0; i < deleted_targets->nelts; i++)
- {
- svn_boolean_t parent_empty;
- patch_target_info_t *target_info;
- const char *parent;
-
- svn_pool_clear(iterpool);
-
- if (ctx->cancel_func)
- SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
-
- target_info = APR_ARRAY_IDX(deleted_targets, i, patch_target_info_t *);
-
- parent = svn_dirent_dirname(target_info->local_abspath, iterpool);
-
- if (apr_hash_get(non_empty_dirs, parent, APR_HASH_KEY_STRING))
- continue;
- else if (apr_hash_get(empty_dirs, parent, APR_HASH_KEY_STRING))
- continue;
+ struct can_delete_baton_t cb;
+ svn_error_t *err;
+ apr_pool_t *iterpool = svn_pool_create(scratch_pool);
- SVN_ERR(check_dir_empty(&parent_empty, parent, ctx->wc_ctx,
- deleted_targets, NULL, iterpool));
- if (parent_empty)
- apr_hash_set(empty_dirs, apr_pstrdup(scratch_pool, parent),
- APR_HASH_KEY_STRING, "");
- else
- apr_hash_set(non_empty_dirs, apr_pstrdup(scratch_pool, parent),
- APR_HASH_KEY_STRING, "");
- }
+ const char *dir_abspath = svn_dirent_dirname(deleted_target, scratch_pool);
- /* We have nothing to do if there aren't any empty directories. */
- if (apr_hash_count(empty_dirs) == 0)
+ while (svn_dirent_is_child(apply_root, dir_abspath, iterpool))
{
- svn_pool_destroy(iterpool);
- return SVN_NO_ERROR;
- }
-
- /* Determine the minimal set of empty directories we need to delete. */
- do
- {
- apr_hash_t *empty_dirs_copy;
-
svn_pool_clear(iterpool);
- if (ctx->cancel_func)
- SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
-
- /* Rebuild the empty dirs list, replacing empty dirs which have
- * an empty parent with their parent. */
- again = FALSE;
- empty_dirs_copy = apr_hash_copy(iterpool, empty_dirs);
- SVN_ERR(svn_hash__clear(empty_dirs, iterpool));
-
- for (hi = apr_hash_first(iterpool, empty_dirs_copy);
- hi;
- hi = apr_hash_next(hi))
- {
- svn_boolean_t parent_empty;
- const char *empty_dir;
- const char *parent;
+ cb.local_abspath = dir_abspath;
+ cb.must_keep = FALSE;
+ cb.targets_info = targets_info;
+
+ err = svn_wc_walk_status(ctx->wc_ctx, dir_abspath, svn_depth_infinity,
+ TRUE, FALSE, FALSE, NULL,
+ can_delete_callback, &cb,
+ ctx->cancel_func, ctx->cancel_baton,
+ iterpool);
+
+ if (err)
+ {
+ if (err->apr_err != SVN_ERR_CEASE_INVOCATION)
+ return svn_error_trace(err);
- empty_dir = svn__apr_hash_index_key(hi);
- parent = svn_dirent_dirname(empty_dir, iterpool);
+ svn_error_clear(err);
+ }
- if (apr_hash_get(empty_dirs, parent, APR_HASH_KEY_STRING))
- continue;
+ if (cb.must_keep)
+ {
+ break;
+ }
- SVN_ERR(check_dir_empty(&parent_empty, parent, ctx->wc_ctx,
- deleted_targets, empty_dirs_copy,
- iterpool));
- if (parent_empty)
- {
- again = TRUE;
- apr_hash_set(empty_dirs, apr_pstrdup(scratch_pool, parent),
- APR_HASH_KEY_STRING, "");
- }
- else
- apr_hash_set(empty_dirs, apr_pstrdup(scratch_pool, empty_dir),
- APR_HASH_KEY_STRING, "");
+ if (! dry_run)
+ {
+ SVN_ERR(svn_wc_delete4(ctx->wc_ctx, dir_abspath, FALSE, FALSE,
+ ctx->cancel_func, ctx->cancel_baton,
+ NULL, NULL,
+ scratch_pool));
}
- }
- while (again);
- /* Finally, delete empty directories. */
- for (hi = apr_hash_first(scratch_pool, empty_dirs);
- hi;
- hi = apr_hash_next(hi))
- {
- const char *empty_dir;
+ {
+ patch_target_info_t *pti = apr_pcalloc(result_pool, sizeof(*pti));
- svn_pool_clear(iterpool);
+ pti->local_abspath = apr_pstrdup(result_pool, dir_abspath);
+ pti->deleted = TRUE;
+
+ APR_ARRAY_PUSH(targets_info, patch_target_info_t *) = pti;
+ }
- if (ctx->cancel_func)
- SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
- empty_dir = svn__apr_hash_index_key(hi);
- if (! dry_run)
- SVN_ERR(svn_wc_delete4(ctx->wc_ctx, empty_dir, FALSE, FALSE,
- ctx->cancel_func, ctx->cancel_baton,
- NULL, NULL, /* no duplicate notification */
- iterpool));
if (ctx->notify_func2)
{
svn_wc_notify_t *notify;
- notify = svn_wc_create_notify(empty_dir, svn_wc_notify_delete,
- iterpool);
- (*ctx->notify_func2)(ctx->notify_baton2, notify, iterpool);
+ notify = svn_wc_create_notify(dir_abspath, svn_wc_notify_delete,
+ iterpool);
+ notify->kind = svn_node_dir;
+
+ ctx->notify_func2(ctx->notify_baton2, notify, iterpool);
}
+
+ /* And check if we must also delete the parent */
+ dir_abspath = svn_dirent_dirname(dir_abspath, scratch_pool);
}
+
svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
@@ -2897,7 +2939,7 @@ apply_patches(/* The path to the patch f
{
/* Save info we'll still need when we're done patching. */
patch_target_info_t *target_info =
- apr_palloc(scratch_pool, sizeof(patch_target_info_t));
+ apr_pcalloc(scratch_pool, sizeof(patch_target_info_t));
target_info->local_abspath = apr_pstrdup(scratch_pool,
target->local_abspath);
target_info->deleted = target->deleted;
@@ -2920,14 +2962,19 @@ apply_patches(/* The path to the patch f
SVN_ERR(write_out_rejected_hunks(target, dry_run, iterpool));
}
SVN_ERR(send_patch_notification(target, ctx, iterpool));
+
+ if (target->deleted && !target->skipped)
+ {
+ SVN_ERR(check_ancestor_delete(target_info->local_abspath,
+ targets_info, abs_wc_path,
+ dry_run, ctx,
+ scratch_pool, iterpool));
+ }
}
}
}
while (patch);
- /* Delete directories which are empty after patching, if any. */
- SVN_ERR(delete_empty_dirs(targets_info, ctx, dry_run, scratch_pool));
-
SVN_ERR(svn_diff_close_patch_file(patch_file, iterpool));
svn_pool_destroy(iterpool);
Modified: subversion/branches/ev2-export/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/repos_diff.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/repos_diff.c Mon Jan 21 23:37:01 2013
@@ -597,9 +597,8 @@ delete_entry(const char *path,
svn_boolean_t tree_conflicted = FALSE;
apr_pool_t *scratch_pool;
- /* Skip *everything* within a newly tree-conflicted directory,
- * and directories the children of which should be skipped. */
- if (pb->skip || pb->tree_conflicted || pb->skip_children)
+ /* Process skips. */
+ if (pb->skip_children)
return SVN_NO_ERROR;
scratch_pool = svn_pool_create(eb->pool);
@@ -671,9 +670,10 @@ add_directory(const char *path,
/* Skip *everything* within a newly tree-conflicted directory,
* and directories the children of which should be skipped. */
- if (pb->skip || pb->tree_conflicted || pb->skip_children)
+ if (pb->skip_children)
{
db->skip = TRUE;
+ db->skip_children = TRUE;
return SVN_NO_ERROR;
}
@@ -755,11 +755,11 @@ open_directory(const char *path,
*child_baton = db;
- /* Skip *everything* within a newly tree-conflicted directory
- * and directories the children of which should be skipped. */
- if (pb->skip || pb->tree_conflicted || pb->skip_children)
+ /* Process Skips. */
+ if (pb->skip_children)
{
db->skip = TRUE;
+ db->skip_children = TRUE;
return SVN_NO_ERROR;
}
@@ -789,9 +789,8 @@ add_file(const char *path,
fb = make_file_baton(path, TRUE, pb->edit_baton, pool);
*file_baton = fb;
- /* Skip *everything* within a newly tree-conflicted directory.
- * and directories the children of which should be skipped. */
- if (pb->skip || pb->tree_conflicted || pb->skip_children)
+ /* Process Skips. */
+ if (pb->skip_children)
{
fb->skip = TRUE;
return SVN_NO_ERROR;
@@ -816,9 +815,8 @@ open_file(const char *path,
fb = make_file_baton(path, FALSE, pb->edit_baton, pool);
*file_baton = fb;
- /* Skip *everything* within a newly tree-conflicted directory
- * and directories the children of which should be skipped. */
- if (pb->skip || pb->tree_conflicted || pb->skip_children)
+ /* Process Skips. */
+ if (pb->skip_children)
{
fb->skip = TRUE;
return SVN_NO_ERROR;
@@ -1097,16 +1095,9 @@ close_directory(void *dir_baton,
apr_pool_t *scratch_pool;
apr_hash_t *pristine_props;
- /* Skip *everything* within a newly tree-conflicted directory. */
- if (db->skip)
- {
- svn_pool_destroy(db->pool);
- return SVN_NO_ERROR;
- }
-
scratch_pool = db->pool;
- if (db->has_propchange)
+ if (db->has_propchange && !db->skip)
{
if (db->added)
{
@@ -1180,7 +1171,7 @@ close_directory(void *dir_baton,
/* Notify about this directory itself (unless it was added, in which
* case the notification was done at that time). */
- if (!db->added && eb->notify_func)
+ if (!db->added && eb->notify_func && !db->skip)
{
svn_wc_notify_t *notify;
svn_wc_notify_action_t action;
Modified: subversion/branches/ev2-export/subversion/libsvn_client/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/status.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/status.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/status.c Mon Jan 21 23:37:01 2013
@@ -530,6 +530,7 @@ svn_client_status5(svn_revnum_t *result_
SVN_ERR(svn_client__do_external_status(ctx, external_map,
depth, get_all,
update, no_ignore,
+ sb.anchor_abspath, sb.anchor_relpath,
status_func, status_baton, pool));
}
Modified: subversion/branches/ev2-export/subversion/libsvn_client/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_client/update.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_client/update.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_client/update.c Mon Jan 21 23:37:01 2013
@@ -376,23 +376,9 @@ update_internal(svn_revnum_t *result_rev
dfb.target_revision = revnum;
dfb.anchor_url = anchor_loc->url;
- err = svn_client__get_inheritable_props(&wcroot_iprops, local_abspath,
- revnum, depth, ra_session,
- ctx, pool, pool);
-
- /* We might be trying to update to a non-existant path-rev. */
- if (err)
- {
- if (err->apr_err == SVN_ERR_FS_NOT_FOUND)
- {
- svn_error_clear(err);
- err = NULL;
- }
- else
- {
- return svn_error_trace(err);
- }
- }
+ SVN_ERR(svn_client__get_inheritable_props(&wcroot_iprops, local_abspath,
+ revnum, depth, ra_session,
+ ctx, pool, pool));
/* Fetch the update editor. If REVISION is invalid, that's okay;
the RA driver will call editor->set_target_revision later on. */
Modified: subversion/branches/ev2-export/subversion/libsvn_delta/editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_delta/editor.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_delta/editor.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_delta/editor.c Mon Jan 21 23:37:01 2013
@@ -35,9 +35,18 @@
introduce additional memory and runtime overhead, and should not be used
in production builds.
- ### Remove before release? */
+ ### Remove before release?
+
+ ### Disabled for now. If I call svn_editor_alter_directory(A) then
+ svn_editor_add_file(A/f) the latter fails on SHOULD_ALLOW_ADD.
+ If I modify svn_editor_alter_directory to MARK_ALLOW_ADD(child)
+ then if I call svn_editor_alter_directory(A) followed by
+ svn_editor_alter_directory(A/B/C) the latter fails on
+ VERIFY_PARENT_MAY_EXIST. */
+#if 0
#define ENABLE_ORDERING_CHECK
#endif
+#endif
struct svn_editor_t
@@ -666,6 +675,7 @@ svn_editor_alter_directory(svn_editor_t
apr_hash_set(editor->pending_incomplete_children, child,
APR_HASH_KEY_STRING, "");
+ /* Perhaps MARK_ALLOW_ADD(editor, child); ? */
}
}
#endif
Modified: subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.c Mon Jan 21 23:37:01 2013
@@ -485,6 +485,8 @@ svn_error_t *
svn_fs_verify(const char *path,
svn_cancel_func_t cancel_func,
void *cancel_baton,
+ svn_fs_progress_notify_func_t notify_func,
+ void *notify_baton,
svn_revnum_t start,
svn_revnum_t end,
apr_pool_t *pool)
@@ -497,7 +499,8 @@ svn_fs_verify(const char *path,
SVN_MUTEX__WITH_LOCK(common_pool_lock,
vtable->verify_fs(fs, path, cancel_func, cancel_baton,
- start, end, pool, common_pool));
+ notify_func, notify_baton, start,
+ end, pool, common_pool));
return SVN_NO_ERROR;
}
@@ -625,6 +628,16 @@ svn_fs_recover(const char *path,
}
svn_error_t *
+svn_fs_verify_rev(svn_fs_t *fs,
+ svn_revnum_t revision,
+ apr_pool_t *scratch_pool)
+{
+ SVN_ERR(fs->vtable->verify_rev(fs, revision, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
svn_fs_freeze(svn_fs_t *fs,
svn_error_t *(*freeze_body)(void *baton, apr_pool_t *pool),
void *baton,
Modified: subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.h?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs/fs-loader.h Mon Jan 21 23:37:01 2013
@@ -88,8 +88,9 @@ typedef struct fs_library_vtable_t
svn_error_t *(*upgrade_fs)(svn_fs_t *fs, const char *path, apr_pool_t *pool,
apr_pool_t *common_pool);
svn_error_t *(*verify_fs)(svn_fs_t *fs, const char *path,
- /* ### notification? */
svn_cancel_func_t cancel_func, void *cancel_baton,
+ svn_fs_progress_notify_func_t notify_func,
+ void *notify_baton,
svn_revnum_t start,
svn_revnum_t end,
apr_pool_t *pool,
@@ -202,6 +203,9 @@ typedef struct fs_vtable_t
svn_fs_get_locks_callback_t get_locks_func,
void *get_locks_baton,
apr_pool_t *pool);
+ svn_error_t *(*verify_rev)(svn_fs_t *fs,
+ svn_revnum_t revision,
+ apr_pool_t *pool);
svn_error_t *(*freeze)(svn_fs_t *fs,
svn_error_t *(*freeze_body)(void *, apr_pool_t *),
void *baton, apr_pool_t *pool);
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_base/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_base/fs.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_base/fs.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_base/fs.c Mon Jan 21 23:37:01 2013
@@ -472,6 +472,15 @@ bdb_write_config(svn_fs_t *fs)
}
static svn_error_t *
+base_bdb_verify_rev(svn_fs_t *fs,
+ svn_revnum_t revision,
+ apr_pool_t *scratch_pool)
+{
+ /* Verifying is currently a no op for BDB. */
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
base_bdb_freeze(svn_fs_t *fs,
svn_error_t *(*freeze_body)(void *, apr_pool_t *),
void *baton,
@@ -500,6 +509,7 @@ static fs_vtable_t fs_vtable = {
svn_fs_base__unlock,
svn_fs_base__get_lock,
svn_fs_base__get_locks,
+ base_bdb_verify_rev,
base_bdb_freeze,
base_bdb_set_errcall,
};
@@ -894,6 +904,8 @@ static svn_error_t *
base_verify(svn_fs_t *fs, const char *path,
svn_cancel_func_t cancel_func,
void *cancel_baton,
+ svn_fs_progress_notify_func_t notify_func,
+ void *notify_baton,
svn_revnum_t start,
svn_revnum_t end,
apr_pool_t *pool,
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs.c Mon Jan 21 23:37:01 2013
@@ -184,6 +184,7 @@ static fs_vtable_t fs_vtable = {
svn_fs_fs__unlock,
svn_fs_fs__get_lock,
svn_fs_fs__get_locks,
+ svn_fs_fs__verify_rev,
fs_freeze,
fs_set_errcall
};
@@ -285,6 +286,8 @@ static svn_error_t *
fs_verify(svn_fs_t *fs, const char *path,
svn_cancel_func_t cancel_func,
void *cancel_baton,
+ svn_fs_progress_notify_func_t notify_func,
+ void *notify_baton,
svn_revnum_t start,
svn_revnum_t end,
apr_pool_t *pool,
@@ -295,7 +298,8 @@ fs_verify(svn_fs_t *fs, const char *path
SVN_ERR(svn_fs_fs__open(fs, path, pool));
SVN_ERR(svn_fs_fs__initialize_caches(fs, pool));
SVN_ERR(fs_serialized_init(fs, common_pool, pool));
- return svn_fs_fs__verify(fs, cancel_func, cancel_baton, start, end, pool);
+ return svn_fs_fs__verify(fs, cancel_func, cancel_baton, notify_func,
+ notify_baton, start, end, pool);
}
static svn_error_t *
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.c Mon Jan 21 23:37:01 2013
@@ -10289,6 +10289,28 @@ svn_fs_fs__pack(svn_fs_t *fs,
/** Verifying. **/
+/* Baton type expected by verify_walker(). The purpose is to reuse open
+ * rev / pack file handles between calls. Its contents need to be cleaned
+ * periodically to limit resource usage.
+ */
+typedef struct verify_walker_baton_t
+{
+ /* number of calls to verify_walker() since the last clean */
+ int iteration_count;
+
+ /* number of files opened since the last clean */
+ int file_count;
+
+ /* current file handle (or NULL) */
+ apr_file_t *file_hint;
+
+ /* corresponding revision (or SVN_INVALID_REVNUM) */
+ svn_revnum_t rev_hint;
+
+ /* pool to use for the file handles etc. */
+ apr_pool_t *pool;
+} verify_walker_baton_t;
+
/* Used by svn_fs_fs__verify().
Implements svn_fs_fs__walk_rep_reference().walker. */
static svn_error_t *
@@ -10300,13 +10322,40 @@ verify_walker(representation_t *rep,
struct rep_state *rs;
struct rep_args *rep_args;
-#ifdef SVN_DEBUG
- /* verify_walker() is called directly by get_shared_rep() with baton=NULL. */
- SVN_ERR_ASSERT(!baton);
-#endif
+ if (baton)
+ {
+ verify_walker_baton_t *walker_baton = baton;
+ apr_file_t * previous_file;
+
+ /* free resources periodically */
+ if ( walker_baton->iteration_count > 1000
+ || walker_baton->file_count > 16)
+ {
+ svn_pool_clear(walker_baton->pool);
+
+ walker_baton->iteration_count = 0;
+ walker_baton->file_count = 0;
+ walker_baton->file_hint = NULL;
+ walker_baton->rev_hint = SVN_INVALID_REVNUM;
+ }
- /* ### Should this be using read_rep_line() directly? */
- SVN_ERR(create_rep_state(&rs, &rep_args, NULL, NULL, rep, fs, scratch_pool));
+ /* access the repo data */
+ previous_file = walker_baton->file_hint;
+ SVN_ERR(create_rep_state(&rs, &rep_args, &walker_baton->file_hint,
+ &walker_baton->rev_hint, rep, fs,
+ walker_baton->pool));
+
+ /* update resource usage counters */
+ walker_baton->iteration_count++;
+ if (previous_file != walker_baton->file_hint)
+ walker_baton->file_count++;
+ }
+ else
+ {
+ /* ### Should this be using read_rep_line() directly? */
+ SVN_ERR(create_rep_state(&rs, &rep_args, NULL, NULL, rep, fs,
+ scratch_pool));
+ }
return SVN_NO_ERROR;
}
@@ -10315,6 +10364,8 @@ svn_error_t *
svn_fs_fs__verify(svn_fs_t *fs,
svn_cancel_func_t cancel_func,
void *cancel_baton,
+ svn_fs_progress_notify_func_t notify_func,
+ void *notify_baton,
svn_revnum_t start,
svn_revnum_t end,
apr_pool_t *pool)
@@ -10322,7 +10373,6 @@ svn_fs_fs__verify(svn_fs_t *fs,
fs_fs_data_t *ffd = fs->fsap_data;
svn_boolean_t exists;
svn_revnum_t youngest = ffd->youngest_rev_cache; /* cache is current */
- apr_pool_t *iterpool = svn_pool_create(pool);
if (ffd->format < SVN_FS_FS__MIN_REP_SHARING_FORMAT)
return SVN_NO_ERROR;
@@ -10332,42 +10382,54 @@ svn_fs_fs__verify(svn_fs_t *fs,
start = 0;
if (! SVN_IS_VALID_REVNUM(end))
end = youngest;
- SVN_ERR(ensure_revision_exists(fs, start, iterpool));
- SVN_ERR(ensure_revision_exists(fs, end, iterpool));
+ SVN_ERR(ensure_revision_exists(fs, start, pool));
+ SVN_ERR(ensure_revision_exists(fs, end, pool));
/* rep-cache verification. */
SVN_ERR(svn_fs_fs__exists_rep_cache(&exists, fs, pool));
if (exists)
- /* Do not attempt to walk the rep-cache database if its file does not exist,
- since doing so would create it --- which may confuse the administrator.
- Don't take any lock. */
- SVN_ERR(svn_fs_fs__walk_rep_reference(fs, verify_walker, NULL,
- cancel_func, cancel_baton,
- start, end,
- pool));
+ {
+ /* provide a baton to allow the reuse of open file handles between
+ iterations (saves 2/3 of OS level file operations). */
+ verify_walker_baton_t *baton = apr_pcalloc(pool, sizeof(*baton));
+ baton->rev_hint = SVN_INVALID_REVNUM;
+ baton->pool = svn_pool_create(pool);
+
+ /* Do not attempt to walk the rep-cache database if its file does
+ not exist, since doing so would create it --- which may confuse
+ the administrator. Don't take any lock. */
+ SVN_ERR(svn_fs_fs__walk_rep_reference(fs, verify_walker, baton,
+ cancel_func, cancel_baton,
+ notify_func, notify_baton,
+ start, end,
+ pool));
+
+ /* walker resource cleanup */
+ svn_pool_destroy(baton->pool);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_fs_fs__verify_rev(svn_fs_t *fs,
+ svn_revnum_t revision,
+ apr_pool_t *pool)
+{
+ svn_fs_root_t *root;
/* Issue #4129: bogus pred-counts and minfo-cnt's on the root node-rev
(and elsewhere). This code makes more thorough checks than the
commit-time checks in validate_root_noderev(). */
- {
- svn_revnum_t i;
- for (i = start; i <= end; i++)
- {
- svn_fs_root_t *root;
-
- svn_pool_clear(iterpool);
-
- /* ### TODO: Make sure caches are disabled.
-
- When this code is called in the library, we want to ensure we
- use the on-disk data --- rather than some data that was read
- in the possibly-distance past and cached since. */
- SVN_ERR(svn_fs_fs__revision_root(&root, fs, i, iterpool));
- SVN_ERR(svn_fs_fs__verify_root(root, iterpool));
- }
- }
- svn_pool_destroy(iterpool);
+ /* ### TODO: Make sure caches are disabled.
+
+ When this code is called in the library, we want to ensure we
+ use the on-disk data --- rather than some data that was read
+ in the possibly-distance past and cached since. */
+ SVN_ERR(svn_fs_fs__revision_root(&root, fs, revision, pool));
+ SVN_ERR(svn_fs_fs__verify_root(root, pool));
+
return SVN_NO_ERROR;
}
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.h?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/fs_fs.h Mon Jan 21 23:37:01 2013
@@ -42,10 +42,18 @@ svn_error_t *svn_fs_fs__upgrade(svn_fs_t
svn_error_t *svn_fs_fs__verify(svn_fs_t *fs,
svn_cancel_func_t cancel_func,
void *cancel_baton,
+ svn_fs_progress_notify_func_t notify_func,
+ void *notify_baton,
svn_revnum_t start,
svn_revnum_t end,
apr_pool_t *pool);
+/* Verify REVISION in filesystem FS. Use POOL for temporary allocations. */
+svn_error_t *
+svn_fs_fs__verify_rev(svn_fs_t *fs,
+ svn_revnum_t revision,
+ apr_pool_t *pool);
+
/* Copy the fsfs filesystem SRC_FS at SRC_PATH into a new copy DST_FS at
* DST_PATH. If INCREMENTAL is TRUE, do not re-copy data which already
* exists in DST_FS. Use POOL for temporary allocations. */
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.c Mon Jan 21 23:37:01 2013
@@ -135,6 +135,8 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *
void *walker_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
+ svn_fs_progress_notify_func_t notify_func,
+ void *notify_baton,
svn_revnum_t start,
svn_revnum_t end,
apr_pool_t *pool)
@@ -143,6 +145,7 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *
svn_sqlite__stmt_t *stmt;
svn_boolean_t have_row;
int iterations = 0;
+ svn_revnum_t last_notified_revision = SVN_INVALID_REVNUM;
apr_pool_t *iterpool = svn_pool_create(pool);
@@ -164,6 +167,9 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *
SVN_ERR(svn_sqlite__reset(stmt));
if (SVN_IS_VALID_REVNUM(max)) /* The rep-cache could be empty. */
SVN_ERR(svn_fs_fs__revision_exists(max, fs, iterpool));
+
+ if (notify_func)
+ notify_func(SVN_INVALID_REVNUM, notify_baton, iterpool);
}
SVN_ERR(svn_sqlite__get_statement(&stmt, ffd->rep_cache_db,
@@ -210,6 +216,16 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *
return svn_error_compose_create(err, svn_sqlite__reset(stmt));
SVN_ERR(svn_sqlite__step(&have_row, stmt));
+
+ /* Notify (occasionally, because walking is fast and we can't
+ guarantee a properly ordered notification sequence anyway) */
+ if ( notify_func
+ && (iterations % 1024 == 0)
+ && (rep->revision != last_notified_revision))
+ {
+ notify_func(rep->revision, notify_baton, iterpool);
+ last_notified_revision = rep->revision;
+ }
}
SVN_ERR(svn_sqlite__reset(stmt));
Modified: subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.h?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_fs_fs/rep-cache.h Mon Jan 21 23:37:01 2013
@@ -55,6 +55,8 @@ svn_fs_fs__walk_rep_reference(svn_fs_t *
void *walker_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
+ svn_fs_progress_notify_func_t notify_func,
+ void *notify_baton,
svn_revnum_t start,
svn_revnum_t end,
apr_pool_t *pool);
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_local/ra_plugin.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_local/ra_plugin.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_local/ra_plugin.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_local/ra_plugin.c Mon Jan 21 23:37:01 2013
@@ -1220,7 +1220,7 @@ svn_ra_local__get_dir(svn_ra_session_t *
apr_hash_t *prophash;
const char *datestring, *entryname, *fullpath;
svn_fs_dirent_t *fs_entry;
- svn_dirent_t *entry = apr_pcalloc(pool, sizeof(*entry));
+ svn_dirent_t *entry = svn_dirent_create(pool);
svn_pool_clear(subpool);
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/ra_serf.h
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/ra_serf.h?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/ra_serf.h (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/ra_serf.h Mon Jan 21 23:37:01 2013
@@ -230,10 +230,12 @@ struct svn_ra_serf__session_t {
svn_ra_serf__blncache_t *blncache;
- /* Flag that indicates if we request the server for bulk updates (TRUE) with
- all the properties and content in the update-report response. If FALSE,
- request a skelta update-report with inlined properties. */
- svn_boolean_t bulk_updates;
+ /* Trisate flag that indicates user preference for using bulk updates
+ (svn_tristate_true) with all the properties and content in the
+ update-report response. If svn_tristate_false, request a skelta
+ update-report with inlined properties. If svn_tristate_unknown then use
+ server preference. */
+ svn_tristate_t bulk_updates;
/* Indicates if the server wants bulk update requests (Prefer) or only
accepts skelta requests (Off). If this value is On both options are
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/serf.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/serf.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/serf.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/serf.c Mon Jan 21 23:37:01 2013
@@ -187,24 +187,21 @@ load_config(svn_ra_serf__session_t *sess
/* Use the default proxy-specific settings if and only if
"http-proxy-exceptions" is not set to exclude this host. */
svn_config_get(config, &exceptions, SVN_CONFIG_SECTION_GLOBAL,
- SVN_CONFIG_OPTION_HTTP_PROXY_EXCEPTIONS, NULL);
- if (exceptions)
- {
- if (! svn_cstring_match_glob_list(session->session_url.hostname,
- svn_cstring_split(exceptions, ",",
- TRUE, pool)))
- {
- svn_config_get(config, &proxy_host, SVN_CONFIG_SECTION_GLOBAL,
- SVN_CONFIG_OPTION_HTTP_PROXY_HOST, NULL);
- svn_config_get(config, &port_str, SVN_CONFIG_SECTION_GLOBAL,
- SVN_CONFIG_OPTION_HTTP_PROXY_PORT, NULL);
- svn_config_get(config, &session->proxy_username,
- SVN_CONFIG_SECTION_GLOBAL,
- SVN_CONFIG_OPTION_HTTP_PROXY_USERNAME, NULL);
- svn_config_get(config, &session->proxy_password,
- SVN_CONFIG_SECTION_GLOBAL,
- SVN_CONFIG_OPTION_HTTP_PROXY_PASSWORD, NULL);
- }
+ SVN_CONFIG_OPTION_HTTP_PROXY_EXCEPTIONS, "");
+ if (! svn_cstring_match_glob_list(session->session_url.hostname,
+ svn_cstring_split(exceptions, ",",
+ TRUE, pool)))
+ {
+ svn_config_get(config, &proxy_host, SVN_CONFIG_SECTION_GLOBAL,
+ SVN_CONFIG_OPTION_HTTP_PROXY_HOST, NULL);
+ svn_config_get(config, &port_str, SVN_CONFIG_SECTION_GLOBAL,
+ SVN_CONFIG_OPTION_HTTP_PROXY_PORT, NULL);
+ svn_config_get(config, &session->proxy_username,
+ SVN_CONFIG_SECTION_GLOBAL,
+ SVN_CONFIG_OPTION_HTTP_PROXY_USERNAME, NULL);
+ svn_config_get(config, &session->proxy_password,
+ SVN_CONFIG_SECTION_GLOBAL,
+ SVN_CONFIG_OPTION_HTTP_PROXY_PASSWORD, NULL);
}
/* Load the global ssl settings, if set. */
@@ -217,10 +214,11 @@ load_config(svn_ra_serf__session_t *sess
/* If set, read the flag that tells us to do bulk updates or not. Defaults
to skelta updates. */
- SVN_ERR(svn_config_get_bool(config, &session->bulk_updates,
- SVN_CONFIG_SECTION_GLOBAL,
- SVN_CONFIG_OPTION_HTTP_BULK_UPDATES,
- FALSE));
+ SVN_ERR(svn_config_get_tristate(config, &session->bulk_updates,
+ SVN_CONFIG_SECTION_GLOBAL,
+ SVN_CONFIG_OPTION_HTTP_BULK_UPDATES,
+ "auto",
+ svn_tristate_unknown));
/* Load the maximum number of parallel session connections. */
svn_config_get_int64(config, &session->max_connections,
@@ -272,10 +270,11 @@ load_config(svn_ra_serf__session_t *sess
session->ssl_authorities);
/* Load the group bulk updates flag. */
- SVN_ERR(svn_config_get_bool(config, &session->bulk_updates,
- server_group,
- SVN_CONFIG_OPTION_HTTP_BULK_UPDATES,
- session->bulk_updates));
+ SVN_ERR(svn_config_get_tristate(config, &session->bulk_updates,
+ server_group,
+ SVN_CONFIG_OPTION_HTTP_BULK_UPDATES,
+ "auto",
+ session->bulk_updates));
/* Load the maximum number of parallel session connections,
overriding global values. */
@@ -803,7 +802,7 @@ path_dirent_walker(void *baton,
{
const char *base_name;
- entry = apr_pcalloc(pool, sizeof(*entry));
+ entry = svn_dirent_create(pool);
apr_hash_set(dirents->full_paths, path, path_len, entry);
@@ -921,7 +920,7 @@ svn_ra_serf__stat(svn_ra_session_t *ra_s
return svn_error_trace(err);
}
- dwb.entry = apr_pcalloc(pool, sizeof(*dwb.entry));
+ dwb.entry = svn_dirent_create(pool);
dwb.supports_deadprop_count = &deadprop_count;
dwb.result_pool = pool;
SVN_ERR(svn_ra_serf__walk_node_props(props, dirent_walker, &dwb, pool));
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_serf/update.c Mon Jan 21 23:37:01 2013
@@ -1644,7 +1644,12 @@ start_report(svn_ra_serf__xml_parser_t *
val = svn_xml_get_attr_value("send-all", attrs);
if (val && (strcmp(val, "true") == 0))
- ctx->send_all_mode = TRUE;
+ {
+ ctx->send_all_mode = TRUE;
+
+ /* All properties are included in send-all mode. */
+ ctx->add_props_included = TRUE;
+ }
}
else if (state == NONE && strcmp(name.name, "target-revision") == 0)
{
@@ -3131,6 +3136,7 @@ make_update_reporter(svn_ra_session_t *r
svn_boolean_t server_supports_depth;
svn_ra_serf__session_t *sess = ra_session->priv;
svn_stringbuf_t *buf = NULL;
+ svn_boolean_t use_bulk_updates;
SVN_ERR(svn_ra_serf__has_capability(ra_session, &server_supports_depth,
SVN_RA_CAPABILITY_DEPTH, scratch_pool));
@@ -3177,42 +3183,58 @@ make_update_reporter(svn_ra_session_t *r
svn_io_file_del_on_pool_cleanup,
report->pool, scratch_pool));
- if (sess->server_allows_bulk)
+ if (sess->bulk_updates == svn_tristate_true)
{
- if (apr_strnatcasecmp(sess->server_allows_bulk, "off") == 0)
- {
- /* Server doesn't want bulk updates */
- sess->bulk_updates = FALSE;
- }
- else if (apr_strnatcasecmp(sess->server_allows_bulk, "prefer") == 0)
- {
- /* Server prefers bulk updates, and we respect that */
- sess->bulk_updates = TRUE;
- }
- else
- {
- /* Server allows bulk updates, but doesn't dictate its use. Do
- whatever is the default or what the user defined in the config. */
- }
+ /* User would like to use bulk updates. */
+ use_bulk_updates = TRUE;
+ }
+ else if (sess->bulk_updates == svn_tristate_false)
+ {
+ /* User doesn't want bulk updates. */
+ use_bulk_updates = FALSE;
}
else
{
- /* Pre-1.8 server didn't send the bulk_updates header. Check if server
- supports inlining properties in update editor report. */
- if (sess->supports_inline_props)
+ /* User doesn't have any preferences on bulk updates. Decide on server
+ preferences and capabilities. */
+ if (sess->server_allows_bulk)
{
- /* Inline props supported: do not use bulk updates. */
- sess->bulk_updates = FALSE;
+ if (apr_strnatcasecmp(sess->server_allows_bulk, "off") == 0)
+ {
+ /* Server doesn't want bulk updates */
+ use_bulk_updates = FALSE;
+ }
+ else if (apr_strnatcasecmp(sess->server_allows_bulk, "prefer") == 0)
+ {
+ /* Server prefers bulk updates, and we respect that */
+ use_bulk_updates = TRUE;
+ }
+ else
+ {
+ /* Server allows bulk updates, but doesn't dictate its use. Do
+ whatever is the default. */
+ use_bulk_updates = FALSE;
+ }
}
else
{
- /* Inline props are noot supported: use bulk updates to avoid
- * PROPFINDs for every added node. */
- sess->bulk_updates = TRUE;
+ /* Pre-1.8 server didn't send the bulk_updates header. Check if server
+ supports inlining properties in update editor report. */
+ if (sess->supports_inline_props)
+ {
+ /* Inline props supported: do not use bulk updates. */
+ use_bulk_updates = FALSE;
+ }
+ else
+ {
+ /* Inline props are not supported: use bulk updates to avoid
+ * PROPFINDs for every added node. */
+ use_bulk_updates = TRUE;
+ }
}
}
- if (sess->bulk_updates)
+ if (use_bulk_updates)
{
svn_xml_make_open_tag(&buf, scratch_pool, svn_xml_normal,
"S:update-report",
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_svn/client.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_svn/client.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_svn/client.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_svn/client.c Mon Jan 21 23:37:01 2013
@@ -1274,7 +1274,7 @@ static svn_error_t *ra_svn_get_dir(svn_r
&name, &kind, &size, &has_props,
&crev, &cdate, &cauthor));
name = svn_relpath_canonicalize(name, pool);
- dirent = apr_palloc(pool, sizeof(*dirent));
+ dirent = svn_dirent_create(pool);
dirent->kind = svn_node_kind_from_word(kind);
dirent->size = size;/* FIXME: svn_filesize_t */
dirent->has_props = has_props;
@@ -1748,7 +1748,7 @@ static svn_error_t *ra_svn_stat(svn_ra_s
&kind, &size, &has_props,
&crev, &cdate, &cauthor));
- the_dirent = apr_palloc(pool, sizeof(*the_dirent));
+ the_dirent = svn_dirent_create(pool);
the_dirent->kind = svn_node_kind_from_word(kind);
the_dirent->size = size;/* FIXME: svn_filesize_t */
the_dirent->has_props = has_props;
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_svn/editorp.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_svn/editorp.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_svn/editorp.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_svn/editorp.c Mon Jan 21 23:37:01 2013
@@ -976,7 +976,7 @@ svn_error_t *svn_ra_svn_drive_editor2(sv
else
{
err = svn_error_createf(SVN_ERR_RA_SVN_UNKNOWN_CMD, NULL,
- _("Unknown command '%s'"), cmd);
+ _("Unknown editor command '%s'"), cmd);
err = svn_error_create(SVN_ERR_RA_SVN_CMD_ERR, err, NULL);
}
}
Modified: subversion/branches/ev2-export/subversion/libsvn_ra_svn/marshal.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_ra_svn/marshal.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_ra_svn/marshal.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_ra_svn/marshal.c Mon Jan 21 23:37:01 2013
@@ -1799,7 +1799,7 @@ svn_error_t *svn_ra_svn_handle_commands2
else
{
err = svn_error_createf(SVN_ERR_RA_SVN_UNKNOWN_CMD, NULL,
- _("Unknown command '%s'"), cmdname);
+ _("Unknown editor command '%s'"), cmdname);
err = svn_error_create(SVN_ERR_RA_SVN_CMD_ERR, err, NULL);
}
Modified: subversion/branches/ev2-export/subversion/libsvn_repos/dump.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/dump.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/dump.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/dump.c Mon Jan 21 23:37:01 2013
@@ -1321,13 +1321,15 @@ verify_directory_entry(void *baton, cons
void *val, apr_pool_t *pool)
{
struct dir_baton *db = baton;
+ svn_fs_dirent_t *dirent = (svn_fs_dirent_t *)val;
char *path = svn_relpath_join(db->path, (const char *)key, pool);
- svn_node_kind_t kind;
apr_hash_t *dirents;
svn_filesize_t len;
- SVN_ERR(svn_fs_check_path(&kind, db->edit_baton->fs_root, path, pool));
- switch (kind) {
+ /* since we can't access the directory entries directly by their ID,
+ we need to navigate from the FS_ROOT to them (relatively expensive
+ because we may start at a never rev than the last change to node). */
+ switch (dirent->kind) {
case svn_node_dir:
/* Getting this directory's contents is enough to ensure that our
link to it is correct. */
@@ -1340,7 +1342,8 @@ verify_directory_entry(void *baton, cons
break;
default:
return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
- _("Unexpected node kind %d for '%s'"), kind, path);
+ _("Unexpected node kind %d for '%s'"),
+ dirent->kind, path);
}
return SVN_NO_ERROR;
@@ -1359,6 +1362,32 @@ verify_close_directory(void *dir_baton,
return close_directory(dir_baton, pool);
}
+/* Baton type used for forwarding notifications from FS API to REPOS API. */
+struct verify_fs2_notify_func_baton_t
+{
+ /* notification function to call (must not be NULL) */
+ svn_repos_notify_func_t notify_func;
+
+ /* baton to use for it */
+ void *notify_baton;
+
+ /* type of notification to send (we will simply plug in the revision) */
+ svn_repos_notify_t *notify;
+};
+
+/* Forward the notification to BATON. */
+static void
+verify_fs2_notify_func(svn_revnum_t revision,
+ void *baton,
+ apr_pool_t *pool)
+{
+ struct verify_fs2_notify_func_baton_t *notify_baton = baton;
+
+ notify_baton->notify->revision = revision;
+ notify_baton->notify_func(notify_baton->notify_baton,
+ notify_baton->notify, pool);
+}
+
svn_error_t *
svn_repos_verify_fs2(svn_repos_t *repos,
svn_revnum_t start_rev,
@@ -1374,6 +1403,8 @@ svn_repos_verify_fs2(svn_repos_t *repos,
svn_revnum_t rev;
apr_pool_t *iterpool = svn_pool_create(pool);
svn_repos_notify_t *notify;
+ svn_fs_progress_notify_func_t verify_notify = NULL;
+ struct verify_fs2_notify_func_baton_t *verify_notify_baton = NULL;
/* Determine the current youngest revision of the filesystem. */
SVN_ERR(svn_fs_youngest_rev(&youngest, fs, pool));
@@ -1396,15 +1427,26 @@ svn_repos_verify_fs2(svn_repos_t *repos,
"(youngest revision is %ld)"),
end_rev, youngest);
+ /* Create a notify object that we can reuse within the loop and a
+ forwarding structure for notifications from inside svn_fs_verify(). */
+ if (notify_func)
+ {
+ notify = svn_repos_notify_create(svn_repos_notify_verify_rev_end,
+ pool);
+
+ verify_notify = verify_fs2_notify_func;
+ verify_notify_baton = apr_palloc(pool, sizeof(*verify_notify_baton));
+ verify_notify_baton->notify_func = notify_func;
+ verify_notify_baton->notify_baton = notify_baton;
+ verify_notify_baton->notify
+ = svn_repos_notify_create(svn_repos_notify_verify_struc_rev, pool);
+ }
+
/* Verify global/auxiliary data and backend-specific data first. */
SVN_ERR(svn_fs_verify(svn_fs_path(fs, pool), cancel_func, cancel_baton,
+ verify_notify, verify_notify_baton,
start_rev, end_rev, pool));
- /* Create a notify object that we can reuse within the loop. */
- if (notify_func)
- notify = svn_repos_notify_create(svn_repos_notify_verify_rev_end,
- pool);
-
for (rev = start_rev; rev <= end_rev; rev++)
{
const svn_delta_editor_t *dump_editor;
@@ -1432,6 +1474,8 @@ svn_repos_verify_fs2(svn_repos_t *repos,
&cancel_edit_baton,
iterpool));
+ SVN_ERR(svn_fs_verify_rev(fs, rev, iterpool));
+
SVN_ERR(svn_fs_revision_root(&to_root, fs, rev, iterpool));
SVN_ERR(svn_repos_replay2(to_root, "", SVN_INVALID_REVNUM, FALSE,
cancel_editor, cancel_edit_baton,
Modified: subversion/branches/ev2-export/subversion/libsvn_repos/reporter.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/reporter.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/reporter.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/reporter.c Mon Jan 21 23:37:01 2013
@@ -447,7 +447,8 @@ static svn_error_t *
change_dir_prop(report_baton_t *b, void *dir_baton, const char *name,
const svn_string_t *value, apr_pool_t *pool)
{
- return b->editor->change_dir_prop(dir_baton, name, value, pool);
+ return svn_error_trace(b->editor->change_dir_prop(dir_baton, name, value,
+ pool));
}
/* Call the file property-setting function of B->editor to set the
@@ -456,7 +457,8 @@ static svn_error_t *
change_file_prop(report_baton_t *b, void *file_baton, const char *name,
const svn_string_t *value, apr_pool_t *pool)
{
- return b->editor->change_file_prop(file_baton, name, value, pool);
+ return svn_error_trace(b->editor->change_file_prop(file_baton, name, value,
+ pool));
}
/* For the report B, return the relevant revprop data of revision REV in
@@ -752,8 +754,8 @@ check_auth(report_baton_t *b, svn_boolea
apr_pool_t *pool)
{
if (b->authz_read_func)
- return b->authz_read_func(allowed, b->t_root, path,
- b->authz_read_baton, pool);
+ return svn_error_trace(b->authz_read_func(allowed, b->t_root, path,
+ b->authz_read_baton, pool));
*allowed = TRUE;
return SVN_NO_ERROR;
}
@@ -879,9 +881,9 @@ add_file_smartly(report_baton_t *b,
}
}
- return b->editor->add_file(path, parent_baton,
- *copyfrom_path, *copyfrom_rev,
- pool, new_file_baton);
+ return svn_error_trace(b->editor->add_file(path, parent_baton,
+ *copyfrom_path, *copyfrom_rev,
+ pool, new_file_baton));
}
@@ -1016,7 +1018,7 @@ update_entry(report_baton_t *b, svn_revn
/* If there's no target, we have nothing more to do. */
if (!t_entry)
- return skip_path_info(b, e_path);
+ return svn_error_trace(skip_path_info(b, e_path));
/* Check if the user is authorized to find out about the target. */
SVN_ERR(check_auth(b, &allowed, t_path, pool));
@@ -1026,7 +1028,7 @@ update_entry(report_baton_t *b, svn_revn
SVN_ERR(b->editor->absent_directory(e_path, dir_baton, pool));
else
SVN_ERR(b->editor->absent_file(e_path, dir_baton, pool));
- return skip_path_info(b, e_path);
+ return svn_error_trace(skip_path_info(b, e_path));
}
if (t_entry->kind == svn_node_dir)
@@ -1042,7 +1044,7 @@ update_entry(report_baton_t *b, svn_revn
SVN_ERR(delta_dirs(b, s_rev, s_path, t_path, new_baton, e_path,
info ? info->start_empty : FALSE,
wc_depth, requested_depth, pool));
- return b->editor->close_directory(new_baton, pool);
+ return svn_error_trace(b->editor->close_directory(new_baton, pool));
}
else
{
@@ -1074,7 +1076,8 @@ update_entry(report_baton_t *b, svn_revn
SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_md5, b->t_root,
t_path, TRUE, pool));
hex_digest = svn_checksum_to_cstring(checksum, pool);
- return b->editor->close_file(new_baton, hex_digest, pool);
+ return svn_error_trace(b->editor->close_file(new_baton, hex_digest,
+ pool));
}
}
@@ -1353,8 +1356,6 @@ drive(report_baton_t *b, svn_revnum_t s_
/* Collect information about the source and target nodes. */
s_fullpath = svn_fspath__join(b->fs_base, b->s_operand, pool);
- /* ### Weird: When I have a file external defined as "^/A/a X/xa",
- * ### S_FULLPATH becomes "/A/a/xa" here, which is complete nonsense. */
SVN_ERR(get_source_root(b, &s_root, s_rev));
SVN_ERR(fake_dirent(&s_entry, s_root, s_fullpath, pool));
SVN_ERR(fake_dirent(&t_entry, b->t_root, b->t_path, pool));
@@ -1392,7 +1393,7 @@ drive(report_baton_t *b, svn_revnum_t s_
t_entry, root_baton, b->s_operand, info,
info->depth, b->requested_depth, pool));
- return b->editor->close_directory(root_baton, pool);
+ return svn_error_trace(b->editor->close_directory(root_baton, pool));
}
/* Initialize the baton fields for editor-driving, and drive the editor. */
@@ -1448,7 +1449,8 @@ finish_report(report_baton_t *b, apr_poo
b->s_roots[i] = NULL;
{
- svn_error_t *err = drive(b, s_rev, info, pool);
+ svn_error_t *err = svn_error_trace(drive(b, s_rev, info, pool));
+
if (err == SVN_NO_ERROR)
return svn_error_trace(b->editor->close_edit(b->edit_baton, pool));
@@ -1500,7 +1502,8 @@ write_path_info(report_baton_t *b, const
rep = apr_psprintf(pool, "+%" APR_SIZE_T_FMT ":%s%s%s%s%c%s",
strlen(path), path, lrep, rrep, drep,
start_empty ? '+' : '-', ltrep);
- return svn_spillbuf__reader_write(b->reader, rep, strlen(rep), pool);
+ return svn_error_trace(
+ svn_spillbuf__reader_write(b->reader, rep, strlen(rep), pool));
}
svn_error_t *
@@ -1508,8 +1511,9 @@ svn_repos_set_path3(void *baton, const c
svn_depth_t depth, svn_boolean_t start_empty,
const char *lock_token, apr_pool_t *pool)
{
- return write_path_info(baton, path, NULL, rev, depth, start_empty,
- lock_token, pool);
+ return svn_error_trace(
+ write_path_info(baton, path, NULL, rev, depth, start_empty,
+ lock_token, pool));
}
svn_error_t *
@@ -1522,8 +1526,9 @@ svn_repos_link_path3(void *baton, const
return svn_error_create(SVN_ERR_REPOS_BAD_ARGS, NULL,
_("Depth 'exclude' not supported for link"));
- return write_path_info(baton, path, link_path, rev, depth,
- start_empty, lock_token, pool);
+ return svn_error_trace(
+ write_path_info(baton, path, link_path, rev, depth,
+ start_empty, lock_token, pool));
}
svn_error_t *
@@ -1531,8 +1536,9 @@ svn_repos_delete_path(void *baton, const
{
/* We pass svn_depth_infinity because deletion of a path always
deletes everything underneath it. */
- return write_path_info(baton, path, NULL, SVN_INVALID_REVNUM,
- svn_depth_infinity, FALSE, NULL, pool);
+ return svn_error_trace(
+ write_path_info(baton, path, NULL, SVN_INVALID_REVNUM,
+ svn_depth_infinity, FALSE, NULL, pool));
}
svn_error_t *
Modified: subversion/branches/ev2-export/subversion/libsvn_repos/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_repos/repos.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_repos/repos.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_repos/repos.c Mon Jan 21 23:37:01 2013
@@ -2122,7 +2122,7 @@ svn_repos_stat(svn_dirent_t **dirent,
return SVN_NO_ERROR;
}
- ent = apr_pcalloc(pool, sizeof(*ent));
+ ent = svn_dirent_create(pool);
ent->kind = kind;
if (kind == svn_node_file)
Modified: subversion/branches/ev2-export/subversion/libsvn_subr/config.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/config.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/config.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/config.c Mon Jan 21 23:37:01 2013
@@ -796,6 +796,36 @@ svn_config_get_yes_no_ask(svn_config_t *
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_config_get_tristate(svn_config_t *cfg, svn_tristate_t *valuep,
+ const char *section, const char *option,
+ const char *unknown_value,
+ svn_tristate_t default_value)
+{
+ const char *tmp_value;
+
+ svn_config_get(cfg, &tmp_value, section, option, NULL);
+
+ if (! tmp_value)
+ {
+ *valuep = default_value;
+ }
+ else if (0 == svn_cstring_casecmp(tmp_value, unknown_value))
+ {
+ *valuep = svn_tristate_unknown;
+ }
+ else
+ {
+ svn_boolean_t bool_val;
+ /* We already incorporated default_value into tmp_value if
+ necessary, so the FALSE below will be ignored unless the
+ caller is doing something it shouldn't be doing. */
+ SVN_ERR(get_bool(&bool_val, tmp_value, FALSE, section, option));
+ *valuep = bool_val ? svn_tristate_true : svn_tristate_false;
+ }
+
+ return SVN_NO_ERROR;
+}
int
svn_config_enumerate_sections(svn_config_t *cfg,
Modified: subversion/branches/ev2-export/subversion/libsvn_subr/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/ev2-export/subversion/libsvn_subr/deprecated.c?rev=1436688&r1=1436687&r2=1436688&view=diff
==============================================================================
--- subversion/branches/ev2-export/subversion/libsvn_subr/deprecated.c (original)
+++ subversion/branches/ev2-export/subversion/libsvn_subr/deprecated.c Mon Jan 21 23:37:01 2013
@@ -878,6 +878,22 @@ svn_io_dir_walk(const char *dirname,
&baton, pool));
}
+svn_error_t *
+svn_io_stat_dirent(const svn_io_dirent2_t **dirent_p,
+ const char *path,
+ svn_boolean_t ignore_enoent,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ return svn_error_trace(
+ svn_io_stat_dirent2(dirent_p,
+ path,
+ FALSE,
+ ignore_enoent,
+ result_pool,
+ scratch_pool));
+}
+
/*** From constructors.c ***/
svn_log_changed_path_t *
svn_log_changed_path_dup(const svn_log_changed_path_t *changed_path,