Modified: subversion/branches/svn-bisect/subversion/libsvn_client/ra.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/ra.c?rev=1204374&r1=1204373&r2=1204374&view=diff ============================================================================== --- subversion/branches/svn-bisect/subversion/libsvn_client/ra.c (original) +++ subversion/branches/svn-bisect/subversion/libsvn_client/ra.c Mon Nov 21 07:07:56 2011 @@ -368,7 +368,7 @@ svn_client__open_ra_session_internal(svn } return SVN_NO_ERROR; - } +} #undef SVN_CLIENT__MAX_REDIRECT_ATTEMPTS @@ -385,54 +385,60 @@ svn_client_open_ra_session(svn_ra_sessio } -svn_error_t * -svn_client_uuid_from_url(const char **uuid, - const char *url, - svn_client_ctx_t *ctx, - apr_pool_t *pool) -{ - svn_ra_session_t *ra_session; - apr_pool_t *subpool = svn_pool_create(pool); - - /* use subpool to create a temporary RA session */ - SVN_ERR(svn_client__open_ra_session_internal(&ra_session, NULL, url, - NULL, /* no base dir */ - NULL, FALSE, TRUE, - ctx, subpool)); - - SVN_ERR(svn_ra_get_uuid2(ra_session, uuid, pool)); - - /* destroy the RA session */ - svn_pool_destroy(subpool); + - return SVN_NO_ERROR; -} +/* Given PATH_OR_URL, which contains either a working copy path or an + absolute URL, a peg revision PEG_REVISION, and a desired revision + REVISION, find the path at which that object exists in REVISION, + following copy history if necessary. If REVISION is younger than + PEG_REVISION, then check that PATH_OR_URL is the same node in both + PEG_REVISION and REVISION, and return @c + SVN_ERR_CLIENT_UNRELATED_RESOURCES if it is not the same node. + + If PEG_REVISION->kind is 'unspecified', the peg revision is 'head' + for a URL or 'working' for a WC path. If REVISION->kind is + 'unspecified', the operative revision is the peg revision. + + Store the actual revision number of the object in *REV_P, and the + final resulting URL in *URL_P. REV_P and/or URL_P may be NULL if not + wanted. + Use authentication baton cached in CTX to authenticate against the + repository. -svn_error_t * -svn_client_uuid_from_path2(const char **uuid, - const char *local_abspath, - svn_client_ctx_t *ctx, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) + Use POOL for all allocations. */ +static svn_error_t * +resolve_rev_and_url(svn_revnum_t *rev_p, + const char **url_p, + svn_ra_session_t *ra_session, + const char *path_or_url, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_client_ctx_t *ctx, + apr_pool_t *pool) { - return svn_error_trace( - svn_wc__node_get_repos_info(NULL, uuid, ctx->wc_ctx, local_abspath, - result_pool, scratch_pool)); -} + svn_opt_revision_t peg_rev = *peg_revision; + svn_opt_revision_t start_rev = *revision; + const char *url; + svn_revnum_t rev; + SVN_ERR(svn_opt_resolve_revisions(&peg_rev, &start_rev, + svn_path_is_url(path_or_url), + TRUE, + pool)); - + /* Run the history function to get the object's (possibly + different) url in REVISION. */ + SVN_ERR(svn_client__repos_locations(&url, &rev, NULL, NULL, + ra_session, path_or_url, &peg_rev, + &start_rev, NULL, ctx, pool)); + + if (rev_p) + *rev_p = rev; + if (url_p) + *url_p = url; -/* Convert a path or URL for display: if it is a local path, convert it to - * the local path style; if it is a URL, return it unchanged. */ -static const char * -path_or_url_local_style(const char *path_or_url, - apr_pool_t *pool) -{ - if (svn_path_is_url(path_or_url)) - return path_or_url; - return svn_dirent_local_style(path_or_url, pool); + return SVN_NO_ERROR; } svn_error_t * @@ -441,19 +447,15 @@ svn_client__ra_session_from_path(svn_ra_ const char **url_p, const char *path_or_url, const char *base_dir_abspath, - const svn_opt_revision_t *peg_revision_p, + const svn_opt_revision_t *peg_revision, const svn_opt_revision_t *revision, svn_client_ctx_t *ctx, apr_pool_t *pool) { svn_ra_session_t *ra_session; - const char *initial_url, *url; - svn_opt_revision_t *good_rev; - svn_opt_revision_t peg_revision, start_rev; - svn_opt_revision_t dead_end_rev; - svn_opt_revision_t *ignored_rev; - svn_revnum_t rev; - const char *ignored_url, *corrected_url; + const char *initial_url; + const char *corrected_url; + const char *resolved_url; SVN_ERR(svn_client_url_from_path2(&initial_url, path_or_url, ctx, pool, pool)); @@ -461,13 +463,6 @@ svn_client__ra_session_from_path(svn_ra_ return svn_error_createf(SVN_ERR_ENTRY_MISSING_URL, NULL, _("'%s' has no URL"), path_or_url); - start_rev = *revision; - peg_revision = *peg_revision_p; - SVN_ERR(svn_opt_resolve_revisions(&peg_revision, &start_rev, - svn_path_is_url(path_or_url), - TRUE, - pool)); - SVN_ERR(svn_client__open_ra_session_internal(&ra_session, &corrected_url, initial_url, base_dir_abspath, NULL, @@ -479,30 +474,16 @@ svn_client__ra_session_from_path(svn_ra_ if (corrected_url && svn_path_is_url(path_or_url)) path_or_url = corrected_url; - dead_end_rev.kind = svn_opt_revision_unspecified; - - /* Run the history function to get the object's (possibly - different) url in REVISION. */ - SVN_ERR(svn_client__repos_locations(&url, &good_rev, - &ignored_url, &ignored_rev, - ra_session, - path_or_url, &peg_revision, - /* search range: */ - &start_rev, &dead_end_rev, - ctx, pool)); + SVN_ERR(resolve_rev_and_url(rev_p, &resolved_url, ra_session, + path_or_url, peg_revision, revision, + ctx, pool)); /* Make the session point to the real URL. */ - SVN_ERR(svn_ra_reparent(ra_session, url, pool)); - - /* Resolve good_rev into a real revnum. */ - if (good_rev->kind == svn_opt_revision_unspecified) - good_rev->kind = svn_opt_revision_head; - SVN_ERR(svn_client__get_revision_number(&rev, NULL, ctx->wc_ctx, url, - ra_session, good_rev, pool)); + SVN_ERR(svn_ra_reparent(ra_session, resolved_url, pool)); *ra_session_p = ra_session; - *rev_p = rev; - *url_p = url; + if (url_p) + *url_p = resolved_url; return SVN_NO_ERROR; } @@ -586,12 +567,106 @@ svn_client__repos_location_segments(apr_ return SVN_NO_ERROR; } +/* Set *START_URL and *END_URL to the URLs that the object URL@PEG_REVNUM + * had in revisions START_REVNUM and END_REVNUM. Return an error if the + * node cannot be traced back to one of the requested revisions. + * + * START_URL and/or END_URL may be NULL if not wanted. START_REVNUM and + * END_REVNUM must be valid revision numbers except that END_REVNUM may + * be SVN_INVALID_REVNUM if END_URL is NULL. RA_SESSION is required. + */ +static svn_error_t * +repos_locations(const char **start_url, + const char **end_url, + svn_ra_session_t *ra_session, + const char *url, + svn_revnum_t peg_revnum, + svn_revnum_t start_revnum, + svn_revnum_t end_revnum, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + const char *repos_url, *start_path, *end_path; + apr_array_header_t *revs; + apr_hash_t *rev_locs; + + SVN_ERR_ASSERT(peg_revnum != SVN_INVALID_REVNUM); + SVN_ERR_ASSERT(start_revnum != SVN_INVALID_REVNUM); + SVN_ERR_ASSERT(end_revnum != SVN_INVALID_REVNUM || end_url == NULL); + + /* Avoid a network request in the common easy case. */ + if (start_revnum == peg_revnum + && (end_revnum == peg_revnum || end_revnum == SVN_INVALID_REVNUM)) + { + if (start_url) + *start_url = url; + if (end_url) + *end_url = url; + return SVN_NO_ERROR; + } + + SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_url, scratch_pool)); + + revs = apr_array_make(scratch_pool, 2, sizeof(svn_revnum_t)); + APR_ARRAY_PUSH(revs, svn_revnum_t) = start_revnum; + if (end_revnum != start_revnum && end_revnum != SVN_INVALID_REVNUM) + APR_ARRAY_PUSH(revs, svn_revnum_t) = end_revnum; + + SVN_ERR(svn_ra_get_locations(ra_session, &rev_locs, "", peg_revnum, + revs, scratch_pool)); + + /* We'd better have all the paths we were looking for! */ + if (start_url) + { + start_path = apr_hash_get(rev_locs, &start_revnum, sizeof(svn_revnum_t)); + if (! start_path) + return svn_error_createf + (SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL, + _("Unable to find repository location for '%s' in revision %ld"), + url, start_revnum); + *start_url = svn_path_url_add_component2(repos_url, start_path + 1, + result_pool); + } + + if (end_url) + { + end_path = apr_hash_get(rev_locs, &end_revnum, sizeof(svn_revnum_t)); + if (! end_path) + return svn_error_createf + (SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL, + _("The location for '%s' for revision %ld does not exist in the " + "repository or refers to an unrelated object"), + url, end_revnum); + + *end_url = svn_path_url_add_component2(repos_url, end_path + 1, + result_pool); + } + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client__repos_location(const char **op_url, + svn_ra_session_t *ra_session, + const char *peg_url, + svn_revnum_t peg_revnum, + svn_revnum_t op_revnum, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + SVN_ERR(repos_locations(op_url, NULL, + ra_session, peg_url, peg_revnum, + op_revnum, SVN_INVALID_REVNUM, + result_pool, scratch_pool)); + return SVN_NO_ERROR; +} svn_error_t * svn_client__repos_locations(const char **start_url, - svn_opt_revision_t **start_revision, + svn_revnum_t *start_revision, const char **end_url, - svn_opt_revision_t **end_revision, + svn_revnum_t *end_revision, svn_ra_session_t *ra_session, const char *path, const svn_opt_revision_t *revision, @@ -600,16 +675,11 @@ svn_client__repos_locations(const char * svn_client_ctx_t *ctx, apr_pool_t *pool) { - const char *repos_url; const char *url; - const char *start_path = NULL; - const char *end_path = NULL; const char *local_abspath_or_url; svn_revnum_t peg_revnum = SVN_INVALID_REVNUM; svn_revnum_t start_revnum, end_revnum; svn_revnum_t youngest_rev = SVN_INVALID_REVNUM; - apr_array_header_t *revs; - apr_hash_t *rev_locs; apr_pool_t *subpool = svn_pool_create(pool); /* Ensure that we are given some real revision data to work with. @@ -619,9 +689,17 @@ svn_client__repos_locations(const char * || start->kind == svn_opt_revision_unspecified) return svn_error_create(SVN_ERR_CLIENT_BAD_REVISION, NULL, NULL); - /* Check to see if this is schedule add with history working copy - path. If it is, then we need to use the URL and peg revision of - the copyfrom information. */ + if (end == NULL) + { + static const svn_opt_revision_t unspecified_rev + = { svn_opt_revision_unspecified, { 0 } }; + + end = &unspecified_rev; + } + + /* Determine LOCAL_ABSPATH_OR_URL, URL, and possibly PEG_REVNUM. + If we are looking at the working version of a WC path that is scheduled + as a copy, then we need to use the copy-from URL and peg revision. */ if (! svn_path_is_url(path)) { SVN_ERR(svn_dirent_get_absolute(&local_abspath_or_url, path, subpool)); @@ -703,57 +781,19 @@ svn_client__repos_locations(const char * ra_session, end, pool)); /* Set the output revision variables. */ - *start_revision = apr_pcalloc(pool, sizeof(**start_revision)); - (*start_revision)->kind = svn_opt_revision_number; - (*start_revision)->value.number = start_revnum; - if (end->kind != svn_opt_revision_unspecified) + if (start_revision) { - *end_revision = apr_pcalloc(pool, sizeof(**end_revision)); - (*end_revision)->kind = svn_opt_revision_number; - (*end_revision)->value.number = end_revnum; + *start_revision = start_revnum; } - - if (start_revnum == peg_revnum && end_revnum == peg_revnum) + if (end_revision && end->kind != svn_opt_revision_unspecified) { - /* Avoid a network request in the common easy case. */ - *start_url = url; - if (end->kind != svn_opt_revision_unspecified) - *end_url = url; - svn_pool_destroy(subpool); - return SVN_NO_ERROR; + *end_revision = end_revnum; } - SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_url, subpool)); - - revs = apr_array_make(subpool, 2, sizeof(svn_revnum_t)); - APR_ARRAY_PUSH(revs, svn_revnum_t) = start_revnum; - if (end_revnum != start_revnum) - APR_ARRAY_PUSH(revs, svn_revnum_t) = end_revnum; - - SVN_ERR(svn_ra_get_locations(ra_session, &rev_locs, "", peg_revnum, - revs, subpool)); - - /* We'd better have all the paths we were looking for! */ - start_path = apr_hash_get(rev_locs, &start_revnum, sizeof(svn_revnum_t)); - if (! start_path) - return svn_error_createf - (SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL, - _("Unable to find repository location for '%s' in revision %ld"), - path_or_url_local_style(path, pool), start_revnum); - - end_path = apr_hash_get(rev_locs, &end_revnum, sizeof(svn_revnum_t)); - if (! end_path) - return svn_error_createf - (SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL, - _("The location for '%s' for revision %ld does not exist in the " - "repository or refers to an unrelated object"), - path_or_url_local_style(path, pool), end_revnum); - - /* Set our return variables */ - *start_url = svn_path_url_add_component2(repos_url, start_path + 1, pool); - if (end->kind != svn_opt_revision_unspecified) - *end_url = svn_path_url_add_component2(repos_url, end_path + 1, pool); - + SVN_ERR(repos_locations(start_url, end_url, + ra_session, url, peg_revnum, + start_revnum, end_revnum, + pool, subpool)); svn_pool_destroy(subpool); return SVN_NO_ERROR; } @@ -769,6 +809,8 @@ svn_client__get_youngest_common_ancestor svn_client_ctx_t *ctx, apr_pool_t *pool) { + apr_pool_t *sesspool = svn_pool_create(pool); + svn_ra_session_t *session1, *session2; apr_hash_t *history1, *history2; apr_hash_index_t *hi; svn_revnum_t yc_revision = SVN_INVALID_REVNUM; @@ -781,22 +823,35 @@ svn_client__get_youngest_common_ancestor revision1.value.number = rev1; revision2.value.number = rev2; + /* Open RA sessions for the two locations. + * ### TODO: As they are assumed to be in the same repository, we + * should share a single session, tracking the two URLs separately. */ + { + SVN_ERR(svn_client__ra_session_from_path(&session1, NULL, NULL, + path_or_url1, NULL, + &revision1, &revision1, + ctx, sesspool)); + SVN_ERR(svn_client__ra_session_from_path(&session2, NULL, NULL, + path_or_url2, NULL, + &revision2, &revision2, + ctx, sesspool)); + } /* We're going to cheat and use history-as-mergeinfo because it saves us a bunch of annoying custom data comparisons and such. */ SVN_ERR(svn_client__get_history_as_mergeinfo(&history1, &has_rev_zero_history1, - path_or_url1, - &revision1, + rev1, SVN_INVALID_REVNUM, SVN_INVALID_REVNUM, - NULL, ctx, pool)); + session1, ctx, pool)); SVN_ERR(svn_client__get_history_as_mergeinfo(&history2, &has_rev_zero_history2, - path_or_url2, - &revision2, + rev2, SVN_INVALID_REVNUM, SVN_INVALID_REVNUM, - NULL, ctx, pool)); + session2, ctx, pool)); + /* Close the source and target sessions. */ + svn_pool_destroy(sesspool); /* Loop through the first location's history, check for overlapping paths and ranges in the second location's history, and
Modified: subversion/branches/svn-bisect/subversion/libsvn_client/relocate.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/relocate.c?rev=1204374&r1=1204373&r2=1204374&view=diff ============================================================================== --- subversion/branches/svn-bisect/subversion/libsvn_client/relocate.c (original) +++ subversion/branches/svn-bisect/subversion/libsvn_client/relocate.c Mon Nov 21 07:07:56 2011 @@ -139,16 +139,13 @@ relocate_externals(const char *local_abs apr_array_header_t *ext_desc, const char *old_parent_repos_root_url, const char *new_parent_repos_root_url, + svn_boolean_t ignore_externals, svn_client_ctx_t *ctx, apr_pool_t *scratch_pool) { - const char *url; apr_pool_t *iterpool; int i; - SVN_ERR(svn_client_url_from_path2(&url, local_abspath, ctx, - scratch_pool, scratch_pool)); - /* Parse an externals definition into an array of external items. */ iterpool = svn_pool_create(scratch_pool); @@ -184,8 +181,8 @@ relocate_externals(const char *local_abs ext_item->target_dir, iterpool), iterpool)); - err = svn_client_root_url_from_path(&target_repos_root_url, - target_abspath, ctx, iterpool); + err = svn_client_get_repos_root(&target_repos_root_url, NULL /* uuid */, + target_abspath, ctx, iterpool, iterpool); /* Ignore externals that aren't present in the working copy. * This can happen if an external is deleted from disk accidentally, @@ -202,7 +199,7 @@ relocate_externals(const char *local_abs SVN_ERR(svn_client_relocate2(target_abspath, old_parent_repos_root_url, new_parent_repos_root_url, - TRUE, ctx, iterpool)); + ignore_externals, ctx, iterpool)); } svn_pool_destroy(iterpool); @@ -247,16 +244,16 @@ svn_client_relocate2(const char *wcroot_ } /* Fetch our current root URL. */ - SVN_ERR(svn_client_root_url_from_path(&old_repos_root_url, local_abspath, - ctx, pool)); + SVN_ERR(svn_client_get_repos_root(&old_repos_root_url, NULL /* uuid */, + local_abspath, ctx, pool, pool)); /* Perform the relocation. */ SVN_ERR(svn_wc_relocate4(ctx->wc_ctx, local_abspath, from_prefix, to_prefix, validator_func, &vb, pool)); /* Now fetch new current root URL. */ - SVN_ERR(svn_client_root_url_from_path(&new_repos_root_url, local_abspath, - ctx, pool)); + SVN_ERR(svn_client_get_repos_root(&new_repos_root_url, NULL /* uuid */, + local_abspath, ctx, pool, pool)); /* Relocate externals, too (if any). */ @@ -284,7 +281,8 @@ svn_client_relocate2(const char *wcroot_ iterpool)); if (ext_desc->nelts) SVN_ERR(relocate_externals(this_abspath, ext_desc, old_repos_root_url, - new_repos_root_url, ctx, iterpool)); + new_repos_root_url, ignore_externals, ctx, + iterpool)); } svn_pool_destroy(iterpool); Modified: subversion/branches/svn-bisect/subversion/libsvn_client/repos_diff.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/repos_diff.c?rev=1204374&r1=1204373&r2=1204374&view=diff ============================================================================== --- subversion/branches/svn-bisect/subversion/libsvn_client/repos_diff.c (original) +++ subversion/branches/svn-bisect/subversion/libsvn_client/repos_diff.c Mon Nov 21 07:07:56 2011 @@ -51,14 +51,6 @@ /* Overall crawler editor baton. */ struct edit_baton { - /* TARGET is a working-copy directory which corresponds to the base - URL open in RA_SESSION below. */ - const char *target; - - /* A working copy context for TARGET, NULL if this is purely a - repository operation. */ - svn_wc_context_t *wc_ctx; - /* The passed depth */ svn_depth_t depth; @@ -98,6 +90,9 @@ struct edit_baton { FALSE otherwise. */ svn_boolean_t walk_deleted_repos_dirs; + /* Whether to report text deltas */ + svn_boolean_t text_deltas; + /* A callback used to see if the client wishes to cancel the running operation. */ svn_cancel_func_t cancel_func; @@ -137,9 +132,6 @@ struct dir_baton { /* The path of the directory within the repository */ const char *path; - /* The path of the directory in the wc, relative to cwd */ - const char *wcpath; - /* The baton for the parent directory, or null if this is the root of the hierarchy to be compared. */ struct dir_baton *dir_baton; @@ -176,9 +168,6 @@ struct file_baton { /* The path of the file within the repository */ const char *path; - /* The path of the file in the wc, relative to cwd */ - const char *wcpath; - /* The path and APR file handle to the temporary file that contains the first repository version. Also, the pristine-property list of this file. */ @@ -239,7 +228,6 @@ make_dir_baton(const char *path, dir_baton->skip_children = FALSE; dir_baton->pool = dir_pool; dir_baton->path = apr_pstrdup(dir_pool, path); - dir_baton->wcpath = svn_dirent_join(edit_baton->target, path, dir_pool); dir_baton->propchanges = apr_array_make(pool, 1, sizeof(svn_prop_t)); return dir_baton; @@ -265,7 +253,6 @@ make_file_baton(const char *path, file_baton->skip = FALSE; file_baton->pool = file_pool; file_baton->path = apr_pstrdup(file_pool, path); - file_baton->wcpath = svn_dirent_join(edit_baton->target, path, file_pool); file_baton->propchanges = apr_array_make(pool, 1, sizeof(svn_prop_t)); file_baton->base_revision = edit_baton->revision; @@ -315,11 +302,19 @@ get_file_mime_types(const char **mimetyp } -/* Get revision REVISION of the file described by B from the repository. - * Set B->path_start_revision to the path of a new temporary file containing - * the file's text. Set B->pristine_props to a new hash containing the - * file's properties. Install a pool cleanup handler on B->pool to delete - * the file. +/* Get revision B->base_revision of the file described by B from the + * repository, through B->edit_baton->ra_session. + * + * Unless PROPS_ONLY is true: + * Set B->path_start_revision to the path of a new temporary file containing + * the file's text. + * Set B->start_md5_checksum to that file's MD-5 checksum. + * Install a pool cleanup handler on B->pool to delete the file. + * + * Always: + * Set B->pristine_props to a new hash containing the file's properties. + * + * Allocate all results in B->pool. */ static svn_error_t * get_file_from_ra(struct file_baton *b, @@ -332,7 +327,7 @@ get_file_from_ra(struct file_baton *b, SVN_ERR(svn_stream_open_unique(&fstream, &(b->path_start_revision), NULL, svn_io_file_del_on_pool_cleanup, - scratch_pool, scratch_pool)); + b->pool, scratch_pool)); fstream = svn_stream_checksummed2(fstream, NULL, &b->start_md5_checksum, svn_checksum_md5, TRUE, scratch_pool); @@ -359,7 +354,11 @@ get_file_from_ra(struct file_baton *b, return SVN_NO_ERROR; } -/* Issue #3657 'dav update report handler in skelta mode can cause +/* Remove every no-op property change from CHANGES: that is, remove every + entry in which the target value is the same as the value of the + corresponding property in PRISTINE_PROPS. + + Issue #3657 'dav update report handler in skelta mode can cause spurious conflicts'. When communicating with the repository via ra_serf and ra_neon, the change_dir_prop and change_file_prop svn_delta_editor_t callbacks are called (obviously) when a directory or file property has @@ -386,8 +385,6 @@ get_file_from_ra(struct file_baton *b, See http://subversion.tigris.org/issues/show_bug.cgi?id=3657#desc9 and http://svn.haxx.se/dev/archive-2010-08/0351.shtml for more details. - - This function filters these property changes from the change hash */ static void remove_non_prop_changes(apr_hash_t *pristine_props, @@ -475,9 +472,6 @@ open_root(void *edit_baton, struct edit_baton *eb = edit_baton; struct dir_baton *b = make_dir_baton("", NULL, eb, FALSE, pool); - /* Override the wcpath in our baton. */ - b->wcpath = apr_pstrdup(pool, eb->target); - SVN_ERR(get_dirprops_from_ra(b, base_revision)); *root_baton = b; @@ -485,7 +479,7 @@ open_root(void *edit_baton, } /* Recursively walk tree rooted at DIR (at REVISION) in the repository, - * reporting all files as deleted. Part of a workaround for issue 2333. + * reporting all children as deleted. Part of a workaround for issue 2333. * * DIR is a repository path relative to the URL in RA_SESSION. REVISION * must be a valid revision number, not SVN_INVALID_REVNUM. EB is the @@ -537,14 +531,17 @@ diff_deleted_dir(const char *dir, /* Compare a file being deleted against an empty file */ b = make_file_baton(path, FALSE, eb, iterpool); - SVN_ERR(get_file_from_ra(b, FALSE, iterpool)); + if (eb->text_deltas) + SVN_ERR(get_file_from_ra(b, FALSE, iterpool)); + else + SVN_ERR(get_empty_file(eb, &b->path_start_revision)); SVN_ERR(get_empty_file(b->edit_baton, &(b->path_end_revision))); get_file_mime_types(&mimetype1, &mimetype2, b); SVN_ERR(eb->diff_callbacks->file_deleted( - NULL, NULL, b->wcpath, + NULL, NULL, b->path, b->path_start_revision, b->path_end_revision, mimetype1, mimetype2, @@ -554,13 +551,18 @@ diff_deleted_dir(const char *dir, } if (dirent->kind == svn_node_dir) - SVN_ERR(diff_deleted_dir(path, - revision, - ra_session, - eb, - cancel_func, - cancel_baton, - iterpool)); + { + SVN_ERR(eb->diff_callbacks->dir_deleted( + NULL, NULL, path, + eb->diff_cmd_baton, iterpool)); + SVN_ERR(diff_deleted_dir(path, + revision, + ra_session, + eb, + cancel_func, + cancel_baton, + iterpool)); + } } svn_pool_destroy(iterpool); @@ -602,13 +604,17 @@ delete_entry(const char *path, /* Compare a file being deleted against an empty file */ b = make_file_baton(path, FALSE, eb, scratch_pool); - SVN_ERR(get_file_from_ra(b, FALSE, scratch_pool)); + if (eb->text_deltas) + SVN_ERR(get_file_from_ra(b, FALSE, scratch_pool)); + else + SVN_ERR(get_empty_file(eb, &b->path_start_revision)); + SVN_ERR(get_empty_file(b->edit_baton, &(b->path_end_revision))); get_file_mime_types(&mimetype1, &mimetype2, b); SVN_ERR(eb->diff_callbacks->file_deleted( - &state, &tree_conflicted, b->wcpath, + &state, &tree_conflicted, b->path, b->path_start_revision, b->path_end_revision, mimetype1, mimetype2, @@ -622,7 +628,7 @@ delete_entry(const char *path, { SVN_ERR(eb->diff_callbacks->dir_deleted( &state, &tree_conflicted, - svn_dirent_join(eb->target, path, pool), + path, eb->diff_cmd_baton, scratch_pool)); if (eb->walk_deleted_repos_dirs) @@ -653,9 +659,9 @@ delete_entry(const char *path, if (eb->notify_func) { - const char* deleted_path; + const char *deleted_path = apr_pstrdup(eb->pool, path); deleted_path_notify_t *dpn = apr_pcalloc(eb->pool, sizeof(*dpn)); - deleted_path = svn_dirent_join(eb->target, path, eb->pool); + dpn->kind = kind; dpn->action = tree_conflicted ? svn_wc_notify_tree_conflict : action; dpn->state = state; @@ -699,7 +705,7 @@ add_directory(const char *path, SVN_ERR(eb->diff_callbacks->dir_added( &state, &b->tree_conflicted, - &b->skip, &b->skip_children, b->wcpath, + &b->skip, &b->skip_children, b->path, eb->target_revision, copyfrom_path, copyfrom_revision, eb->diff_cmd_baton, pool)); @@ -718,12 +724,12 @@ add_directory(const char *path, /* Find out if a pending delete notification for this path is * still around. */ - dpn = apr_hash_get(eb->deleted_paths, b->wcpath, APR_HASH_KEY_STRING); + dpn = apr_hash_get(eb->deleted_paths, b->path, APR_HASH_KEY_STRING); if (dpn) { /* If any was found, we will handle the pending 'deleted path * notification' (DPN) here. Remove it from the list. */ - apr_hash_set(eb->deleted_paths, b->wcpath, + apr_hash_set(eb->deleted_paths, b->path, APR_HASH_KEY_STRING, NULL); /* the pending delete might be on a different node kind. */ @@ -749,7 +755,7 @@ add_directory(const char *path, else action = svn_wc_notify_update_add; - notify = svn_wc_create_notify(b->wcpath, action, pool); + notify = svn_wc_create_notify(b->path, action, pool); notify->kind = kind; notify->content_state = notify->prop_state = state; (*eb->notify_func)(eb->notify_baton, notify, pool); @@ -785,7 +791,7 @@ open_directory(const char *path, SVN_ERR(eb->diff_callbacks->dir_opened( &b->tree_conflicted, &b->skip, - &b->skip_children, b->wcpath, base_revision, + &b->skip_children, b->path, base_revision, b->edit_baton->diff_cmd_baton, pool)); return SVN_NO_ERROR; @@ -848,7 +854,7 @@ open_file(const char *path, SVN_ERR(eb->diff_callbacks->file_opened( &b->tree_conflicted, &b->skip, - b->wcpath, base_revision, eb->diff_cmd_baton, pool)); + b->path, base_revision, eb->diff_cmd_baton, pool)); return SVN_NO_ERROR; } @@ -893,6 +899,19 @@ apply_textdelta(void *file_baton, return SVN_NO_ERROR; } + /* If we're not sending file text, then ignore any that we receive. */ + if (! b->edit_baton->text_deltas) + { + /* Supply valid paths to indicate there is a text change. */ + SVN_ERR(get_empty_file(b->edit_baton, &b->path_start_revision)); + SVN_ERR(get_empty_file(b->edit_baton, &b->path_end_revision)); + + *handler = svn_delta_noop_window_handler; + *handler_baton = NULL; + + return SVN_NO_ERROR; + } + /* We need the expected pristine file, so go get it */ if (!b->added) SVN_ERR(get_file_from_ra(b, FALSE, scratch_pool)); @@ -969,7 +988,7 @@ close_file(void *file_baton, scratch_pool = b->pool; - if (expected_md5_digest) + if (expected_md5_digest && eb->text_deltas) { svn_checksum_t *expected_md5_checksum; @@ -1006,7 +1025,7 @@ close_file(void *file_baton, if (b->added) SVN_ERR(eb->diff_callbacks->file_added( &content_state, &prop_state, &b->tree_conflicted, - b->wcpath, + b->path, b->path_end_revision ? b->path_start_revision : NULL, b->path_end_revision, 0, @@ -1019,7 +1038,7 @@ close_file(void *file_baton, else SVN_ERR(eb->diff_callbacks->file_changed( &content_state, &prop_state, - &b->tree_conflicted, b->wcpath, + &b->tree_conflicted, b->path, b->path_end_revision ? b->path_start_revision : NULL, b->path_end_revision, b->edit_baton->revision, @@ -1040,12 +1059,12 @@ close_file(void *file_baton, /* Find out if a pending delete notification for this path is * still around. */ - dpn = apr_hash_get(eb->deleted_paths, b->wcpath, APR_HASH_KEY_STRING); + dpn = apr_hash_get(eb->deleted_paths, b->path, APR_HASH_KEY_STRING); if (dpn) { /* If any was found, we will handle the pending 'deleted path * notification' (DPN) here. Remove it from the list. */ - apr_hash_set(eb->deleted_paths, b->wcpath, + apr_hash_set(eb->deleted_paths, b->path, APR_HASH_KEY_STRING, NULL); /* the pending delete might be on a different node kind. */ @@ -1074,7 +1093,7 @@ close_file(void *file_baton, else action = svn_wc_notify_update_update; - notify = svn_wc_create_notify(b->wcpath, action, scratch_pool); + notify = svn_wc_create_notify(b->path, action, scratch_pool); notify->kind = kind; notify->content_state = content_state; notify->prop_state = prop_state; @@ -1086,7 +1105,13 @@ close_file(void *file_baton, return SVN_NO_ERROR; } -/* An svn_delta_editor_t function. */ +/* Report any accumulated prop changes via the 'dir_props_changed' callback, + * and then call the 'dir_closed' callback. Notify about any deleted paths + * within this directory that have not already been notified, and then about + * this directory itself (unless it was added, in which case the notification + * was done at that time). + * + * An svn_delta_editor_t function. */ static svn_error_t * close_directory(void *dir_baton, apr_pool_t *pool) @@ -1110,12 +1135,13 @@ close_directory(void *dir_baton, if (!b->added && b->propchanges->nelts > 0) remove_non_prop_changes(b->pristine_props, b->propchanges); + /* Report any prop changes. */ if (b->propchanges->nelts > 0) { svn_boolean_t tree_conflicted = FALSE; SVN_ERR(eb->diff_callbacks->dir_props_changed( &prop_state, &tree_conflicted, - b->wcpath, b->added, + b->path, b->added, b->propchanges, b->pristine_props, b->edit_baton->diff_cmd_baton, scratch_pool)); if (tree_conflicted) @@ -1130,12 +1156,12 @@ close_directory(void *dir_baton, } SVN_ERR(eb->diff_callbacks->dir_closed(NULL, NULL, NULL, - b->wcpath, b->added, + b->path, b->added, b->edit_baton->diff_cmd_baton, scratch_pool)); - /* Don't notify added directories as they triggered notification - in add_directory. */ + /* Notify about any deleted paths within this directory that have not + * already been notified. */ if (!skipped && !b->added && eb->notify_func) { apr_hash_index_t *hi; @@ -1157,6 +1183,8 @@ 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 (!b->added && eb->notify_func) { svn_wc_notify_t *notify; @@ -1169,7 +1197,7 @@ close_directory(void *dir_baton, else action = svn_wc_notify_update_update; - notify = svn_wc_create_notify(b->wcpath, action, pool); + notify = svn_wc_create_notify(b->path, action, pool); notify->kind = svn_node_dir; /* In case of a tree conflict during merge, the diff callback @@ -1188,7 +1216,9 @@ close_directory(void *dir_baton, } -/* An svn_delta_editor_t function. */ +/* Record a prop change, which we will report later in close_file(). + * + * An svn_delta_editor_t function. */ static svn_error_t * change_file_prop(void *file_baton, const char *name, @@ -1209,7 +1239,9 @@ change_file_prop(void *file_baton, return SVN_NO_ERROR; } -/* An svn_delta_editor_t function. */ +/* Make a note of this prop change, to be reported when the dir is closed. + * + * An svn_delta_editor_t function. */ static svn_error_t * change_dir_prop(void *dir_baton, const char *name, @@ -1243,7 +1275,8 @@ close_edit(void *edit_baton, return SVN_NO_ERROR; } -/* An svn_delta_editor_t function. */ +/* Notify that the node at PATH is 'missing'. + * An svn_delta_editor_t function. */ static svn_error_t * absent_directory(const char *path, void *parent_baton, @@ -1257,11 +1290,8 @@ absent_directory(const char *path, if (eb->notify_func) { svn_wc_notify_t *notify - = svn_wc_create_notify(svn_dirent_join(pb->wcpath, - svn_relpath_basename(path, - NULL), - pool), - svn_wc_notify_skip, pool); + = svn_wc_create_notify(path, svn_wc_notify_skip, pool); + notify->kind = svn_node_dir; notify->content_state = notify->prop_state = svn_wc_notify_state_missing; @@ -1272,7 +1302,8 @@ absent_directory(const char *path, } -/* An svn_delta_editor_t function. */ +/* Notify that the node at PATH is 'missing'. + * An svn_delta_editor_t function. */ static svn_error_t * absent_file(const char *path, void *parent_baton, @@ -1286,11 +1317,8 @@ absent_file(const char *path, if (eb->notify_func) { svn_wc_notify_t *notify - = svn_wc_create_notify(svn_dirent_join(pb->wcpath, - svn_relpath_basename(path, - pool), - pool), - svn_wc_notify_skip, pool); + = svn_wc_create_notify(path, svn_wc_notify_skip, pool); + notify->kind = svn_node_file; notify->content_state = notify->prop_state = svn_wc_notify_state_missing; @@ -1304,12 +1332,11 @@ absent_file(const char *path, svn_error_t * svn_client__get_diff_editor(const svn_delta_editor_t **editor, void **edit_baton, - svn_wc_context_t *wc_ctx, - const char *target, svn_depth_t depth, svn_ra_session_t *ra_session, svn_revnum_t revision, svn_boolean_t walk_deleted_dirs, + svn_boolean_t text_deltas, const svn_wc_diff_callbacks4_t *diff_callbacks, void *diff_cmd_baton, svn_cancel_func_t cancel_func, @@ -1321,13 +1348,10 @@ svn_client__get_diff_editor(const svn_de apr_pool_t *editor_pool = svn_pool_create(result_pool); svn_delta_editor_t *tree_editor = svn_delta_default_editor(editor_pool); struct edit_baton *eb = apr_pcalloc(editor_pool, sizeof(*eb)); - const char *target_abspath; - - SVN_ERR(svn_dirent_get_absolute(&target_abspath, target, editor_pool)); + svn_delta_shim_callbacks_t *shim_callbacks = + svn_delta_shim_callbacks_default(editor_pool); eb->pool = editor_pool; - eb->target = target; - eb->wc_ctx = wc_ctx; eb->depth = depth; eb->diff_callbacks = diff_callbacks; eb->diff_cmd_baton = diff_cmd_baton; @@ -1340,6 +1364,7 @@ svn_client__get_diff_editor(const svn_de eb->notify_func = notify_func; eb->notify_baton = notify_baton; eb->walk_deleted_repos_dirs = walk_deleted_dirs; + eb->text_deltas = text_deltas; eb->cancel_func = cancel_func; eb->cancel_baton = cancel_baton; @@ -1359,11 +1384,14 @@ svn_client__get_diff_editor(const svn_de tree_editor->absent_directory = absent_directory; tree_editor->absent_file = absent_file; - return svn_delta_get_cancellation_editor(cancel_func, - cancel_baton, - tree_editor, - eb, - editor, - edit_baton, - eb->pool); + SVN_ERR(svn_delta_get_cancellation_editor(cancel_func, cancel_baton, + tree_editor, eb, + editor, edit_baton, + eb->pool)); + + SVN_ERR(svn_editor__insert_shims(editor, edit_baton, *editor, *edit_baton, + shim_callbacks, + result_pool, result_pool)); + + return SVN_NO_ERROR; } Modified: subversion/branches/svn-bisect/subversion/libsvn_client/status.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/status.c?rev=1204374&r1=1204373&r2=1204374&view=diff ============================================================================== --- subversion/branches/svn-bisect/subversion/libsvn_client/status.c (original) +++ subversion/branches/svn-bisect/subversion/libsvn_client/status.c Mon Nov 21 07:07:56 2011 @@ -85,12 +85,23 @@ tweak_status(void *baton, /* If the status item has an entry, but doesn't belong to one of the changelists our caller is interested in, we filter out this status transmission. */ - if (sb->changelist_hash - && (! status->changelist - || ! apr_hash_get(sb->changelist_hash, status->changelist, - APR_HASH_KEY_STRING))) + /* ### duplicated in ../libsvn_wc/diff_local.c */ + if (sb->changelist_hash) { - return SVN_NO_ERROR; + if (status->changelist) + { + /* Skip unless the caller requested this changelist. */ + if (! apr_hash_get(sb->changelist_hash, status->changelist, + APR_HASH_KEY_STRING)) + return SVN_NO_ERROR; + } + else + { + /* Skip unless the caller requested changelist-lacking items. */ + if (! apr_hash_get(sb->changelist_hash, "", + APR_HASH_KEY_STRING)) + return SVN_NO_ERROR; + } } /* If we know that the target was deleted in HEAD of the repository, @@ -419,7 +430,7 @@ svn_client_status5(svn_revnum_t *result_ pool)); } - if (depth_as_sticky) + if (depth_as_sticky || !server_supports_depth) status_depth = depth; else status_depth = svn_depth_unknown; /* Use depth from WC */ @@ -570,10 +581,6 @@ svn_client_status_dup(const svn_client_s if (status->moved_to_abspath) st->moved_to_abspath = apr_pstrdup(result_pool, status->moved_to_abspath); - if (status->moved_to_op_root_abspath) - st->moved_to_op_root_abspath = - apr_pstrdup(result_pool, status->moved_to_op_root_abspath); - return st; } @@ -613,27 +620,12 @@ svn_client__create_status(svn_client_sta (*cst)->repos_relpath = status->repos_relpath; (*cst)->switched = status->switched; - (*cst)->file_external = FALSE; - - if (/* Old style file-externals */ - (status->versioned - && status->switched - && status->kind == svn_node_file)) - { - svn_node_kind_t external_kind; - - SVN_ERR(svn_wc__read_external_info(&external_kind, NULL, NULL, NULL, - NULL, wc_ctx, - local_abspath /* wri_abspath */, - local_abspath, TRUE, - scratch_pool, scratch_pool)); - if (external_kind == svn_node_file) - { - (*cst)->file_external = TRUE; - (*cst)->switched = FALSE; - (*cst)->node_status = (*cst)->text_status; - } + (*cst)->file_external = status->file_external; + if (status->file_external) + { + (*cst)->switched = FALSE; + (*cst)->node_status = (*cst)->text_status; } (*cst)->lock = status->lock; @@ -680,7 +672,6 @@ svn_client__create_status(svn_client_sta (*cst)->moved_from_abspath = status->moved_from_abspath; (*cst)->moved_to_abspath = status->moved_to_abspath; - (*cst)->moved_to_op_root_abspath = status->moved_to_op_root_abspath; return SVN_NO_ERROR; } Modified: subversion/branches/svn-bisect/subversion/libsvn_client/update.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/update.c?rev=1204374&r1=1204373&r2=1204374&view=diff ============================================================================== --- subversion/branches/svn-bisect/subversion/libsvn_client/update.c (original) +++ subversion/branches/svn-bisect/subversion/libsvn_client/update.c Mon Nov 21 07:07:56 2011 @@ -83,8 +83,7 @@ svn_client__dirent_fetcher(void *baton, *dirents = NULL; if (old_url) - SVN_ERR(svn_client__ensure_ra_session_url(&old_url, dfb->ra_session, - old_url, scratch_pool)); + SVN_ERR(svn_ra_reparent(dfb->ra_session, old_url, scratch_pool)); return SVN_NO_ERROR; } @@ -169,7 +168,7 @@ is_empty_wc(svn_boolean_t *clean_checkou This is typically either the same as LOCAL_ABSPATH, or the immediate parent of LOCAL_ABSPATH. - If NOTIFY_SUMMARY is set (and there's a notification hander in + If NOTIFY_SUMMARY is set (and there's a notification handler in CTX), transmit the final update summary upon successful completion of the update. */ @@ -390,7 +389,9 @@ update_internal(svn_revnum_t *result_rev invalid revnum, that means RA will use the latest revision. */ SVN_ERR(svn_ra_do_update2(ra_session, &reporter, &report_baton, revnum, target, - depth_is_sticky ? depth : svn_depth_unknown, + (!server_supports_depth || depth_is_sticky + ? depth + : svn_depth_unknown), FALSE, update_editor, update_edit_baton, pool)); /* Drive the reporter structure, describing the revisions within Modified: subversion/branches/svn-bisect/subversion/libsvn_client/url.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/url.c?rev=1204374&r1=1204373&r2=1204374&view=diff ============================================================================== --- subversion/branches/svn-bisect/subversion/libsvn_client/url.c (original) +++ subversion/branches/svn-bisect/subversion/libsvn_client/url.c Mon Nov 21 07:07:56 2011 @@ -61,18 +61,3 @@ svn_client_url_from_path2(const char **u return SVN_NO_ERROR; } - - -svn_error_t * -svn_client_root_url_from_path(const char **url, - const char *path_or_url, - svn_client_ctx_t *ctx, - apr_pool_t *pool) -{ - if (!svn_path_is_url(path_or_url)) - SVN_ERR(svn_dirent_get_absolute(&path_or_url, path_or_url, pool)); - - return svn_error_trace( - svn_client__get_repos_root(url, path_or_url, - ctx, pool, pool)); -} Modified: subversion/branches/svn-bisect/subversion/libsvn_client/util.c URL: http://svn.apache.org/viewvc/subversion/branches/svn-bisect/subversion/libsvn_client/util.c?rev=1204374&r1=1204373&r2=1204374&view=diff ============================================================================== --- subversion/branches/svn-bisect/subversion/libsvn_client/util.c (original) +++ subversion/branches/svn-bisect/subversion/libsvn_client/util.c Mon Nov 21 07:07:56 2011 @@ -102,17 +102,15 @@ svn_client__path_relative_to_root(const SVN_ERR_ASSERT(repos_relpath != NULL); } - /* Merge handling passes a root that is not the repos root */ else if (repos_root != NULL) { - if (!svn_uri__is_ancestor(repos_root, abspath_or_url)) + repos_relpath = svn_uri_skip_ancestor(repos_root, abspath_or_url, + result_pool); + if (!repos_relpath) return svn_error_createf(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL, _("URL '%s' is not a child of repository " "root URL '%s'"), abspath_or_url, repos_root); - - repos_relpath = svn_uri_skip_ancestor(repos_root, abspath_or_url, - result_pool); } else { @@ -144,18 +142,19 @@ svn_client__path_relative_to_root(const } svn_error_t * -svn_client__get_repos_root(const char **repos_root, - const char *abspath_or_url, - svn_client_ctx_t *ctx, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) +svn_client_get_repos_root(const char **repos_root, + const char **repos_uuid, + const char *abspath_or_url, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) { svn_ra_session_t *ra_session; /* If PATH_OR_URL is a local path we can fetch the repos root locally. */ if (!svn_path_is_url(abspath_or_url)) { - SVN_ERR(svn_wc__node_get_repos_info(repos_root, NULL, + SVN_ERR(svn_wc__node_get_repos_info(repos_root, repos_uuid, ctx->wc_ctx, abspath_or_url, result_pool, scratch_pool)); @@ -168,7 +167,10 @@ svn_client__get_repos_root(const char ** NULL, NULL, FALSE, TRUE, ctx, scratch_pool)); - SVN_ERR(svn_ra_get_repos_root2(ra_session, repos_root, result_pool)); + if (repos_root) + SVN_ERR(svn_ra_get_repos_root2(ra_session, repos_root, result_pool)); + if (repos_uuid) + SVN_ERR(svn_ra_get_uuid2(ra_session, repos_uuid, result_pool)); return SVN_NO_ERROR; }
