Return-Path: X-Original-To: apmail-subversion-commits-archive@minotaur.apache.org Delivered-To: apmail-subversion-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id E5E53E94F for ; Sun, 23 Dec 2012 18:35:00 +0000 (UTC) Received: (qmail 74827 invoked by uid 500); 23 Dec 2012 18:35:00 -0000 Delivered-To: apmail-subversion-commits-archive@subversion.apache.org Received: (qmail 74784 invoked by uid 500); 23 Dec 2012 18:35:00 -0000 Mailing-List: contact commits-help@subversion.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@subversion.apache.org Delivered-To: mailing list commits@subversion.apache.org Received: (qmail 74776 invoked by uid 99); 23 Dec 2012 18:35:00 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 23 Dec 2012 18:35:00 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 23 Dec 2012 18:34:57 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id E19AE2388AB8; Sun, 23 Dec 2012 18:34:36 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1425508 [4/17] - in /subversion/branches/javahl-ra: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ build/hudson/ notes/ notes/api-errata/1.8/ notes/obliterate/ notes/tree-conflicts/ subversion/ subversion/bindings/s... Date: Sun, 23 Dec 2012 18:34:20 -0000 To: commits@subversion.apache.org From: vmpn@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20121223183436.E19AE2388AB8@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Modified: subversion/branches/javahl-ra/subversion/include/svn_ra_svn.h URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/include/svn_ra_svn.h?rev=1425508&r1=1425507&r2=1425508&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/include/svn_ra_svn.h (original) +++ subversion/branches/javahl-ra/subversion/include/svn_ra_svn.h Sun Dec 23 18:34:14 2012 @@ -62,6 +62,10 @@ extern "C" { #define SVN_RA_SVN_CAP_PARTIAL_REPLAY "partial-replay" /* maps to SVN_RA_CAPABILITY_ATOMIC_REVPROPS */ #define SVN_RA_SVN_CAP_ATOMIC_REVPROPS "atomic-revprops" +/* maps to SVN_RA_CAPABILITY_INHERITED_PROPERTIES: */ +#define SVN_RA_SVN_CAP_INHERITED_PROPS "inherited-props" +/* maps to SVN_RA_CAPABILITY_EPHEMERAL_TXNPROPS */ +#define SVN_RA_SVN_CAP_EPHEMERAL_TXNPROPS "ephemeral-txnprops" /** ra_svn passes @c svn_dirent_t fields over the wire as a list of * words, these are the values used to represent each field. @@ -158,6 +162,64 @@ typedef struct svn_ra_svn_item_t typedef svn_error_t *(*svn_ra_svn_edit_callback)(void *baton); /** + * List of all commands supported by the SVN:// protocol. + * + * @since New in 1.8 + */ +typedef enum svn_ra_svn_cmd_t +{ + svn_ra_svn_cmd_target_rev, + svn_ra_svn_cmd_open_root, + svn_ra_svn_cmd_delete_entry, + svn_ra_svn_cmd_add_dir, + svn_ra_svn_cmd_open_dir, + svn_ra_svn_cmd_change_dir_prop, + svn_ra_svn_cmd_close_dir, + svn_ra_svn_cmd_absent_dir, + svn_ra_svn_cmd_add_file, + svn_ra_svn_cmd_open_file, + svn_ra_svn_cmd_change_file_prop, + svn_ra_svn_cmd_close_file, + svn_ra_svn_cmd_absent_file, + svn_ra_svn_cmd_textdelta_chunk, + svn_ra_svn_cmd_textdelta_end, + svn_ra_svn_cmd_apply_textdelta, + svn_ra_svn_cmd_close_edit, + svn_ra_svn_cmd_abort_edit, + + svn_ra_svn_cmd_set_path, + svn_ra_svn_cmd_delete_path, + svn_ra_svn_cmd_link_path, + svn_ra_svn_cmd_finish_report, + svn_ra_svn_cmd_abort_report, + + svn_ra_svn_cmd_reparent, + svn_ra_svn_cmd_get_latest_rev, + svn_ra_svn_cmd_get_dated_rev, + svn_ra_svn_cmd_change_rev_prop2, + svn_ra_svn_cmd_change_rev_prop, + svn_ra_svn_cmd_rev_proplist, + svn_ra_svn_cmd_rev_prop, + svn_ra_svn_cmd_get_file, + svn_ra_svn_cmd_update, + svn_ra_svn_cmd_switch, + svn_ra_svn_cmd_status, + svn_ra_svn_cmd_diff, + svn_ra_svn_cmd_check_path, + svn_ra_svn_cmd_stat, + svn_ra_svn_cmd_get_file_revs, + svn_ra_svn_cmd_lock, + svn_ra_svn_cmd_unlock, + svn_ra_svn_cmd_get_lock, + svn_ra_svn_cmd_get_locks, + svn_ra_svn_cmd_replay, + svn_ra_svn_cmd_replay_range, + svn_ra_svn_cmd_get_deleted_rev, + + svn_ra_svn_cmd__last +} svn_ra_svn_cmd_t; + +/** * Set the shim callbacks to be used by @a conn to @a shim_callbacks. * * @note This is a private API, external consumers should not use it. @@ -170,10 +232,32 @@ svn_ra_svn__set_shim_callbacks(svn_ra_sv * input/output files. * * Either @a sock or @a in_file/@a out_file must be set, not both. - * Specify the desired network data compression level (zlib) from - * 0 (no compression) to 9 (best but slowest). + * @a compression_level specifies the desired network data compression + * level (zlib) from 0 (no compression) to 9 (best but slowest). + * + * To reduce the overhead of checking for cancellation requests from the + * data receiver, set @a error_check_interval to some non-zero value. + * It defines the number of bytes that must have been sent since the last + * check before the next check will be made. + * + * Allocate the result in @a pool. + * + * @since New in 1.8 + */ +svn_ra_svn_conn_t *svn_ra_svn_create_conn3(apr_socket_t *sock, + apr_file_t *in_file, + apr_file_t *out_file, + int compression_level, + apr_size_t zero_copy_limit, + apr_size_t error_check_interval, + apr_pool_t *pool); + +/** Similar to svn_ra_svn_create_conn3() but disables the zero copy code + * path and sets the error checking interval to 0. * * @since New in 1.7. + * + * @deprecated Provided for backward compatibility with the 1.7 API. */ svn_ra_svn_conn_t * svn_ra_svn_create_conn2(apr_socket_t *sock, @@ -182,7 +266,7 @@ svn_ra_svn_create_conn2(apr_socket_t *so int compression_level, apr_pool_t *pool); -/** Similar to svn_ra_svn_create_conn2() but uses default +/** Similar to svn_ra_svn_create_conn2() but uses the default * compression level (#SVN_DELTA_COMPRESSION_LEVEL_DEFAULT) for network * transmissions. * @@ -219,6 +303,13 @@ svn_ra_svn_has_capability(svn_ra_svn_con int svn_ra_svn_compression_level(svn_ra_svn_conn_t *conn); +/** Return the zero-copy data block limit to use for network transmissions + * + * @since New in 1.8. + */ +apr_size_t +svn_ra_svn_zero_copy_limit(svn_ra_svn_conn_t *conn); + /** Returns the remote address of the connection as a string, if known, * or NULL if inapplicable. */ const char * @@ -448,13 +539,28 @@ svn_ra_svn_handle_commands(svn_ra_svn_co /** Write a command over the network, using the same format string notation * as svn_ra_svn_write_tuple(). + * + * @deprecated Provided for backward compatibility with the 1.7 API. + * Use svn_ra_svn_write_templated_cmd instead. */ +SVN_DEPRECATED svn_error_t * svn_ra_svn_write_cmd(svn_ra_svn_conn_t *conn, apr_pool_t *pool, const char *cmdname, const char *fmt, ...); +/** Write a command of type @a cmd over the network connection @a conn. + * The parameters to be provided are command-specific. @a pool will be + * used for allocations. + * + * @since New in 1.8. + */ +svn_error_t * +svn_ra_svn_write_templated_cmd(svn_ra_svn_conn_t *conn, + apr_pool_t *pool, + svn_ra_svn_cmd_t cmd, ...); + /** Write a successful command response over the network, using the * same format string notation as svn_ra_svn_write_tuple(). Do not use * partial tuples with this function; if you need to use partial Modified: subversion/branches/javahl-ra/subversion/include/svn_repos.h URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/include/svn_repos.h?rev=1425508&r1=1425507&r2=1425508&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/include/svn_repos.h (original) +++ subversion/branches/javahl-ra/subversion/include/svn_repos.h Sun Dec 23 18:34:14 2012 @@ -778,16 +778,25 @@ const char * svn_repos_post_unlock_hook(svn_repos_t *repos, apr_pool_t *pool); -/** Set the environment that @a repos's hooks will inherit to @a hooks_env, - * a hash table where keys and values represent names and values of environment - * variables. @a hooks_env must live at least as long as @a repos. +/** Set the environment that @a repos's hooks will inherit. + * The environment is specified in a file at @a hooks_env_path. + * If @a hooks_env_path is @c NULL, the file is searched at its + * default location in the repository. If @a hooks_env_path is + * not absolute, it specifies a path relative to the parent of + * the file's default location in the repository. * - * If this function is not called, hooks will run in an empty environment. + * The @a result_pool should be the same pool that @a repos was allocated in. + * The @a scratch_pool is used for temporary allocations. + * + * If this function is not called, or if the file does not list any + * environment variables, hooks will run in an empty environment. * * @since New in 1.8. */ -void +svn_error_t * svn_repos_hooks_setenv(svn_repos_t *repos, - apr_hash_t *hooks_env); + const char *hooks_env_path, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); /** @} */ @@ -833,6 +842,13 @@ svn_repos_hooks_setenv(svn_repos_t *repo * avoid sending data through @a editor/@a edit_baton which is not * authorized for transmission. * + * @a zero_copy_limit controls up to which size in bytes data blocks may + * be sent using the zero-copy code path. On that path, a number of + * in-memory copy operations have been eliminated to maximize throughput. + * However, until the whole block has been pushed to the network stack, + * other clients may get blocked. Thus, be careful when using larger + * values here. 0 disables the optimization. + * * All allocation for the context and collected state will occur in * @a pool. * @@ -865,7 +881,33 @@ svn_repos_hooks_setenv(svn_repos_t *repo * than or equal to the depth of the working copy, then the editor * operations will affect only paths at or above @a depth. * + * @since New in 1.8. + */ +svn_error_t * +svn_repos_begin_report3(void **report_baton, + svn_revnum_t revnum, + svn_repos_t *repos, + const char *fs_base, + const char *target, + const char *tgt_path, + svn_boolean_t text_deltas, + svn_depth_t depth, + svn_boolean_t ignore_ancestry, + svn_boolean_t send_copyfrom_args, + const svn_delta_editor_t *editor, + void *edit_baton, + svn_repos_authz_func_t authz_read_func, + void *authz_read_baton, + apr_size_t zero_copy_limit, + apr_pool_t *pool); + +/** + * The same as svn_repos_begin_report3(), but setting the @a zero_copy_limit + * to 0. + * * @since New in 1.5. + * + * @deprecated Provided for backward compatibility with the 1.7 API. */ svn_error_t * svn_repos_begin_report2(void **report_baton, @@ -917,7 +959,7 @@ svn_repos_begin_report(void **report_bat /** - * Given a @a report_baton constructed by svn_repos_begin_report2(), + * Given a @a report_baton constructed by svn_repos_begin_report3(), * record the presence of @a path, at @a revision with depth @a depth, * in the current tree. * @@ -988,7 +1030,7 @@ svn_repos_set_path(void *report_baton, apr_pool_t *pool); /** - * Given a @a report_baton constructed by svn_repos_begin_report2(), + * Given a @a report_baton constructed by svn_repos_begin_report3(), * record the presence of @a path in the current tree, containing the contents * of @a link_path at @a revision with depth @a depth. * @@ -1054,7 +1096,7 @@ svn_repos_link_path(void *report_baton, svn_boolean_t start_empty, apr_pool_t *pool); -/** Given a @a report_baton constructed by svn_repos_begin_report2(), +/** Given a @a report_baton constructed by svn_repos_begin_report3(), * record the non-existence of @a path in the current tree. * * @a path may not be underneath a path on which svn_repos_set_path3() @@ -1070,7 +1112,7 @@ svn_repos_delete_path(void *report_baton const char *path, apr_pool_t *pool); -/** Given a @a report_baton constructed by svn_repos_begin_report2(), +/** Given a @a report_baton constructed by svn_repos_begin_report3(), * finish the report and drive the editor as specified when the report * baton was constructed. * @@ -1087,7 +1129,7 @@ svn_repos_finish_report(void *report_bat apr_pool_t *pool); -/** Given a @a report_baton constructed by svn_repos_begin_report2(), +/** Given a @a report_baton constructed by svn_repos_begin_report3(), * abort the report. This function can be called anytime before * svn_repos_finish_report() is called. * @@ -1161,7 +1203,7 @@ svn_repos_abort_report(void *report_bato * the total size of the delta. * * ### svn_repos_dir_delta2 is mostly superseded by the reporter - * ### functionality (svn_repos_begin_report2 and friends). + * ### functionality (svn_repos_begin_report3 and friends). * ### svn_repos_dir_delta2 does allow the roots to be transaction * ### roots rather than just revision roots, and it has the * ### entry_props flag. Almost all of Subversion's own code uses the @@ -2307,7 +2349,7 @@ svn_repos_fs_change_txn_props(svn_fs_txn * @{ * * As it turns out, the svn_repos_replay2(), svn_repos_dir_delta2() and - * svn_repos_begin_report2() interfaces can be extremely useful for + * svn_repos_begin_report3() interfaces can be extremely useful for * examining the repository, or more exactly, changes to the repository. * These drivers allows for differences between two trees to be * described using an editor. @@ -2360,7 +2402,7 @@ typedef struct svn_repos_node_t * repos's filesystem. * * The editor can also be driven by svn_repos_dir_delta2() or - * svn_repos_begin_report2(), but unless you have special needs, + * svn_repos_begin_report3(), but unless you have special needs, * svn_repos_replay2() is preferred. * * Invoke svn_repos_node_from_baton() on @a edit_baton to obtain the root @@ -3233,6 +3275,31 @@ svn_repos_check_revision_access(svn_repo void *authz_read_baton, apr_pool_t *pool); +/** + * Set @a *inherited_values to a depth-first ordered array of + * #svn_prop_inherited_item_t * structures (the path_or_url members of + * which are relative filesystem paths) representing the properties + * inherited by @a path in @a root. If no properties are inherited, + * then set @a *inherited_values to an empty array. + * + * If optional @a authz_read_func is non-NULL, then use this function + * (along with optional @a authz_read_baton) to check the readability + * of each parent path from which properties are inherited. Silently omit + * properties for unreadable parent paths. + * + * Allocate @a *inherited_props in @a result_pool. Use @a scratch_pool for + * temporary allocations. + * + * @since New in 1.8. + */ +svn_error_t * +svn_repos_fs_get_inherited_props(apr_array_header_t **inherited_props, + svn_fs_root_t *root, + const char *path, + svn_repos_authz_func_t authz_read_func, + void *authz_read_baton, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); /** Capabilities **/ Modified: subversion/branches/javahl-ra/subversion/include/svn_string.h URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/include/svn_string.h?rev=1425508&r1=1425507&r2=1425508&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/include/svn_string.h (original) +++ subversion/branches/javahl-ra/subversion/include/svn_string.h Sun Dec 23 18:34:14 2012 @@ -307,6 +307,45 @@ void svn_stringbuf_appendcstr(svn_stringbuf_t *targetstr, const char *cstr); +/** Read @a count bytes from @a bytes and insert them into @a str at + * position @a pos and following. The resulting string will be + * @c count+str->len bytes long. If @c pos is larger or equal to the + * number of bytes currently used in @a str, simply append @a bytes. + * + * Reallocs if necessary. @a str is affected, nothing else is. + * + * @note The inserted string may be a sub-range if @a str. + */ +void +svn_stringbuf_insert(svn_stringbuf_t *str, + apr_size_t pos, + const char *bytes, + apr_size_t count); + +/** Removes @a count bytes from @a str, starting at position @a pos. + * If that range exceeds the current string data, @a str gets truncated + * at @a pos. If the latter is larger or equal to @c str->pos, this will + * be a no-op. Otherwise, the resulting string will be @c str->len-count + * bytes long. + */ +void +svn_stringbuf_remove(svn_stringbuf_t *str, + apr_size_t pos, + apr_size_t count); + +/** Faster but functionally equivalent to the following sequence: + * @code + * svn_stringbuf_remove(str, pos, old_count); + * svn_stringbuf_insert(str, pos, bytes, new_count); + * @endcode + */ +void +svn_stringbuf_replace(svn_stringbuf_t *str, + apr_size_t pos, + apr_size_t old_count, + const char *bytes, + apr_size_t new_count); + /** Return a duplicate of @a original_string. */ svn_stringbuf_t * svn_stringbuf_dup(const svn_stringbuf_t *original_string, apr_pool_t *pool); Modified: subversion/branches/javahl-ra/subversion/include/svn_types.h URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/include/svn_types.h?rev=1425508&r1=1425507&r2=1425508&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/include/svn_types.h (original) +++ subversion/branches/javahl-ra/subversion/include/svn_types.h Sun Dec 23 18:34:14 2012 @@ -509,7 +509,7 @@ svn_depth_to_word(svn_depth_t depth); svn_depth_t svn_depth_from_word(const char *word); -/* Return #svn_depth_infinity if boolean @a recurse is TRUE, else +/** Return #svn_depth_infinity if boolean @a recurse is TRUE, else * return #svn_depth_files. * * @note New code should never need to use this, it is called only @@ -520,7 +520,7 @@ svn_depth_from_word(const char *word); #define SVN_DEPTH_INFINITY_OR_FILES(recurse) \ ((recurse) ? svn_depth_infinity : svn_depth_files) -/* Return #svn_depth_infinity if boolean @a recurse is TRUE, else +/** Return #svn_depth_infinity if boolean @a recurse is TRUE, else * return #svn_depth_immediates. * * @note New code should never need to use this, it is called only @@ -531,7 +531,7 @@ svn_depth_from_word(const char *word); #define SVN_DEPTH_INFINITY_OR_IMMEDIATES(recurse) \ ((recurse) ? svn_depth_infinity : svn_depth_immediates) -/* Return #svn_depth_infinity if boolean @a recurse is TRUE, else +/** Return #svn_depth_infinity if boolean @a recurse is TRUE, else * return #svn_depth_empty. * * @note New code should never need to use this, it is called only @@ -542,7 +542,7 @@ svn_depth_from_word(const char *word); #define SVN_DEPTH_INFINITY_OR_EMPTY(recurse) \ ((recurse) ? svn_depth_infinity : svn_depth_empty) -/* Return a recursion boolean based on @a depth. +/** Return a recursion boolean based on @a depth. * * Although much code has been converted to use depth, some code still * takes a recurse boolean. In most cases, it makes sense to treat @@ -1261,7 +1261,7 @@ svn_location_segment_dup(const svn_locat */ typedef unsigned long svn_linenum_t; -/* The maximum value of an svn_linenum_t. +/** The maximum value of an svn_linenum_t. * * @since New in 1.7. */ Modified: subversion/branches/javahl-ra/subversion/include/svn_version.h URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/include/svn_version.h?rev=1425508&r1=1425507&r2=1425508&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/include/svn_version.h (original) +++ subversion/branches/javahl-ra/subversion/include/svn_version.h Sun Dec 23 18:34:14 2012 @@ -34,6 +34,7 @@ #ifndef APR_STRINGIFY #include #endif +#include #include "svn_types.h" @@ -256,6 +257,153 @@ const svn_version_t * svn_subr_version(void); +/** + * Extended version infomation, including info about the running system. + * + * @since New in 1.8. + */ +typedef struct svn_version_extended_t svn_version_extended_t; + +/** + * Return version information for the running program. If @a verbose + * is true, collect extra information that may be expensive to + * retrieve (for example, the OS release name, list of shared + * libraries, etc.). Use @a pool for all allocations. + * + * @since New in 1.8. + */ +const svn_version_extended_t * +svn_version_extended(svn_boolean_t verbose, + apr_pool_t *pool); + + +/** + * Accessor for svn_version_extended_t. + * + * @return The date when the libsvn_subr library was compiled, in the + * format defined by the C standard macro @c __DATE__. + * + * @since New in 1.8. + */ +const char * +svn_version_ext_build_date(const svn_version_extended_t *ext_info); + +/** + * Accessor for svn_version_extended_t. + * + * @return The time when the libsvn_subr library was compiled, in the + * format defined by the C standard macro @c __TIME__. + * + * @since New in 1.8. + */ +const char * +svn_version_ext_build_time(const svn_version_extended_t *ext_info); + +/** + * Accessor for svn_version_extended_t. + * + * @return The canonical host triplet (arch-vendor-osname) of the + * system where libsvn_subr was compiled. + * + * @note On Unix-like systems (includng Mac OS X), this string is the + * same as the output of the config.guess script. + * + * @since New in 1.8. + */ +const char * +svn_version_ext_build_host(const svn_version_extended_t *ext_info); + +/** + * Accessor for svn_version_extended_t. + * + * @return The localized copyright notice. + * + * @since New in 1.8. + */ +const char * +svn_version_ext_copyright(const svn_version_extended_t *ext_info); + +/** + * Accessor for svn_version_extended_t. + * + * @return The canonical host triplet (arch-vendor-osname) of the + * system where the current process is running. + * + * @note This string may not be the same as the output of config.guess + * on the same system. + * + * @since New in 1.8. + */ +const char * +svn_version_ext_runtime_host(const svn_version_extended_t *ext_info); + +/** + * Accessor for svn_version_extended_t. + * + * @return The "commercial" release name of the running operating + * system, if available. Not to be confused with, e.g., the output of + * "uname -v" or "uname -r". The returned value may be @c NULL. + * + * @since New in 1.8. + */ +const char * +svn_version_ext_runtime_osname(const svn_version_extended_t *ext_info); + +/** + * Dependent library information. + * Describes the name and versions of known dependencies + * used by libsvn_subr. + * + * @since New in 1.8. + */ +typedef struct svn_version_ext_linked_lib_t +{ + const char *name; /**< Library name */ + const char *compiled_version; /**< Compile-time version string */ + const char *runtime_version; /**< Run-time version string (optional) */ +} svn_version_ext_linked_lib_t; + +/** + * Accessor for svn_version_extended_t. + * + * @return Array of svn_version_ext_linked_lib_t describing dependent + * libraries. The returned value may be @c NULL. + * + * @since New in 1.8. + */ +const apr_array_header_t * +svn_version_ext_linked_libs(const svn_version_extended_t *ext_info); + + +/** + * Loaded shared library information. + * Describes the name and, where available, version of the shared libraries + * loaded by the running program. + * + * @since New in 1.8. + */ +typedef struct svn_version_ext_loaded_lib_t +{ + const char *name; /**< Library name */ + const char *version; /**< Library version (optional) */ +} svn_version_ext_loaded_lib_t; + + +/** + * Accessor for svn_version_extended_t. + * + * @return Array of svn_version_ext_loaded_lib_t describing loaded + * shared libraries. The returned value may be @c NULL. + * + * @note On Mac OS X, the loaded frameworks, private frameworks and + * system libraries will not be listed. + * + * @since New in 1.8. + */ +const apr_array_header_t * +svn_version_ext_loaded_libs(const svn_version_extended_t *ext_info); + + #ifdef __cplusplus } #endif /* __cplusplus */ Modified: subversion/branches/javahl-ra/subversion/include/svn_wc.h URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/include/svn_wc.h?rev=1425508&r1=1425507&r2=1425508&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/include/svn_wc.h (original) +++ subversion/branches/javahl-ra/subversion/include/svn_wc.h Sun Dec 23 18:34:14 2012 @@ -828,7 +828,7 @@ svn_error_t * svn_wc_external_item2_create(svn_wc_external_item2_t **item, apr_pool_t *pool); -/* Same as svn_wc_external_item2_create() except the pointer to the new +/** Same as svn_wc_external_item2_create() except the pointer to the new * empty item is 'const' which is stupid since the next thing you need to do * is fill in its fields. * @@ -1142,7 +1142,7 @@ typedef enum svn_wc_notify_action_t /** The mergeinfo on path was updated. @since New in 1.7. */ svn_wc_notify_merge_record_info, - /** An working copy directory was upgraded to the latest format + /** A working copy directory was upgraded to the latest format. * @since New in 1.7. */ svn_wc_notify_upgraded_path, @@ -1950,7 +1950,7 @@ svn_wc_conflict_description_create_text( * * Set the @c local_abspath field of the created struct to @a local_abspath * (which must be an absolute path), the @c kind field - * to #svn_wc_conflict_kind_prop, the @c node_kind to @a node_kind, and + * to #svn_wc_conflict_kind_property, the @c node_kind to @a node_kind, and * the @c property_name to @a property_name. * * @note: It is the caller's responsibility to set the other required fields @@ -3725,7 +3725,7 @@ typedef struct svn_wc_status3_t * @since New in 1.8. */ const char *moved_to_abspath; - /* TRUE iff the item is a file brought in by an svn:externals definition. + /** TRUE iff the item is a file brought in by an svn:externals definition. * @since New in 1.8. */ svn_boolean_t file_external; @@ -3851,7 +3851,7 @@ typedef struct svn_wc_status2_t /** - * Same as #svn_wc_status2_t, but without the #svn_lock_t 'repos_lock' field. + * Same as #svn_wc_status2_t, but without the #svn_lock_t 'repos_lock', const char 'url', #svn_revnum_t 'ood_last_cmt_rev', apr_time_t 'ood_last_cmt_date', #svn_node_kind_t 'ood_kind', const char 'ood_last_cmt_author', #svn_wc_conflict_description_t 'tree_conflict', #svn_boolean_t 'file_external', #svn_wc_status_kind 'pristine_text_status', and #svn_wc_status_kind 'pristine_prop_status' fields. * * @deprecated Provided for backward compatibility with the 1.1 API. */ @@ -3989,11 +3989,6 @@ svn_wc_status(svn_wc_status_t **status, * * @a scratch_pool will be cleared between invocations to the callback. * - * ### we might be revamping the status infrastructure, and this callback - * ### could totally disappear by the end of 1.7 development. however, we - * ### need to mark the STATUS parameter as "const" so that it is easier - * ### to reason about who/what can modify those structures. - * * @since New in 1.7. */ typedef svn_error_t *(*svn_wc_status_func4_t)(void *baton, @@ -4410,6 +4405,8 @@ svn_wc_copy(const char *src, * Use @a scratch_pool for temporary allocations. * * @since New in 1.7. + * @deprecated Provided for backward compatibility with the 1.7 API. + * @see svn_client_move7() */ svn_error_t * svn_wc_move(svn_wc_context_t *wc_ctx, @@ -7058,7 +7055,7 @@ typedef svn_error_t * (*svn_wc_upgrade_g * (typically #SVN_ERR_CANCELLED), return that error immediately. * * For each directory converted, @a notify_func will be called with - * in @a notify_baton action #svn_wc_notify_upgrade_path and as path + * in @a notify_baton action #svn_wc_notify_upgraded_path and as path * the path of the upgraded directory. @a notify_func may be @c NULL * if this notification is not needed. * @@ -7844,7 +7841,8 @@ svn_wc_set_changelist(const char *path, /** - * The callback type used by svn_client_get_changelists(). + * The callback type used by svn_wc_get_changelists() and + * svn_client_get_changelists(). * * On each invocation, @a path is a newly discovered member of the * changelist, and @a baton is a private function closure. @@ -7857,7 +7855,10 @@ typedef svn_error_t *(*svn_changelist_re apr_pool_t *pool); -/* @since New in 1.7. +/** + * ### TODO: Doc string, please. + * + * @since New in 1.7. */ svn_error_t * svn_wc_get_changelists(svn_wc_context_t *wc_ctx, Modified: subversion/branches/javahl-ra/subversion/include/svn_xml.h URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/include/svn_xml.h?rev=1425508&r1=1425507&r2=1425508&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/include/svn_xml.h (original) +++ subversion/branches/javahl-ra/subversion/include/svn_xml.h Sun Dec 23 18:34:14 2012 @@ -297,7 +297,10 @@ svn_xml_make_header2(svn_stringbuf_t **s const char *encoding, apr_pool_t *pool); -/* Like svn_xml_make_header2, but does not emit encoding information. */ +/** Like svn_xml_make_header2(), but does not emit encoding information. + * + * @deprecated Provided for backward compatibility with the 1.6 API. + */ SVN_DEPRECATED void svn_xml_make_header(svn_stringbuf_t **str, Modified: subversion/branches/javahl-ra/subversion/libsvn_auth_gnome_keyring/gnome_keyring.c URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_auth_gnome_keyring/gnome_keyring.c?rev=1425508&r1=1425507&r2=1425508&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/libsvn_auth_gnome_keyring/gnome_keyring.c (original) +++ subversion/branches/javahl-ra/subversion/libsvn_auth_gnome_keyring/gnome_keyring.c Sun Dec 23 18:34:14 2012 @@ -28,6 +28,7 @@ /*** Includes. ***/ #include +#include #include "svn_auth.h" #include "svn_config.h" #include "svn_error.h" @@ -38,7 +39,6 @@ #include "svn_private_config.h" #include -#include #include @@ -138,9 +138,9 @@ callback_default_keyring(GnomeKeyringRes return; } -/* Returns the default keyring name. */ +/* Returns the default keyring name, allocated in RESULT_POOL. */ static char* -get_default_keyring_name(apr_pool_t *pool) +get_default_keyring_name(apr_pool_t *result_pool) { char *def = NULL; struct gnome_keyring_baton key_info; @@ -159,7 +159,7 @@ get_default_keyring_name(apr_pool_t *poo return NULL; } - def = strdup(key_info.keyring_name); + def = apr_pstrdup(result_pool, key_info.keyring_name); callback_destroy_data_keyring(&key_info); return def; @@ -291,7 +291,6 @@ password_get_gnome_keyring(svn_boolean_t svn_boolean_t non_interactive, apr_pool_t *pool) { - char *default_keyring = NULL; GnomeKeyringResult result; GList *items; @@ -299,8 +298,6 @@ password_get_gnome_keyring(svn_boolean_t SVN_ERR(ensure_gnome_keyring_is_unlocked(non_interactive, parameters, pool)); - default_keyring = get_default_keyring_name(pool); - if (! apr_hash_get(parameters, "gnome-keyring-opening-failed", APR_HASH_KEY_STRING)) @@ -339,8 +336,6 @@ password_get_gnome_keyring(svn_boolean_t ""); } - free(default_keyring); - return SVN_NO_ERROR; } @@ -356,7 +351,6 @@ password_set_gnome_keyring(svn_boolean_t svn_boolean_t non_interactive, apr_pool_t *pool) { - char *default_keyring = NULL; GnomeKeyringResult result; guint32 item_id; @@ -364,8 +358,6 @@ password_set_gnome_keyring(svn_boolean_t SVN_ERR(ensure_gnome_keyring_is_unlocked(non_interactive, parameters, pool)); - default_keyring = get_default_keyring_name(pool); - if (! apr_hash_get(parameters, "gnome-keyring-opening-failed", APR_HASH_KEY_STRING)) @@ -388,8 +380,6 @@ password_set_gnome_keyring(svn_boolean_t ""); } - free(default_keyring); - *done = (result == GNOME_KEYRING_RESULT_OK); return SVN_NO_ERROR; } Modified: subversion/branches/javahl-ra/subversion/libsvn_client/add.c URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/add.c?rev=1425508&r1=1425507&r2=1425508&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/libsvn_client/add.c (original) +++ subversion/branches/javahl-ra/subversion/libsvn_client/add.c Sun Dec 23 18:34:14 2012 @@ -671,6 +671,8 @@ svn_client_add4(const char *path, const char *parent_abspath; const char *local_abspath; const char *existing_parent_abspath; + svn_boolean_t is_wc_root; + svn_error_t *err; if (svn_path_is_url(path)) return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL, @@ -678,20 +680,55 @@ svn_client_add4(const char *path, SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool)); - /* ### this is a hack. - ### before we switched to absolute paths, if a user tried to do - ### 'svn add .', PATH would be "" and PARENT_PATH would also be "", - ### thus emulating the behavior below. Now that we are using - ### absolute paths, svn_dirent_dirname() doesn't behave the same way - ### w.r.t. '.', so we need to include the following hack. This - ### behavior is tested in schedule_tests-11. */ - if (path[0] == 0) - parent_abspath = local_abspath; + /* See if we're being asked to add a wc-root. That's typically not + okay, unless we're in "force" mode. svn_wc__strictly_is_wc_root() + will return TRUE even if LOCAL_ABSPATH is a *symlink* to a working + copy root, which is a scenario we want to treat differently. */ + err = svn_wc__strictly_is_wc_root(&is_wc_root, ctx->wc_ctx, + local_abspath, pool); + if (err) + { + if (err->apr_err != SVN_ERR_WC_PATH_NOT_FOUND + && err->apr_err != SVN_ERR_WC_NOT_WORKING_COPY) + { + return svn_error_trace(err); + } + + svn_error_clear(err); + err = NULL; /* SVN_NO_ERROR */ + is_wc_root = FALSE; + } + if (is_wc_root) + { +#ifdef HAVE_SYMLINK + svn_node_kind_t disk_kind; + svn_boolean_t is_special; + + SVN_ERR(svn_io_check_special_path(local_abspath, &disk_kind, &is_special, + pool)); + + /* A symlink can be an unversioned target and a wcroot. Lets try to add + the symlink, which can't be a wcroot. */ + if (is_special) + is_wc_root = FALSE; + else +#endif + { + if (! force) + return svn_error_createf( + SVN_ERR_ENTRY_EXISTS, NULL, + _("'%s' is already under version control"), + svn_dirent_local_style(local_abspath, pool)); + } + } + + if (is_wc_root) + parent_abspath = local_abspath; /* We will only add children */ else parent_abspath = svn_dirent_dirname(local_abspath, pool); existing_parent_abspath = NULL; - if (add_parents) + if (add_parents && !is_wc_root) { apr_pool_t *subpool; const char *existing_parent_abspath2; @@ -707,8 +744,8 @@ svn_client_add4(const char *path, SVN_WC__CALL_WITH_WRITE_LOCK( add(local_abspath, depth, force, no_ignore, existing_parent_abspath, ctx, pool), - ctx->wc_ctx, - existing_parent_abspath ? existing_parent_abspath : parent_abspath, + ctx->wc_ctx, (existing_parent_abspath ? existing_parent_abspath + : parent_abspath), FALSE /* lock_anchor */, pool); return SVN_NO_ERROR; } Modified: subversion/branches/javahl-ra/subversion/libsvn_client/cat.c URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/cat.c?rev=1425508&r1=1425507&r2=1425508&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/libsvn_client/cat.c (original) +++ subversion/branches/javahl-ra/subversion/libsvn_client/cat.c Sun Dec 23 18:34:14 2012 @@ -62,7 +62,6 @@ svn_client__get_normalized_stream(svn_st svn_string_t *eol_style, *keywords, *special; const char *eol = NULL; svn_boolean_t local_mod = FALSE; - apr_time_t tm; svn_stream_t *input; svn_node_kind_t kind; @@ -118,27 +117,15 @@ svn_client__get_normalized_stream(svn_st if (eol_style) svn_subst_eol_style_from_value(&style, &eol, eol_style->data); - if (local_mod && (! special)) - { - /* Use the modified time from the working copy if - the file */ - SVN_ERR(svn_io_file_affected_time(&tm, local_abspath, scratch_pool)); - } - else - { - SVN_ERR(svn_wc__node_get_changed_info(NULL, &tm, NULL, wc_ctx, - local_abspath, scratch_pool, - scratch_pool)); - } - if (keywords) { svn_revnum_t changed_rev; const char *rev_str; const char *author; const char *url; + apr_time_t tm; - SVN_ERR(svn_wc__node_get_changed_info(&changed_rev, NULL, &author, wc_ctx, + SVN_ERR(svn_wc__node_get_changed_info(&changed_rev, &tm, &author, wc_ctx, local_abspath, scratch_pool, scratch_pool)); SVN_ERR(svn_wc__node_get_url(&url, wc_ctx, local_abspath, scratch_pool, @@ -152,6 +139,13 @@ svn_client__get_normalized_stream(svn_st current user's username */ rev_str = apr_psprintf(scratch_pool, "%ldM", changed_rev); author = _("(local)"); + + if (! special) + { + /* Use the modified time from the working copy for files */ + SVN_ERR(svn_io_file_affected_time(&tm, local_abspath, + scratch_pool)); + } } else { Modified: subversion/branches/javahl-ra/subversion/libsvn_client/cleanup.c URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/cleanup.c?rev=1425508&r1=1425507&r2=1425508&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/libsvn_client/cleanup.c (original) +++ subversion/branches/javahl-ra/subversion/libsvn_client/cleanup.c Sun Dec 23 18:34:14 2012 @@ -144,8 +144,9 @@ svn_client_upgrade(const char *path, upgrade to avoid that errors in the externals causes the wc upgrade to fail. Thanks to caching the performance penalty of walking the wc a second time shouldn't be too severe */ - SVN_ERR(svn_client_propget4(&externals, SVN_PROP_EXTERNALS, local_abspath, - &rev, &rev, NULL, svn_depth_infinity, NULL, ctx, + SVN_ERR(svn_client_propget5(&externals, NULL, SVN_PROP_EXTERNALS, + local_abspath, &rev, &rev, NULL, + svn_depth_infinity, NULL, ctx, scratch_pool, scratch_pool)); iterpool = svn_pool_create(scratch_pool); Modified: subversion/branches/javahl-ra/subversion/libsvn_client/client.h URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/client.h?rev=1425508&r1=1425507&r2=1425508&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/libsvn_client/client.h (original) +++ subversion/branches/javahl-ra/subversion/libsvn_client/client.h Sun Dec 23 18:34:14 2012 @@ -217,40 +217,6 @@ svn_client__get_youngest_common_ancestor apr_pool_t *result_pool, apr_pool_t *scratch_pool); -/* 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, create an RA connection to that object as it exists in - that revision, following copy history if necessary. If REVISION is - younger than PEG_REVISION, then PATH_OR_URL will be checked to see - that it is the same node in both PEG_REVISION and REVISION. If it - is not, then @c SVN_ERR_CLIENT_UNRELATED_RESOURCES is returned. - - BASE_DIR_ABSPATH is the working copy path the ra_session corresponds to, - and should only be used if PATH_OR_URL is a url - ### else NULL? what's it for? - - 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 resulting ra_session in *RA_SESSION_P. Store the final - resolved location of the object in *RESOLVED_LOC_P. RESOLVED_LOC_P - may be NULL if not wanted. - - Use authentication baton cached in CTX to authenticate against the - repository. - - Use POOL for all allocations. */ -svn_error_t * -svn_client__ra_session_from_path2(svn_ra_session_t **ra_session_p, - svn_client__pathrev_t **resolved_loc_p, - const char *path_or_url, - const char *base_dir_abspath, - const svn_opt_revision_t *peg_revision, - const svn_opt_revision_t *revision, - svn_client_ctx_t *ctx, - apr_pool_t *pool); - /* Ensure that RA_SESSION's session URL matches SESSION_URL, reparenting that session if necessary. Store the previous session URL in *OLD_SESSION_URL (so that if the @@ -562,6 +528,34 @@ svn_client__switch_internal(svn_revnum_t /* ---------------------------------------------------------------- */ +/*** Inheritable Properties ***/ + +/* Fetch the inherited properties for the base of LOCAL_ABSPATH as well + as any WC roots under LOCAL_ABSPATH (as limited by DEPTH) using + RA_SESSION. Store the results in *WCROOT_IPROPS, a hash mapping + const char * absolute working copy paths to depth-first ordered arrays + of svn_prop_inherited_item_t * structures. + + If LOCAL_ABSPATH has no base then do nothing. + + RA_SESSION should be an open RA session pointing at the URL of PATH, + or NULL, in which case this function will open its own temporary session. + + Allocate *WCROOT_IPROPS in RESULT_POOL, use SCRATCH_POOL for temporary + allocations. +*/ +svn_error_t * +svn_client__get_inheritable_props(apr_hash_t **wcroot_iprops, + const char *local_abspath, + svn_revnum_t revision, + svn_depth_t depth, + svn_ra_session_t *ra_session, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool); + +/* ---------------------------------------------------------------- */ + /*** Editor for repository diff ***/ /* Create an editor for a pure repository comparison, i.e. comparing one @@ -1033,21 +1027,6 @@ svn_client__get_shim_callbacks(svn_wc_co apr_hash_t *relpath_map, apr_pool_t *result_pool); -/* Return true if KIND is a revision kind that is dependent on the working - * copy. Otherwise, return false. */ -#define SVN_CLIENT__REVKIND_NEEDS_WC(kind) \ - ((kind) == svn_opt_revision_base || \ - (kind) == svn_opt_revision_previous || \ - (kind) == svn_opt_revision_working || \ - (kind) == svn_opt_revision_committed) \ - -/* Return true if KIND is a revision kind that the WC can supply without - * contacting the repository. Otherwise, return false. */ -#define SVN_CLIENT__REVKIND_IS_LOCAL_TO_WC(kind) \ - ((kind) == svn_opt_revision_base || \ - (kind) == svn_opt_revision_working || \ - (kind) == svn_opt_revision_committed) - /* Return REVISION unless its kind is 'unspecified' in which case return * a pointer to a statically allocated revision structure of kind 'head' * if PATH_OR_URL is a URL or 'base' if it is a WC path. */ Modified: subversion/branches/javahl-ra/subversion/libsvn_client/commit.c URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/commit.c?rev=1425508&r1=1425507&r2=1425508&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/libsvn_client/commit.c (original) +++ subversion/branches/javahl-ra/subversion/libsvn_client/commit.c Sun Dec 23 18:34:14 2012 @@ -1770,9 +1770,16 @@ svn_client_commit6(const apr_array_heade cb.info = &commit_info; cb.pool = pool; + /* Get the RA editor from the first lock target, rather than BASE_ABSPATH. + * When committing from multiple WCs, BASE_ABSPATH might be an unrelated + * parent of nested working copies. We don't support commits to multiple + * repositories so using the first WC to get the RA session is safe. */ cmt_err = svn_error_trace( svn_client__open_ra_session_internal(&ra_session, NULL, base_url, - base_abspath, commit_items, + APR_ARRAY_IDX(lock_targets, + 0, + const char *), + commit_items, TRUE, FALSE, ctx, pool)); if (cmt_err) Modified: subversion/branches/javahl-ra/subversion/libsvn_client/commit_util.c URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/commit_util.c?rev=1425508&r1=1425507&r2=1425508&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/libsvn_client/commit_util.c (original) +++ subversion/branches/javahl-ra/subversion/libsvn_client/commit_util.c Sun Dec 23 18:34:14 2012 @@ -482,8 +482,8 @@ harvest_not_present_for_copy(svn_wc_cont svn_pool_clear(iterpool); - SVN_ERR(svn_wc__node_is_status_not_present(¬_present, wc_ctx, - this_abspath, scratch_pool)); + SVN_ERR(svn_wc__node_is_not_present(¬_present, NULL, NULL, wc_ctx, + this_abspath, scratch_pool)); if (!not_present) continue; Modified: subversion/branches/javahl-ra/subversion/libsvn_client/copy.c URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/copy.c?rev=1425508&r1=1425507&r2=1425508&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/libsvn_client/copy.c (original) +++ subversion/branches/javahl-ra/subversion/libsvn_client/copy.c Sun Dec 23 18:34:14 2012 @@ -244,6 +244,7 @@ do_wc_to_wc_moves_with_locks2(svn_client const char *dst_parent_abspath, svn_boolean_t lock_src, svn_boolean_t lock_dst, + svn_boolean_t allow_mixed_revisions, svn_client_ctx_t *ctx, apr_pool_t *scratch_pool) { @@ -252,11 +253,12 @@ do_wc_to_wc_moves_with_locks2(svn_client dst_abspath = svn_dirent_join(dst_parent_abspath, pair->base_name, scratch_pool); - SVN_ERR(svn_wc_move(ctx->wc_ctx, pair->src_abspath_or_url, - dst_abspath, FALSE /* metadata_only */, - ctx->cancel_func, ctx->cancel_baton, - ctx->notify_func2, ctx->notify_baton2, - scratch_pool)); + SVN_ERR(svn_wc__move2(ctx->wc_ctx, pair->src_abspath_or_url, + dst_abspath, FALSE /* metadata_only */, + allow_mixed_revisions, + ctx->cancel_func, ctx->cancel_baton, + ctx->notify_func2, ctx->notify_baton2, + scratch_pool)); return SVN_NO_ERROR; } @@ -267,17 +269,20 @@ do_wc_to_wc_moves_with_locks1(svn_client const char *dst_parent_abspath, svn_boolean_t lock_src, svn_boolean_t lock_dst, + svn_boolean_t allow_mixed_revisions, svn_client_ctx_t *ctx, apr_pool_t *scratch_pool) { if (lock_dst) SVN_WC__CALL_WITH_WRITE_LOCK( do_wc_to_wc_moves_with_locks2(pair, dst_parent_abspath, lock_src, - lock_dst, ctx, scratch_pool), + lock_dst, allow_mixed_revisions, ctx, + scratch_pool), ctx->wc_ctx, dst_parent_abspath, FALSE, scratch_pool); else SVN_ERR(do_wc_to_wc_moves_with_locks2(pair, dst_parent_abspath, lock_src, - lock_dst, ctx, scratch_pool)); + lock_dst, allow_mixed_revisions, + ctx, scratch_pool)); return SVN_NO_ERROR; } @@ -287,6 +292,7 @@ do_wc_to_wc_moves_with_locks1(svn_client static svn_error_t * do_wc_to_wc_moves(const apr_array_header_t *copy_pairs, const char *dst_path, + svn_boolean_t allow_mixed_revisions, svn_client_ctx_t *ctx, apr_pool_t *pool) { @@ -341,13 +347,15 @@ do_wc_to_wc_moves(const apr_array_header if (lock_src) SVN_WC__CALL_WITH_WRITE_LOCK( do_wc_to_wc_moves_with_locks1(pair, pair->dst_parent_abspath, - lock_src, lock_dst, ctx, iterpool), + lock_src, lock_dst, + allow_mixed_revisions, ctx, iterpool), ctx->wc_ctx, src_parent_abspath, FALSE, iterpool); else SVN_ERR(do_wc_to_wc_moves_with_locks1(pair, pair->dst_parent_abspath, - lock_src, lock_dst, ctx, - iterpool)); + lock_src, lock_dst, + allow_mixed_revisions, + ctx, iterpool)); } svn_pool_destroy(iterpool); @@ -389,11 +397,30 @@ verify_wc_srcs_and_dsts(const apr_array_ /* If DST_PATH does not exist, then its basename will become a new file or dir added to its parent (possibly an implicit '.'). Else, just error out. */ - SVN_ERR(svn_io_check_path(pair->dst_abspath_or_url, &dst_kind, - iterpool)); + SVN_ERR(svn_wc_read_kind(&dst_kind, ctx->wc_ctx, + pair->dst_abspath_or_url, TRUE /* show_hidden */, + iterpool)); if (dst_kind != svn_node_none) { - if (is_move + svn_boolean_t is_not_present; + svn_boolean_t is_excluded; + svn_boolean_t is_server_excluded; + + SVN_ERR(svn_wc__node_is_not_present(&is_not_present, &is_excluded, + &is_server_excluded, ctx->wc_ctx, + pair->dst_abspath_or_url, + iterpool)); + + if (is_excluded || is_server_excluded) + { + return svn_error_createf( + SVN_ERR_WC_OBSTRUCTED_UPDATE, + NULL, _("Path '%s' exists, but is excluded"), + svn_dirent_local_style(pair->dst_abspath_or_url, iterpool)); + } + + if ((! is_not_present) + && is_move && copy_pairs->nelts == 1 && strcmp(svn_dirent_dirname(pair->src_abspath_or_url, iterpool), svn_dirent_dirname(pair->dst_abspath_or_url, @@ -432,10 +459,20 @@ verify_wc_srcs_and_dsts(const apr_array_ } } - return svn_error_createf( - SVN_ERR_ENTRY_EXISTS, NULL, - _("Path '%s' already exists"), - svn_dirent_local_style(pair->dst_abspath_or_url, pool)); + if (! is_not_present) + { + svn_boolean_t is_deleted; + + SVN_ERR(svn_wc__node_is_status_deleted(&is_deleted, ctx->wc_ctx, + pair->dst_abspath_or_url, pool)); + + if (! is_deleted) + return svn_error_createf( + SVN_ERR_ENTRY_EXISTS, NULL, + _("Path '%s' already exists"), + svn_dirent_local_style(pair->dst_abspath_or_url, + pool)); + } } svn_dirent_split(&pair->dst_parent_abspath, &pair->base_name, @@ -1613,13 +1650,15 @@ repos_to_wc_copy_locked(const apr_array_ svn_client__copy_pair_t *pair = APR_ARRAY_IDX(copy_pairs, i, svn_client__copy_pair_t *); svn_node_kind_t kind; + svn_boolean_t is_not_present; svn_boolean_t is_excluded; svn_boolean_t is_server_excluded; + svn_boolean_t is_deleted; svn_pool_clear(iterpool); SVN_ERR(svn_wc_read_kind(&kind, ctx->wc_ctx, pair->dst_abspath_or_url, - FALSE, iterpool)); + TRUE /* show_hidden */, iterpool)); if (kind == svn_node_none) continue; @@ -1627,48 +1666,34 @@ repos_to_wc_copy_locked(const apr_array_ ### simplify the conditions? */ /* Hidden by client exclusion */ - SVN_ERR(svn_wc__node_is_status_excluded(&is_excluded, ctx->wc_ctx, - pair->dst_abspath_or_url, - iterpool)); - if (is_excluded) - { - return svn_error_createf - (SVN_ERR_ENTRY_EXISTS, - NULL, _("'%s' is already under version control"), - svn_dirent_local_style(pair->dst_abspath_or_url, iterpool)); - } + SVN_ERR(svn_wc__node_is_not_present(&is_not_present, &is_excluded, + &is_server_excluded, ctx->wc_ctx, + pair->dst_abspath_or_url, + iterpool)); - /* Hidden by server exclusion (not authorized) */ - SVN_ERR(svn_wc__node_is_status_server_excluded(&is_server_excluded, - ctx->wc_ctx, - pair->dst_abspath_or_url, - iterpool)); - if (is_server_excluded) - { - return svn_error_createf - (SVN_ERR_ENTRY_EXISTS, - NULL, _("'%s' is already under version control"), + if (is_not_present) + continue; + + if (is_excluded || is_server_excluded) + { + return svn_error_createf( + SVN_ERR_WC_OBSTRUCTED_UPDATE, + NULL, _("Path '%s' exists, but is excluded"), svn_dirent_local_style(pair->dst_abspath_or_url, iterpool)); } /* Working file missing to something other than being scheduled for addition or in "deleted" state. */ - if (kind != svn_node_dir) - { - svn_boolean_t is_deleted; - svn_boolean_t is_not_present; - SVN_ERR(svn_wc__node_is_status_deleted(&is_deleted, ctx->wc_ctx, - pair->dst_abspath_or_url, - iterpool)); - SVN_ERR(svn_wc__node_is_status_not_present(&is_not_present, - ctx->wc_ctx, - pair->dst_abspath_or_url, - iterpool)); - if ((! is_deleted) && (! is_not_present)) - return svn_error_createf - (SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL, - _("Entry for '%s' exists (though the working file is missing)"), + SVN_ERR(svn_wc__node_is_status_deleted(&is_deleted, ctx->wc_ctx, + pair->dst_abspath_or_url, + iterpool)); + + if (! is_deleted) + { + return svn_error_createf( + SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL, + _("Path '%s' exists, but the working file is missing"), svn_dirent_local_style(pair->dst_abspath_or_url, iterpool)); } } @@ -1856,6 +1881,7 @@ static svn_error_t * try_copy(const apr_array_header_t *sources, const char *dst_path_in, svn_boolean_t is_move, + svn_boolean_t allow_mixed_revisions, svn_boolean_t make_parents, svn_boolean_t ignore_externals, const apr_hash_t *revprop_table, @@ -2145,8 +2171,9 @@ try_copy(const apr_array_header_t *sourc /* Copy or move all targets. */ if (is_move) - return svn_error_trace(do_wc_to_wc_moves(copy_pairs, dst_path_in, ctx, - pool)); + return svn_error_trace(do_wc_to_wc_moves(copy_pairs, dst_path_in, + allow_mixed_revisions, + ctx, pool)); else return svn_error_trace(do_wc_to_wc_copies(copy_pairs, ctx, pool)); } @@ -2195,6 +2222,7 @@ svn_client_copy6(const apr_array_header_ err = try_copy(sources, dst_path, FALSE /* is_move */, + TRUE /* allow_mixed_revisions */, make_parents, ignore_externals, revprop_table, @@ -2226,6 +2254,7 @@ svn_client_copy6(const apr_array_header_ subpool) : svn_dirent_join(dst_path, src_basename, subpool), FALSE /* is_move */, + TRUE /* allow_mixed_revisions */, make_parents, ignore_externals, revprop_table, @@ -2240,10 +2269,11 @@ svn_client_copy6(const apr_array_header_ svn_error_t * -svn_client_move6(const apr_array_header_t *src_paths, +svn_client_move7(const apr_array_header_t *src_paths, const char *dst_path, svn_boolean_t move_as_child, svn_boolean_t make_parents, + svn_boolean_t allow_mixed_revisions, const apr_hash_t *revprop_table, svn_commit_callback2_t commit_callback, void *commit_baton, @@ -2277,6 +2307,7 @@ svn_client_move6(const apr_array_header_ err = try_copy(sources, dst_path, TRUE /* is_move */, + allow_mixed_revisions, make_parents, FALSE, revprop_table, @@ -2307,6 +2338,7 @@ svn_client_move6(const apr_array_header_ src_basename, pool) : svn_dirent_join(dst_path, src_basename, pool), TRUE /* is_move */, + allow_mixed_revisions, make_parents, FALSE, revprop_table, Modified: subversion/branches/javahl-ra/subversion/libsvn_client/ctx.c URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/ctx.c?rev=1425508&r1=1425507&r2=1425508&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/libsvn_client/ctx.c (original) +++ subversion/branches/javahl-ra/subversion/libsvn_client/ctx.c Sun Dec 23 18:34:14 2012 @@ -76,9 +76,12 @@ call_conflict_func(svn_wc_conflict_resul } svn_error_t * -svn_client_create_context(svn_client_ctx_t **ctx, - apr_pool_t *pool) +svn_client_create_context2(svn_client_ctx_t **ctx, + apr_hash_t *cfg_hash, + apr_pool_t *pool) { + svn_config_t *cfg_config; + *ctx = apr_pcalloc(pool, sizeof(svn_client_ctx_t)); (*ctx)->notify_func2 = call_notify_func; @@ -87,8 +90,23 @@ svn_client_create_context(svn_client_ctx (*ctx)->conflict_func2 = call_conflict_func; (*ctx)->conflict_baton2 = *ctx; - SVN_ERR(svn_wc_context_create(&(*ctx)->wc_ctx, NULL /* config */, pool, + (*ctx)->config = cfg_hash; + + if (cfg_hash) + cfg_config = apr_hash_get(cfg_hash, SVN_CONFIG_CATEGORY_CONFIG, + APR_HASH_KEY_STRING); + else + cfg_config = NULL; + + SVN_ERR(svn_wc_context_create(&(*ctx)->wc_ctx, cfg_config, pool, pool)); return SVN_NO_ERROR; } + +svn_error_t * +svn_client_create_context(svn_client_ctx_t **ctx, + apr_pool_t *pool) +{ + return svn_client_create_context2(ctx, NULL, pool); +} Modified: subversion/branches/javahl-ra/subversion/libsvn_client/deprecated.c URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/deprecated.c?rev=1425508&r1=1425507&r2=1425508&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/libsvn_client/deprecated.c (original) +++ subversion/branches/javahl-ra/subversion/libsvn_client/deprecated.c Sun Dec 23 18:34:14 2012 @@ -699,6 +699,25 @@ svn_client_copy(svn_client_commit_info_t } svn_error_t * +svn_client_move6(const apr_array_header_t *src_paths, + const char *dst_path, + svn_boolean_t move_as_child, + svn_boolean_t make_parents, + const apr_hash_t *revprop_table, + svn_commit_callback2_t commit_callback, + void *commit_baton, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + return svn_error_trace(svn_client_move7(src_paths, dst_path, + move_as_child, make_parents, + TRUE, /* allow_mixed_revisions */ + revprop_table, + commit_callback, commit_baton, + ctx, pool)); +} + +svn_error_t * svn_client_move5(svn_commit_info_t **commit_info_p, const apr_array_header_t *src_paths, const char *dst_path, @@ -1712,6 +1731,26 @@ svn_client_revprop_set(const char *propn } svn_error_t * +svn_client_propget4(apr_hash_t **props, + const char *propname, + const char *target, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_revnum_t *actual_revnum, + svn_depth_t depth, + const apr_array_header_t *changelists, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ + return svn_error_trace(svn_client_propget5(props, NULL, propname, target, + peg_revision, revision, + actual_revnum, depth, + changelists, ctx, + result_pool, scratch_pool)); +} + +svn_error_t * svn_client_propget3(apr_hash_t **props, const char *propname, const char *path_or_url, @@ -1851,6 +1890,70 @@ svn_client_proplist_item_dup(const svn_c return new_item; } +/* Baton for use with wrap_proplist_receiver */ +struct proplist_receiver_wrapper_baton { + void *baton; + svn_proplist_receiver_t receiver; +}; + +/* This implements svn_client_proplist_receiver2_t */ +static svn_error_t * +proplist_wrapper_receiver(void *baton, + const char *path, + apr_hash_t *prop_hash, + apr_array_header_t *inherited_props, + apr_pool_t *pool) +{ + struct proplist_receiver_wrapper_baton *plrwb = baton; + + if (plrwb->receiver) + return plrwb->receiver(plrwb->baton, path, prop_hash, pool); + + return SVN_NO_ERROR; +} + +static void +wrap_proplist_receiver(svn_proplist_receiver2_t *receiver2, + void **receiver2_baton, + svn_proplist_receiver_t receiver, + void *receiver_baton, + apr_pool_t *pool) +{ + struct proplist_receiver_wrapper_baton *plrwb = apr_palloc(pool, + sizeof(*plrwb)); + + /* Set the user provided old format callback in the baton. */ + plrwb->baton = receiver_baton; + plrwb->receiver = receiver; + + *receiver2_baton = plrwb; + *receiver2 = proplist_wrapper_receiver; +} + +svn_error_t * +svn_client_proplist3(const char *target, + const svn_opt_revision_t *peg_revision, + const svn_opt_revision_t *revision, + svn_depth_t depth, + const apr_array_header_t *changelists, + svn_proplist_receiver_t receiver, + void *receiver_baton, + svn_client_ctx_t *ctx, + apr_pool_t *pool) +{ + + svn_proplist_receiver2_t receiver2; + void *receiver2_baton; + + wrap_proplist_receiver(&receiver2, &receiver2_baton, receiver, receiver_baton, + pool); + + return svn_error_trace(svn_client_proplist4(target, peg_revision, revision, + depth, changelists, FALSE, + receiver2, receiver2_baton, + ctx, pool, pool)); +} + /* Receiver baton used by proplist2() */ struct proplist_receiver_baton { apr_array_header_t *props; Modified: subversion/branches/javahl-ra/subversion/libsvn_client/diff.c URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/diff.c?rev=1425508&r1=1425507&r2=1425508&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/libsvn_client/diff.c (original) +++ subversion/branches/javahl-ra/subversion/libsvn_client/diff.c Sun Dec 23 18:34:14 2012 @@ -1044,6 +1044,9 @@ diff_content_changed(const char *path, subpool, subpool)); SVN_ERR(svn_stream_copy3(stream, svn_stream_disown(errstream, subpool), NULL, NULL, subpool)); + + /* We have a printed a diff for this path, mark it as visited. */ + mark_path_as_visited(diff_cmd_baton, path); } else /* use libsvn_diff to generate the diff */ { Modified: subversion/branches/javahl-ra/subversion/libsvn_client/externals.c URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/externals.c?rev=1425508&r1=1425507&r2=1425508&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/libsvn_client/externals.c (original) +++ subversion/branches/javahl-ra/subversion/libsvn_client/externals.c Sun Dec 23 18:34:14 2012 @@ -475,12 +475,16 @@ switch_file_external(const char *local_a ### We can't enable this now, because that would move the external ### information into the wrong working copy */ const char *definition_abspath = svn_dirent_dirname(local_abspath,subpool); + apr_array_header_t *inherited_props; /* Open an RA session to 'source' URL */ SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &switch_loc, url, dir_abspath, peg_revision, revision, ctx, subpool)); + /* Get the external file's iprops. */ + SVN_ERR(svn_ra_get_inherited_props(ra_session, &inherited_props, "", + switch_loc->rev, subpool, subpool)); SVN_ERR(svn_ra_reparent(ra_session, svn_uri_dirname(url, subpool), subpool)); @@ -492,6 +496,7 @@ switch_file_external(const char *local_a switch_loc->url, switch_loc->repos_root_url, switch_loc->repos_uuid, + inherited_props, use_commit_times, diff3_cmd, preserved_exts, definition_abspath /* def */, Modified: subversion/branches/javahl-ra/subversion/libsvn_client/merge.c URL: http://svn.apache.org/viewvc/subversion/branches/javahl-ra/subversion/libsvn_client/merge.c?rev=1425508&r1=1425507&r2=1425508&view=diff ============================================================================== --- subversion/branches/javahl-ra/subversion/libsvn_client/merge.c (original) +++ subversion/branches/javahl-ra/subversion/libsvn_client/merge.c Sun Dec 23 18:34:14 2012 @@ -1607,8 +1607,8 @@ merge_file_changed(svn_wc_notify_state_t way svn_wc_merge5() can do the merge. */ if (wc_kind != svn_node_file || is_deleted) { - const char *moved_to_abspath; - svn_error_t *err; + svn_boolean_t moved_away; + svn_wc_conflict_reason_t reason; /* Maybe the node is excluded via depth filtering? */ @@ -1638,44 +1638,23 @@ merge_file_changed(svn_wc_notify_state_t /* This is use case 4 described in the paper attached to issue * #2282. See also notes/tree-conflicts/detection.txt */ - err = svn_wc__node_was_moved_away(&moved_to_abspath, NULL, - ctx->wc_ctx, local_abspath, - scratch_pool, scratch_pool); - if (err) - { - if (err->apr_err == SVN_ERR_WC_PATH_NOT_FOUND) - { - svn_error_clear(err); - moved_to_abspath = NULL; - } - else - return svn_error_trace(err); - } - - if (moved_to_abspath) - { - /* File has been moved away locally -- apply incoming - * changes at the new location. */ - local_abspath = moved_to_abspath; - } + SVN_ERR(check_moved_away(&moved_away, ctx->wc_ctx, + local_abspath, scratch_pool)); + if (moved_away) + reason = svn_wc_conflict_reason_moved_away; + else if (is_deleted) + reason = svn_wc_conflict_reason_deleted; else - { - svn_wc_conflict_reason_t reason; - - if (is_deleted) - reason = svn_wc_conflict_reason_deleted; - else - reason = svn_wc_conflict_reason_missing; - SVN_ERR(tree_conflict(merge_b, local_abspath, svn_node_file, - svn_wc_conflict_action_edit, reason)); - if (tree_conflicted) - *tree_conflicted = TRUE; - if (content_state) - *content_state = svn_wc_notify_state_missing; - if (prop_state) - *prop_state = svn_wc_notify_state_missing; - return SVN_NO_ERROR; - } + reason = svn_wc_conflict_reason_missing; + SVN_ERR(tree_conflict(merge_b, local_abspath, svn_node_file, + svn_wc_conflict_action_edit, reason)); + if (tree_conflicted) + *tree_conflicted = TRUE; + if (content_state) + *content_state = svn_wc_notify_state_missing; + if (prop_state) + *prop_state = svn_wc_notify_state_missing; + return SVN_NO_ERROR; } /* ### TODO: Thwart attempts to merge into a path that has @@ -1904,7 +1883,7 @@ merge_file_added(svn_wc_notify_state_t * svn_revnum_t copyfrom_rev; svn_stream_t *new_contents, *new_base_contents; apr_hash_t *new_base_props, *new_props; - const svn_wc_conflict_description2_t *existing_conflict; + svn_boolean_t existing_tree_conflict; svn_error_t *err; /* If this is a merge from the same repository as our @@ -1941,10 +1920,9 @@ merge_file_added(svn_wc_notify_state_t * scratch_pool, scratch_pool)); } - err = svn_wc__get_tree_conflict(&existing_conflict, - merge_b->ctx->wc_ctx, - mine_abspath, merge_b->pool, - merge_b->pool); + err = svn_wc_conflicted_p3(NULL, NULL, &existing_tree_conflict, + merge_b->ctx->wc_ctx, mine_abspath, + merge_b->pool); if (err) { @@ -1952,10 +1930,10 @@ merge_file_added(svn_wc_notify_state_t * return svn_error_trace(err); svn_error_clear(err); - existing_conflict = FALSE; + existing_tree_conflict = FALSE; } - if (existing_conflict) + if (existing_tree_conflict) { svn_boolean_t moved_here; svn_wc_conflict_reason_t reason; @@ -5754,10 +5732,10 @@ get_wc_explicit_mergeinfo_catalog(apr_ha apr_pool_t *iterpool = svn_pool_create(scratch_pool); apr_hash_index_t *hi; - SVN_ERR(svn_client_propget4(subtrees_with_mergeinfo, SVN_PROP_MERGEINFO, - target_abspath, &working_revision, - &working_revision, NULL, depth, NULL, - ctx, result_pool, scratch_pool)); + SVN_ERR(svn_client_propget5(subtrees_with_mergeinfo, NULL, + SVN_PROP_MERGEINFO, target_abspath, + &working_revision, &working_revision, NULL, + depth, NULL, ctx, result_pool, scratch_pool)); /* Convert property values to svn_mergeinfo_t. */ for (hi = apr_hash_first(scratch_pool, *subtrees_with_mergeinfo); @@ -11159,57 +11137,6 @@ typedef struct source_and_target_t svn_client__pathrev_t *yca; } source_and_target_t; -/* "Open" the source and target branches of a merge. That means: - * - find out their exact repository locations (resolve WC paths and - * non-numeric revision numbers), - * - check the branches are suitably related, - * - establish RA session(s) to the repo, - * - check the WC for suitability (throw an error if unsuitable) - * - * Record this information and return it in a new "merge context" object. - */ -static svn_error_t * -open_source_and_target(source_and_target_t **source_and_target, - const char *source_path_or_url, - const svn_opt_revision_t *source_peg_revision, - const char *target_abspath, - svn_boolean_t allow_mixed_rev, - svn_boolean_t allow_local_mods, - svn_boolean_t allow_switched_subtrees, - svn_client_ctx_t *ctx, - apr_pool_t *session_pool, - apr_pool_t *result_pool, - apr_pool_t *scratch_pool) -{ - source_and_target_t *s_t = apr_palloc(result_pool, sizeof(*s_t)); - - /* Target */ - SVN_ERR(open_target_wc(&s_t->target, target_abspath, - allow_mixed_rev, allow_local_mods, allow_switched_subtrees, - ctx, result_pool, scratch_pool)); - SVN_ERR(svn_client_open_ra_session(&s_t->target_ra_session, - s_t->target->loc.url, - ctx, session_pool)); - - /* Source */ - SVN_ERR(svn_client__ra_session_from_path2( - &s_t->source_ra_session, &s_t->source, - source_path_or_url, NULL, source_peg_revision, source_peg_revision, - ctx, result_pool)); - - *source_and_target = s_t; - return SVN_NO_ERROR; -} - -/* "Close" any resources that were acquired in the S_T structure. */ -static svn_error_t * -close_source_and_target(source_and_target_t *s_t, - apr_pool_t *scratch_pool) -{ - /* close s_t->source_/target_ra_session */ - return SVN_NO_ERROR; -} - /* Set *INTERSECTION_P to the intersection of BRANCH_HISTORY with the * revision range OLDEST_REV to YOUNGEST_REV (inclusive). * @@ -11474,7 +11401,7 @@ find_base_on_target(svn_client__pathrev_ return SVN_NO_ERROR; } -/* The body of svn_client__find_symmetric_merge(), which see. +/* The body of svn_client_find_symmetric_merge(), which see. */ static svn_error_t * find_symmetric_merge(svn_client__pathrev_t **base_p, @@ -11494,14 +11421,23 @@ find_symmetric_merge(svn_client__pathrev svn_mergeinfo_inherited, FALSE /* squelch_incapable */, scratch_pool)); - SVN_ERR(svn_client__get_wc_or_repos_mergeinfo(&s_t->target_mergeinfo, - NULL /* inherited */, - NULL /* from_repos */, - FALSE /* repos_only */, - svn_mergeinfo_inherited, - s_t->target_ra_session, - s_t->target->abspath, - ctx, scratch_pool)); + if (! s_t->target->abspath) + SVN_ERR(svn_client__get_repos_mergeinfo(&s_t->target_mergeinfo, + s_t->target_ra_session, + s_t->target->loc.url, + s_t->target->loc.rev, + svn_mergeinfo_inherited, + FALSE /* squelch_incapable */, + scratch_pool)); + else + SVN_ERR(svn_client__get_wc_or_repos_mergeinfo(&s_t->target_mergeinfo, + NULL /* inherited */, + NULL /* from_repos */, + FALSE /* repos_only */, + svn_mergeinfo_inherited, + s_t->target_ra_session, + s_t->target->abspath, + ctx, scratch_pool)); /* Get the location-history of each branch. */ s_t->source_branch.tip = s_t->source; @@ -11545,35 +11481,92 @@ find_symmetric_merge(svn_client__pathrev return SVN_NO_ERROR; } +/* Details of a symmetric merge. */ +struct svn_client_symmetric_merge_t +{ + svn_client__pathrev_t *yca, *base, *mid, *right, *target; + svn_boolean_t allow_mixed_rev, allow_local_mods, allow_switched_subtrees; +}; + svn_error_t * -svn_client__find_symmetric_merge(svn_client__symmetric_merge_t **merge_p, +svn_client_find_symmetric_merge_no_wc( + svn_client_symmetric_merge_t **merge_p, const char *source_path_or_url, const svn_opt_revision_t *source_revision, - const char *target_wcpath, - svn_boolean_t allow_mixed_rev, - svn_boolean_t allow_local_mods, - svn_boolean_t allow_switched_subtrees, + const char *target_path_or_url, + const svn_opt_revision_t *target_revision, svn_client_ctx_t *ctx, apr_pool_t *result_pool, apr_pool_t *scratch_pool) { + source_and_target_t *s_t = apr_palloc(scratch_pool, sizeof(*s_t)); + svn_client__pathrev_t *target_loc; + svn_client_symmetric_merge_t *merge = apr_palloc(result_pool, sizeof(*merge)); + + /* Source */ + SVN_ERR(svn_client__ra_session_from_path2( + &s_t->source_ra_session, &s_t->source, + source_path_or_url, NULL, source_revision, source_revision, + ctx, result_pool)); + + /* Target */ + SVN_ERR(svn_client__ra_session_from_path2( + &s_t->target_ra_session, &target_loc, + target_path_or_url, NULL, target_revision, target_revision, + ctx, result_pool)); + s_t->target = apr_palloc(scratch_pool, sizeof(*s_t->target)); + s_t->target->kind = svn_node_none; + s_t->target->abspath = NULL; /* indicate the target is not a WC */ + s_t->target->loc = *target_loc; + + SVN_ERR(find_symmetric_merge(&merge->base, &merge->mid, s_t, + ctx, result_pool, scratch_pool)); + + merge->right = s_t->source; + merge->target = &s_t->target->loc; + merge->yca = s_t->yca; + *merge_p = merge; + + return SVN_NO_ERROR; +} + +svn_error_t * +svn_client_find_symmetric_merge(svn_client_symmetric_merge_t **merge_p, + const char *source_path_or_url, + const svn_opt_revision_t *source_revision, + const char *target_wcpath, + svn_boolean_t allow_mixed_rev, + svn_boolean_t allow_local_mods, + svn_boolean_t allow_switched_subtrees, + svn_client_ctx_t *ctx, + apr_pool_t *result_pool, + apr_pool_t *scratch_pool) +{ const char *target_abspath; - source_and_target_t *s_t; - svn_client__symmetric_merge_t *merge = apr_palloc(result_pool, sizeof(*merge)); + source_and_target_t *s_t = apr_palloc(result_pool, sizeof(*s_t)); + svn_client_symmetric_merge_t *merge = apr_palloc(result_pool, sizeof(*merge)); SVN_ERR(svn_dirent_get_absolute(&target_abspath, target_wcpath, scratch_pool)); - /* Open RA sessions to the source and target trees. We're not going - * to check the target WC for mixed-rev, local mods or switched - * subtrees yet. After we find out what kind of merge is required, - * then if a reintegrate-like merge is required we'll do the stricter - * checks, in do_symmetric_merge_locked(). */ - SVN_ERR(open_source_and_target(&s_t, source_path_or_url, source_revision, - target_abspath, - TRUE /*allow_mixed_rev*/, - TRUE /*allow_local_mods*/, - TRUE /*allow_switched_subtrees*/, - ctx, result_pool, result_pool, scratch_pool)); + /* "Open" the target WC. We're not going to check the target WC for + * mixed-rev, local mods or switched subtrees yet. After we find out + * what kind of merge is required, then if a reintegrate-like merge is + * required we'll do the stricter checks, in do_symmetric_merge_locked(). */ + SVN_ERR(open_target_wc(&s_t->target, target_abspath, + TRUE /*allow_mixed_rev*/, + TRUE /*allow_local_mods*/, + TRUE /*allow_switched_subtrees*/, + ctx, result_pool, scratch_pool)); + + /* Open RA sessions to the source and target trees. */ + SVN_ERR(svn_client_open_ra_session(&s_t->target_ra_session, + s_t->target->loc.url, + ctx, result_pool)); + /* ### check for null URL (i.e. added path) here, like in reintegrate? */ + SVN_ERR(svn_client__ra_session_from_path2( + &s_t->source_ra_session, &s_t->source, + source_path_or_url, NULL, source_revision, source_revision, + ctx, result_pool)); /* Check source is in same repos as target. */ SVN_ERR(check_same_repos(s_t->source, source_path_or_url, @@ -11590,12 +11583,12 @@ svn_client__find_symmetric_merge(svn_cli *merge_p = merge; - SVN_ERR(close_source_and_target(s_t, scratch_pool)); + /* TODO: Close the source and target sessions here? */ return SVN_NO_ERROR; } -/* The body of svn_client__do_symmetric_merge(), which see. +/* The body of svn_client_do_symmetric_merge(), which see. * * Five locations are inputs: YCA, BASE, MID, RIGHT, TARGET, as shown * depending on whether the base is on the source branch or the target @@ -11623,7 +11616,7 @@ svn_client__find_symmetric_merge(svn_cli * eliminate already-cherry-picked revisions from the source. */ static svn_error_t * -do_symmetric_merge_locked(const svn_client__symmetric_merge_t *merge, +do_symmetric_merge_locked(const svn_client_symmetric_merge_t *merge, const char *target_abspath, svn_depth_t depth, svn_boolean_t force, @@ -11742,15 +11735,15 @@ do_symmetric_merge_locked(const svn_clie } svn_error_t * -svn_client__do_symmetric_merge(const svn_client__symmetric_merge_t *merge, - const char *target_wcpath, - svn_depth_t depth, - svn_boolean_t force, - svn_boolean_t record_only, - svn_boolean_t dry_run, - const apr_array_header_t *merge_options, - svn_client_ctx_t *ctx, - apr_pool_t *pool) +svn_client_do_symmetric_merge(const svn_client_symmetric_merge_t *merge, + const char *target_wcpath, + svn_depth_t depth, + svn_boolean_t force, + svn_boolean_t record_only, + svn_boolean_t dry_run, + const apr_array_header_t *merge_options, + svn_client_ctx_t *ctx, + apr_pool_t *pool) { const char *target_abspath, *lock_abspath; @@ -11772,3 +11765,30 @@ svn_client__do_symmetric_merge(const svn return SVN_NO_ERROR; } + +svn_boolean_t +svn_client_symmetric_merge_is_reintegrate_like( + const svn_client_symmetric_merge_t *merge) +{ + return merge->mid != NULL; +} + +svn_error_t * +svn_client__symmetric_merge_get_locations( + svn_client__pathrev_t **yca, + svn_client__pathrev_t **base, + svn_client__pathrev_t **right, + svn_client__pathrev_t **target, + const svn_client_symmetric_merge_t *merge, + apr_pool_t *result_pool) +{ + if (yca) + *yca = svn_client__pathrev_dup(merge->yca, result_pool); + if (base) + *base = svn_client__pathrev_dup(merge->base, result_pool); + if (right) + *right = svn_client__pathrev_dup(merge->right, result_pool); + if (target) + *target = svn_client__pathrev_dup(merge->target, result_pool); + return SVN_NO_ERROR; +}