Modified: subversion/branches/shelve-checkpoint/subversion/include/svn_fs.h URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/include/svn_fs.h?rev=1829257&r1=1829256&r2=1829257&view=diff ============================================================================== --- subversion/branches/shelve-checkpoint/subversion/include/svn_fs.h (original) +++ subversion/branches/shelve-checkpoint/subversion/include/svn_fs.h Mon Apr 16 12:21:02 2018 @@ -1744,7 +1744,7 @@ svn_fs_paths_changed3(svn_fs_path_change * * Use @a pool for all allocations, including the hash and its values. * - * @note Retrieving the #node_rev_id element of #svn_fs_path_change2_t may + * @note Retrieving the #svn_fs_path_change2_t.node_rev_id element may * be expensive in some FS backends. * * @since New in 1.6. @@ -2492,7 +2492,7 @@ svn_fs_file_md5_checksum(unsigned char d * svn_fs_file_contents(). In that case, the result of reading from * @a *contents is undefined. * - * ### @todo kff: I am worried about lifetime issues with this pool vs + * @todo kff: I am worried about lifetime issues with this pool vs * the trail created farther down the call stack. Trace this function * to investigate... */
Modified: subversion/branches/shelve-checkpoint/subversion/include/svn_opt.h URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/include/svn_opt.h?rev=1829257&r1=1829256&r2=1829257&view=diff ============================================================================== --- subversion/branches/shelve-checkpoint/subversion/include/svn_opt.h (original) +++ subversion/branches/shelve-checkpoint/subversion/include/svn_opt.h Mon Apr 16 12:21:02 2018 @@ -69,6 +69,10 @@ typedef svn_error_t *(svn_opt_subcommand /** The maximum number of options that can be accepted by a subcommand. */ #define SVN_OPT_MAX_OPTIONS 50 +/** The maximum number of paragraphs of help text a subcommand can have. + * @since New in 1.11. */ +#define SVN_OPT_MAX_PARAGRAPHS 100 + /** Options that have no short option char should use an identifying * integer equal to or greater than this. */ @@ -77,7 +81,39 @@ typedef svn_error_t *(svn_opt_subcommand /** One element of a subcommand dispatch table. * + * @since New in 1.11. + */ +typedef struct svn_opt_subcommand_desc3_t +{ + /** The full name of this command. */ + const char *name; + + /** The function this command invokes. */ + svn_opt_subcommand_t *cmd_func; + + /** A list of alias names for this command (e.g., 'up' for 'update'). */ + const char *aliases[SVN_OPT_MAX_ALIASES]; + + /** A multi-paragraph string describing this command. */ + const char *help[SVN_OPT_MAX_PARAGRAPHS]; + + /** A list of options accepted by this command. Each value in the + * array is a unique enum (the 2nd field in apr_getopt_option_t) + */ + int valid_options[SVN_OPT_MAX_OPTIONS]; + + /** A list of option help descriptions, keyed by the option unique enum + * (the 2nd field in apr_getopt_option_t), which override the generic + * descriptions given in an apr_getopt_option_t on a per-subcommand basis. + */ + struct { int optch; const char *desc; } desc_overrides[SVN_OPT_MAX_OPTIONS]; +} svn_opt_subcommand_desc3_t; + + +/** One element of a subcommand dispatch table. + * * @since New in 1.4. + * @deprecated Provided for backward compatibility with the 1.10 API. */ typedef struct svn_opt_subcommand_desc2_t { @@ -139,8 +175,21 @@ typedef struct svn_opt_subcommand_desc_t * Return the entry in @a table whose name matches @a cmd_name, or @c NULL if * none. @a cmd_name may be an alias. * + * @since New in 1.11. + */ +const svn_opt_subcommand_desc3_t * +svn_opt_get_canonical_subcommand3(const svn_opt_subcommand_desc3_t *table, + const char *cmd_name); + + +/** + * Same as svn_opt_get_canonical_subcommand3(), but with a different + * version of the subcommand description table. + * * @since New in 1.4. + * @deprecated Provided for backward compatibility with the 1.10 API. */ +SVN_DEPRECATED const svn_opt_subcommand_desc2_t * svn_opt_get_canonical_subcommand2(const svn_opt_subcommand_desc2_t *table, const char *cmd_name); @@ -170,8 +219,22 @@ svn_opt_get_canonical_subcommand(const s * * The returned value may be statically allocated, or allocated in @a pool. * + * @since New in 1.11. + */ +const apr_getopt_option_t * +svn_opt_get_option_from_code3(int code, + const apr_getopt_option_t *option_table, + const svn_opt_subcommand_desc3_t *command, + apr_pool_t *pool); + +/** + * Same as svn_opt_get_option_from_code3(), but with a different + * version of the subcommand description table. + * * @since New in 1.4. + * @deprecated Provided for backward compatibility with the 1.10 API. */ +SVN_DEPRECATED const apr_getopt_option_t * svn_opt_get_option_from_code2(int code, const apr_getopt_option_t *option_table, @@ -198,8 +261,21 @@ svn_opt_get_option_from_code(int code, * non-NULL, it is a zero-terminated array, and all subcommands take * the options listed in it. * + * @since New in 1.11. + */ +svn_boolean_t +svn_opt_subcommand_takes_option4(const svn_opt_subcommand_desc3_t *command, + int option_code, + const int *global_options); + +/** + * Same as svn_opt_subcommand_takes_option4(), but with a different + * version of the subcommand description table. + * * @since New in 1.5. + * @deprecated Provided for backward compatibility with the 1.10 API. */ +SVN_DEPRECATED svn_boolean_t svn_opt_subcommand_takes_option3(const svn_opt_subcommand_desc2_t *command, int option_code, @@ -235,7 +311,7 @@ svn_opt_subcommand_takes_option(const sv /** * Print a generic (not command-specific) usage message to @a stream. * - * ### @todo Why is @a stream a stdio file instead of an svn stream? + * @todo Why is @a stream a stdio file instead of an svn stream? * * If @a header is non-NULL, print @a header followed by a newline. Then * loop over @a cmd_table printing the usage for each command (getting @@ -244,8 +320,24 @@ svn_opt_subcommand_takes_option(const sv * * Use @a pool for temporary allocation. * + * @since New in 1.11. + */ +void +svn_opt_print_generic_help3(const char *header, + const svn_opt_subcommand_desc3_t *cmd_table, + const apr_getopt_option_t *opt_table, + const char *footer, + apr_pool_t *pool, + FILE *stream); + +/** + * Same as svn_opt_print_generic_help3(), but with a different + * version of the subcommand description table. + * * @since New in 1.4. + * @deprecated Provided for backward compatibility with the 1.10 API. */ +SVN_DEPRECATED void svn_opt_print_generic_help2(const char *header, const svn_opt_subcommand_desc2_t *cmd_table, @@ -297,8 +389,23 @@ svn_opt_format_option(const char **strin * use that second name as an alias for the first name. This additional * behaviour is new in 1.7. * + * @since New in 1.11. + */ +void +svn_opt_subcommand_help4(const char *subcommand, + const svn_opt_subcommand_desc3_t *table, + const apr_getopt_option_t *options_table, + const int *global_options, + apr_pool_t *pool); + +/** + * Same as svn_opt_subcommand_help4(), but with a different + * version of the subcommand description table. + * * @since New in 1.5. + * @deprecated Provided for backward compatibility with the 1.10 API. */ +SVN_DEPRECATED void svn_opt_subcommand_help3(const char *subcommand, const svn_opt_subcommand_desc2_t *table, @@ -709,9 +816,30 @@ svn_opt_parse_path(svn_opt_revision_t *r * --version flag *and* subcommand arguments on a help command line. * The logic for handling such a situation should be in one place. * - * @since New in 1.8. + * @since New in 1.11. */ +svn_error_t * +svn_opt_print_help5(apr_getopt_t *os, + const char *pgm_name, + svn_boolean_t print_version, + svn_boolean_t quiet, + svn_boolean_t verbose, + const char *version_footer, + const char *header, + const svn_opt_subcommand_desc3_t *cmd_table, + const apr_getopt_option_t *option_table, + const int *global_options, + const char *footer, + apr_pool_t *pool); +/** + * Same as svn_opt_print_help5(), but with a different + * version of the subcommand description table. + * + * @since New in 1.8. + * @deprecated Provided for backward compatibility with the 1.10 API. + */ +SVN_DEPRECATED svn_error_t * svn_opt_print_help4(apr_getopt_t *os, const char *pgm_name, Modified: subversion/branches/shelve-checkpoint/subversion/include/svn_props.h URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/include/svn_props.h?rev=1829257&r1=1829256&r2=1829257&view=diff ============================================================================== --- subversion/branches/shelve-checkpoint/subversion/include/svn_props.h (original) +++ subversion/branches/shelve-checkpoint/subversion/include/svn_props.h Mon Apr 16 12:21:02 2018 @@ -415,19 +415,26 @@ svn_prop_name_is_valid(const char *prop_ /** Describes external items to check out into this directory. * * The format is a series of lines, each in the following format: - * [-r REV] URL[@PEG] LOCALPATH + * + * [-r REV] URL[@PEG] LOCALPATH + * * LOCALPATH is relative to the directory having this property. * REV pins the external to revision REV. * URL may be a full URL or a relative URL starting with one of: - * ../ to the parent directory of the extracted external - * ^/ to the repository root - * / to the server root - * // to the URL scheme + * + * ../ to the parent directory of the extracted external + * ^/ to the repository root + * / to the server root + * // to the URL scheme + * * The following format is supported for interoperability with * Subversion 1.4 and earlier clients: - * LOCALPATH [-r PEG] URL + * + * LOCALPATH [-r PEG] URL + * * The ambiguous format 'relative_path relative_path' is taken as * 'relative_url relative_path' with peg revision support. + * * Lines starting with a '#' character are ignored. */ #define SVN_PROP_EXTERNALS SVN_PROP_PREFIX "externals" Modified: subversion/branches/shelve-checkpoint/subversion/include/svn_ra.h URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/include/svn_ra.h?rev=1829257&r1=1829256&r2=1829257&view=diff ============================================================================== --- subversion/branches/shelve-checkpoint/subversion/include/svn_ra.h (original) +++ subversion/branches/shelve-checkpoint/subversion/include/svn_ra.h Mon Apr 16 12:21:02 2018 @@ -555,9 +555,9 @@ typedef struct svn_ra_callbacks2_t /** Fetch working copy properties. * - *<pre> ### we might have a problem if the RA layer ever wants a property - * ### that corresponds to a different revision of the file than - * ### what is in the WC. we'll cross that bridge one day...</pre> + * @note we might have a problem if the RA layer ever wants a property + * that corresponds to a different revision of the file than + * what is in the WC. we'll cross that bridge one day... */ svn_ra_get_wc_prop_func_t get_wc_prop; @@ -1857,7 +1857,7 @@ svn_ra_get_location_segments(svn_ra_sess * @note Prior to Subversion 1.9, this function may request delta handlers * from @a handler even for empty text deltas. Starting with 1.9, the * delta handler / baton return arguments passed to @a handler will be - * #NULL unless there is an actual difference in the file contents between + * NULL unless there is an actual difference in the file contents between * the current and the previous call. * * @since New in 1.5. Modified: subversion/branches/shelve-checkpoint/subversion/include/svn_ra_svn.h URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/include/svn_ra_svn.h?rev=1829257&r1=1829256&r2=1829257&view=diff ============================================================================== --- subversion/branches/shelve-checkpoint/subversion/include/svn_ra_svn.h (original) +++ subversion/branches/shelve-checkpoint/subversion/include/svn_ra_svn.h Mon Apr 16 12:21:02 2018 @@ -179,7 +179,9 @@ typedef svn_error_t *(*svn_ra_svn_edit_c * * Either @a sock or @a in_stream/@a out_stream must be set, not both. * @a compression_level specifies the desired network data compression - * level (zlib) from 0 (no compression) to 9 (best but slowest). + * level from 0 (no compression) to 9 (best but slowest). The effect + * of the parameter depends on the compression algorithm; for example, + * it is used verbatim by zlib/deflate but ignored by LZ4. * * If @a zero_copy_limit is not 0, cached file contents smaller than the * given limit may be sent directly to the network socket. Otherwise, Modified: subversion/branches/shelve-checkpoint/subversion/include/svn_repos.h URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/include/svn_repos.h?rev=1829257&r1=1829256&r2=1829257&view=diff ============================================================================== --- subversion/branches/shelve-checkpoint/subversion/include/svn_repos.h (original) +++ subversion/branches/shelve-checkpoint/subversion/include/svn_repos.h Mon Apr 16 12:21:02 2018 @@ -861,7 +861,7 @@ typedef svn_error_t *(*svn_repos_freeze_ * @since New in 1.8. */ svn_error_t * -svn_repos_freeze(apr_array_header_t *paths, +svn_repos_freeze(const apr_array_header_t *paths, svn_repos_freeze_func_t freeze_func, void *freeze_baton, apr_pool_t *pool); @@ -2404,7 +2404,7 @@ svn_repos_fs_get_mergeinfo(svn_mergeinfo * @note Prior to Subversion 1.9, this function may request delta handlers * from @a handler even for empty text deltas. Starting with 1.9, the * delta handler / baton return arguments passed to @a handler will be - * #NULL unless there is an actual difference in the file contents between + * NULL unless there is an actual difference in the file contents between * the current and the previous call. * * @since New in 1.5. @@ -3803,7 +3803,7 @@ typedef struct svn_repos_parse_fns3_t * * @since New in 1.8. - * @since Starting in 1.10, @a parse_fns may contain #NULL pointers for + * @since Starting in 1.10, @a parse_fns may contain NULL pointers for * those callbacks that the caller is not interested in. */ svn_error_t * Modified: subversion/branches/shelve-checkpoint/subversion/libsvn_client/client.h URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/libsvn_client/client.h?rev=1829257&r1=1829256&r2=1829257&view=diff ============================================================================== --- subversion/branches/shelve-checkpoint/subversion/libsvn_client/client.h (original) +++ subversion/branches/shelve-checkpoint/subversion/libsvn_client/client.h Mon Apr 16 12:21:02 2018 @@ -754,40 +754,23 @@ typedef struct svn_client__copy_pair_t /*** Commit Stuff ***/ -/* WARNING: This is all new, untested, un-peer-reviewed conceptual - stuff. +/* The "Harvest Committables" System - The day that 'svn switch' came into existence, our old commit - crawler (svn_wc_crawl_local_mods) became obsolete. It relied far - too heavily on the on-disk hierarchy of files and directories, and - simply had no way to support disjoint working copy trees or nest - working copies. The primary reason for this is that commit - process, in order to guarantee atomicity, is a single drive of a + The commit process requires, per repository, a single drive of a commit editor which is based not on working copy paths, but on - URLs. With the completion of 'svn switch', it became all too - likely that the on-disk working copy hierarchy would no longer be - guaranteed to map to a similar in-repository hierarchy. - - Aside from this new brokenness of the old system, an unrelated - feature request had cropped up -- the ability to know in advance of - your commit, exactly what would be committed (so that log messages - could be initially populated with this information). Since the old - crawler discovered commit candidates while in the process of - committing, it was impossible to harvest this information upfront. - As a workaround, svn_wc_statuses() was used to stat the whole - working copy for changes before the commit started...and then the - commit would again stat the whole tree for changes. - - Enter the new system. + URLs. The on-disk working copy hierarchy does not, in general, + map to a similar in-repository hierarchy, due to switched subtrees + and disjoint working copies. + + Also we wish to know exactly what would be committed, in advance of + the commit, so that a log message editor can be initially populated + with this information. The primary goal of this system is very straightforward: harvest all commit candidate information up front, and cache enough info in the process to use this to drive a URL-sorted commit. - *** END-OF-KNOWLEDGE *** - - The prototypes below are still in development. In general, the - idea is that commit-y processes ('svn mkdir URL', 'svn delete URL', + The idea is that commit-y processes ('svn mkdir URL', 'svn delete URL', 'svn commit', 'svn copy WC_PATH URL', 'svn copy URL1 URL2', 'svn move URL1 URL2', others?) generate the cached commit candidate information, and hand this information off to a consumer which is @@ -844,7 +827,7 @@ typedef svn_error_t *(*svn_client__check - if the candidate has a lock token, add it to the LOCK_TOKENS hash. - if the candidate is a directory scheduled for deletion, crawl - the directories children recursively for any lock tokens and + the directory's children recursively for any lock tokens and add them to the LOCK_TOKENS array. At the successful return of this function, COMMITTABLES will point @@ -1129,14 +1112,34 @@ svn_client__resolve_conflicts(svn_boolea svn_client_ctx_t *ctx, apr_pool_t *scratch_pool); -/* Produce a diff with depth DEPTH between two files or two directories at - * LEFT_ABSPATH1 and RIGHT_ABSPATH, using the provided diff callbacks to - * show changes in files. The files and directories involved may be part of - * a working copy or they may be unversioned. For versioned files, show - * property changes, too. - * - * If ANCHOR_ABSPATH is not null, set it to the anchor of the diff before - * the first processor call. (The anchor is LEFT_ABSPATH or an ancestor of it) +/* Produce a diff with depth DEPTH between the file or directory at + * LEFT_ABSPATH and the file or directory at RIGHT_ABSPATH, reporting + * differences to DIFF_PROCESSOR. + * + * The files and directories involved may be part of a working copy or + * they may be unversioned. For versioned files, show property changes, + * too. + * + * No copy or move information is reported to the diff processor. + * + * If both LEFT_ABSPATH and RIGHT_ABSPATH are directories on disk: + * set *ROOT_RELPATH to "" and + * set *ROOT_IS_DIR to TRUE and + * send diff processor relpaths relative to LEFT_ABSPATH + * (which is the same as relative to RIGHT_ABSPATH); + * else: + * set *ROOT_RELPATH to the basename of LEFT_ABSPATH and + * set *ROOT_IS_DIR to FALSE and + * send diff processor relpaths relative to the parent of LEFT_ABSPATH + * (so they all start with a basename(LEFT_ABSPATH) component). + * + * As any children reached by recursion are matched by name, a diff + * processor relpath applies equally to both sides of the diff, except + * for its first component in the latter case above. + * + * Assignments to *ROOT_RELPATH and *ROOT_IS_DIR are made before the first + * call to DIFF_PROCESSOR. Each of ROOT_RELPATH and ROOT_IS_DIR may be NULL + * if not wanted. */ svn_error_t * svn_client__arbitrary_nodes_diff(const char **root_relpath, @@ -1267,39 +1270,6 @@ svn_client__merge_locked(svn_client__con apr_pool_t *result_pool, apr_pool_t *scratch_pool); -/** Set @a shelf's revprop @a prop_name to @a prop_val. - * - * If @a prop_val is NULL, delete the property (if present). - */ -svn_error_t * -svn_client__shelf_revprop_set(svn_client_shelf_t *shelf, - const char *prop_name, - const svn_string_t *prop_val, - apr_pool_t *scratch_pool); - -/** Get @a shelf's revprop @a prop_name into @a *prop_val. - * - * If the property is not present, set @a *prop_val to NULL. - * - * The lifetime of the result is limited to that of @a shelf and/or - * of @a result_pool. - */ -svn_error_t * -svn_client__shelf_revprop_get(svn_string_t **prop_val, - svn_client_shelf_t *shelf, - const char *prop_name, - apr_pool_t *result_pool); - -/** Get @a shelf's revprops into @a props. - * - * The lifetime of the result is limited to that of @a shelf and/or - * of @a result_pool. - */ -svn_error_t * -svn_client__shelf_revprop_list(apr_hash_t **props, - svn_client_shelf_t *shelf, - apr_pool_t *result_pool); - #ifdef __cplusplus } #endif /* __cplusplus */ Modified: subversion/branches/shelve-checkpoint/subversion/libsvn_client/conflicts.c URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/libsvn_client/conflicts.c?rev=1829257&r1=1829256&r2=1829257&view=diff ============================================================================== --- subversion/branches/shelve-checkpoint/subversion/libsvn_client/conflicts.c (original) +++ subversion/branches/shelve-checkpoint/subversion/libsvn_client/conflicts.c Mon Apr 16 12:21:02 2018 @@ -255,7 +255,7 @@ struct repos_move_info { /* The revision in which this move was committed. */ svn_revnum_t rev; - /* The author who commited the revision in which this move was committed. */ + /* The author who committed the revision in which this move was committed. */ const char *rev_author; /* The repository relpath the node was moved from in this revision. */ @@ -5944,8 +5944,11 @@ describe_incoming_edit_list_modified_rev { if (i == edits->nelts - (max_revs_to_display / 2)) s = apr_psprintf(result_pool, - _("%s\n [%d revisions omitted for " - "brevity],\n"), + Q_("%s\n [%d revision omitted for " + "brevity],\n", + "%s\n [%d revisions omitted for " + "brevity],\n", + num_revs_to_skip), s, num_revs_to_skip); s = apr_psprintf(result_pool, _("%s r%ld by %s%s"), s, @@ -6704,8 +6707,9 @@ resolve_merge_incoming_added_file_text_u /* Revert the path in order to restore the repository's line of * history, which is part of the BASE tree. This revert operation * is why are being careful about not losing the temporary copy. */ - err = svn_wc_revert5(ctx->wc_ctx, local_abspath, svn_depth_empty, + err = svn_wc_revert6(ctx->wc_ctx, local_abspath, svn_depth_empty, FALSE, NULL, TRUE, FALSE, + TRUE /*added_keep_local*/, NULL, NULL, /* no cancellation */ ctx->notify_func2, ctx->notify_baton2, scratch_pool); @@ -8708,8 +8712,9 @@ resolve_incoming_move_dir_merge(svn_clie svn_opt_revision_t incoming_new_opt_rev; /* Revert the incoming move target directory. */ - SVN_ERR(svn_wc_revert5(ctx->wc_ctx, moved_to_abspath, svn_depth_infinity, + SVN_ERR(svn_wc_revert6(ctx->wc_ctx, moved_to_abspath, svn_depth_infinity, FALSE, NULL, TRUE, FALSE, + TRUE /*added_keep_local*/, NULL, NULL, /* no cancellation */ ctx->notify_func2, ctx->notify_baton2, scratch_pool)); @@ -9672,11 +9677,13 @@ configure_option_incoming_delete_ignore( incoming_details = conflict->tree_conflict_incoming_details; is_incoming_move = (incoming_details != NULL && incoming_details->moves != NULL); - if (local_change == svn_wc_conflict_reason_edited && is_incoming_move) + if (local_change == svn_wc_conflict_reason_moved_away || + local_change == svn_wc_conflict_reason_edited) { /* An option which ignores the incoming deletion makes no sense - * if we know it is actually a move. */ - return SVN_NO_ERROR; + * if we know there was a local move and/or an incoming move. */ + if (is_incoming_move) + return SVN_NO_ERROR; } else if (local_change == svn_wc_conflict_reason_deleted) { @@ -9737,14 +9744,17 @@ configure_option_incoming_delete_accept( if (incoming_change == svn_wc_conflict_action_delete) { struct conflict_tree_incoming_delete_details *incoming_details; + svn_boolean_t is_incoming_move; incoming_details = conflict->tree_conflict_incoming_details; - - if (local_change == svn_wc_conflict_reason_edited && - incoming_details != NULL && incoming_details->moves != NULL) + is_incoming_move = (incoming_details != NULL && + incoming_details->moves != NULL); + if (is_incoming_move && + (local_change == svn_wc_conflict_reason_edited || + local_change == svn_wc_conflict_reason_moved_away)) { /* An option which accepts the incoming deletion makes no sense - * if we know it is actually a move. */ + * if we know there was a local move and/or an incoming move. */ return SVN_NO_ERROR; } else @@ -9892,6 +9902,7 @@ configure_option_incoming_dir_merge(svn_ { svn_node_kind_t victim_node_kind; svn_wc_conflict_action_t incoming_change; + svn_wc_conflict_reason_t local_change; const char *incoming_old_repos_relpath; svn_revnum_t incoming_old_pegrev; svn_node_kind_t incoming_old_kind; @@ -9900,6 +9911,7 @@ configure_option_incoming_dir_merge(svn_ svn_node_kind_t incoming_new_kind; incoming_change = svn_client_conflict_get_incoming_change(conflict); + local_change = svn_client_conflict_get_local_change(conflict); victim_node_kind = svn_client_conflict_tree_get_victim_node_kind(conflict); SVN_ERR(svn_client_conflict_get_incoming_old_repos_location( &incoming_old_repos_relpath, &incoming_old_pegrev, @@ -9913,7 +9925,8 @@ configure_option_incoming_dir_merge(svn_ if (victim_node_kind == svn_node_dir && incoming_old_kind == svn_node_dir && incoming_new_kind == svn_node_none && - incoming_change == svn_wc_conflict_action_delete) + incoming_change == svn_wc_conflict_action_delete && + local_change == svn_wc_conflict_reason_edited) { struct conflict_tree_incoming_delete_details *details; const char *description; Modified: subversion/branches/shelve-checkpoint/subversion/libsvn_client/diff.c URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/libsvn_client/diff.c?rev=1829257&r1=1829256&r2=1829257&view=diff ============================================================================== --- subversion/branches/shelve-checkpoint/subversion/libsvn_client/diff.c (original) +++ subversion/branches/shelve-checkpoint/subversion/libsvn_client/diff.c Mon Apr 16 12:21:02 2018 @@ -66,6 +66,26 @@ _("Path '%s' must be an immediate child of " \ "the directory '%s'"), path, relative_to_dir) +/* State provided by the diff drivers; used by the diff writer */ +typedef struct diff_driver_info_t +{ + /* The anchor to prefix before wc paths */ + const char *anchor; + + /* Relative path of ra session from repos_root_url */ + const char *session_relpath; + + svn_wc_context_t *wc_ctx; + + /* The original targets passed to the diff command. We may need + these to construct distinctive diff labels when comparing the + same relative path in the same revision, under different anchors + (for example, when comparing a trunk against a branch). */ + const char *orig_path_1; + const char *orig_path_2; +} diff_driver_info_t; + + /* Calculate the repository relative path of DIFF_RELPATH, using * SESSION_RELPATH and WC_CTX, and return the result in *REPOS_RELPATH. * ORIG_TARGET is the related original target passed to the diff command, @@ -383,28 +403,33 @@ maybe_print_mode_change(svn_stream_t *os } /* Print a git diff header showing the OPERATION to the stream OS using - * HEADER_ENCODING. Return suitable diff labels for the git diff in *LABEL1 - * and *LABEL2. REPOS_RELPATH1 and REPOS_RELPATH2 are relative to reposroot. - * are the paths passed to the original diff command. REV1 and REV2 are - * revisions being diffed. COPYFROM_PATH and COPYFROM_REV indicate where the + * HEADER_ENCODING. + * + * Return suitable diff labels for the git diff in *LABEL1 and *LABEL2. + * + * REV1 and REV2 are the revisions being diffed. + * COPYFROM_PATH and COPYFROM_REV indicate where the * diffed item was copied from. * Use SCRATCH_POOL for temporary allocations. */ static svn_error_t * print_git_diff_header(svn_stream_t *os, const char **label1, const char **label2, svn_diff_operation_kind_t operation, - const char *repos_relpath1, - const char *repos_relpath2, svn_revnum_t rev1, svn_revnum_t rev2, + const char *diff_relpath, const char *copyfrom_path, svn_revnum_t copyfrom_rev, apr_hash_t *left_props, apr_hash_t *right_props, const char *git_index_shas, const char *header_encoding, + const diff_driver_info_t *ddi, apr_pool_t *scratch_pool) { + const char *repos_relpath1; + const char *repos_relpath2; + const char *copyfrom_repos_relpath = NULL; svn_boolean_t exec_bit1 = (svn_prop_get_value(left_props, SVN_PROP_EXECUTABLE) != NULL); svn_boolean_t exec_bit2 = (svn_prop_get_value(right_props, @@ -414,6 +439,26 @@ print_git_diff_header(svn_stream_t *os, svn_boolean_t symlink_bit2 = (svn_prop_get_value(right_props, SVN_PROP_SPECIAL) != NULL); + SVN_ERR(make_repos_relpath(&repos_relpath1, diff_relpath, + ddi->orig_path_1, + ddi->session_relpath, + ddi->wc_ctx, + ddi->anchor, + scratch_pool, scratch_pool)); + SVN_ERR(make_repos_relpath(&repos_relpath2, diff_relpath, + ddi->orig_path_2, + ddi->session_relpath, + ddi->wc_ctx, + ddi->anchor, + scratch_pool, scratch_pool)); + if (copyfrom_path) + SVN_ERR(make_repos_relpath(©from_repos_relpath, copyfrom_path, + ddi->orig_path_2, + ddi->session_relpath, + ddi->wc_ctx, + ddi->anchor, + scratch_pool, scratch_pool)); + if (operation == svn_diff_op_deleted) { SVN_ERR(print_git_diff_header_deleted(os, header_encoding, @@ -494,24 +539,20 @@ print_git_diff_header(svn_stream_t *os, ### FIXME needs proper docstring If USE_GIT_DIFF_FORMAT is TRUE, pring git diff headers, which always - show paths relative to the repository root. RA_SESSION and WC_CTX are - needed to normalize paths relative the repository root, and are ignored - if USE_GIT_DIFF_FORMAT is FALSE. + show paths relative to the repository root. DDI->session_relpath and + DDI->wc_ctx are needed to normalize paths relative the repository root, + and are ignored if USE_GIT_DIFF_FORMAT is FALSE. If @a pretty_print_mergeinfo is true, then describe 'svn:mergeinfo' property changes in a human-readable form that says what changes were merged or reverse merged; otherwise (or if the mergeinfo property values don't parse correctly) display them just like any other property. - - ANCHOR is the local path where the diff editor is anchored. */ + */ static svn_error_t * display_prop_diffs(const apr_array_header_t *propchanges, apr_hash_t *left_props, apr_hash_t *right_props, const char *diff_relpath, - const char *anchor, - const char *orig_path1, - const char *orig_path2, svn_revnum_t rev1, svn_revnum_t rev2, const char *encoding, @@ -520,32 +561,27 @@ display_prop_diffs(const apr_array_heade svn_boolean_t show_diff_header, svn_boolean_t use_git_diff_format, svn_boolean_t pretty_print_mergeinfo, - const char *ra_session_relpath, + const diff_driver_info_t *ddi, svn_cancel_func_t cancel_func, void *cancel_baton, - svn_wc_context_t *wc_ctx, apr_pool_t *scratch_pool) { const char *repos_relpath1 = NULL; - const char *repos_relpath2 = NULL; const char *index_path = diff_relpath; - const char *adjusted_path1 = orig_path1; - const char *adjusted_path2 = orig_path2; + const char *adjusted_path1 = ddi->orig_path_1; + const char *adjusted_path2 = ddi->orig_path_2; if (use_git_diff_format) { - SVN_ERR(make_repos_relpath(&repos_relpath1, diff_relpath, orig_path1, - ra_session_relpath, wc_ctx, anchor, - scratch_pool, scratch_pool)); - SVN_ERR(make_repos_relpath(&repos_relpath2, diff_relpath, orig_path2, - ra_session_relpath, wc_ctx, anchor, + SVN_ERR(make_repos_relpath(&repos_relpath1, diff_relpath, ddi->orig_path_1, + ddi->session_relpath, ddi->wc_ctx, ddi->anchor, scratch_pool, scratch_pool)); } /* If we're creating a diff on the wc root, path would be empty. */ SVN_ERR(adjust_paths_for_diff_labels(&index_path, &adjusted_path1, &adjusted_path2, - relative_to_dir, anchor, + relative_to_dir, ddi->anchor, scratch_pool, scratch_pool)); if (show_diff_header) @@ -567,13 +603,12 @@ display_prop_diffs(const apr_array_heade if (use_git_diff_format) SVN_ERR(print_git_diff_header(outstream, &label1, &label2, svn_diff_op_modified, - repos_relpath1, repos_relpath2, - rev1, rev2, NULL, - SVN_INVALID_REVNUM, - left_props, - right_props, + rev1, rev2, + diff_relpath, + NULL, SVN_INVALID_REVNUM, + left_props, right_props, NULL, - encoding, scratch_pool)); + encoding, ddi, scratch_pool)); /* --- label1 * +++ label2 */ @@ -605,24 +640,6 @@ display_prop_diffs(const apr_array_heade /*** Callbacks for 'svn diff', invoked by the repos-diff editor. ***/ -/* State provided by the diff drivers; used by the diff writer */ -typedef struct diff_driver_info_t -{ - /* The anchor to prefix before wc paths */ - const char *anchor; - - /* Relative path of ra session from repos_root_url */ - const char *session_relpath; - - /* The original targets passed to the diff command. We may need - these to construct distinctive diff labels when comparing the - same relative path in the same revision, under different anchors - (for example, when comparing a trunk against a branch). */ - const char *orig_path_1; - const char *orig_path_2; -} diff_driver_info_t; - - /* Diff writer state */ typedef struct diff_writer_info_t { @@ -680,8 +697,6 @@ typedef struct diff_writer_info_t /* Empty files for creating diffs or NULL if not used yet */ const char *empty_file; - svn_wc_context_t *wc_ctx; - svn_cancel_func_t cancel_func; void *cancel_baton; @@ -717,9 +732,6 @@ diff_props_changed(const char *diff_relp * dir_props_changed(). */ SVN_ERR(display_prop_diffs(props, left_props, right_props, diff_relpath, - dwi->ddi.anchor, - dwi->ddi.orig_path_1, - dwi->ddi.orig_path_2, rev1, rev2, dwi->header_encoding, @@ -728,10 +740,9 @@ diff_props_changed(const char *diff_relp show_diff_header, dwi->use_git_diff_format, dwi->pretty_print_mergeinfo, - dwi->ddi.session_relpath, + &dwi->ddi, dwi->cancel_func, dwi->cancel_baton, - dwi->wc_ctx, scratch_pool)); } @@ -795,9 +806,12 @@ transform_link_to_git(const char **new_t } /* Show differences between TMPFILE1 and TMPFILE2. DIFF_RELPATH, REV1, and - REV2 are used in the headers to indicate the file and revisions. If either - MIMETYPE1 or MIMETYPE2 indicate binary content, don't show a diff, - but instead print a warning message. + REV2 are used in the headers to indicate the file and revisions. + + If either side has an svn:mime-type property that indicates 'binary' + content, then if DWI->force_binary is set, attempt to produce the + diff in the usual way, otherwise produce a 'GIT binary diff' in git mode + or print a warning message in non-git mode. If FORCE_DIFF is TRUE, always write a diff, even for empty diffs. @@ -893,40 +907,17 @@ diff_content_changed(svn_boolean_t *wrot { svn_stream_t *left_stream; svn_stream_t *right_stream; - const char *repos_relpath1; - const char *repos_relpath2; - const char *copyfrom_repos_relpath = NULL; - - SVN_ERR(make_repos_relpath(&repos_relpath1, diff_relpath, - dwi->ddi.orig_path_1, - dwi->ddi.session_relpath, - dwi->wc_ctx, - dwi->ddi.anchor, - scratch_pool, scratch_pool)); - SVN_ERR(make_repos_relpath(&repos_relpath2, diff_relpath, - dwi->ddi.orig_path_2, - dwi->ddi.session_relpath, - dwi->wc_ctx, - dwi->ddi.anchor, - scratch_pool, scratch_pool)); - if (copyfrom_path) - SVN_ERR(make_repos_relpath(©from_repos_relpath, copyfrom_path, - dwi->ddi.orig_path_2, - dwi->ddi.session_relpath, - dwi->wc_ctx, - dwi->ddi.anchor, - scratch_pool, scratch_pool)); - SVN_ERR(print_git_diff_header(outstream, &label1, &label2, + + SVN_ERR(print_git_diff_header(outstream, + &label1, &label2, operation, - repos_relpath1, repos_relpath2, rev1, rev2, - copyfrom_repos_relpath, - copyfrom_rev, - left_props, - right_props, + diff_relpath, + copyfrom_path, copyfrom_rev, + left_props, right_props, index_shas, dwi->header_encoding, - scratch_pool)); + &dwi->ddi, scratch_pool)); SVN_ERR(svn_stream_open_readonly(&left_stream, tmpfile1, scratch_pool, scratch_pool)); @@ -1066,41 +1057,16 @@ diff_content_changed(svn_boolean_t *wrot if (dwi->use_git_diff_format) { - const char *repos_relpath1; - const char *repos_relpath2; - const char *copyfrom_repos_relpath = NULL; - - SVN_ERR(make_repos_relpath(&repos_relpath1, diff_relpath, - dwi->ddi.orig_path_1, - dwi->ddi.session_relpath, - dwi->wc_ctx, - dwi->ddi.anchor, - scratch_pool, scratch_pool)); - SVN_ERR(make_repos_relpath(&repos_relpath2, diff_relpath, - dwi->ddi.orig_path_2, - dwi->ddi.session_relpath, - dwi->wc_ctx, - dwi->ddi.anchor, - scratch_pool, scratch_pool)); - if (copyfrom_path) - SVN_ERR(make_repos_relpath(©from_repos_relpath, - copyfrom_path, - dwi->ddi.orig_path_2, - dwi->ddi.session_relpath, - dwi->wc_ctx, - dwi->ddi.anchor, - scratch_pool, scratch_pool)); - SVN_ERR(print_git_diff_header(outstream, &label1, &label2, + SVN_ERR(print_git_diff_header(outstream, + &label1, &label2, operation, - repos_relpath1, repos_relpath2, rev1, rev2, - copyfrom_repos_relpath, - copyfrom_rev, - left_props, - right_props, + diff_relpath, + copyfrom_path, copyfrom_rev, + left_props, right_props, index_shas, dwi->header_encoding, - scratch_pool)); + &dwi->ddi, scratch_pool)); } /* Output the actual diff */ @@ -1547,11 +1513,22 @@ check_diff_target_exists(const char *url /** Prepare a repos repos diff between PATH_OR_URL1 and * PATH_OR_URL2@PEG_REVISION, in the revision range REVISION1:REVISION2. - * Return URLs and peg revisions in *URL1, *REV1 and in *URL2, *REV2. - * Return suitable anchors in *ANCHOR1 and *ANCHOR2, and targets in - * *TARGET1 and *TARGET2, based on *URL1 and *URL2. - * Indicate the corresponding node kinds in *KIND1 and *KIND2, and verify + * + * Return the resolved URL and peg revision pairs in *URL1, *REV1 and in + * *URL2, *REV2. + * + * Return suitable anchor URL and target pairs in *ANCHOR1, *TARGET1 and + * in *ANCHOR2, *TARGET2, corresponding to *URL1 and *URL2. + * + * (The choice of anchor URLs here appears to be: start with *URL1, *URL2; + * then take the parent dir on both sides, unless either of *URL1 or *URL2 + * is the repository root or the parent dir of *URL1 is unreadable.) + * + * Set *KIND1 and *KIND2 to the node kinds of *URL1 and *URL2, and verify * that at least one of the diff targets exists. + * + * Set *RA_SESSION to an RA session parented at the URL *ANCHOR1. + * * Use client context CTX. Do all allocations in POOL. */ static svn_error_t * diff_prepare_repos_repos(const char **url1, @@ -1823,6 +1800,16 @@ unsupported_diff_error(svn_error_t *chil PATH1 and PATH2 are both working copy paths. REVISION1 and REVISION2 are their respective revisions. + For now, require PATH1=PATH2, REVISION1='base', REVISION2='working', + otherwise return an error. + + Set *ROOT_RELPATH to "" if PATH1 is a WC root, else to basename(PATH1). + Set *ROOT_IS_DIR to TRUE if the working version of PATH1 is + a directory, else to FALSE. + + If DDI is non-null: Set DDI->anchor to the parent of PATH1 if the working + version of PATH1 is a dir, else to PATH1; set DDI->orig_path* to PATH*. + All other options are the same as those passed to svn_client_diff7(). */ static svn_error_t * diff_wc_wc(const char **root_relpath, @@ -1870,6 +1857,9 @@ diff_wc_wc(const char **root_relpath, ddi->anchor = svn_dirent_dirname(path1, scratch_pool); else ddi->anchor = path1; + + ddi->orig_path_1 = path1; + ddi->orig_path_2 = path2; } SVN_ERR(svn_wc__diff7(root_relpath, root_is_dir, @@ -1889,6 +1879,20 @@ diff_wc_wc(const char **root_relpath, and the actual two paths compared are determined by following copy history from PATH_OR_URL2. + If DDI is non-null: Set DDI->orig_path_* to the two diff target URLs as + resolved at the given revisions; set DDI->anchor to an anchor WC path + if either of PATH_OR_URL* is given as a WC path, else to null; set + DDI->session_relpath to the repository-relpath of the anchor URL for + DDI->orig_path_1. + + (The choice of WC anchor implementated here for DDI->anchor appears to + be: choose PATH_OR_URL2 (if it's a WC path) or else PATH_OR_URL1 (if + it's a WC path); then take its parent dir unless both resolved URLs + refer to directories.) + + (For the choice of URL anchor for DDI->session_relpath, see + diff_prepare_repos_repos().) + All other options are the same as those passed to svn_client_diff7(). */ static svn_error_t * diff_repos_repos(const char **root_relpath, @@ -2059,6 +2063,11 @@ diff_repos_repos(const char **root_relpa If REVERSE is TRUE, the diff will be reported in reverse. + If DDI is non-null: Set DDI->orig_path_* to the URLs of the two diff + targets as resolved at the given revisions; set DDI->anchor to a WC path + anchor for PATH2; set DDI->session_relpath to the repository-relpath of + the URL of that same anchor WC path. + All other options are the same as those passed to svn_client_diff7(). */ static svn_error_t * diff_repos_wc(const char **root_relpath, @@ -2405,7 +2414,12 @@ do_diff(const char **root_relpath, SVN_ERR(svn_dirent_get_absolute(&abspath2, path_or_url2, scratch_pool)); - /* ### What about ddi? */ + if (ddi) + { + ddi->orig_path_1 = path_or_url1; + ddi->orig_path_2 = path_or_url2; + } + /* Ignores changelists, ignore_ancestry */ SVN_ERR(svn_client__arbitrary_nodes_diff(root_relpath, root_is_dir, abspath1, abspath2, @@ -2493,6 +2507,72 @@ create_diff_writer_info(diff_writer_info return SVN_NO_ERROR; } +/* Set up *DIFF_PROCESSOR and *DDI for normal and git-style diffs (but not + * summary diffs). + */ +static svn_error_t * +get_diff_processor(svn_diff_tree_processor_t **diff_processor, + struct diff_driver_info_t **ddi, + const apr_array_header_t *options, + const char *relative_to_dir, + svn_boolean_t no_diff_added, + svn_boolean_t no_diff_deleted, + svn_boolean_t show_copies_as_adds, + svn_boolean_t ignore_content_type, + svn_boolean_t ignore_properties, + svn_boolean_t properties_only, + svn_boolean_t use_git_diff_format, + svn_boolean_t pretty_print_mergeinfo, + const char *header_encoding, + svn_stream_t *outstream, + svn_stream_t *errstream, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + diff_writer_info_t *dwi = apr_pcalloc(pool, sizeof(*dwi)); + svn_diff_tree_processor_t *processor; + + /* setup callback and baton */ + + SVN_ERR(create_diff_writer_info(dwi, options, + ctx->config, pool)); + dwi->pool = pool; + dwi->outstream = outstream; + dwi->errstream = errstream; + dwi->header_encoding = header_encoding; + + dwi->force_binary = ignore_content_type; + dwi->ignore_properties = ignore_properties; + dwi->properties_only = properties_only; + dwi->relative_to_dir = relative_to_dir; + dwi->use_git_diff_format = use_git_diff_format; + dwi->no_diff_added = no_diff_added; + dwi->no_diff_deleted = no_diff_deleted; + dwi->show_copies_as_adds = show_copies_as_adds; + dwi->pretty_print_mergeinfo = pretty_print_mergeinfo; + + dwi->cancel_func = ctx->cancel_func; + dwi->cancel_baton = ctx->cancel_baton; + + dwi->ddi.wc_ctx = ctx->wc_ctx; + dwi->ddi.session_relpath = NULL; + dwi->ddi.anchor = NULL; + + processor = svn_diff__tree_processor_create(dwi, pool); + + processor->dir_added = diff_dir_added; + processor->dir_changed = diff_dir_changed; + processor->dir_deleted = diff_dir_deleted; + + processor->file_added = diff_file_added; + processor->file_changed = diff_file_changed; + processor->file_deleted = diff_file_deleted; + + *diff_processor = processor; + *ddi = &dwi->ddi; + return SVN_NO_ERROR; +} + /*----------------------------------------------------------------------- */ /*** Public Interfaces. ***/ @@ -2553,10 +2633,9 @@ svn_client_diff7(const apr_array_header_ svn_client_ctx_t *ctx, apr_pool_t *pool) { - diff_writer_info_t dwi = { 0 }; svn_opt_revision_t peg_revision; - const svn_diff_tree_processor_t *diff_processor; - svn_diff_tree_processor_t *processor; + svn_diff_tree_processor_t *diff_processor; + struct diff_driver_info_t *ddi; if (ignore_properties && properties_only) return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL, @@ -2566,51 +2645,26 @@ svn_client_diff7(const apr_array_header_ /* We will never do a pegged diff from here. */ peg_revision.kind = svn_opt_revision_unspecified; - /* setup callback and baton */ - dwi.ddi.orig_path_1 = path_or_url1; - dwi.ddi.orig_path_2 = path_or_url2; - - SVN_ERR(create_diff_writer_info(&dwi, options, - ctx->config, pool)); - dwi.pool = pool; - dwi.outstream = outstream; - dwi.errstream = errstream; - dwi.header_encoding = header_encoding; - - dwi.force_binary = ignore_content_type; - dwi.ignore_properties = ignore_properties; - dwi.properties_only = properties_only; - dwi.relative_to_dir = relative_to_dir; - dwi.use_git_diff_format = use_git_diff_format; - dwi.no_diff_added = no_diff_added; - dwi.no_diff_deleted = no_diff_deleted; - dwi.show_copies_as_adds = show_copies_as_adds; - dwi.pretty_print_mergeinfo = pretty_print_mergeinfo; - - dwi.cancel_func = ctx->cancel_func; - dwi.cancel_baton = ctx->cancel_baton; - - dwi.wc_ctx = ctx->wc_ctx; - dwi.ddi.session_relpath = NULL; - dwi.ddi.anchor = NULL; - - processor = svn_diff__tree_processor_create(&dwi, pool); - - processor->dir_added = diff_dir_added; - processor->dir_changed = diff_dir_changed; - processor->dir_deleted = diff_dir_deleted; - - processor->file_added = diff_file_added; - processor->file_changed = diff_file_changed; - processor->file_deleted = diff_file_deleted; - - diff_processor = processor; - /* --show-copies-as-adds and --git imply --notice-ancestry */ if (show_copies_as_adds || use_git_diff_format) ignore_ancestry = FALSE; - return svn_error_trace(do_diff(NULL, NULL, &dwi.ddi, + SVN_ERR(get_diff_processor(&diff_processor, &ddi, + options, + relative_to_dir, + no_diff_added, + no_diff_deleted, + show_copies_as_adds, + ignore_content_type, + ignore_properties, + properties_only, + use_git_diff_format, + pretty_print_mergeinfo, + header_encoding, + outstream, errstream, + ctx, pool)); + + return svn_error_trace(do_diff(NULL, NULL, ddi, path_or_url1, path_or_url2, revision1, revision2, &peg_revision, TRUE /* no_peg_revision */, @@ -2643,60 +2697,34 @@ svn_client_diff_peg7(const apr_array_hea svn_client_ctx_t *ctx, apr_pool_t *pool) { - diff_writer_info_t dwi = { 0 }; - const svn_diff_tree_processor_t *diff_processor; - svn_diff_tree_processor_t *processor; + svn_diff_tree_processor_t *diff_processor; + struct diff_driver_info_t *ddi; if (ignore_properties && properties_only) return svn_error_create(SVN_ERR_INCORRECT_PARAMS, NULL, _("Cannot ignore properties and show only " "properties at the same time")); - /* setup callback and baton */ - dwi.ddi.orig_path_1 = path_or_url; - dwi.ddi.orig_path_2 = path_or_url; - - SVN_ERR(create_diff_writer_info(&dwi, options, - ctx->config, pool)); - dwi.pool = pool; - dwi.outstream = outstream; - dwi.errstream = errstream; - dwi.header_encoding = header_encoding; - - dwi.force_binary = ignore_content_type; - dwi.ignore_properties = ignore_properties; - dwi.properties_only = properties_only; - dwi.relative_to_dir = relative_to_dir; - dwi.use_git_diff_format = use_git_diff_format; - dwi.no_diff_added = no_diff_added; - dwi.no_diff_deleted = no_diff_deleted; - dwi.show_copies_as_adds = show_copies_as_adds; - dwi.pretty_print_mergeinfo = pretty_print_mergeinfo; - - dwi.cancel_func = ctx->cancel_func; - dwi.cancel_baton = ctx->cancel_baton; - - dwi.wc_ctx = ctx->wc_ctx; - dwi.ddi.session_relpath = NULL; - dwi.ddi.anchor = NULL; - - processor = svn_diff__tree_processor_create(&dwi, pool); - - processor->dir_added = diff_dir_added; - processor->dir_changed = diff_dir_changed; - processor->dir_deleted = diff_dir_deleted; - - processor->file_added = diff_file_added; - processor->file_changed = diff_file_changed; - processor->file_deleted = diff_file_deleted; - - diff_processor = processor; - /* --show-copies-as-adds and --git imply --notice-ancestry */ if (show_copies_as_adds || use_git_diff_format) ignore_ancestry = FALSE; - return svn_error_trace(do_diff(NULL, NULL, &dwi.ddi, + SVN_ERR(get_diff_processor(&diff_processor, &ddi, + options, + relative_to_dir, + no_diff_added, + no_diff_deleted, + show_copies_as_adds, + ignore_content_type, + ignore_properties, + properties_only, + use_git_diff_format, + pretty_print_mergeinfo, + header_encoding, + outstream, errstream, + ctx, pool)); + + return svn_error_trace(do_diff(NULL, NULL, ddi, path_or_url, path_or_url, start_revision, end_revision, peg_revision, FALSE /* no_peg_revision */, Modified: subversion/branches/shelve-checkpoint/subversion/libsvn_client/export.c URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/libsvn_client/export.c?rev=1829257&r1=1829256&r2=1829257&view=diff ============================================================================== --- subversion/branches/shelve-checkpoint/subversion/libsvn_client/export.c (original) +++ subversion/branches/shelve-checkpoint/subversion/libsvn_client/export.c Mon Apr 16 12:21:02 2018 @@ -453,12 +453,12 @@ export_node(void *baton, * If PATH exists but is a file, then error with SVN_ERR_WC_NOT_WORKING_COPY. * * If PATH is a already a directory, then error with - * SVN_ERR_WC_OBSTRUCTED_UPDATE, unless FORCE, in which case just + * SVN_ERR_WC_OBSTRUCTED_UPDATE, unless OVERWRITE, in which case just * export into PATH with no error. */ static svn_error_t * open_root_internal(const char *path, - svn_boolean_t force, + svn_boolean_t overwrite, svn_wc_notify_func2_t notify_func, void *notify_baton, apr_pool_t *pool) @@ -472,7 +472,7 @@ open_root_internal(const char *path, return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL, _("'%s' exists and is not a directory"), svn_dirent_local_style(path, pool)); - else if ((kind != svn_node_dir) || (! force)) + else if ((kind != svn_node_dir) || (! overwrite)) return svn_error_createf(SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL, _("'%s' already exists"), svn_dirent_local_style(path, pool)); @@ -501,7 +501,7 @@ struct edit_baton const char *repos_root_url; const char *root_path; const char *root_url; - svn_boolean_t force; + svn_boolean_t overwrite; svn_revnum_t *target_revision; apr_hash_t *externals; const char *native_eol; @@ -587,7 +587,7 @@ open_root(void *edit_baton, struct edit_baton *eb = edit_baton; struct dir_baton *db = apr_pcalloc(pool, sizeof(*db)); - SVN_ERR(open_root_internal(eb->root_path, eb->force, + SVN_ERR(open_root_internal(eb->root_path, eb->overwrite, eb->notify_func, eb->notify_baton, pool)); /* Build our dir baton. */ @@ -621,7 +621,7 @@ add_directory(const char *path, return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL, _("'%s' exists and is not a directory"), svn_dirent_local_style(full_path, pool)); - else if (! (kind == svn_node_dir && eb->force)) + else if (! (kind == svn_node_dir && eb->overwrite)) return svn_error_createf(SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL, _("'%s' already exists"), svn_dirent_local_style(full_path, pool)); @@ -1077,7 +1077,7 @@ add_directory_ev2(void *baton, return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL, _("'%s' exists and is not a directory"), svn_dirent_local_style(full_path, scratch_pool)); - else if (! (kind == svn_node_dir && eb->force)) + else if (! (kind == svn_node_dir && eb->overwrite)) return svn_error_createf(SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL, _("'%s' already exists"), svn_dirent_local_style(full_path, scratch_pool)); @@ -1141,7 +1141,7 @@ get_editor_ev2(const svn_delta_editor_t exb, result_pool)); /* Create the root of the export. */ - SVN_ERR(open_root_internal(eb->root_path, eb->force, eb->notify_func, + SVN_ERR(open_root_internal(eb->root_path, eb->overwrite, eb->notify_func, eb->notify_baton, scratch_pool)); return SVN_NO_ERROR; @@ -1153,7 +1153,6 @@ export_file_ev2(const char *from_url, struct edit_baton *eb, svn_client__pathrev_t *loc, svn_ra_session_t *ra_session, - svn_boolean_t overwrite, apr_pool_t *scratch_pool) { apr_hash_t *props; @@ -1177,7 +1176,7 @@ export_file_ev2(const char *from_url, SVN_ERR(svn_io_check_path(to_path, &to_kind, scratch_pool)); if ((to_kind == svn_node_file || to_kind == svn_node_unknown) && - ! overwrite) + ! eb->overwrite) return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, _("Destination file '%s' exists, and " "will not be overwritten unless forced"), @@ -1207,7 +1206,6 @@ export_file(const char *from_url, struct edit_baton *eb, svn_client__pathrev_t *loc, svn_ra_session_t *ra_session, - svn_boolean_t overwrite, apr_pool_t *scratch_pool) { apr_hash_t *props; @@ -1232,7 +1230,7 @@ export_file(const char *from_url, SVN_ERR(svn_io_check_path(to_path, &to_kind, scratch_pool)); if ((to_kind == svn_node_file || to_kind == svn_node_unknown) && - ! overwrite) + ! eb->overwrite) return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, _("Destination file '%s' exists, and " "will not be overwritten unless forced"), @@ -1289,7 +1287,6 @@ export_directory(const char *from_url, struct edit_baton *eb, svn_client__pathrev_t *loc, svn_ra_session_t *ra_session, - svn_boolean_t overwrite, svn_boolean_t ignore_externals, svn_boolean_t ignore_keywords, svn_depth_t depth, @@ -1344,7 +1341,7 @@ export_directory(const char *from_url, SVN_ERR(svn_io_check_path(to_path, &kind, scratch_pool)); if (kind == svn_node_none) SVN_ERR(open_root_internal - (to_path, overwrite, ctx->notify_func2, + (to_path, eb->overwrite, ctx->notify_func2, ctx->notify_baton2, scratch_pool)); if (! ignore_externals && depth == svn_depth_infinity) @@ -1415,7 +1412,7 @@ svn_client_export5(svn_revnum_t *result_ SVN_ERR(svn_ra_get_repos_root2(ra_session, &eb->repos_root_url, pool)); eb->root_path = to_path; eb->root_url = loc->url; - eb->force = overwrite; + eb->overwrite = overwrite; eb->target_revision = &edit_revision; eb->externals = apr_hash_make(pool); eb->native_eol = native_eol; @@ -1431,15 +1428,15 @@ svn_client_export5(svn_revnum_t *result_ { if (!ENABLE_EV2_IMPL) SVN_ERR(export_file(from_url, to_path, eb, loc, ra_session, - overwrite, pool)); + pool)); else SVN_ERR(export_file_ev2(from_url, to_path, eb, loc, - ra_session, overwrite, pool)); + ra_session, pool)); } else if (kind == svn_node_dir) { SVN_ERR(export_directory(from_url, to_path, - eb, loc, ra_session, overwrite, + eb, loc, ra_session, ignore_externals, ignore_keywords, depth, native_eol, ctx, pool)); } Modified: subversion/branches/shelve-checkpoint/subversion/libsvn_client/info.c URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/libsvn_client/info.c?rev=1829257&r1=1829256&r2=1829257&view=diff ============================================================================== --- subversion/branches/shelve-checkpoint/subversion/libsvn_client/info.c (original) +++ subversion/branches/shelve-checkpoint/subversion/libsvn_client/info.c Mon Apr 16 12:21:02 2018 @@ -253,17 +253,17 @@ same_resource_in_head(svn_boolean_t *sam apr_pool_t *pool) { svn_error_t *err; - svn_opt_revision_t start_rev, peg_rev; + svn_opt_revision_t operative_rev, peg_rev; const char *head_url; - start_rev.kind = svn_opt_revision_head; - peg_rev.kind = svn_opt_revision_number; - peg_rev.value.number = rev; + peg_rev.kind = svn_opt_revision_head; + operative_rev.kind = svn_opt_revision_number; + operative_rev.value.number = rev; err = svn_client__repos_locations(&head_url, NULL, NULL, NULL, ra_session, url, &peg_rev, - &start_rev, NULL, + &operative_rev, NULL, ctx, pool); if (err && ((err->apr_err == SVN_ERR_CLIENT_UNRELATED_RESOURCES) || Modified: subversion/branches/shelve-checkpoint/subversion/libsvn_client/patch.c URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/libsvn_client/patch.c?rev=1829257&r1=1829256&r2=1829257&view=diff ============================================================================== --- subversion/branches/shelve-checkpoint/subversion/libsvn_client/patch.c (original) +++ subversion/branches/shelve-checkpoint/subversion/libsvn_client/patch.c Mon Apr 16 12:21:02 2018 @@ -343,7 +343,9 @@ strip_path(const char **result, const ch components = svn_path_decompose(path, scratch_pool); if (strip_count > components->nelts) return svn_error_createf(SVN_ERR_CLIENT_PATCH_BAD_STRIP_COUNT, NULL, - _("Cannot strip %u components from '%s'"), + Q_("Cannot strip %u component from '%s'", + "Cannot strip %u components from '%s'", + strip_count), strip_count, svn_dirent_local_style(path, scratch_pool)); Modified: subversion/branches/shelve-checkpoint/subversion/libsvn_client/shelf.c URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/libsvn_client/shelf.c?rev=1829257&r1=1829256&r2=1829257&view=diff ============================================================================== --- subversion/branches/shelve-checkpoint/subversion/libsvn_client/shelf.c (original) +++ subversion/branches/shelve-checkpoint/subversion/libsvn_client/shelf.c Mon Apr 16 12:21:02 2018 @@ -59,7 +59,7 @@ shelf_name_encode(char **encoded_name_p, while (*name) { - apr_snprintf(out_pos, 3, "%02x", *name++); + apr_snprintf(out_pos, 3, "%02x", (unsigned char)(*name++)); out_pos += 2; } *encoded_name_p = encoded_name; @@ -187,7 +187,9 @@ get_log_abspath(char **log_abspath, return SVN_NO_ERROR; } -/* Set SHELF->revprops by reading from its file storage. +/* Set SHELF->revprops by reading from its storage (the '.log' file). + * Set SHELF->revprops to empty if the storage file does not exist; this + * is not an error. */ static svn_error_t * shelf_read_revprops(svn_client_shelf_t *shelf, @@ -237,10 +239,10 @@ shelf_write_revprops(svn_client_shelf_t } svn_error_t * -svn_client__shelf_revprop_set(svn_client_shelf_t *shelf, - const char *prop_name, - const svn_string_t *prop_val, - apr_pool_t *scratch_pool) +svn_client_shelf_revprop_set(svn_client_shelf_t *shelf, + const char *prop_name, + const svn_string_t *prop_val, + apr_pool_t *scratch_pool) { svn_hash_sets(shelf->revprops, apr_pstrdup(shelf->pool, prop_name), svn_string_dup(prop_val, shelf->pool)); @@ -249,19 +251,32 @@ svn_client__shelf_revprop_set(svn_client } svn_error_t * -svn_client__shelf_revprop_get(svn_string_t **prop_val, - svn_client_shelf_t *shelf, - const char *prop_name, - apr_pool_t *result_pool) +svn_client_shelf_revprop_set_all(svn_client_shelf_t *shelf, + apr_hash_t *revprop_table, + apr_pool_t *scratch_pool) +{ + if (revprop_table) + shelf->revprops = svn_prop_hash_dup(revprop_table, shelf->pool); + else + shelf->revprops = apr_hash_make(shelf->pool); + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_shelf_revprop_get(svn_string_t **prop_val, + svn_client_shelf_t *shelf, + const char *prop_name, + apr_pool_t *result_pool) { *prop_val = svn_hash_gets(shelf->revprops, prop_name); return SVN_NO_ERROR; } svn_error_t * -svn_client__shelf_revprop_list(apr_hash_t **props, - svn_client_shelf_t *shelf, - apr_pool_t *result_pool) +svn_client_shelf_revprop_list(apr_hash_t **props, + svn_client_shelf_t *shelf, + apr_pool_t *result_pool) { *props = shelf->revprops; return SVN_NO_ERROR; @@ -282,7 +297,9 @@ get_current_abspath(char **current_abspa return SVN_NO_ERROR; } -/* */ +/* Read SHELF->max_version from its storage (the '.current' file). + * Set SHELF->max_version to -1 if that file does not exist. + */ static svn_error_t * shelf_read_current(svn_client_shelf_t *shelf, apr_pool_t *scratch_pool) @@ -294,7 +311,7 @@ shelf_read_current(svn_client_shelf_t *s fp = fopen(current_abspath, "r"); if (! fp) { - shelf->max_version = 0; + shelf->max_version = -1; return SVN_NO_ERROR; } fscanf(fp, "%d", &shelf->max_version); @@ -436,7 +453,7 @@ svn_client_shelf_open_existing(svn_clien local_abspath, ctx, result_pool)); SVN_ERR(shelf_read_revprops(*shelf_p, result_pool)); SVN_ERR(shelf_read_current(*shelf_p, result_pool)); - if ((*shelf_p)->max_version <= 0) + if ((*shelf_p)->max_version < 0) { return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, _("Shelf '%s' not found"), @@ -446,16 +463,24 @@ svn_client_shelf_open_existing(svn_clien } svn_error_t * -svn_client_shelf_open(svn_client_shelf_t **shelf_p, - const char *name, - const char *local_abspath, - svn_client_ctx_t *ctx, - apr_pool_t *result_pool) +svn_client_shelf_open_or_create(svn_client_shelf_t **shelf_p, + const char *name, + const char *local_abspath, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool) { - SVN_ERR(shelf_construct(shelf_p, name, + svn_client_shelf_t *shelf; + + SVN_ERR(shelf_construct(&shelf, name, local_abspath, ctx, result_pool)); - SVN_ERR(shelf_read_revprops(*shelf_p, result_pool)); - SVN_ERR(shelf_read_current(*shelf_p, result_pool)); + SVN_ERR(shelf_read_revprops(shelf, result_pool)); + SVN_ERR(shelf_read_current(shelf, result_pool)); + if (shelf->max_version < 0) + { + shelf->max_version = 0; + SVN_ERR(shelf_write_current(shelf, result_pool)); + } + *shelf_p = shelf; return SVN_NO_ERROR; } @@ -567,6 +592,82 @@ svn_client_shelf_paths_changed(apr_hash_ return SVN_NO_ERROR; } +/* A filter to only apply the patch to a particular file. */ +struct patch_filter_baton_t +{ + /* The single path to be selected for patching */ + const char *path; +}; + +static svn_error_t * +patch_filter(void *baton, + svn_boolean_t *filtered, + const char *canon_path_from_patchfile, + const char *patch_abspath, + const char *reject_abspath, + apr_pool_t *scratch_pool) +{ + struct patch_filter_baton_t *fb = baton; + + *filtered = (strcmp(canon_path_from_patchfile, fb->path) != 0); + return SVN_NO_ERROR; +} + +/* Intercept patch notifications to detect when there is a conflict */ +struct patch_notify_baton_t +{ + svn_boolean_t conflict; +}; + +/* Intercept patch notifications to detect when there is a conflict */ +static void +patch_notify(void *baton, + const svn_wc_notify_t *notify, + apr_pool_t *pool) +{ + struct patch_notify_baton_t *nb = baton; + + if (notify->action == svn_wc_notify_patch_rejected_hunk + || notify->action == svn_wc_notify_skip) + nb->conflict = TRUE; +} + +svn_error_t * +svn_client_shelf_test_apply_file(svn_boolean_t *conflict_p, + svn_client_shelf_version_t *shelf_version, + const char *file_relpath, + apr_pool_t *scratch_pool) +{ + svn_client_ctx_t *ctx = shelf_version->shelf->ctx; + svn_wc_notify_func2_t ctx_notify_func; + void *ctx_notify_baton; + struct patch_filter_baton_t fb; + struct patch_notify_baton_t nb; + + fb.path = file_relpath; + + nb.conflict = FALSE; + ctx_notify_func = ctx->notify_func2; + ctx_notify_baton = ctx->notify_baton2; + ctx->notify_func2 = patch_notify; + ctx->notify_baton2 = &nb; + + SVN_ERR(svn_client_patch(shelf_version->patch_abspath, + shelf_version->shelf->wc_root_abspath, + TRUE /*dry_run*/, 0 /*strip*/, + FALSE /*reverse*/, + FALSE /*ignore_whitespace*/, + TRUE /*remove_tempfiles*/, + patch_filter, &fb, + shelf_version->shelf->ctx, scratch_pool)); + + ctx->notify_func2 = ctx_notify_func; + ctx->notify_baton2 = ctx_notify_baton; + + *conflict_p = nb.conflict; + return SVN_NO_ERROR; +} + svn_error_t * svn_client_shelf_apply(svn_client_shelf_version_t *shelf_version, svn_boolean_t dry_run, @@ -607,32 +708,38 @@ svn_client_shelf_unapply(svn_client_shel svn_error_t * svn_client_shelf_set_current_version(svn_client_shelf_t *shelf, - int version, + int version_number, apr_pool_t *scratch_pool) { + svn_client_shelf_version_t *shelf_version; + + SVN_ERR(svn_client_shelf_version_open(&shelf_version, shelf, version_number, + scratch_pool, scratch_pool)); + SVN_ERR(svn_client_shelf_delete_newer_versions(shelf, shelf_version, + scratch_pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_shelf_delete_newer_versions(svn_client_shelf_t *shelf, + svn_client_shelf_version_t *shelf_version, + apr_pool_t *scratch_pool) +{ + int previous_version = shelf_version ? shelf_version->version_number : 0; int i; /* Delete any newer checkpoints */ - for (i = shelf->max_version; i > version; i--) + for (i = shelf->max_version; i > previous_version; i--) { SVN_ERR(shelf_delete_patch_file(shelf, i, scratch_pool)); } - shelf->max_version = version; + shelf->max_version = previous_version; SVN_ERR(shelf_write_current(shelf, scratch_pool)); return SVN_NO_ERROR; } svn_error_t * -svn_client_shelf_get_patch_abspath(const char **patch_abspath, - svn_client_shelf_version_t *shelf_version, - apr_pool_t *scratch_pool) -{ - *patch_abspath = shelf_version->patch_abspath; - return SVN_NO_ERROR; -} - -svn_error_t * svn_client_shelf_export_patch(svn_client_shelf_version_t *shelf_version, svn_stream_t *outstream, apr_pool_t *scratch_pool) @@ -648,11 +755,12 @@ svn_client_shelf_export_patch(svn_client } svn_error_t * -svn_client_shelf_save_new_version(svn_client_shelf_t *shelf, - const apr_array_header_t *paths, - svn_depth_t depth, - const apr_array_header_t *changelists, - apr_pool_t *scratch_pool) +svn_client_shelf_save_new_version2(svn_client_shelf_version_t **new_version_p, + svn_client_shelf_t *shelf, + const apr_array_header_t *paths, + svn_depth_t depth, + const apr_array_header_t *changelists, + apr_pool_t *scratch_pool) { int next_version = shelf->max_version + 1; const char *patch_abspath; @@ -668,18 +776,40 @@ svn_client_shelf_save_new_version(svn_cl SVN_ERR(svn_io_stat(&file_info, patch_abspath, APR_FINFO_MTIME, scratch_pool)); if (file_info.size > 0) { - SVN_ERR(svn_client_shelf_set_current_version(shelf, next_version, - scratch_pool)); + shelf->max_version = next_version; + SVN_ERR(shelf_write_current(shelf, scratch_pool)); + + if (new_version_p) + SVN_ERR(svn_client_shelf_version_open(new_version_p, shelf, next_version, + scratch_pool, scratch_pool)); + } + else + { + if (new_version_p) + *new_version_p = NULL; } return SVN_NO_ERROR; } svn_error_t * +svn_client_shelf_save_new_version(svn_client_shelf_t *shelf, + const apr_array_header_t *paths, + svn_depth_t depth, + const apr_array_header_t *changelists, + apr_pool_t *scratch_pool) +{ + SVN_ERR(svn_client_shelf_save_new_version2(NULL, shelf, + paths, depth, changelists, + scratch_pool)); + return SVN_NO_ERROR; +} + +svn_error_t * svn_client_shelf_get_log_message(char **log_message, svn_client_shelf_t *shelf, apr_pool_t *result_pool) { - svn_string_t *propval = svn_hash_gets(shelf->revprops, "svn:log"); + svn_string_t *propval = svn_hash_gets(shelf->revprops, SVN_PROP_REVISION_LOG); if (propval) *log_message = apr_pstrdup(result_pool, propval->data); @@ -690,39 +820,14 @@ svn_client_shelf_get_log_message(char ** svn_error_t * svn_client_shelf_set_log_message(svn_client_shelf_t *shelf, - apr_hash_t *revprop_table, - svn_boolean_t dry_run, + const char *message, apr_pool_t *scratch_pool) { - svn_client_ctx_t *ctx = shelf->ctx; - const char *message = ""; - - /* Fetch the log message and any other revprops */ - if (SVN_CLIENT__HAS_LOG_MSG_FUNC(ctx)) - { - const char *tmp_file; - apr_array_header_t *commit_items - = apr_array_make(scratch_pool, 1, sizeof(void *)); - - SVN_ERR(svn_client__get_log_msg(&message, &tmp_file, commit_items, - ctx, scratch_pool)); - if (! message) - return SVN_NO_ERROR; - } - - if (revprop_table) - shelf->revprops = svn_prop_hash_dup(revprop_table, shelf->pool); - else - shelf->revprops = apr_hash_make(shelf->pool); - - if (message && !dry_run) - { - svn_string_t *propval = svn_string_create(message, shelf->pool); - - SVN_ERR(svn_client__shelf_revprop_set(shelf, "svn:log", propval, - scratch_pool)); - } + svn_string_t *propval + = message ? svn_string_create(message, shelf->pool) : NULL; + SVN_ERR(svn_client_shelf_revprop_set(shelf, SVN_PROP_REVISION_LOG, propval, + scratch_pool)); return SVN_NO_ERROR; } @@ -771,7 +876,7 @@ svn_client_shelf_list(apr_hash_t **shelf svn_error_t * svn_client_shelf_version_open(svn_client_shelf_version_t **shelf_version_p, svn_client_shelf_t *shelf, - int version, + int version_number, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { @@ -781,7 +886,7 @@ svn_client_shelf_version_open(svn_client shelf_version->shelf = shelf; SVN_ERR(get_existing_patch_abspath(&shelf_version->patch_abspath, - shelf, version, + shelf, version_number, result_pool, scratch_pool)); SVN_ERR(svn_io_stat_dirent2(&dirent, shelf_version->patch_abspath, @@ -789,6 +894,48 @@ svn_client_shelf_version_open(svn_client TRUE /*ignore_enoent*/, result_pool, scratch_pool)); shelf_version->mtime = dirent->mtime; + shelf_version->version_number = version_number; *shelf_version_p = shelf_version; return SVN_NO_ERROR; } + +svn_error_t * +svn_client_shelf_get_newest_version(svn_client_shelf_version_t **shelf_version_p, + svn_client_shelf_t *shelf, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + if (shelf->max_version == 0) + { + *shelf_version_p = NULL; + return SVN_NO_ERROR; + } + + SVN_ERR(svn_client_shelf_version_open(shelf_version_p, + shelf, shelf->max_version, + result_pool, scratch_pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_shelf_get_all_versions(apr_array_header_t **versions_p, + svn_client_shelf_t *shelf, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + int i; + + *versions_p = apr_array_make(result_pool, shelf->max_version - 1, + sizeof(svn_client_shelf_version_t *)); + + for (i = 1; i <= shelf->max_version; i++) + { + svn_client_shelf_version_t *shelf_version; + + SVN_ERR(svn_client_shelf_version_open(&shelf_version, + shelf, i, + result_pool, scratch_pool)); + APR_ARRAY_PUSH(*versions_p, svn_client_shelf_version_t *) = shelf_version; + } + return SVN_NO_ERROR; +} Modified: subversion/branches/shelve-checkpoint/subversion/libsvn_client/update.c URL: http://svn.apache.org/viewvc/subversion/branches/shelve-checkpoint/subversion/libsvn_client/update.c?rev=1829257&r1=1829256&r2=1829257&view=diff ============================================================================== --- subversion/branches/shelve-checkpoint/subversion/libsvn_client/update.c (original) +++ subversion/branches/shelve-checkpoint/subversion/libsvn_client/update.c Mon Apr 16 12:21:02 2018 @@ -567,7 +567,7 @@ svn_client__update_internal(svn_revnum_t { const char *anchor_abspath, *lockroot_abspath; svn_error_t *err; - svn_opt_revision_t peg_revision = *revision; + svn_opt_revision_t opt_rev = *revision; /* operative revision */ apr_hash_t *conflicted_paths = ctx->conflict_func2 ? apr_hash_make(pool) : NULL; @@ -620,7 +620,7 @@ svn_client__update_internal(svn_revnum_t err = update_internal(result_rev, timestamp_sleep, conflicted_paths, &ra_session, missing_parent, - anchor_abspath, &peg_revision, svn_depth_empty, + anchor_abspath, &opt_rev, svn_depth_empty, FALSE, ignore_externals, allow_unver_obstructions, adds_as_modification, FALSE, ctx, pool, iterpool); @@ -631,8 +631,8 @@ svn_client__update_internal(svn_revnum_t /* If we successfully updated a missing parent, let's re-use the returned revision number for future updates for the sake of consistency. */ - peg_revision.kind = svn_opt_revision_number; - peg_revision.value.number = *result_rev; + opt_rev.kind = svn_opt_revision_number; + opt_rev.value.number = *result_rev; } svn_pool_destroy(iterpool); @@ -648,7 +648,7 @@ svn_client__update_internal(svn_revnum_t err = update_internal(result_rev, timestamp_sleep, conflicted_paths, &ra_session, local_abspath, anchor_abspath, - &peg_revision, depth, depth_is_sticky, + &opt_rev, depth, depth_is_sticky, ignore_externals, allow_unver_obstructions, adds_as_modification, TRUE, ctx, pool, pool);