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 2010/12/10 22:23:13 UTC
svn commit: r1044516 [8/22] - in /subversion/branches/ignore-mergeinfo: ./
build/ac-macros/ build/generator/ contrib/server-side/ notes/ notes/wc-ng/
subversion/bindings/javahl/native/
subversion/bindings/javahl/src/org/apache/subversion/javahl/ subver...
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/merge.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/merge.c?rev=1044516&r1=1044515&r2=1044516&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/merge.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/merge.c Fri Dec 10 21:23:03 2010
@@ -437,27 +437,7 @@ obstructed_or_missing(svn_wc_notify_stat
local_abspath,
pool));
if (is_deleted)
- {
- /* ### While we are not at single-db: detect missing .svn dirs.
- ### Once we switch to single db expected kind should be always
- ### none, just like for files */
- if (kind_expected == svn_node_dir)
- {
- if (kind_on_disk == svn_node_none)
- {
- svn_boolean_t is_obstructed;
-
- SVN_ERR(svn_wc__node_is_status_obstructed(&is_obstructed,
- merge_b->ctx->wc_ctx,
- local_abspath,
- pool));
- if (!is_obstructed)
- kind_expected = svn_node_none;
- }
- }
- else
- kind_expected = svn_node_none;
- }
+ kind_expected = svn_node_none;
}
if (kind_expected == kind_on_disk)
@@ -3367,6 +3347,7 @@ get_full_mergeinfo(svn_mergeinfo_t *reco
svn_revnum_t target_rev;
svn_opt_revision_t peg_revision;
apr_pool_t *sesspool = NULL;
+ svn_error_t *err;
/* Assert that we have sane input. */
SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(start)
@@ -3374,9 +3355,26 @@ get_full_mergeinfo(svn_mergeinfo_t *reco
&& (start > end));
peg_revision.kind = svn_opt_revision_working;
- SVN_ERR(svn_client__derive_location(&url, &target_rev, target_abspath,
- &peg_revision, ra_session,
- ctx, result_pool, scratch_pool));
+ err = svn_client__derive_location(&url, &target_rev, target_abspath,
+ &peg_revision, ra_session,
+ ctx, result_pool, scratch_pool);
+
+ if (err)
+ {
+ if (err->apr_err == SVN_ERR_CLIENT_VERSIONED_PATH_REQUIRED)
+ {
+ /* We've been asked to operate on a target which has no location
+ * in the repository. Either it's unversioned (but attempts to
+ * merge into unversioned targets should not get as far as here),
+ * or it is locally added, in which case the target's implicit
+ * mergeinfo is empty. */
+ svn_error_clear(err);
+ *implicit_mergeinfo = apr_hash_make(result_pool);
+ return SVN_NO_ERROR;
+ }
+ else
+ return svn_error_return(err);
+ }
if (target_rev <= end)
{
@@ -5284,6 +5282,17 @@ struct get_mergeinfo_walk_baton
{
/* Array of paths that have explicit mergeinfo and/or are switched. */
apr_array_header_t *children_with_mergeinfo;
+
+ /* A hash of MERGE_TARGET_ABSPATH's subdirectories' dirents. Maps
+ const char * absolute working copy paths to dirent hashes as obtained
+ by svn_io_get_dirents3(). Contents are allocated in CB_POOL. */
+ apr_hash_t *subtree_dirents;
+
+ /* A hash to keep track of any subtrees in the merge target which are
+ unexpectedly missing from disk. Maps const char * absolute working
+ copy paths to the same. Contents are allocated in CB_POOL. */
+ apr_hash_t *missing_subtrees;
+
/* Merge source canonical path. */
const char* merge_src_canon_path;
@@ -5304,8 +5313,111 @@ struct get_mergeinfo_walk_baton
/* Pool from which to allocate new elements of CHILDREN_WITH_MERGEINFO. */
apr_pool_t *pool;
+
+ /* Pool with a lifetime guaranteed over all the get_mergeinfo_walk_cb
+ callbacks. */
+ apr_pool_t *cb_pool;
};
+/* Helper for the svn_wc__node_found_func_t callback get_mergeinfo_walk_cb().
+
+ Checks for issue #2915 subtrees, i.e. those that the WC thinks are on disk
+ but have been removed due to an OS-level deletion.
+
+ If the supposed working path LOCAL_ABSPATH, of kind KIND, is the root
+ of a missing subtree, then add a (const char *) WC absolute path to
+ (const char *) WC absolute path mapping to MISSING_SUBTREES, where the
+ paths are both a copy of LOCAL_ABSPATH, allocated in RESULT_POOL.
+
+ If LOCAL_ABSPATH is a directory and is not missing from disk, then add
+ a (const char *) WC absolute path to (svn_io_dirent2_t *) dirent mapping
+ to SUBTREE_DIRENTS, again allocated in RESULT_POOL (see
+ svn_io_get_dirents3).
+
+ SCRATCH_POOL is used for temporary allocations.
+
+ Note: Since this is effetively a svn_wc__node_found_func_t callback, it
+ must be called in depth-first order. */
+static svn_error_t *
+record_missing_subtree_roots(const char *local_abspath,
+ svn_node_kind_t kind,
+ apr_hash_t *subtree_dirents,
+ apr_hash_t *missing_subtrees,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ svn_boolean_t missing_subtree_root = FALSE;
+
+ /* Store the dirents for each directory in SUBTREE_DIRENTS. */
+ if (kind == svn_node_dir)
+ {
+ /* If SUBTREE_DIRENTS is empty LOCAL_ABSPATH is merge target. */
+ if (apr_hash_count(subtree_dirents) == 0
+ || apr_hash_get(subtree_dirents,
+ svn_dirent_dirname(local_abspath,
+ scratch_pool),
+ APR_HASH_KEY_STRING))
+ {
+ apr_hash_t *dirents;
+ svn_error_t *err = svn_io_get_dirents3(&dirents, local_abspath,
+ TRUE, result_pool,
+ scratch_pool);
+ if (err)
+ {
+ if (APR_STATUS_IS_ENOENT(err->apr_err)
+ || SVN__APR_STATUS_IS_ENOTDIR(err->apr_err))
+ {
+ /* We can't get this directory's dirents, it's missing
+ from disk. */
+ svn_error_clear(err);
+ missing_subtree_root = TRUE;
+ }
+ else
+ {
+ return err;
+ }
+ }
+ else
+ {
+ apr_hash_set(subtree_dirents,
+ apr_pstrdup(result_pool, local_abspath),
+ APR_HASH_KEY_STRING, dirents);
+ }
+ }
+ }
+ else /* kind != svn_node_dir */
+ {
+ /* Is this non-directory missing from disk? Check LOCAL_ABSPATH's
+ parent's dirents. */
+ apr_hash_t *parent_dirents = apr_hash_get(subtree_dirents,
+ svn_dirent_dirname(local_abspath,
+ scratch_pool),
+ APR_HASH_KEY_STRING);
+
+ /* If the parent_dirents is NULL, then LOCAL_ABSPATH is the
+ subtree of a missing subtree. Since we only report the roots
+ of missing subtrees there is nothing more to do in that case. */
+ if (parent_dirents)
+ {
+ svn_io_dirent2_t *dirent =
+ apr_hash_get(parent_dirents,
+ svn_dirent_basename(local_abspath, scratch_pool),
+ APR_HASH_KEY_STRING);
+ if (!dirent)
+ missing_subtree_root = TRUE;
+ }
+ }
+
+ if (missing_subtree_root)
+ {
+ const char *path = apr_pstrdup(result_pool, local_abspath);
+
+ apr_hash_set(missing_subtrees, path,
+ APR_HASH_KEY_STRING, path);
+ }
+
+ return SVN_NO_ERROR;
+}
/* svn_wc__node_found_func_t callback for get_mergeinfo_paths().
@@ -5333,7 +5445,6 @@ get_mergeinfo_walk_cb(const char *local_
svn_boolean_t is_present;
svn_boolean_t deleted;
svn_boolean_t absent;
- svn_boolean_t obstructed;
svn_boolean_t immediate_child_dir;
/* TODO(#2843) How to deal with a excluded item on merge? */
@@ -5345,14 +5456,12 @@ get_mergeinfo_walk_cb(const char *local_
if (!is_present)
return SVN_NO_ERROR;
- SVN_ERR(svn_wc__node_is_status_obstructed(&obstructed, wb->ctx->wc_ctx,
- local_abspath, scratch_pool));
SVN_ERR(svn_wc__node_is_status_deleted(&deleted, wb->ctx->wc_ctx,
local_abspath, scratch_pool));
SVN_ERR(svn_wc__node_is_status_absent(&absent, wb->ctx->wc_ctx,
local_abspath, scratch_pool));
- if (obstructed || deleted || absent)
+ if (deleted || absent)
{
propval = NULL;
switched = FALSE;
@@ -5382,6 +5491,13 @@ get_mergeinfo_walk_cb(const char *local_
&&(kind == svn_node_dir)
&& (strcmp(abs_parent_path,
wb->merge_target_abspath) == 0));
+ /* Make sure what the WC thinks is present on disk really is. */
+ if (!absent && !deleted)
+ SVN_ERR(record_missing_subtree_roots(local_abspath, kind,
+ wb->subtree_dirents,
+ wb->missing_subtrees,
+ wb->cb_pool,
+ scratch_pool));
/* Store PATHs with explict mergeinfo, which are switched, are missing
children due to a sparse checkout, are scheduled for deletion are absent
@@ -5600,7 +5716,7 @@ insert_parent_and_sibs_of_sw_absent_del_
/* Helper for do_directory_merge()
If HONOR_MERGEINFO is TRUE, then perform a depth first walk of the working
- copy tree rooted at MERGE_CMD_BATON->TARGET_ABSPATH.
+ copy tree rooted at MERGE_CMD_BATON->TARGET_ABSPATH to depth DEPTH.
Create an svn_client__merge_path_t * for any path which meets one or more
of the following criteria:
@@ -5628,6 +5744,9 @@ insert_parent_and_sibs_of_sw_absent_del_
If HONOR_MERGEINFO is FALSE, then create an svn_client__merge_path_t * only
for MERGE_CMD_BATON->TARGET_ABSPATH (i.e. only criteria 7 is applied).
+ If subtrees within the requested DEPTH are unexpectedly missing disk,
+ then raise SVN_ERR_CLIENT_NOT_READY_TO_MERGE.
+
Store the svn_client__merge_path_t *'s in *CHILDREN_WITH_MERGEINFO in
depth-first order based on the svn_client__merge_path_t *s path member as
sorted by svn_path_compare_paths(). Set the remaining_ranges field of each
@@ -5667,6 +5786,9 @@ get_mergeinfo_paths(apr_array_header_t *
struct get_mergeinfo_walk_baton wb = { 0 };
wb.children_with_mergeinfo = children_with_mergeinfo;
+ wb.cb_pool = svn_pool_create(scratch_pool);
+ wb.subtree_dirents = apr_hash_make(wb.cb_pool);
+ wb.missing_subtrees = apr_hash_make(wb.cb_pool);
wb.merge_src_canon_path = merge_src_canon_path;
wb.merge_target_abspath = merge_cmd_baton->target_abspath;
wb.source_root_url = source_root_url;
@@ -5690,6 +5812,35 @@ get_mergeinfo_paths(apr_array_header_t *
merge_cmd_baton->ctx->cancel_baton,
scratch_pool));
+ if (apr_hash_count(wb.missing_subtrees))
+ {
+ apr_hash_index_t *hi;
+ svn_stringbuf_t *missing_subtree_err_buf =
+ svn_stringbuf_create(_("Merge tracking not allowed with missing "
+ "subtrees; try restoring these items "
+ "first:\n"), scratch_pool);
+
+ iterpool = svn_pool_create(scratch_pool);
+
+ for (hi = apr_hash_first(scratch_pool, wb.missing_subtrees);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ svn_pool_clear(iterpool);
+ svn_stringbuf_appendcstr(missing_subtree_err_buf,
+ svn_dirent_local_style(
+ svn__apr_hash_index_key(hi), iterpool));
+ svn_stringbuf_appendcstr(missing_subtree_err_buf, "\n");
+ }
+
+ return svn_error_create(SVN_ERR_CLIENT_NOT_READY_TO_MERGE,
+ NULL, missing_subtree_err_buf->data);
+ }
+
+ /* This pool is only needed across all the callbacks to detect
+ missing subtrees. */
+ svn_pool_destroy(wb.cb_pool);
+
/* CHILDREN_WITH_MERGEINFO must be in depth first order, but the node
walk code returns nodes in a non particular order. Also, we may need
to add elements to the array to cover case 3) through 5) from the
@@ -7192,7 +7343,8 @@ record_mergeinfo_for_dir_merge(svn_merge
merge target, with no pre-existing explicit mergeinfo, during a --depth
immediates merge). Stash those that are inoperative at any depth in
INOPERATIVE_IMMEDIATE_CHILDREN. */
- if (!merge_b->record_only && range.start <= range.end)
+ if (!merge_b->record_only && range.start <= range.end
+ && depth == svn_depth_immediates)
SVN_ERR(get_inoperative_immediate_children(
&inoperative_immediate_children,
notify_b->children_with_mergeinfo,
@@ -8316,6 +8468,11 @@ do_merge(apr_hash_t **modified_subtrees,
SVN_ERR(svn_wc_read_kind(&target_kind, ctx->wc_ctx, target_abspath, FALSE,
pool));
+ if (target_kind != svn_node_dir && target_kind != svn_node_file)
+ return svn_error_return(svn_error_createf(
+ SVN_ERR_ILLEGAL_TARGET, NULL,
+ _("Merge target '%s' does not exist in the "
+ "working copy"), target_abspath));
/* Ensure a known depth. */
if (depth == svn_depth_unknown)
@@ -8693,12 +8850,26 @@ merge_locked(const char *source1,
apr_pool_t *sesspool;
svn_boolean_t same_repos;
const char *source_repos_uuid1, *source_repos_uuid2;
+ svn_node_kind_t target_kind;
- /* Sanity check our input -- we require specified revisions. */
+ /* Make sure the target is really there. */
+ SVN_ERR(svn_io_check_path(target_abspath, &target_kind, scratch_pool));
+ if (target_kind == svn_node_none)
+ return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+ _("Path '%s' does not exist"),
+ svn_dirent_local_style(target_abspath,
+ scratch_pool));
+
+ /* Sanity check our input -- we require specified revisions,
+ * and either 2 paths or 2 URLs. */
if ((revision1->kind == svn_opt_revision_unspecified)
|| (revision2->kind == svn_opt_revision_unspecified))
return svn_error_create(SVN_ERR_CLIENT_BAD_REVISION, NULL,
_("Not all required revisions are specified"));
+ if (svn_path_is_url(source1) != svn_path_is_url(source2))
+ return svn_error_return(svn_error_create(SVN_ERR_ILLEGAL_TARGET, NULL,
+ _("Merge sources must both be "
+ "either paths or URLs")));
/* ### FIXME: This function really ought to do a history check on
the left and right sides of the merge source, and -- if one is an
@@ -8726,6 +8897,14 @@ merge_locked(const char *source1,
_("'%s' has no URL"),
svn_dirent_local_style(source2, scratch_pool));
+ SVN_ERR(svn_wc_read_kind(&target_kind, ctx->wc_ctx, target_abspath, FALSE,
+ scratch_pool));
+ if (target_kind != svn_node_dir && target_kind != svn_node_file)
+ return svn_error_return(svn_error_createf(
+ SVN_ERR_ILLEGAL_TARGET, NULL,
+ _("Merge target '%s' does not exist in the "
+ "working copy"), target_abspath));
+
/* Determine the working copy target's repository root URL. */
working_rev.kind = svn_opt_revision_working;
SVN_ERR(svn_client__get_repos_root(&wc_repos_root, target_abspath,
@@ -9956,6 +10135,15 @@ merge_reintegrate_locked(const char *sou
struct get_subtree_mergeinfo_walk_baton wb;
const char *target_url;
svn_revnum_t target_base_rev;
+ svn_node_kind_t kind;
+
+ /* Make sure the target is really there. */
+ SVN_ERR(svn_io_check_path(target_abspath, &kind, scratch_pool));
+ if (kind == svn_node_none)
+ return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+ _("Path '%s' does not exist"),
+ svn_dirent_local_style(target_abspath,
+ scratch_pool));
/* Make sure we're dealing with a real URL. */
SVN_ERR(svn_client_url_from_path2(&url2, source, ctx,
@@ -10216,8 +10404,17 @@ merge_peg_locked(const char *source,
svn_boolean_t use_sleep = FALSE;
svn_error_t *err;
svn_boolean_t same_repos;
+ svn_node_kind_t target_kind;
SVN_ERR_ASSERT(svn_dirent_is_absolute(target_abspath));
+
+ /* Make sure the target is really there. */
+ SVN_ERR(svn_io_check_path(target_abspath, &target_kind, scratch_pool));
+ if (target_kind == svn_node_none)
+ return svn_error_createf(SVN_ERR_WC_PATH_NOT_FOUND, NULL,
+ _("Path '%s' does not exist"),
+ svn_dirent_local_style(target_abspath,
+ scratch_pool));
/* Make sure we're dealing with a real URL. */
SVN_ERR(svn_client_url_from_path2(&URL, source, ctx,
@@ -10227,6 +10424,14 @@ merge_peg_locked(const char *source,
_("'%s' has no URL"),
svn_dirent_local_style(source, scratch_pool));
+ SVN_ERR(svn_wc_read_kind(&target_kind, ctx->wc_ctx, target_abspath, FALSE,
+ scratch_pool));
+ if (target_kind != svn_node_dir && target_kind != svn_node_file)
+ return svn_error_return(svn_error_createf(
+ SVN_ERR_ILLEGAL_TARGET, NULL,
+ _("Merge target '%s' does not exist in the "
+ "working copy"), target_abspath));
+
/* Determine the working copy target's repository root URL. */
working_rev.kind = svn_opt_revision_working;
SVN_ERR(svn_client__get_repos_root(&wc_repos_root, target_abspath,
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/patch.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/patch.c?rev=1044516&r1=1044515&r2=1044516&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/patch.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/patch.c Fri Dec 10 21:23:03 2010
@@ -48,7 +48,7 @@
typedef struct hunk_info_t {
/* The hunk. */
- const svn_hunk_t *hunk;
+ const svn_diff_hunk_t *hunk;
/* The line where the hunk matched in the target file. */
svn_linenum_t matched_line;
@@ -176,7 +176,7 @@ typedef struct patch_target_t {
/* True if at least one hunk was rejected. */
svn_boolean_t had_rejects;
- /* True if atleast one property hunk was rejected. */
+ /* True if at least one property hunk was rejected. */
svn_boolean_t had_prop_rejects;
/* True if the target file had local modifications before the
@@ -197,10 +197,10 @@ typedef struct patch_target_t {
/* True if the target has the executable bit set. */
svn_boolean_t executable;
- /* True if the patch changes the text of the target */
+ /* True if the patch changed the text of the target. */
svn_boolean_t has_text_changes;
- /* True if the patch changes any of the properties of the target */
+ /* True if the patch changed any of the properties of the target. */
svn_boolean_t has_prop_changes;
/* All the information that is specific to the content of the target. */
@@ -256,7 +256,8 @@ strip_path(const char **result, const ch
return SVN_NO_ERROR;
}
-/* Obtain KEYWORDS, EOL_STYLE and EOL_STR for LOCAL_ABSPATH, from WC_CTX.
+/* Obtain KEYWORDS, EOL_STYLE and EOL_STR for LOCAL_ABSPATH.
+ * WC_CTX is a context for the working copy the patch is applied to.
* Use RESULT_POOL for allocations of fields in TARGET.
* Use SCRATCH_POOL for all other allocations. */
static svn_error_t *
@@ -271,7 +272,6 @@ obtain_eol_and_keywords_for_file(apr_has
apr_hash_t *props;
svn_string_t *keywords_val, *eol_style_val;
- /* Handle svn:keyword and svn:eol-style properties. */
SVN_ERR(svn_wc_prop_list2(&props, wc_ctx, local_abspath,
scratch_pool, scratch_pool));
keywords_val = apr_hash_get(props, SVN_PROP_KEYWORDS,
@@ -322,8 +322,9 @@ obtain_eol_and_keywords_for_file(apr_has
* Indicate in TARGET->SKIPPED whether the target should be skipped.
* STRIP_COUNT specifies the number of leading path components
* which should be stripped from target paths in the patch.
- * PROP_CHANGES_ONLY is used for determining if the target path is allowed
- * to be a dir.
+ * PROP_CHANGES_ONLY specifies whether the target path is allowed to have
+ * only property changes, and no content changes (in which case the target
+ * must be a directory).
* Use RESULT_POOL for allocations of fields in TARGET.
* Use SCRATCH_POOL for all other allocations. */
static svn_error_t *
@@ -437,7 +438,7 @@ resolve_target_path(patch_target_t *targ
SVN_ERR(svn_wc_read_kind(&target->db_kind, wc_ctx, target->local_abspath,
FALSE, scratch_pool));
- /* If the target is a version directory not missing from disk,
+ /* 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)
@@ -510,14 +511,10 @@ init_prop_target(prop_patch_target_t **p
}
if (value)
- {
- /* We assume that a property is small enough to be kept in memory during
- * the patch process. */
- content_info->stream = svn_stream_from_string(value, result_pool);
- }
+ content_info->stream = svn_stream_from_string(value, result_pool);
/* Create a temporary file to write the patched result to. For properties,
- * we don't have to worrry about different eol-style. */
+ * we don't have to worry about eol-style. ### Why not? */
SVN_ERR(svn_stream_open_unique(&content_info->patched,
&patched_path, NULL,
remove_tempfiles ?
@@ -535,17 +532,22 @@ init_prop_target(prop_patch_target_t **p
* described by PATCH. Use working copy context WC_CTX.
* STRIP_COUNT specifies the number of leading path components
* which should be stripped from target paths in the patch.
+ * OLD_PATCH_TARGET_NAMES indicates whether the old target's name parsed
+ * from the patch file should be preferred over the new target's name.
* The patch target structure is allocated in RESULT_POOL, but if the target
* should be skipped, PATCH_TARGET->SKIPPED is set and the target should be
* treated as not fully initialized, e.g. the caller should not not do any
* further operations on the target if it is marked to be skipped.
- * REMOVE_TEMPFILES as in svn_client_patch().
+ * If REMOVE_TEMPFILES is TRUE, set up temporary files to be removed as
+ * soon as they are no longer needed.
* Use SCRATCH_POOL for all other allocations. */
static svn_error_t *
init_patch_target(patch_target_t **patch_target,
const svn_patch_t *patch,
const char *base_dir,
- svn_wc_context_t *wc_ctx, int strip_count,
+ svn_wc_context_t *wc_ctx,
+ int strip_count,
+ svn_boolean_t old_patch_target_names,
svn_boolean_t remove_tempfiles,
apr_pool_t *result_pool, apr_pool_t *scratch_pool)
{
@@ -557,7 +559,6 @@ init_patch_target(patch_target_t **patch
{
apr_hash_index_t *hi;
- /* ### Should we use an iterpool here? */
for (hi = apr_hash_first(scratch_pool, patch->prop_patches);
hi;
hi = apr_hash_next(hi))
@@ -592,7 +593,8 @@ init_patch_target(patch_target_t **patch
target->prop_targets = apr_hash_make(result_pool);
target->pool = result_pool;
- SVN_ERR(resolve_target_path(target, patch->new_filename,
+ SVN_ERR(resolve_target_path(target, old_patch_target_names ?
+ patch->old_filename : patch->new_filename,
base_dir, strip_count, prop_changes_only,
wc_ctx, result_pool, scratch_pool));
if (! target->skipped)
@@ -602,18 +604,17 @@ init_patch_target(patch_target_t **patch
apr_size_t len;
svn_stream_t *patched_raw;
+ /* Create a temporary file, and associated streams,
+ * to write the patched result to. */
if (target->kind_on_disk == svn_node_file)
{
- /* Open the file. */
SVN_ERR(svn_io_file_open(&target->file, target->local_abspath,
APR_READ | APR_BINARY | APR_BUFFERED,
APR_OS_DEFAULT, result_pool));
- /* Create a stream to read from the target. */
content_info->stream = svn_stream_from_aprfile2(target->file,
FALSE, result_pool);
- /* Also check the file for local mods and the Xbit. */
SVN_ERR(svn_wc_text_modified_p2(&target->local_mods, wc_ctx,
target->local_abspath, FALSE,
scratch_pool));
@@ -630,7 +631,14 @@ init_patch_target(patch_target_t **patch
scratch_pool));
}
- /* Create a temporary file to write the patched result to. */
+ /* ### Is it ok to set target->added here? Isn't the target supposed to
+ * ### be marked as added after it's been proven that it can be added?
+ * ### One alternative is to include a git_added flag. Or maybe we
+ * ### should have kept the patch field in patch_target_t? Then we
+ * ### could have checked for target->patch->operation == added */
+ if (patch->operation == svn_diff_op_added)
+ target->added = TRUE;
+
SVN_ERR(svn_stream_open_unique(&patched_raw,
&target->patched_path, NULL,
remove_tempfiles ?
@@ -638,16 +646,15 @@ init_patch_target(patch_target_t **patch
svn_io_file_del_none,
result_pool, scratch_pool));
- /* Expand keywords in the patched file.
- * Repair newlines if svn:eol-style dictates a particular style. */
+ /* We always expand keywords in the patched file, but repair newlines
+ * only if svn:eol-style dictates a particular style. */
repair_eol = (content_info->eol_style == svn_subst_eol_style_fixed
|| content_info->eol_style == svn_subst_eol_style_native);
content_info->patched = svn_subst_stream_translated(
patched_raw, content_info->eol_str, repair_eol,
content_info->keywords, TRUE, result_pool);
- /* We'll also need a stream to write rejected hunks to.
- * We don't expand keywords, nor normalise line-endings,
+ /* We don't expand keywords, nor normalise line-endings,
* in reject files. */
SVN_ERR(svn_stream_open_unique(&content_info->reject,
&target->reject_path, NULL,
@@ -665,7 +672,7 @@ init_patch_target(patch_target_t **patch
len = strlen(diff_header);
SVN_ERR(svn_stream_write(content_info->reject, diff_header, &len));
- /* Time for the properties */
+ /* Handle properties. */
if (! target->skipped)
{
apr_hash_index_t *hi;
@@ -678,7 +685,6 @@ init_patch_target(patch_target_t **patch
svn_prop_patch_t *prop_patch = svn__apr_hash_index_val(hi);
prop_patch_target_t *prop_target;
- /* Obtain info about this property */
SVN_ERR(init_prop_target(&prop_target,
prop_name,
prop_patch->operation,
@@ -687,7 +693,6 @@ init_patch_target(patch_target_t **patch
wc_ctx, target->local_abspath,
result_pool, scratch_pool));
- /* Store the info */
apr_hash_set(target->prop_targets, prop_name,
APR_HASH_KEY_STRING, prop_target);
}
@@ -800,7 +805,7 @@ seek_to_line(target_content_info_t *cont
* Do temporary allocations in POOL. */
static svn_error_t *
match_hunk(svn_boolean_t *matched, target_content_info_t *content_info,
- const svn_hunk_t *hunk, int fuzz,
+ const svn_diff_hunk_t *hunk, int fuzz,
svn_boolean_t ignore_whitespace,
svn_boolean_t match_modified, apr_pool_t *pool)
{
@@ -811,7 +816,7 @@ match_hunk(svn_boolean_t *matched, targe
svn_boolean_t hunk_eof;
svn_boolean_t lines_matched;
apr_pool_t *iterpool;
- svn_linenum_t original_length;
+ svn_linenum_t hunk_length;
svn_linenum_t leading_context;
svn_linenum_t trailing_context;
@@ -823,13 +828,18 @@ match_hunk(svn_boolean_t *matched, targe
saved_line = content_info->current_line;
lines_read = 0;
lines_matched = FALSE;
- original_length = svn_diff_hunk_get_original_length(hunk);
leading_context = svn_diff_hunk_get_leading_context(hunk);
trailing_context = svn_diff_hunk_get_trailing_context(hunk);
if (match_modified)
- SVN_ERR(svn_diff_hunk_reset_modified_text(hunk));
+ {
+ SVN_ERR(svn_diff_hunk_reset_modified_text(hunk));
+ hunk_length = svn_diff_hunk_get_modified_length(hunk);
+ }
else
- SVN_ERR(svn_diff_hunk_reset_original_text(hunk));
+ {
+ SVN_ERR(svn_diff_hunk_reset_original_text(hunk));
+ hunk_length = svn_diff_hunk_get_original_length(hunk);
+ }
iterpool = svn_pool_create(pool);
do
{
@@ -852,59 +862,41 @@ match_hunk(svn_boolean_t *matched, targe
NULL, FALSE,
content_info->keywords, FALSE,
iterpool));
- lines_read++;
SVN_ERR(read_line(content_info, &target_line, iterpool, iterpool));
- if (! hunk_eof)
+
+ lines_read++;
+
+ /* If the last line doesn't have a newline, we get EOF but still
+ * have a non-empty line to compare. */
+ if ((hunk_eof && hunk_line->len == 0) ||
+ (content_info->eof && strlen(target_line) == 0))
+ break;
+
+ /* Leading/trailing fuzzy lines always match. */
+ if ((lines_read <= fuzz && leading_context > fuzz) ||
+ (lines_read > hunk_length - fuzz && trailing_context > fuzz))
+ lines_matched = TRUE;
+ else
{
- if (lines_read <= fuzz && leading_context > fuzz)
- lines_matched = TRUE;
- else if (lines_read > original_length - fuzz &&
- trailing_context > fuzz)
- lines_matched = TRUE;
- else
+ if (ignore_whitespace)
{
- if (ignore_whitespace)
- {
- char *stripped_hunk_line = apr_pstrdup(pool,
- hunk_line_translated);
- char *stripped_target_line = apr_pstrdup(pool, target_line);
-
- apr_collapse_spaces(stripped_hunk_line,
- hunk_line_translated);
- apr_collapse_spaces(stripped_target_line, target_line);
- lines_matched = ! strcmp(stripped_hunk_line,
- stripped_target_line);
- }
- else
- lines_matched = ! strcmp(hunk_line_translated, target_line);
+ char *hunk_line_trimmed;
+ char *target_line_trimmed;
+
+ hunk_line_trimmed = apr_pstrdup(iterpool, hunk_line_translated);
+ target_line_trimmed = apr_pstrdup(iterpool, target_line);
+ apr_collapse_spaces(hunk_line_trimmed, hunk_line_trimmed);
+ apr_collapse_spaces(target_line_trimmed, target_line_trimmed);
+ lines_matched = ! strcmp(hunk_line_trimmed, target_line_trimmed);
}
+ else
+ lines_matched = ! strcmp(hunk_line_translated, target_line);
}
}
- while (lines_matched && ! (hunk_eof || content_info->eof));
+ while (lines_matched);
- if (hunk_eof)
- *matched = lines_matched;
- else if (content_info->eof)
- {
- /* If the target has no newline at end-of-file, we get an EOF
- * indication for the target earlier than we do get it for the hunk. */
- if (match_modified)
- SVN_ERR(svn_diff_hunk_readline_modified_text(hunk, &hunk_line,
- NULL, &hunk_eof,
- iterpool, iterpool));
- else
- SVN_ERR(svn_diff_hunk_readline_original_text(hunk, &hunk_line,
- NULL, &hunk_eof,
- iterpool, iterpool));
+ *matched = lines_matched && hunk_eof && hunk_line->len == 0;
- /* When comparing modified text we require that all lines match, else
- * a hunk that adds a newline at the end will be treated as already
- * applied even if it isn't. */
- if (! match_modified && hunk_line->len == 0 && hunk_eof)
- *matched = lines_matched;
- else
- *matched = FALSE;
- }
SVN_ERR(seek_to_line(content_info, saved_line, iterpool));
svn_pool_destroy(iterpool);
@@ -929,7 +921,7 @@ match_hunk(svn_boolean_t *matched, targe
static svn_error_t *
scan_for_match(svn_linenum_t *matched_line,
target_content_info_t *content_info,
- const svn_hunk_t *hunk, svn_boolean_t match_first,
+ const svn_diff_hunk_t *hunk, svn_boolean_t match_first,
svn_linenum_t upper_line, int fuzz,
svn_boolean_t ignore_whitespace,
svn_boolean_t match_modified,
@@ -1001,7 +993,7 @@ scan_for_match(svn_linenum_t *matched_li
static svn_error_t *
match_existing_target(svn_boolean_t *match,
target_content_info_t *content_info,
- const svn_hunk_t *hunk,
+ const svn_diff_hunk_t *hunk,
svn_stream_t *stream,
apr_pool_t *scratch_pool)
{
@@ -1057,14 +1049,16 @@ match_existing_target(svn_boolean_t *mat
* RESULT_POOL. Use fuzz factor FUZZ. Set HI->FUZZ to FUZZ. If no correct
* line can be determined, set HI->REJECTED to TRUE.
* IGNORE_WHITESPACE tells whether whitespace should be considered when
- * matching. When this function returns, neither CONTENT_INFO->CURRENT_LINE nor
+ * matching. IS_PROP_HUNK indicates whether the hunk patches file content
+ * or a property.
+ * When this function returns, neither CONTENT_INFO->CURRENT_LINE nor
* the file offset in the target file will have changed.
* Call cancel CANCEL_FUNC with baton CANCEL_BATON to trigger cancellation.
* Do temporary allocations in POOL. */
static svn_error_t *
get_hunk_info(hunk_info_t **hi, patch_target_t *target,
target_content_info_t *content_info,
- const svn_hunk_t *hunk, int fuzz,
+ const svn_diff_hunk_t *hunk, int fuzz,
svn_boolean_t ignore_whitespace,
svn_boolean_t is_prop_hunk,
svn_cancel_func_t cancel_func, void *cancel_baton,
@@ -1100,7 +1094,7 @@ get_hunk_info(hunk_info_t **hi, patch_ta
SVN_ERR(match_existing_target(&file_matches, content_info, hunk,
stream, scratch_pool));
- svn_stream_close(stream);
+ SVN_ERR(svn_stream_close(stream));
if (file_matches)
{
@@ -1148,54 +1142,55 @@ get_hunk_info(hunk_info_t **hi, patch_ta
else if (original_start > 0 && content_info->stream)
{
svn_linenum_t saved_line = content_info->current_line;
- svn_linenum_t modified_start;
- /* Check if the hunk is already applied.
- * We only check for an exact match here, and don't bother checking
- * for already applied patches with offset/fuzz, because such a
- * check would be ambiguous. */
- if (fuzz == 0)
+ /* Scan for a match at the line where the hunk thinks it
+ * should be going. */
+ SVN_ERR(seek_to_line(content_info, original_start, scratch_pool));
+ if (content_info->current_line != original_start)
{
- modified_start = svn_diff_hunk_get_modified_start(hunk);
- if (modified_start == 0)
- {
- /* Patch wants to delete the file. */
- already_applied = target->locally_deleted;
- }
- else
- {
- SVN_ERR(seek_to_line(content_info, modified_start,
- scratch_pool));
- SVN_ERR(scan_for_match(&matched_line, content_info,
- hunk, TRUE,
- modified_start + 1,
- fuzz, ignore_whitespace, TRUE,
- cancel_func, cancel_baton,
- scratch_pool));
- already_applied = (matched_line == modified_start);
- }
+ /* Seek failed. */
+ matched_line = 0;
}
else
- already_applied = FALSE;
+ SVN_ERR(scan_for_match(&matched_line, content_info, hunk, TRUE,
+ original_start + 1, fuzz,
+ ignore_whitespace, FALSE,
+ cancel_func, cancel_baton,
+ scratch_pool));
- if (! already_applied)
+ if (matched_line != original_start)
{
- /* Scan for a match at the line where the hunk thinks it
- * should be going. */
- SVN_ERR(seek_to_line(content_info, original_start, scratch_pool));
- if (content_info->current_line != original_start)
+ /* Check if the hunk is already applied.
+ * We only check for an exact match here, and don't bother checking
+ * for already applied patches with offset/fuzz, because such a
+ * check would be ambiguous. */
+ if (fuzz == 0)
{
- /* Seek failed. */
- matched_line = 0;
+ svn_linenum_t modified_start;
+
+ modified_start = svn_diff_hunk_get_modified_start(hunk);
+ if (modified_start == 0)
+ {
+ /* Patch wants to delete the file. */
+ already_applied = target->locally_deleted;
+ }
+ else
+ {
+ SVN_ERR(seek_to_line(content_info, modified_start,
+ scratch_pool));
+ SVN_ERR(scan_for_match(&matched_line, content_info,
+ hunk, TRUE,
+ modified_start + 1,
+ fuzz, ignore_whitespace, TRUE,
+ cancel_func, cancel_baton,
+ scratch_pool));
+ already_applied = (matched_line == modified_start);
+ }
}
else
- SVN_ERR(scan_for_match(&matched_line, content_info, hunk, TRUE,
- original_start + 1, fuzz,
- ignore_whitespace, FALSE,
- cancel_func, cancel_baton,
- scratch_pool));
+ already_applied = FALSE;
- if (matched_line != original_start)
+ if (! already_applied)
{
/* Scan the whole file again from the start. */
SVN_ERR(seek_to_line(content_info, 1, scratch_pool));
@@ -1313,6 +1308,8 @@ reject_hunk(patch_target_t *target, targ
SVN_ERR(svn_stream_write(content_info->reject, prop_header, &len));
+ /* ### What about just setting a variable to either "@@" or "##",
+ * ### and merging with the else clause below? */
hunk_header = apr_psprintf(pool, "## -%lu,%lu +%lu,%lu ##%s",
svn_diff_hunk_get_original_start(hi->hunk),
svn_diff_hunk_get_original_length(hi->hunk),
@@ -1362,8 +1359,11 @@ reject_hunk(patch_target_t *target, targ
return SVN_NO_ERROR;
}
-/* Write the modified text of hunk described by HI to the patched
- * stream of CONTENT_INFO. Do temporary allocations in POOL. */
+/* Write the modified text of the hunk described by HI to the patched
+ * stream of CONTENT_INFO. TARGET is the patch target.
+ * If PROP_NAME is not NULL, the hunk is assumed to be targeted for
+ * a property with the given name.
+ * Do temporary allocations in POOL. */
static svn_error_t *
apply_hunk(patch_target_t *target, target_content_info_t *content_info,
hunk_info_t *hi, const char *prop_name, apr_pool_t *pool)
@@ -1449,7 +1449,8 @@ apply_hunk(patch_target_t *target, targe
/* Use client context CTX to send a suitable notification for hunk HI,
* using TARGET to determine the path. If the hunk is a property hunk,
- * PROP_NAME is set, else NULL. Use POOL for temporary allocations. */
+ * PROP_NAME must be the name of the property, else NULL.
+ * Use POOL for temporary allocations. */
static svn_error_t *
send_hunk_notification(const hunk_info_t *hi,
const patch_target_t *target,
@@ -1591,12 +1592,53 @@ send_patch_notification(const patch_targ
return SVN_NO_ERROR;
}
+/* Close the streams of the TARGET so that their content is flushed
+ * to disk. This will also close underlying streams and files. Use POOL for
+ * temporary allocations. */
+static svn_error_t *
+close_target_streams(const patch_target_t *target,
+ apr_pool_t *pool)
+{
+ apr_hash_index_t *hi;
+ target_content_info_t *prop_content_info;
+
+ /* First the streams belonging to properties .. */
+ for (hi = apr_hash_first(pool, target->prop_targets);
+ hi;
+ hi = apr_hash_next(hi))
+ {
+ prop_patch_target_t *prop_target;
+ prop_target = svn__apr_hash_index_val(hi);
+ prop_content_info = prop_target->content_info;
+
+ /* ### If the prop did not exist pre-patching we'll not have a
+ * ### stream to read from. Find a better way to store info on
+ * ### the existence of the target prop. */
+ if (prop_content_info->stream)
+ SVN_ERR(svn_stream_close(prop_content_info->stream));
+
+ SVN_ERR(svn_stream_close(prop_content_info->patched));
+ }
+
+
+ /* .. And then streams associted with the file. The reject stream is
+ * shared between all target_content_info structures. */
+ if (target->kind_on_disk == svn_node_file)
+ SVN_ERR(svn_stream_close(target->content_info->stream));
+ SVN_ERR(svn_stream_close(target->content_info->patched));
+ SVN_ERR(svn_stream_close(target->content_info->reject));
+
+ return SVN_NO_ERROR;
+}
+
/* Apply a PATCH to a working copy at ABS_WC_PATH and put the result
* into temporary files, to be installed in the working copy later.
* Return information about the patch target in *PATCH_TARGET, allocated
* in RESULT_POOL. Use WC_CTX as the working copy context.
* STRIP_COUNT specifies the number of leading path components
* which should be stripped from target paths in the patch.
+ * OLD_PATCH_TARGET_NAMES indicates whether the old filename parsed
+ * from the patch file should be preferred over the new filename.
* REMOVE_TEMPFILES, PATCH_FUNC, and PATCH_BATON as in svn_client_patch().
* IGNORE_WHITESPACE tells whether whitespace should be considered when
* doing the matching.
@@ -1606,6 +1648,7 @@ static svn_error_t *
apply_one_patch(patch_target_t **patch_target, svn_patch_t *patch,
const char *abs_wc_path, svn_wc_context_t *wc_ctx,
int strip_count,
+ svn_boolean_t old_patch_target_names,
svn_boolean_t ignore_whitespace,
svn_boolean_t remove_tempfiles,
svn_client_patch_func_t patch_func,
@@ -1620,7 +1663,8 @@ apply_one_patch(patch_target_t **patch_t
static const int MAX_FUZZ = 2;
apr_hash_index_t *hash_index;
- SVN_ERR(init_patch_target(&target, patch, abs_wc_path, wc_ctx, strip_count,
+ SVN_ERR(init_patch_target(&target, patch, abs_wc_path, wc_ctx,
+ strip_count, old_patch_target_names,
remove_tempfiles, result_pool, scratch_pool));
if (target->skipped)
{
@@ -1645,7 +1689,7 @@ apply_one_patch(patch_target_t **patch_t
/* Match hunks. */
for (i = 0; i < patch->hunks->nelts; i++)
{
- svn_hunk_t *hunk;
+ svn_diff_hunk_t *hunk;
hunk_info_t *hi;
int fuzz = 0;
@@ -1654,7 +1698,7 @@ apply_one_patch(patch_target_t **patch_t
if (cancel_func)
SVN_ERR((cancel_func)(cancel_baton));
- hunk = APR_ARRAY_IDX(patch->hunks, i, svn_hunk_t *);
+ hunk = APR_ARRAY_IDX(patch->hunks, i, svn_diff_hunk_t *);
/* Determine the line the hunk should be applied at.
* If no match is found initially, try with fuzz. */
@@ -1705,7 +1749,7 @@ apply_one_patch(patch_target_t **patch_t
}
}
- /* Match property hunks. */
+ /* Match property hunks. ### Can we use scratch_pool here? */
for (hash_index = apr_hash_first(result_pool, patch->prop_patches);
hash_index;
hash_index = apr_hash_next(hash_index))
@@ -1713,21 +1757,17 @@ apply_one_patch(patch_target_t **patch_t
svn_prop_patch_t *prop_patch;
const char *prop_name;
prop_patch_target_t *prop_target;
- target_content_info_t *prop_content_info;
- /* Fetching the parsed info for one property */
prop_name = svn__apr_hash_index_key(hash_index);
prop_patch = svn__apr_hash_index_val(hash_index);
- /* Fetch the prop_content_info we'll use to store the matched hunks
- * in. */
+ /* We'll store matched hunks in prop_content_info. */
prop_target = apr_hash_get(target->prop_targets, prop_name,
APR_HASH_KEY_STRING);
- prop_content_info = prop_target->content_info;
for (i = 0; i < prop_patch->hunks->nelts; i++)
{
- svn_hunk_t *hunk;
+ svn_diff_hunk_t *hunk;
hunk_info_t *hi;
int fuzz = 0;
@@ -1736,13 +1776,14 @@ apply_one_patch(patch_target_t **patch_t
if (cancel_func)
SVN_ERR((cancel_func)(cancel_baton));
- hunk = APR_ARRAY_IDX(prop_patch->hunks, i, svn_hunk_t *);
+ hunk = APR_ARRAY_IDX(prop_patch->hunks, i, svn_diff_hunk_t *);
/* Determine the line the hunk should be applied at.
* If no match is found initially, try with fuzz. */
do
{
- SVN_ERR(get_hunk_info(&hi, target, prop_content_info, hunk, fuzz,
+ SVN_ERR(get_hunk_info(&hi, target, prop_target->content_info,
+ hunk, fuzz,
ignore_whitespace,
TRUE /* is_prop_hunk */,
cancel_func, cancel_baton,
@@ -1751,7 +1792,7 @@ apply_one_patch(patch_target_t **patch_t
}
while (hi->rejected && fuzz <= MAX_FUZZ && ! hi->already_applied);
- APR_ARRAY_PUSH(prop_content_info->hunks, hunk_info_t *) = hi;
+ APR_ARRAY_PUSH(prop_target->content_info->hunks, hunk_info_t *) = hi;
}
}
@@ -1761,47 +1802,40 @@ apply_one_patch(patch_target_t **patch_t
hash_index = apr_hash_next(hash_index))
{
prop_patch_target_t *prop_target;
- target_content_info_t *prop_content_info;
- const char *prop_patched_path;
prop_target = svn__apr_hash_index_val(hash_index);
- prop_content_info = prop_target->content_info;
- prop_patched_path = prop_target->patched_path;
- for (i = 0; i < prop_content_info->hunks->nelts; i++)
+ for (i = 0; i < prop_target->content_info->hunks->nelts; i++)
{
hunk_info_t *hi;
svn_pool_clear(iterpool);
- hi = APR_ARRAY_IDX(prop_content_info->hunks, i, hunk_info_t *);
+ hi = APR_ARRAY_IDX(prop_target->content_info->hunks, i,
+ hunk_info_t *);
if (hi->already_applied)
continue;
else if (hi->rejected)
- SVN_ERR(reject_hunk(target, prop_content_info, hi,
+ SVN_ERR(reject_hunk(target, prop_target->content_info, hi,
prop_target->name,
iterpool));
else
- SVN_ERR(apply_hunk(target, prop_content_info, hi,
+ SVN_ERR(apply_hunk(target, prop_target->content_info, hi,
prop_target->name,
iterpool));
}
- if (prop_content_info->stream)
+ if (prop_target->content_info->stream)
{
/* Copy any remaining lines to target. */
- SVN_ERR(copy_lines_to_target(prop_content_info, 0,
- prop_patched_path, scratch_pool));
- if (! prop_content_info->eof)
+ SVN_ERR(copy_lines_to_target(prop_target->content_info, 0,
+ prop_target->patched_path,
+ scratch_pool));
+ if (! prop_target->content_info->eof)
{
/* We could not copy the entire target property to the
* temporary file, and would truncate the target if we
- * copied the temporary file on top of it. Skip this target.
- *
- * ### dannas: Do we really want to skip an entire target
- * ### if one of the properties does not apply cleanly,
- * ### e.g. both text changes and all prop changes will not be
- * ### installed. */
+ * copied the temporary file on top of it. Skip this target. */
target->skipped = TRUE;
}
}
@@ -1809,38 +1843,7 @@ apply_one_patch(patch_target_t **patch_t
svn_pool_destroy(iterpool);
- {
- apr_hash_index_t *hi;
- target_content_info_t *prop_content_info;
-
- /* Close the streams of the target so that their content is flushed
- * to disk. This will also close underlying streams and files.
- * First the streams belonging to properties .. */
- for (hi = apr_hash_first(result_pool, target->prop_targets);
- hi;
- hi = apr_hash_next(hi))
- {
- prop_patch_target_t *prop_target;
- prop_target = svn__apr_hash_index_val(hi);
- prop_content_info = prop_target->content_info;
-
- /* ### If the prop did not exist pre-patching we'll not have a
- * ### stream to read from. Find a better way to store info on
- * ### the existence of the target prop. */
- if (prop_content_info->stream)
- svn_stream_close(prop_content_info->stream);
-
- svn_stream_close(prop_content_info->patched);
- }
-
-
- /* .. And then streams associted with the file. The reject stream is
- * shared between all target_content_info structures. */
- if (target->kind_on_disk == svn_node_file)
- SVN_ERR(svn_stream_close(target->content_info->stream));
- SVN_ERR(svn_stream_close(target->content_info->patched));
- SVN_ERR(svn_stream_close(target->content_info->reject));
- }
+ SVN_ERR(close_target_streams(target, scratch_pool));
if (! target->skipped)
{
@@ -1871,9 +1874,13 @@ apply_one_patch(patch_target_t **patch_t
else if (patched_file.size == 0 && working_file.size == 0)
{
/* The target was empty or non-existent to begin with
- * and nothing has changed by patching.
- * Report this as skipped if it didn't exist. */
- if (target->kind_on_disk == svn_node_none)
+ * and no content was changed by patching.
+ * Report this as skipped if it didn't exist, unless in the special
+ * case of adding an empty file which has properties set on it or
+ * adding an empty file with a 'git diff' */
+ if (target->kind_on_disk == svn_node_none
+ && ! target->has_prop_changes
+ && ! target->added)
target->skipped = TRUE;
}
else if (patched_file.size > 0 && working_file.size == 0)
@@ -1966,7 +1973,7 @@ create_missing_parents(patch_target_t *t
}
else
{
- /* It's not a file, it's not a dir..
+ /* It's not a file, it's not a dir...
Let's add a dir */
break;
}
@@ -2149,7 +2156,7 @@ write_out_rejected_hunks(patch_target_t
/* Install the patched properties for TARGET. Use client context CTX to
* retrieve WC_CTX. If DRY_RUN is TRUE, don't modify the working copy.
- * Do tempoary allocations in SCRATCH_POOL. */
+ * Do temporary allocations in SCRATCH_POOL. */
static svn_error_t *
install_patched_prop_targets(patch_target_t *target,
svn_client_ctx_t *ctx, svn_boolean_t dry_run,
@@ -2159,7 +2166,12 @@ install_patched_prop_targets(patch_targe
apr_pool_t *iterpool;
if (dry_run)
- return SVN_NO_ERROR;
+ {
+ if (! target->has_text_changes && target->kind_on_disk == svn_node_none)
+ target->added = TRUE;
+
+ return SVN_NO_ERROR;
+ }
iterpool = svn_pool_create(scratch_pool);
@@ -2183,17 +2195,18 @@ install_patched_prop_targets(patch_targe
SVN_ERR(svn_wc_prop_set4(ctx->wc_ctx, target->local_abspath,
prop_target->name, NULL,
TRUE /* skip_checks */,
- NULL, NULL,
+ NULL, NULL, /* suppress notification */
iterpool));
continue;
}
- /* A property is usually one line long.
- * ### Is this the optimal size to allocate? */
+ /* A property is usually small, at most a couple of bytes.
+ * Start out assuming it won't be larger than a typical line of text. */
prop_content = svn_stringbuf_create_ensure(80, scratch_pool);
/* svn_wc_prop_set4() wants a svn_string_t for input so we need to
- * open the tmp file for reading again. */
+ * open the tmp file for reading again.
+ * ### Just keep it open? */
SVN_ERR(svn_io_file_open(&file, prop_target->patched_path,
APR_READ | APR_BINARY, APR_OS_DEFAULT,
scratch_pool));
@@ -2214,10 +2227,37 @@ install_patched_prop_targets(patch_targe
}
while (! eof);
- svn_stream_close(patched_stream);
+ SVN_ERR(svn_stream_close(patched_stream));
+
+ /* If the patch target doesn't exist yet, the patch wants to add an
+ * empty file with properties set on it. So create an empty file and
+ * add it to version control. But if the patch was in the 'git format'
+ * then the file has already been added.
+ *
+ * ### How can we tell whether the patch really wanted to create
+ * ### an empty directory? */
+ if (! target->has_text_changes
+ && target->kind_on_disk == svn_node_none
+ && ! target->added)
+ {
+ SVN_ERR(svn_io_file_create(target->local_abspath, "", scratch_pool));
+ SVN_ERR(svn_wc_add4(ctx->wc_ctx, target->local_abspath,
+ svn_depth_infinity,
+ NULL, SVN_INVALID_REVNUM,
+ ctx->cancel_func,
+ ctx->cancel_baton,
+ NULL, NULL, /* suppress notification */
+ iterpool));
+ target->added = TRUE;
+ }
/* ### How should we handle SVN_ERR_ILLEGAL_TARGET and
- * ### SVN_ERR_BAD_MIME_TYPE? */
+ * ### SVN_ERR_BAD_MIME_TYPE?
+ *
+ * ### stsp: I'd say reject the property hunk.
+ * ### We should verify all modified prop hunk texts using
+ * ### svn_wc_canonicalize_svn_prop() before starting the
+ * ### patching process, to reject them as early as possible. */
SVN_ERR(svn_wc_prop_set4(ctx->wc_ctx, target->local_abspath,
prop_target->name,
svn_string_create_from_buf(prop_content,
@@ -2511,6 +2551,9 @@ typedef struct {
/* Number of leading components to strip from patch target paths. */
int strip_count;
+ /* Whether to use the old path from the patch file instead of the new one. */
+ svn_boolean_t old_patch_target_names;
+
/* Whether to apply the patch in reverse. */
svn_boolean_t reverse;
@@ -2576,6 +2619,7 @@ apply_patches(void *baton,
SVN_ERR(apply_one_patch(&target, patch, btn->abs_wc_path,
btn->ctx->wc_ctx, btn->strip_count,
+ btn->old_patch_target_names,
btn->ignore_whitespace,
btn->remove_tempfiles,
btn->patch_func, btn->patch_baton,
@@ -2595,7 +2639,7 @@ apply_patches(void *baton,
if (! target->skipped)
{
- if (target->has_text_changes)
+ if (target->has_text_changes || target->added)
SVN_ERR(install_patched_target(target, btn->abs_wc_path,
btn->ctx, btn->dry_run,
iterpool));
@@ -2611,7 +2655,7 @@ apply_patches(void *baton,
SVN_ERR(send_patch_notification(target, btn->ctx, iterpool));
}
- SVN_ERR(svn_diff_close_patch(patch));
+ SVN_ERR(svn_diff_close_patch(patch, iterpool));
}
}
while (patch);
@@ -2631,6 +2675,7 @@ svn_client_patch(const char *patch_abspa
const char *local_abspath,
svn_boolean_t dry_run,
int strip_count,
+ svn_boolean_t old_patch_target_names,
svn_boolean_t reverse,
svn_boolean_t ignore_whitespace,
svn_boolean_t remove_tempfiles,
@@ -2651,6 +2696,7 @@ svn_client_patch(const char *patch_abspa
baton.dry_run = dry_run;
baton.ctx = ctx;
baton.strip_count = strip_count;
+ baton.old_patch_target_names = old_patch_target_names;
baton.reverse = reverse;
baton.ignore_whitespace = ignore_whitespace;
baton.remove_tempfiles = remove_tempfiles;
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/prop_commands.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/prop_commands.c?rev=1044516&r1=1044515&r2=1044516&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/prop_commands.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/prop_commands.c Fri Dec 10 21:23:03 2010
@@ -196,6 +196,8 @@ propset_on_url(const char *propname,
svn_boolean_t skip_checks,
svn_revnum_t base_revision_for_url,
const apr_hash_t *revprop_table,
+ svn_commit_callback2_t commit_callback,
+ void *commit_baton,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
@@ -270,8 +272,8 @@ propset_on_url(const char *propname,
/* Fetch RA commit editor. */
SVN_ERR(svn_ra_get_commit_editor3(ra_session, &editor, &edit_baton,
commit_revprops,
- ctx->commit_callback2,
- ctx->commit_baton,
+ commit_callback,
+ commit_baton,
NULL, TRUE, /* No lock tokens */
pool));
@@ -346,6 +348,8 @@ svn_client_propset4(const char *propname
svn_revnum_t base_revision_for_url,
const apr_array_header_t *changelists,
const apr_hash_t *revprop_table,
+ svn_commit_callback2_t commit_callback,
+ void *commit_baton,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
@@ -397,7 +401,8 @@ svn_client_propset4(const char *propname
"'%s' is not supported"), propname, target);
return propset_on_url(propname, propval, target, skip_checks,
- base_revision_for_url, revprop_table, ctx, pool);
+ base_revision_for_url, revprop_table,
+ commit_callback, commit_baton, ctx, pool);
}
else
{
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/relocate.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/relocate.c?rev=1044516&r1=1044515&r2=1044516&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/relocate.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/relocate.c Fri Dec 10 21:23:03 2010
@@ -126,24 +126,23 @@ validator_func(void *baton,
}
svn_error_t *
-svn_client_relocate(const char *path,
- const char *from,
- const char *to,
- svn_boolean_t recurse,
- svn_client_ctx_t *ctx,
- apr_pool_t *pool)
+svn_client_relocate2(const char *wcroot_dir,
+ const char *from,
+ const char *to,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *pool)
{
struct validator_baton_t vb;
const char *local_abspath;
- /* Now, populate our validator callback baton, and call the relocate code. */
+ /* Populate our validator callback baton, and call the relocate code. */
vb.ctx = ctx;
- vb.path = path;
+ vb.path = wcroot_dir;
vb.url_uuids = apr_array_make(pool, 1, sizeof(struct url_uuid_t));
vb.pool = pool;
- SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
- SVN_ERR(svn_wc_relocate4(ctx->wc_ctx, local_abspath, from, to, recurse,
+ SVN_ERR(svn_dirent_get_absolute(&local_abspath, wcroot_dir, pool));
+ SVN_ERR(svn_wc_relocate4(ctx->wc_ctx, local_abspath, from, to,
validator_func, &vb, pool));
return SVN_NO_ERROR;
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/repos_diff.c?rev=1044516&r1=1044515&r2=1044516&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/repos_diff.c Fri Dec 10 21:23:03 2010
@@ -241,11 +241,10 @@ make_dir_baton(const char *path,
static struct file_baton *
make_file_baton(const char *path,
svn_boolean_t added,
- void *edit_baton,
+ struct edit_baton *edit_baton,
apr_pool_t *pool)
{
struct file_baton *file_baton = apr_pcalloc(pool, sizeof(*file_baton));
- struct edit_baton *eb = edit_baton;
file_baton->edit_baton = edit_baton;
file_baton->added = added;
@@ -253,7 +252,7 @@ make_file_baton(const char *path,
file_baton->skip = FALSE;
file_baton->pool = pool;
file_baton->path = apr_pstrdup(pool, path);
- file_baton->wcpath = svn_dirent_join(eb->target, path, pool);
+ file_baton->wcpath = svn_dirent_join(edit_baton->target, path, pool);
file_baton->propchanges = apr_array_make(pool, 1, sizeof(svn_prop_t));
return file_baton;
@@ -460,7 +459,7 @@ open_root(void *edit_baton,
* reporting all files as deleted. Part of a workaround for issue 2333.
*
* DIR is a repository path relative to the URL in RA_SESSION. REVISION
- * may be NULL, in which case it defaults to HEAD. EB is the
+ * must be a valid revision number, not SVN_INVALID_REVNUM. EB is the
* overall crawler editor baton. If CANCEL_FUNC is not NULL, then it
* should refer to a cancellation function (along with CANCEL_BATON).
*/
@@ -478,6 +477,8 @@ diff_deleted_dir(const char *dir,
apr_pool_t *iterpool = svn_pool_create(pool);
apr_hash_index_t *hi;
+ SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(revision));
+
if (cancel_func)
SVN_ERR(cancel_func(cancel_baton));
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/repos_diff_summarize.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/repos_diff_summarize.c?rev=1044516&r1=1044515&r2=1044516&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/repos_diff_summarize.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/repos_diff_summarize.c Fri Dec 10 21:23:03 2010
@@ -23,6 +23,7 @@
*/
+#include "svn_dirent_uri.h"
#include "svn_props.h"
#include "svn_pools.h"
@@ -45,6 +46,18 @@ struct edit_baton {
/* The start revision for the comparison */
svn_revnum_t revision;
+
+ /* TRUE if the operation needs to walk deleted dirs on the "old" side.
+ FALSE otherwise. */
+ svn_boolean_t walk_deleted_repos_dirs;
+
+ /* A callback used to see if the client wishes to cancel the running
+ operation. */
+ svn_cancel_func_t cancel_func;
+
+ /* A baton to pass to the cancellation callback. */
+ void *cancel_baton;
+
};
@@ -97,7 +110,7 @@ create_item_baton(struct edit_baton *edi
/* Make sure that this item baton contains a summarize struct.
* If it doesn't before this call, allocate a new struct in the item's pool,
* initializing the diff kind to normal.
- * All other fields are also initialized from IB to to NULL/invalid values. */
+ * All other fields are also initialized from IB or to NULL/invalid values. */
static void
ensure_summarize(struct item_baton *ib)
{
@@ -129,6 +142,83 @@ open_root(void *edit_baton,
return SVN_NO_ERROR;
}
+/* Recursively walk the tree rooted at DIR (at REVISION) in the
+ * repository, reporting all files as deleted. Part of a workaround
+ * for issue 2333.
+ *
+ * DIR is a repository path relative to the URL in RA_SESSION. REVISION
+ * may be NULL, in which case it defaults to HEAD. EDIT_BATON is the
+ * overall crawler editor baton. If CANCEL_FUNC is not NULL, then it
+ * should refer to a cancellation function (along with CANCEL_BATON).
+ */
+/* ### TODO: Handle depth. */
+static svn_error_t *
+diff_deleted_dir(const char *dir,
+ svn_revnum_t revision,
+ svn_ra_session_t *ra_session,
+ void *edit_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ apr_pool_t *pool)
+{
+ struct edit_baton *eb = edit_baton;
+ apr_hash_t *dirents;
+ apr_pool_t *iterpool = svn_pool_create(pool);
+ apr_hash_index_t *hi;
+
+ if (cancel_func)
+ SVN_ERR(cancel_func(cancel_baton));
+
+ SVN_ERR(svn_ra_get_dir2(ra_session,
+ &dirents,
+ NULL, NULL,
+ dir,
+ revision,
+ SVN_DIRENT_KIND,
+ pool));
+
+ for (hi = apr_hash_first(pool, dirents); hi;
+ hi = apr_hash_next(hi))
+ {
+ const char *path;
+ const char *name = svn__apr_hash_index_key(hi);
+ svn_dirent_t *dirent = svn__apr_hash_index_val(hi);
+ svn_node_kind_t kind;
+ svn_client_diff_summarize_t *sum;
+
+ svn_pool_clear(iterpool);
+
+ path = svn_relpath_join(dir, name, iterpool);
+
+ SVN_ERR(svn_ra_check_path(eb->ra_session,
+ path,
+ eb->revision,
+ &kind,
+ iterpool));
+
+ sum = apr_pcalloc(pool, sizeof(*sum));
+ sum->summarize_kind = svn_client_diff_summarize_kind_deleted;
+ sum->path = path;
+ sum->node_kind = kind;
+
+ SVN_ERR(eb->summarize_func(sum,
+ eb->summarize_func_baton,
+ iterpool));
+
+ if (dirent->kind == svn_node_dir)
+ SVN_ERR(diff_deleted_dir(path,
+ revision,
+ ra_session,
+ eb,
+ cancel_func,
+ cancel_baton,
+ iterpool));
+ }
+
+ svn_pool_destroy(iterpool);
+ return SVN_NO_ERROR;
+}
+
/* An editor function. */
static svn_error_t *
delete_entry(const char *path,
@@ -153,7 +243,18 @@ delete_entry(const char *path,
sum->path = path;
sum->node_kind = kind;
- return eb->summarize_func(sum, eb->summarize_func_baton, pool);
+ SVN_ERR(eb->summarize_func(sum, eb->summarize_func_baton, pool));
+
+ if (kind == svn_node_dir)
+ SVN_ERR(diff_deleted_dir(path,
+ eb->revision,
+ eb->ra_session,
+ eb,
+ eb->cancel_func,
+ eb->cancel_baton,
+ pool));
+
+ return SVN_NO_ERROR;
}
/* An editor function. */
@@ -298,7 +399,9 @@ change_prop(void *entry_baton,
if (svn_property_kind(NULL, name) == svn_prop_regular_kind)
{
ensure_summarize(ib);
- ib->summarize->prop_changed = TRUE;
+
+ if (ib->summarize->summarize_kind != svn_client_diff_summarize_kind_added)
+ ib->summarize->prop_changed = TRUE;
}
return SVN_NO_ERROR;
@@ -309,7 +412,7 @@ svn_error_t *
svn_client__get_diff_summarize_editor(const char *target,
svn_client_diff_summarize_func_t
summarize_func,
- void *item_baton,
+ void *summarize_baton,
svn_ra_session_t *ra_session,
svn_revnum_t revision,
svn_cancel_func_t cancel_func,
@@ -323,9 +426,12 @@ svn_client__get_diff_summarize_editor(co
eb->target = target;
eb->summarize_func = summarize_func;
- eb->summarize_func_baton = item_baton;
+ eb->summarize_func_baton = summarize_baton;
eb->ra_session = ra_session;
eb->revision = revision;
+ eb->walk_deleted_repos_dirs = TRUE;
+ eb->cancel_func = cancel_func;
+ eb->cancel_baton = cancel_baton;
tree_editor->open_root = open_root;
tree_editor->delete_entry = delete_entry;
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/status.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/status.c?rev=1044516&r1=1044515&r2=1044516&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/status.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/status.c Fri Dec 10 21:23:03 2010
@@ -291,6 +291,7 @@ svn_client_status5(svn_revnum_t *result_
svn_boolean_t update,
svn_boolean_t no_ignore,
svn_boolean_t ignore_externals,
+ svn_boolean_t depth_as_sticky,
svn_boolean_t ignore_mergeinfo,
const apr_array_header_t *changelists,
svn_client_status_func_t status_func,
@@ -496,6 +497,7 @@ svn_client_status5(svn_revnum_t *result_
{
svn_revnum_t revnum;
report_baton_t rb;
+ svn_depth_t status_depth;
if (revision->kind == svn_opt_revision_head)
{
@@ -513,10 +515,15 @@ svn_client_status5(svn_revnum_t *result_
pool));
}
+ if (depth_as_sticky)
+ status_depth = depth;
+ else
+ status_depth = svn_depth_unknown; /* Use depth from WC */
+
/* Do the deed. Let the RA layer drive the status editor. */
SVN_ERR(svn_ra_do_status2(ra_session, &rb.wrapped_reporter,
&rb.wrapped_report_baton,
- target_basename, revnum, svn_depth_unknown,
+ target_basename, revnum, status_depth,
editor, edit_baton, pool));
/* Init the report baton. */
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/switch.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/switch.c?rev=1044516&r1=1044515&r2=1044516&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/switch.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/switch.c Fri Dec 10 21:23:03 2010
@@ -190,7 +190,6 @@ switch_internal(svn_revnum_t *result_rev
depth,
depth_is_sticky, allow_unver_obstructions,
diff3_cmd, preserved_exts,
- NULL, NULL,
ctx->conflict_func, ctx->conflict_baton,
svn_client__external_info_gatherer, &efb,
ctx->cancel_func, ctx->cancel_baton,
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_client/update.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_client/update.c?rev=1044516&r1=1044515&r2=1044516&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_client/update.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_client/update.c Fri Dec 10 21:23:03 2010
@@ -45,49 +45,6 @@
/*** Code. ***/
-/* Context baton for file_fetcher below. */
-struct ff_baton
-{
- svn_client_ctx_t *ctx; /* client context used to open ra session */
- const char *repos_root; /* repository root URL */
- svn_ra_session_t *session; /* the secondary ra session itself */
- apr_pool_t *pool; /* the pool where the ra session is allocated */
-};
-
-
-/* Implementation of svn_wc_get_file_t. A feeble callback wrapper
- around svn_ra_get_file(), so that the update_editor can use it to
- fetch any file, any time. */
-static svn_error_t *
-file_fetcher(void *baton,
- const char *path,
- svn_revnum_t revision,
- svn_stream_t *stream,
- svn_revnum_t *fetched_rev,
- apr_hash_t **props,
- apr_pool_t *pool)
-{
- struct ff_baton *ffb = (struct ff_baton *)baton;
- const char *dirpath, *base_name, *session_url, *old_session_url;
-
- svn_relpath_split(&dirpath, &base_name, path, pool);
- session_url = svn_path_url_add_component2(ffb->repos_root,
- dirpath, pool);
-
- if (ffb->session)
- SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url, ffb->session,
- session_url, ffb->pool));
- else
- SVN_ERR(svn_client__open_ra_session_internal(&(ffb->session), NULL,
- session_url, NULL, NULL,
- FALSE, TRUE,
- ffb->ctx, ffb->pool));
-
- return svn_ra_get_file(ffb->session, base_name, revision, stream,
- fetched_rev, props, pool);
-}
-
-
static svn_error_t *
update_internal(svn_revnum_t *result_rev,
const char *local_abspath,
@@ -98,7 +55,6 @@ update_internal(svn_revnum_t *result_rev
svn_boolean_t ignore_externals,
svn_boolean_t allow_unver_obstructions,
svn_boolean_t *timestamp_sleep,
- svn_boolean_t send_copyfrom_args,
svn_boolean_t innerupdate,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
@@ -120,7 +76,6 @@ update_internal(svn_revnum_t *result_rev
svn_ra_session_t *ra_session;
const char *preserved_exts_str;
apr_array_header_t *preserved_exts;
- struct ff_baton *ffb;
svn_client__external_func_baton_t efb;
svn_boolean_t server_supports_depth;
svn_config_t *cfg = ctx->config ? apr_hash_get(ctx->config,
@@ -216,12 +171,6 @@ update_internal(svn_revnum_t *result_rev
a strict sense, however.) */
SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root, pool));
- /* Build a baton for the file-fetching callback. */
- ffb = apr_pcalloc(pool, sizeof(*ffb));
- ffb->ctx = ctx;
- ffb->repos_root = repos_root;
- ffb->pool = pool;
-
/* Build a baton for the externals-info-gatherer callback. */
efb.externals_new = apr_hash_make(pool);
efb.externals_old = apr_hash_make(pool);
@@ -235,7 +184,6 @@ update_internal(svn_revnum_t *result_rev
target, use_commit_times, depth,
depth_is_sticky, allow_unver_obstructions,
diff3_cmd, preserved_exts,
- file_fetcher, ffb,
ctx->conflict_func, ctx->conflict_baton,
svn_client__external_info_gatherer, &efb,
ctx->cancel_func, ctx->cancel_baton,
@@ -244,12 +192,8 @@ update_internal(svn_revnum_t *result_rev
/* Tell RA to do an update of URL+TARGET to REVISION; if we pass an
invalid revnum, that means RA will use the latest revision. */
- SVN_ERR(svn_ra_do_update2(ra_session,
- &reporter, &report_baton,
- revnum,
- target,
- depth,
- send_copyfrom_args,
+ SVN_ERR(svn_ra_do_update2(ra_session, &reporter, &report_baton,
+ revnum, target, depth, FALSE,
update_editor, update_edit_baton, pool));
SVN_ERR(svn_ra_has_capability(ra_session, &server_supports_depth,
@@ -321,7 +265,6 @@ svn_client__update_internal(svn_revnum_t
svn_boolean_t ignore_externals,
svn_boolean_t allow_unver_obstructions,
svn_boolean_t *timestamp_sleep,
- svn_boolean_t send_copyfrom_args,
svn_boolean_t innerupdate,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
@@ -343,8 +286,7 @@ svn_client__update_internal(svn_revnum_t
err = update_internal(result_rev, local_abspath, anchor_abspath,
revision, depth, depth_is_sticky,
ignore_externals, allow_unver_obstructions,
- timestamp_sleep, send_copyfrom_args,
- innerupdate, ctx, pool);
+ timestamp_sleep, innerupdate, ctx, pool);
err = svn_error_compose_create(
err,
@@ -398,7 +340,7 @@ svn_client_update3(apr_array_header_t **
revision, depth, depth_is_sticky,
ignore_externals,
allow_unver_obstructions,
- &sleep, TRUE, FALSE, ctx, subpool);
+ &sleep, FALSE, ctx, subpool);
if (err && err->apr_err != SVN_ERR_WC_NOT_WORKING_COPY)
{
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/svndiff.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/svndiff.c?rev=1044516&r1=1044515&r2=1044516&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/svndiff.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_delta/svndiff.c Fri Dec 10 21:23:03 2010
@@ -31,10 +31,12 @@
#include "svn_private_config.h"
#include <zlib.h>
-/* This macro is taken from zlib, and was originally the function
- compressBound. It shouldn't ever change, but once every millenium,
- it may be useful for someone to make sure. */
+/* The zlib compressBound function was not exported until 1.2.0. */
+#if ZLIB_VERNUM >= 0x1200
+#define svnCompressBound(LEN) compressBound(LEN)
+#else
#define svnCompressBound(LEN) ((LEN) + ((LEN) >> 12) + ((LEN) >> 14) + 11)
+#endif
/* For svndiff1, address/instruction/new data under this size will not
be compressed using zlib as a secondary compressor. */
Modified: subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/diff_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/diff_file.c?rev=1044516&r1=1044515&r2=1044516&view=diff
==============================================================================
--- subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/diff_file.c (original)
+++ subversion/branches/ignore-mergeinfo/subversion/libsvn_diff/diff_file.c Fri Dec 10 21:23:03 2010
@@ -860,7 +860,7 @@ output_unified_line(svn_diff__file_outpu
{
if (type != svn_diff__file_output_unified_skip)
{
- svn_stringbuf_appendbytes(baton->hunk, curp, 1);
+ svn_stringbuf_appendbyte(baton->hunk, *curp);
}
/* We don't append the LF to extra_context, since it would
* just be stripped anyway. */