Author: julianfoad
Date: Mon Jun 29 13:42:10 2015
New Revision: 1688213
URL: http://svn.apache.org/r1688213
Log:
On the 'move-tracking-2' branch: Catch up to trunk@1688211.
Modified:
subversion/branches/move-tracking-2/ (props changed)
subversion/branches/move-tracking-2/build/ (props changed)
subversion/branches/move-tracking-2/build/ac-macros/apache.m4
subversion/branches/move-tracking-2/subversion/ (props changed)
subversion/branches/move-tracking-2/subversion/bindings/javahl/native/SVNRepos.cpp
subversion/branches/move-tracking-2/subversion/bindings/javahl/native/SVNRepos.h
subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNRepos.cpp
subversion/branches/move-tracking-2/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRepos.java
subversion/branches/move-tracking-2/subversion/bindings/javahl/src/org/apache/subversion/javahl/ReposNotifyInformation.java
subversion/branches/move-tracking-2/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNRepos.java
subversion/branches/move-tracking-2/subversion/include/private/svn_wc_private.h
subversion/branches/move-tracking-2/subversion/include/svn_client.h
subversion/branches/move-tracking-2/subversion/include/svn_error_codes.h
subversion/branches/move-tracking-2/subversion/include/svn_repos.h
subversion/branches/move-tracking-2/subversion/libsvn_client/resolved.c
subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs.c
subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs.h
subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs_fs.c
subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs_fs.h
subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/hotcopy.c
subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/hotcopy.h
subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/pack.c
subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/transaction.c
subversion/branches/move-tracking-2/subversion/libsvn_repos/deprecated.c
subversion/branches/move-tracking-2/subversion/libsvn_repos/dump.c
subversion/branches/move-tracking-2/subversion/libsvn_repos/rev_hunt.c
subversion/branches/move-tracking-2/subversion/libsvn_subr/cache-membuffer.c
subversion/branches/move-tracking-2/subversion/libsvn_subr/config.c
subversion/branches/move-tracking-2/subversion/libsvn_subr/io.c
subversion/branches/move-tracking-2/subversion/libsvn_wc/conflicts.c
subversion/branches/move-tracking-2/subversion/mod_dav_svn/util.c
subversion/branches/move-tracking-2/subversion/svn/cl-conflicts.c
subversion/branches/move-tracking-2/subversion/svn/cl-conflicts.h
subversion/branches/move-tracking-2/subversion/svn/cl.h
subversion/branches/move-tracking-2/subversion/svn/conflict-callbacks.c
subversion/branches/move-tracking-2/subversion/svn/info-cmd.c
subversion/branches/move-tracking-2/subversion/svn/status.c
subversion/branches/move-tracking-2/subversion/svn/util.c
subversion/branches/move-tracking-2/subversion/svnadmin/svnadmin.c
subversion/branches/move-tracking-2/subversion/tests/cmdline/merge_tree_conflict_tests.py
subversion/branches/move-tracking-2/subversion/tests/cmdline/mergeinfo_tests.py
subversion/branches/move-tracking-2/subversion/tests/cmdline/move_tests.py
subversion/branches/move-tracking-2/subversion/tests/cmdline/prop_tests.py
subversion/branches/move-tracking-2/subversion/tests/cmdline/svnadmin_tests.py
subversion/branches/move-tracking-2/subversion/tests/cmdline/svntest/main.py
subversion/branches/move-tracking-2/subversion/tests/cmdline/update_tests.py
subversion/branches/move-tracking-2/subversion/tests/libsvn_client/mtcc-test.c
subversion/branches/move-tracking-2/subversion/tests/libsvn_fs_fs/fs-fs-fuzzy-test.c
subversion/branches/move-tracking-2/subversion/tests/libsvn_fs_fs/fs-fs-private-test.c
subversion/branches/move-tracking-2/subversion/tests/libsvn_subr/config-test.c
subversion/branches/move-tracking-2/subversion/tests/libsvn_subr/config-test.cfg
Propchange: subversion/branches/move-tracking-2/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Jun 29 13:42:10 2015
@@ -90,4 +90,4 @@
/subversion/branches/verify-at-commit:1462039-1462408
/subversion/branches/verify-keep-going:1439280-1546110
/subversion/branches/wc-collate-path:1402685-1480384
-/subversion/trunk:1606692-1686493
+/subversion/trunk:1606692-1688211
Propchange: subversion/branches/move-tracking-2/build/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Jun 29 13:42:10 2015
@@ -82,4 +82,4 @@
/subversion/branches/verify-at-commit/build:1462039-1462408
/subversion/branches/verify-keep-going/build:1439280-1546110
/subversion/branches/wc-collate-path/build:1402685-1480384
-/subversion/trunk/build:1606692-1677758
+/subversion/trunk/build:1606692-1688211
Modified: subversion/branches/move-tracking-2/build/ac-macros/apache.m4
URL:
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/build/ac-macros/apache.m4?rev=1688213&r1=1688212&r2=1688213&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/build/ac-macros/apache.m4 (original)
+++ subversion/branches/move-tracking-2/build/ac-macros/apache.m4 Mon Jun 29
13:42:10 2015
@@ -166,7 +166,7 @@ if test -n "$APXS" && test "$APXS" != "n
if ! test -e $HTTPD ; then
HTTPD="`$APXS -q bindir`/`$APXS -q PROGNAME`"
fi
- HTTPD_VERSION=["`$HTTPD -v | $SED -e 's@^.*/\([0-9.]*\)\(.*$\)@\1@ ; 1q'`"]
+ HTTPD_VERSION=["`$HTTPD -v | $SED -e 's/^.*\/\([0-9.]*\).*$/\1/' -e 1q`"]
case $host in
*-*-cygwin*)
Propchange: subversion/branches/move-tracking-2/subversion/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Jun 29 13:42:10 2015
@@ -82,4 +82,4 @@
/subversion/branches/verify-at-commit/subversion:1462039-1462408
/subversion/branches/verify-keep-going/subversion:1439280-1546110
/subversion/branches/wc-collate-path/subversion:1402685-1480384
-/subversion/trunk/subversion:1606692-1686493
+/subversion/trunk/subversion:1606692-1688211
Modified:
subversion/branches/move-tracking-2/subversion/bindings/javahl/native/SVNRepos.cpp
URL:
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/bindings/javahl/native/SVNRepos.cpp?rev=1688213&r1=1688212&r2=1688213&view=diff
==============================================================================
---
subversion/branches/move-tracking-2/subversion/bindings/javahl/native/SVNRepos.cpp
(original)
+++
subversion/branches/move-tracking-2/subversion/bindings/javahl/native/SVNRepos.cpp
Mon Jun 29 13:42:10 2015
@@ -594,7 +594,7 @@ SVNRepos::getRevnum(svn_revnum_t *revnum
void
SVNRepos::verify(File &path, Revision &revisionStart, Revision &revisionEnd,
- bool keepGoing, bool checkNormalization, bool metadataOnly,
+ bool checkNormalization, bool metadataOnly,
ReposNotifyCallback *notifyCallback)
{
SVN::Pool requestPool;
@@ -639,13 +639,13 @@ SVNRepos::verify(File &path, Revision &r
_("Start revision cannot be higher than end revision")), );
SVN_JNI_ERR(svn_repos_verify_fs3(repos, lower, upper,
- keepGoing,
checkNormalization,
metadataOnly,
notifyCallback != NULL
? ReposNotifyCallback::notify
: NULL,
notifyCallback,
+ NULL, NULL, /* verify callback/baton */
checkCancel, this /* cancel callback/baton
*/,
requestPool.getPool()), );
}
Modified:
subversion/branches/move-tracking-2/subversion/bindings/javahl/native/SVNRepos.h
URL:
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/bindings/javahl/native/SVNRepos.h?rev=1688213&r1=1688212&r2=1688213&view=diff
==============================================================================
---
subversion/branches/move-tracking-2/subversion/bindings/javahl/native/SVNRepos.h
(original)
+++
subversion/branches/move-tracking-2/subversion/bindings/javahl/native/SVNRepos.h
Mon Jun 29 13:42:10 2015
@@ -45,7 +45,7 @@ class SVNRepos : public SVNBase
void rmlocks(File &path, StringArray &locks);
jobject lslocks(File &path, svn_depth_t depth);
void verify(File &path, Revision &revisionStart, Revision &revisionEnd,
- bool keepGoing, bool checkNormalization, bool metadataOnly,
+ bool checkNormalization, bool metadataOnly,
ReposNotifyCallback *notifyCallback);
void setRevProp(File &path, Revision &revision,
const char *propName, const char *propValue,
Modified:
subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNRepos.cpp
URL:
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNRepos.cpp?rev=1688213&r1=1688212&r2=1688213&view=diff
==============================================================================
---
subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNRepos.cpp
(original)
+++
subversion/branches/move-tracking-2/subversion/bindings/javahl/native/org_apache_subversion_javahl_SVNRepos.cpp
Mon Jun 29 13:42:10 2015
@@ -419,7 +419,7 @@ JNIEXPORT void JNICALL
Java_org_apache_subversion_javahl_SVNRepos_verify(
JNIEnv *env, jobject jthis, jobject jpath,
jobject jrevisionStart, jobject jrevisionEnd,
- jboolean jkeepGoing, jboolean jcheckNormalization, jboolean jmetadataOnly,
+ jboolean jcheckNormalization, jboolean jmetadataOnly,
jobject jcallback)
{
JNIEntry(SVNRepos, verify);
@@ -447,7 +447,7 @@ Java_org_apache_subversion_javahl_SVNRep
return;
cl->verify(path, revisionStart, revisionEnd,
- jkeepGoing, jcheckNormalization, jmetadataOnly,
+ jcheckNormalization, jmetadataOnly,
jcallback != NULL ? &callback : NULL);
}
Modified:
subversion/branches/move-tracking-2/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRepos.java
URL:
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRepos.java?rev=1688213&r1=1688212&r2=1688213&view=diff
==============================================================================
---
subversion/branches/move-tracking-2/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRepos.java
(original)
+++
subversion/branches/move-tracking-2/subversion/bindings/javahl/src/org/apache/subversion/javahl/ISVNRepos.java
Mon Jun 29 13:42:10 2015
@@ -299,7 +299,6 @@ public interface ISVNRepos {
* @param path the path to the repository
* @param start the first revision
* @param end the last revision
- * @param keepGoing continue verification even if a revision
is bad
* @param checkNormalization report directory entry and mergeinfo name
collisions
* caused by denormalized Unicode
representations
* @param metadataOnly check only metadata, not file contents
@@ -308,8 +307,7 @@ public interface ISVNRepos {
* @since 1.9
*/
public abstract void verify(File path, Revision start, Revision end,
- boolean keepGoing, boolean checkNormalization,
- boolean metadataOnly,
+ boolean checkNormalization, boolean metadataOnly,
ReposNotifyCallback callback)
throws ClientException;
Modified:
subversion/branches/move-tracking-2/subversion/bindings/javahl/src/org/apache/subversion/javahl/ReposNotifyInformation.java
URL:
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/bindings/javahl/src/org/apache/subversion/javahl/ReposNotifyInformation.java?rev=1688213&r1=1688212&r2=1688213&view=diff
==============================================================================
---
subversion/branches/move-tracking-2/subversion/bindings/javahl/src/org/apache/subversion/javahl/ReposNotifyInformation.java
(original)
+++
subversion/branches/move-tracking-2/subversion/bindings/javahl/src/org/apache/subversion/javahl/ReposNotifyInformation.java
Mon Jun 29 13:42:10 2015
@@ -199,12 +199,6 @@ public class ReposNotifyInformation exte
verify_rev_structure,
/**
- * A revision is found with corruption/errors.
- * @since 1.9
- */
- failure,
-
- /**
* A revprop shard got packed. @
* @since 1.9
*/
Modified:
subversion/branches/move-tracking-2/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNRepos.java
URL:
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNRepos.java?rev=1688213&r1=1688212&r2=1688213&view=diff
==============================================================================
---
subversion/branches/move-tracking-2/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNRepos.java
(original)
+++
subversion/branches/move-tracking-2/subversion/bindings/javahl/src/org/apache/subversion/javahl/SVNRepos.java
Mon Jun 29 13:42:10 2015
@@ -238,12 +238,11 @@ public class SVNRepos implements ISVNRep
ReposNotifyCallback callback)
throws ClientException
{
- verify(path, start, end, false, false, false, callback);
+ verify(path, start, end, false, false, callback);
}
public native void verify(File path, Revision start, Revision end,
- boolean keepGoing, boolean checkNormalization,
- boolean metadataOnly,
+ boolean checkNormalization, boolean metadataOnly,
ReposNotifyCallback callback)
throws ClientException;
Modified:
subversion/branches/move-tracking-2/subversion/include/private/svn_wc_private.h
URL:
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/include/private/svn_wc_private.h?rev=1688213&r1=1688212&r2=1688213&view=diff
==============================================================================
---
subversion/branches/move-tracking-2/subversion/include/private/svn_wc_private.h
(original)
+++
subversion/branches/move-tracking-2/subversion/include/private/svn_wc_private.h
Mon Jun 29 13:42:10 2015
@@ -1905,6 +1905,17 @@ svn_wc__diff7(const char **root_relpath,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
+/**
+ * Read all conflicts at LOCAL_ABSPATH into an array containing pointers to
+ * svn_wc_conflict_description2_t data structures alloated in RESULT_POOL.
+ */
+svn_error_t *
+svn_wc__read_conflict_descriptions2_t(const apr_array_header_t **conflicts,
+ svn_wc_context_t *wc_ctx,
+ const char *local_abspath,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
Modified: subversion/branches/move-tracking-2/subversion/include/svn_client.h
URL:
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/include/svn_client.h?rev=1688213&r1=1688212&r2=1688213&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/include/svn_client.h
(original)
+++ subversion/branches/move-tracking-2/subversion/include/svn_client.h Mon Jun
29 13:42:10 2015
@@ -4361,6 +4361,188 @@ svn_client_revert(const apr_array_header
* @{
*/
+typedef struct svn_client_conflict_t svn_client_conflict_t;
+
+typedef struct svn_client_conflict_option_t svn_client_conflict_option_t;
+
+/**
+ * A public enumuneration of conflict option IDs.
+ *
+ * @since New in 1.10, unless noted otherwise.
+ */
+typedef enum svn_client_conflict_option_id_t {
+
+ /* These values intentionally mirror svn_wc_conflict_choice_t. */
+ svn_client_conflict_option_undefined = -1, /* for private use only */
+ svn_client_conflict_option_postpone = 0,
+ svn_client_conflict_option_base_text,
+ svn_client_conflict_option_incoming_new_text,
+ svn_client_conflict_option_working_text,
+ svn_client_conflict_option_incoming_new_text_for_conflicted_hunks_only,
+ svn_client_conflict_option_working_text_for_conflicted_hunks_only,
+ svn_client_conflict_option_merged_text, /* unsupported */
+ svn_client_conflict_option_unspecified
+ /* Values derived from svn_wc_conflict_choice_t end here. */
+
+} svn_client_conflict_option_id_t;
+
+/**
+ * Return a conflict for the conflicted path @a local_abspath.
+ *
+ * @since New in 1.10.
+ */
+svn_error_t *
+svn_client_conflict_get(svn_client_conflict_t **conflict,
+ const char *local_abspath,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+/**
+ * Return a conflict corresponding to legacy conflict description @a desc.
+ *
+ * @since New in 1.10.
+ */
+svn_error_t *
+svn_client_conflict_from_wc_description2_t(
+ svn_client_conflict_t **conflict,
+ const svn_wc_conflict_description2_t *desc,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+/**
+ * Callback for svn_client_conflict_walk_conflicts();
+ *
+ * @since New in 1.10.
+ */
+typedef svn_error_t *(svn_client_conflict_walk_func_t)(
+ void *baton,
+ svn_client_conflict_t *conflict,
+ apr_pool_t *scratch_pool);
+
+/**
+ * Walk all conflicts within the specified @a depth of @a local_abspath.
+ * Pass each conflict found during the walk to the @conflict_walk_func
+ * callback, along with @a conflict_walk_func_baton.
+ * Use cancellation and notification support provided by client context @a ctx.
+ *
+ * This callback may choose to resolve the conflict. If the act of resolving
+ * a conflict creates new conflicts within the walked working copy (as might
+ * be the case for some tree conflicts), the callback will be invoked for each
+ * such new conflict as well.
+ *
+ * @since New in 1.10.
+ */
+svn_error_t *
+svn_client_conflict_walk(const char *local_abspath,
+ svn_depth_t depth,
+ svn_client_conflict_walk_func_t conflict_walk_func,
+ void *conflict_walk_func_baton,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *scratch_pool);
+
+/**
+* Indicate the types of conflicts present on the working copy node
+* described by @a conflict. Any output argument may be @c NULL if
+* the caller is not interested in the status of a particular type.
+*
+* The returned @a *props_conflicted array is allocated in @a result_pool.
+* It contains the names of conflicted properties. If no property conflit
+* exists, the array will contain no elements.
+*
+* @since New in 1.10.
+*/
+svn_error_t *
+svn_client_conflict_get_conflicted(svn_boolean_t *text_conflicted,
+ apr_array_header_t **props_conflicted,
+ svn_boolean_t *tree_conflicted,
+ svn_client_conflict_t *conflict,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+/**
+ * Set @a *options to an array of pointers to svn_client_conflict_option_t
+ * objects applicable to text conflicts described by @a conflict.
+ *
+ * @since New in 1.10.
+ */
+svn_error_t *
+svn_client_conflict_text_get_resolution_options(apr_array_header_t **options,
+ svn_client_conflict_t
*conflict,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+/**
+ * Set @a *options to an array of pointers to svn_client_conflict_option_t
+ * objects applicable to property conflicts described by @a conflict.
+ *
+ * @since New in 1.10.
+ */
+svn_error_t *
+svn_client_conflict_prop_get_resolution_options(apr_array_header_t **options,
+ svn_client_conflict_t
*conflict,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+/**
+ * Set @a *options to an array of pointers to svn_client_conflict_option_t
+ * objects applicable to the tree conflict described by @a conflict.
+ *
+ * @since New in 1.10.
+ */
+svn_error_t *
+svn_client_conflict_tree_get_resolution_options(apr_array_header_t **options,
+ svn_client_conflict_t
*conflict,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+/**
+ * Return an ID for @a option. This ID can be used by callers to associate
+ * arbitrary data with a particular conflict resolution option.
+ *
+ * The ID of a particular resolution option will never change in future
+ * revisions of this API.
+ *
+ * @since New in 1.10.
+ */
+svn_client_conflict_option_id_t
+svn_client_conflict_option_get_id(svn_client_conflict_option_t *option);
+
+/**
+ * Return a textual human-readable description of @a option, allocated in
+ * @a result_pool. The description is encoded in UTF-8 and may contain
+ * multiple lines separated by @c APR_EOL_STR.
+ *
+ * Additionally, the description may be localized to the language used
+ * by the current locale.
+ *
+ * @since New in 1.10.
+ */
+svn_error_t *
+svn_client_conflict_option_describe(const char **description,
+ svn_client_conflict_option_t *option,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
+
+/**
+ * Resolve @a conflict using resolution option @a option.
+ *
+ * @since New in 1.10.
+ */
+svn_error_t *
+svn_client_conflict_resolve(svn_client_conflict_t *conflict,
+ svn_client_conflict_option_t *option,
+ apr_pool_t *scratch_pool);
+
+/**
+ * Return the kind of conflict (text conflict, property conflict,
+ * or tree conflict) represented by @a conflict.
+ *
+ * New in 1.10.
+ */
+svn_wc_conflict_kind_t
+svn_client_conflict_get_kind(const svn_client_conflict_t *conflict);
+
/**
* Return the absolute path to the conflicted working copy node described
* by @a conflict.
@@ -4368,8 +4550,7 @@ svn_client_revert(const apr_array_header
* @since New in 1.10.
*/
const char *
-svn_client_conflict_get_local_abspath(
- const svn_wc_conflict_description2_t *conflict);
+svn_client_conflict_get_local_abspath(const svn_client_conflict_t *conflict);
/**
* Return the operation during which the conflict described by @a
@@ -4378,8 +4559,7 @@ svn_client_conflict_get_local_abspath(
* @since New in 1.10.
*/
svn_wc_operation_t
-svn_client_conflict_get_operation(
- const svn_wc_conflict_description2_t *conflict);
+svn_client_conflict_get_operation(const svn_client_conflict_t *conflict);
/**
* Return the action an update, switch, or merge operation attempted to
@@ -4388,8 +4568,7 @@ svn_client_conflict_get_operation(
* @since New in 1.10.
*/
svn_wc_conflict_action_t
-svn_client_conflict_get_incoming_change(
- const svn_wc_conflict_description2_t *conflict);
+svn_client_conflict_get_incoming_change(const svn_client_conflict_t *conflict);
/**
* Return the reason why the attempted action performed by an update, switch,
@@ -4403,61 +4582,152 @@ svn_client_conflict_get_incoming_change(
* @since New in 1.10.
*/
svn_wc_conflict_reason_t
-svn_client_conflict_get_local_change(
- const svn_wc_conflict_description2_t *conflict);
+svn_client_conflict_get_local_change(const svn_client_conflict_t *conflict);
/**
- * Accessor functions for svn_wc_conflict_description2_t. This is a temporary
- * API for eventually replacing svn_wc_conflict_description2_t with an opaque
- * type and providing improved APIs for conflict resolution.
- *
- * @since New in 1.10.
+ * Return information about the repository associated with @a conflict.
+ * In case of a foreign-repository merge this will differ from the
+ * repository information associated with the merge target working copy.
+ *
+ * @since New in 1.10.
*/
+svn_error_t *
+svn_client_conflict_get_repos_info(const char **repos_root_url,
+ const char **repos_uuid,
+ const svn_client_conflict_t *conflict,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
-#define svn_client_conflict_get_node_kind(conflict) \
- ((conflict)->node_kind)
-
-#define svn_client_conflict_get_kind(conflict) \
- ((conflict)->kind)
-
-#define svn_client_conflict_get_property_name(conflict) \
- ((conflict)->property_name)
-
-#define svn_client_conflict_get_is_binary(conflict) \
- ((conflict)->is_binary)
-
-#define svn_client_conflict_get_mime_type(conflict) \
- ((conflict)->mime_type)
-
-#define svn_client_conflict_get_base_abspath(conflict) \
- ((conflict)->base_abspath)
-
-#define svn_client_conflict_get_their_abspath(conflict) \
- ((conflict)->their_abspath)
-
-#define svn_client_conflict_get_my_abspath(conflict) \
- ((conflict)->my_abspath)
+/**
+ * Return the repository-relative location and the node kind of the incoming
+ * old version of the conflicted node described by @a conflict.
+ *
+ * If the repository-relative path is not available, the @a
+ * *incoming_old_repos_relpath will be set to @c NULL,
+ *
+ * If the peg revision is not available, @a *incoming_old_regrev will be
+ * set to SVN_INVALID_REVNUM.
+ *
+ * If the node kind is not available or if the node does not exist at the
+ * specified path and revision, @a *incoming_old_node_kind will be set to
+ * svn_node_none.
+ * ### Should return svn_node_unkown if not available?
+ *
+ * Any output parameter may be set to @c NULL by the caller to indicate that
+ * a particular piece of information should not be returned.
+ *
+ * In case of tree conflicts, this path@revision does not necessarily exist
+ * in the repository, and it does not necessarily represent the incoming
+ * change which is responsible for the occurance of the tree conflict.
+ * The responsible incoming change is generally located somewhere between
+ * the old and new incoming versions.
+ *
+ * @since New in 1.10.
+ */
+svn_error_t *
+svn_client_conflict_get_incoming_old_repos_location(
+ const char **incoming_old_repos_relpath,
+ svn_revnum_t *incoming_old_regrev,
+ svn_node_kind_t *incoming_old_node_kind,
+ const svn_client_conflict_t *conflict,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
-#define svn_client_conflict_get_merged_file(conflict) \
- ((conflict)->merged_file)
+/**
+ * Like svn_client_conflict_get_incoming_old_repos_location(), expect this
+ * function returns the same data for the incoming new version.
+ *
+ * The same note about tree conflicts applies.
+ *
+ * @since New in 1.10.
+ */
+svn_error_t *
+svn_client_conflict_get_incoming_new_repos_location(
+ const char **incoming_new_repos_relpath,
+ svn_revnum_t *incoming_new_regrev,
+ svn_node_kind_t *incoming_new_node_kind,
+ const svn_client_conflict_t *conflict,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
-#define svn_client_conflict_get_src_left_version(conflict) \
- ((conflict)->src_left_version)
+/**
+ * Return the node kind of the tree conflict victim described by @a conflict.
+ * The victim is the local node in the working copy which was affected by the
+ * tree conflict at the time the conflict was raised.
+ *
+ * @since New in 1.10.
+ */
+svn_node_kind_t
+svn_client_conflict_tree_get_victim_node_kind(
+ const svn_client_conflict_t *conflict);
-#define svn_client_conflict_get_src_right_version(conflict) \
- ((conflict)->src_right_version)
+/**
+ * Return the name of the conflicted property represented by @a conflict.
+ *
+ * @since New in 1.10.
+ */
+const char *
+svn_client_conflict_prop_get_propname(const svn_client_conflict_t *conflict);
-#define svn_client_conflict_get_prop_reject_abspath(conflict) \
- ((conflict)->prop_reject_abspath)
+/**
+ * Return the path to the legacy property conflicts reject file
+ * for the property conflicts represented by @a conflict.
+ *
+ * This function exists for backwards compatibility only and should not be
+ * used in new code.
+ *
+ * @since New in 1.10.
+ */
+const char *
+svn_client_conflict_prop_get_reject_abspath(
+ const svn_client_conflict_t *conflict);
-#define svn_client_conflict_get_prop_value_working(conflict) \
- ((conflict)->prop_value_working)
+/**
+ * Return the set of property values involved in the property conflict
+ * described by @a conflict. If a property value is unavailable the
+ * corresponding output argument is set to @c NULL.
+ *
+ * A 3-way diff of these property values can be generated with
+ * svn_diff_mem_string_diff3(). A merged version with conflict
+ * markers can be generated with svn_diff_mem_string_output_merge3().
+ *
+ * @since New in 1.10.
+ */
+svn_error_t *
+svn_client_conflict_prop_get_propvals(const svn_string_t **base_propval,
+ const svn_string_t **working_propval,
+ const svn_string_t
**incoming_old_propval,
+ const svn_string_t
**incoming_new_propval,
+ const svn_client_conflict_t *conflict,
+ apr_pool_t *result_pool);
-#define svn_client_conflict_get_prop_value_incoming_old(conflict) \
- ((conflict)->prop_value_incoming_old)
+/**
+ * Return the MIME-type of the working version of the text-conflicted file
+ * described by @a conflict.
+ *
+ * ### Really needed? What about base/incoming_old/incoming_new values?
+ * @since: New in 1.10.
+ */
+const char *
+svn_client_conflict_text_get_mime_type(const svn_client_conflict_t *conflict);
-#define svn_client_conflict_get_prop_value_incoming_new(conflict) \
- ((conflict)->prop_value_incoming_new)
+/**
+ * Return absolute paths to the versions of the text-conflicted file
+ * described by @a conflict.
+ *
+ * If a particular content is not available, it is set to @c NULL.
+ *
+ * ### Should this be returning svn_stream_t instead of paths?
+ * @since: New in 1.10.
+ */
+svn_error_t *
+svn_client_conflict_text_get_contents(const char **base_abspath,
+ const char **working_abspath,
+ const char **incoming_old_abspath,
+ const char **incoming_new_abspath,
+ const svn_client_conflict_t *conflict,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool);
/** @} */
Modified:
subversion/branches/move-tracking-2/subversion/include/svn_error_codes.h
URL:
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/include/svn_error_codes.h?rev=1688213&r1=1688212&r2=1688213&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/include/svn_error_codes.h
(original)
+++ subversion/branches/move-tracking-2/subversion/include/svn_error_codes.h
Mon Jun 29 13:42:10 2015
@@ -922,11 +922,6 @@ SVN_ERROR_START
SVN_ERR_REPOS_CATEGORY_START + 10,
"Repository upgrade is not supported")
- /** @since New in 1.9. */
- SVN_ERRDEF(SVN_ERR_REPOS_VERIFY_FAILED,
- SVN_ERR_REPOS_CATEGORY_START + 11,
- "Repository verification failed")
-
/* generic RA errors */
SVN_ERRDEF(SVN_ERR_RA_ILLEGAL_URL,
@@ -1497,6 +1492,11 @@ SVN_ERROR_START
SVN_ERR_CL_CATEGORY_START + 11,
"Failed processing one or more externals definitions")
+ /** @since New in 1.9. */
+ SVN_ERRDEF(SVN_ERR_CL_REPOS_VERIFY_FAILED,
+ SVN_ERR_CL_CATEGORY_START + 12,
+ "Repository verification failed")
+
/* ra_svn errors */
SVN_ERRDEF(SVN_ERR_RA_SVN_CMD_ERR,
Modified: subversion/branches/move-tracking-2/subversion/include/svn_repos.h
URL:
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/include/svn_repos.h?rev=1688213&r1=1688212&r2=1688213&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/include/svn_repos.h
(original)
+++ subversion/branches/move-tracking-2/subversion/include/svn_repos.h Mon Jun
29 13:42:10 2015
@@ -234,9 +234,6 @@ typedef enum svn_repos_notify_action_t
/** The structure of a revision is being verified. @since New in 1.8. */
svn_repos_notify_verify_rev_structure,
- /** A revision is found with corruption/errors. @since New in 1.9. */
- svn_repos_notify_failure,
-
/** A revprop shard got packed. @since New in 1.9. */
svn_repos_notify_pack_revprops,
@@ -348,11 +345,6 @@ typedef struct svn_repos_notify_t
/** For #svn_repos_notify_load_node_start, the path of the node. */
const char *path;
- /** For #svn_repos_notify_failure, this error chain indicates what
- went wrong during verification.
- @since New in 1.9. */
- svn_error_t *err;
-
/** For #svn_repos_notify_hotcopy_rev_range, the start of the copied
revision range.
@since New in 1.9. */
@@ -2825,6 +2817,28 @@ enum svn_repos_load_uuid
svn_repos_load_uuid_force
};
+/** Callback type for use with svn_repos_verify_fs3(). @a revision
+ * and @a verify_err are the details of a single verification failure
+ * that occurred during the svn_repos_verify_fs3() call. @a baton is
+ * the same baton given to svn_repos_verify_fs3(). @a scratch_pool is
+ * provided for the convenience of the implementor, who should not
+ * expect it to live longer than a single callback call.
+ *
+ * @a verify_err will be cleared and becomes invalid after the callback
+ * returns, use svn_error_dup() to preserve the error. If a callback uses
+ * @a verify_err as the return value or as a part of the return value, it
+ * should also call svn_error_dup() for @a verify_err. Implementors of this
+ * callback are forbidden to call svn_error_clear() for @a verify_err.
+ *
+ * @see svn_repos_verify_fs3
+ *
+ * @since New in 1.9.
+ */
+typedef svn_error_t *(*svn_repos_verify_callback_t)(void *baton,
+ svn_revnum_t revision,
+ svn_error_t *verify_err,
+ apr_pool_t *scratch_pool);
+
/**
* Verify the contents of the file system in @a repos.
*
@@ -2835,9 +2849,6 @@ enum svn_repos_load_uuid
* range, then also verify "global invariants" of the repository, as
* described in svn_fs_verify().
*
- * When a failure is found, if @a keep_going is @c TRUE then continue
- * verification from the next revision, otherwise stop.
- *
* If @a check_normalization is @c TRUE, report any name collisions
* within the same directory or svn:mergeinfo property where the names
* differ only in character representation, but are otherwise
@@ -2848,25 +2859,31 @@ enum svn_repos_load_uuid
* file context reconstruction and verification. For FSFS format 7+ and
* FSX, this allows for a very fast check against external corruption.
*
+ * If @a verify_callback is not @c NULL, call it with @a verify_baton upon
+ * receiving an FS-specific structure failure or a revision verification
+ * failure. Set @c revision callback argument to #SVN_INVALID_REVNUM or
+ * to the revision number respectively. Set @c verify_err to svn_error_t
+ * describing the reason of the failure. @c verify_err will be cleared
+ * after the callback returns, use svn_error_dup() to preserve the error.
+ * If @a verify_callback returns an error different from #SVN_NO_ERROR,
+ * stop verifying the repository and immediately return the error from
+ * @a verify_callback.
+ *
+ * If @a verify_callback is @c NULL, this function returns the first
+ * encountered verification error or #SVN_NO_ERROR if there were no failures
+ * during the verification. Errors that prevent the verification process
+ * from continuing, such as #SVN_ERR_CANCELLED, are returned immediately
+ * and do not trigger an invocation of @a verify_callback.
+ *
* If @a notify_func is not null, then call it with @a notify_baton and
* with a notification structure in which the fields are set as follows.
- * (For a warning or error notification that does not apply to a specific
- * revision, the revision number is #SVN_INVALID_REVNUM.)
+ * (For a warning that does not apply to a specific revision, the revision
+ * number is #SVN_INVALID_REVNUM.)
*
* For each FS-specific structure warning:
* @c action = svn_repos_notify_verify_rev_structure
* @c revision = the revision or #SVN_INVALID_REVNUM
*
- * For a FS-specific structure failure:
- * @c action = #svn_repos_notify_failure
- * @c revision = #SVN_INVALID_REVNUM
- * @c err = the corresponding error chain
- *
- * For each revision verification failure:
- * @c action = #svn_repos_notify_failure
- * @c revision = the revision
- * @c err = the corresponding error chain
- *
* For each revision verification warning:
* @c action = #svn_repos_notify_warning
* @c warning and @c warning_str fields set accordingly
@@ -2888,10 +2905,7 @@ enum svn_repos_load_uuid
*
* Use @a scratch_pool for temporary allocation.
*
- * Return an error if there were any failures during verification, or
- * #SVN_NO_ERROR if there were no failures. A failure means an event that,
- * if a notification callback were provided, would send a notification
- * with @c action = #svn_repos_notify_failure.
+ * @see svn_repos_verify_callback_t
*
* @since New in 1.9.
*/
@@ -2899,18 +2913,20 @@ svn_error_t *
svn_repos_verify_fs3(svn_repos_t *repos,
svn_revnum_t start_rev,
svn_revnum_t end_rev,
- svn_boolean_t keep_going,
svn_boolean_t check_normalization,
svn_boolean_t metadata_only,
svn_repos_notify_func_t notify_func,
void *notify_baton,
+ svn_repos_verify_callback_t verify_callback,
+ void *verify_baton,
svn_cancel_func_t cancel,
void *cancel_baton,
apr_pool_t *scratch_pool);
/**
- * Like svn_repos_verify_fs3(), but with @a keep_going,
- * @a check_normalization and @a metadata_only set to @c FALSE.
+ * Like svn_repos_verify_fs3(), but with @a verify_callback and
+ * @a verify_baton set to @c NULL and with @a check_normalization
+ * and @a metadata_only set to @c FALSE.
*
* @since New in 1.7.
* @deprecated Provided for backward compatibility with the 1.8 API.
Modified:
subversion/branches/move-tracking-2/subversion/libsvn_client/resolved.c
URL:
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_client/resolved.c?rev=1688213&r1=1688212&r2=1688213&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_client/resolved.c
(original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_client/resolved.c Mon
Jun 29 13:42:10 2015
@@ -41,6 +41,9 @@
#include "private/svn_wc_private.h"
#include "svn_private_config.h"
+
+#define ARRAY_LEN(ary) ((sizeof (ary)) / (sizeof ((ary)[0])))
+
/*** Code. ***/
@@ -148,30 +151,823 @@ svn_client_resolve(const char *path,
/*** Dealing with conflicts. ***/
+struct svn_client_conflict_t
+{
+ const char *local_abspath;
+ svn_client_ctx_t *ctx;
+ apr_hash_t *prop_conflicts;
+
+ /* For backwards compat. */
+ const svn_wc_conflict_description2_t *legacy_text_conflict;
+ const svn_wc_conflict_description2_t *legacy_prop_conflict;
+ const svn_wc_conflict_description2_t *legacy_tree_conflict;
+};
+
+static void
+add_legacy_desc_to_conflict(const svn_wc_conflict_description2_t *desc,
+ svn_client_conflict_t *conflict,
+ apr_pool_t *result_pool)
+{
+ switch (desc->kind)
+ {
+ case svn_wc_conflict_kind_text:
+ conflict->legacy_text_conflict = desc;
+ break;
+
+ case svn_wc_conflict_kind_property:
+ conflict->legacy_prop_conflict = desc;
+ break;
+
+ case svn_wc_conflict_kind_tree:
+ conflict->legacy_tree_conflict = desc;
+ break;
+
+ default:
+ SVN_ERR_ASSERT_NO_RETURN(FALSE); /* unknown kind of conflict */
+ }
+}
+
+/* Set up a conflict object. If legacy conflict descriptor DESC is not NULL,
+ * set up the conflict object for backwards compatibility. */
+static svn_error_t *
+conflict_get_internal(svn_client_conflict_t **conflict,
+ const char *local_abspath,
+ const svn_wc_conflict_description2_t *desc,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ const apr_array_header_t *descs;
+ int i;
+
+ *conflict = apr_pcalloc(result_pool, sizeof(**conflict));
+
+ if (desc)
+ {
+ /* Add a single legacy conflict descriptor. */
+ (*conflict)->local_abspath = desc->local_abspath;
+ add_legacy_desc_to_conflict(desc, *conflict, result_pool);
+
+ return SVN_NO_ERROR;
+ }
+
+ (*conflict)->local_abspath = apr_pstrdup(result_pool, local_abspath);
+ (*conflict)->ctx = ctx;
+
+ /* Add all legacy conflict descriptors we can find. Eventually, this code
+ * path should stop relying on svn_wc_conflict_description2_t entirely. */
+ SVN_ERR(svn_wc__read_conflict_descriptions2_t(&descs, ctx->wc_ctx,
+ local_abspath,
+ result_pool, scratch_pool));
+ for (i = 0; i < descs->nelts; i++)
+ {
+ desc = APR_ARRAY_IDX(descs, i, const svn_wc_conflict_description2_t *);
+ if (desc->kind == svn_wc_conflict_kind_property)
+ {
+ if ((*conflict)->prop_conflicts == NULL)
+ (*conflict)->prop_conflicts = apr_hash_make(result_pool);
+ svn_hash_sets((*conflict)->prop_conflicts, desc->property_name,
desc);
+ }
+ else
+ add_legacy_desc_to_conflict(desc, *conflict, result_pool);
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_conflict_get(svn_client_conflict_t **conflict,
+ const char *local_abspath,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ return svn_error_trace(conflict_get_internal(conflict, local_abspath, NULL,
+ ctx, result_pool,
scratch_pool));
+}
+
+svn_error_t *
+svn_client_conflict_from_wc_description2_t(
+ svn_client_conflict_t **conflict,
+ const svn_wc_conflict_description2_t *desc,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ return svn_error_trace(conflict_get_internal(conflict, NULL, desc, NULL,
+ result_pool, scratch_pool));
+}
+
+/* Baton type for conflict_walk_status_func(). */
+typedef struct conflict_walk_status_baton_t {
+
+ svn_client_conflict_walk_func_t *conflict_walk_func;
+ void *conflict_walk_func_baton;
+
+ svn_client_ctx_t *ctx;
+ int conflicts_found;
+
+} conflict_walk_status_baton_t;
+
+/* Implements svn_wc_status_func4_t. */
+static svn_error_t *
+conflict_walk_status_func(void *baton,
+ const char *local_abspath,
+ const svn_wc_status3_t *status,
+ apr_pool_t *scratch_pool)
+{
+ conflict_walk_status_baton_t *b = baton;
+ svn_client_conflict_t *conflict;
+
+ if (!status->conflicted)
+ return SVN_NO_ERROR;
+
+ b->conflicts_found++;
+
+ SVN_ERR(svn_client_conflict_get(&conflict, local_abspath, b->ctx,
+ scratch_pool, scratch_pool));
+ SVN_ERR(b->conflict_walk_func(b->conflict_walk_func_baton,
+ conflict, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_conflict_walk(const char *local_abspath,
+ svn_depth_t depth,
+ svn_client_conflict_walk_func_t conflict_walk_func,
+ void *conflict_walk_func_baton,
+ svn_client_ctx_t *ctx,
+ apr_pool_t *scratch_pool)
+{
+ conflict_walk_status_baton_t b;
+
+ b.conflict_walk_func = conflict_walk_func;
+ b.conflict_walk_func_baton = conflict_walk_func_baton;
+ b.ctx = ctx;
+
+ /* ### Re-run the status walk until a walk finds no conflicts at all.
+ * ### This is a crude implementation but provides the guarantees we offer
+ * ### to the caller. To optimize we should check for notifications of new
+ * ### conflicts created during the first status walk and then keep invoking
+ * ### the callback directly on any new conflicts.
+ */
+ do
+ {
+ b.conflicts_found = 0;
+ SVN_ERR(svn_wc_walk_status(ctx->wc_ctx, local_abspath, depth,
+ FALSE, /* get_all */
+ FALSE, /* no_ignore, */
+ TRUE, /* ignore_externals */
+ NULL, /* ignore_patterns */
+ conflict_walk_status_func, &b,
+ ctx->cancel_func, ctx->cancel_baton,
+ scratch_pool));
+ }
+ while (b.conflicts_found > 0);
+
+ return SVN_NO_ERROR;
+}
+
+typedef svn_error_t *(*conflict_option_resolve_func_t)(
+ svn_client_conflict_option_t *option,
+ svn_client_conflict_t *conflict,
+ apr_pool_t *scratch_pool);
+
+struct svn_client_conflict_option_t
+{
+ svn_client_conflict_option_id_t id;
+ const char *description;
+
+ svn_client_conflict_t *conflict;
+ conflict_option_resolve_func_t do_resolve_func;
+};
+
+static svn_error_t *
+resolve_postpone(svn_client_conflict_option_t *option,
+ svn_client_conflict_t *conflict,
+ apr_pool_t *scratch_pool)
+{
+ /* Nothing to do. */
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+resolve_text_conflict(svn_client_conflict_option_t *option,
+ svn_client_conflict_t *conflict,
+ apr_pool_t *scratch_pool)
+{
+ svn_client_conflict_option_id_t id;
+ const char *local_abspath;
+
+ id = svn_client_conflict_option_get_id(option);
+ local_abspath = svn_client_conflict_get_local_abspath(conflict);
+
+ SVN_ERR(svn_wc_resolved_conflict5(conflict->ctx->wc_ctx, local_abspath,
+ svn_depth_empty, TRUE, NULL, FALSE,
+ id, /* option id is backwards compatible */
+ conflict->ctx->cancel_func,
+ conflict->ctx->cancel_baton,
+ conflict->ctx->notify_func2,
+ conflict->ctx->notify_baton2,
+ scratch_pool));
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+resolve_prop_conflict(svn_client_conflict_option_t *option,
+ svn_client_conflict_t *conflict,
+ apr_pool_t *scratch_pool)
+{
+ svn_client_conflict_option_id_t id;
+ const char *local_abspath;
+
+ id = svn_client_conflict_option_get_id(option);
+ local_abspath = svn_client_conflict_get_local_abspath(conflict);
+
+ SVN_ERR(svn_wc_resolved_conflict5(conflict->ctx->wc_ctx, local_abspath,
+ svn_depth_empty, TRUE, "", FALSE,
+ id, /* option id is backwards compatible */
+ conflict->ctx->cancel_func,
+ conflict->ctx->cancel_baton,
+ conflict->ctx->notify_func2,
+ conflict->ctx->notify_baton2,
+ scratch_pool));
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+resolve_tree_conflict(svn_client_conflict_option_t *option,
+ svn_client_conflict_t *conflict,
+ apr_pool_t *scratch_pool)
+{
+ svn_client_conflict_option_id_t id;
+ const char *local_abspath;
+
+ id = svn_client_conflict_option_get_id(option);
+ local_abspath = svn_client_conflict_get_local_abspath(conflict);
+
+ SVN_ERR(svn_wc_resolved_conflict5(conflict->ctx->wc_ctx, local_abspath,
+ svn_depth_empty, FALSE, NULL, TRUE,
+ id, /* option id is backwards compatible */
+ conflict->ctx->cancel_func,
+ conflict->ctx->cancel_baton,
+ conflict->ctx->notify_func2,
+ conflict->ctx->notify_baton2,
+ scratch_pool));
+ return SVN_NO_ERROR;
+}
+
+/* Resolver options for a text conflict */
+static const svn_client_conflict_option_t text_conflict_options[] =
+{
+ {
+ svn_client_conflict_option_postpone,
+ N_("mark the conflict to be resolved later"),
+ NULL,
+ resolve_postpone
+ },
+
+ {
+ svn_client_conflict_option_incoming_new_text,
+ N_("accept incoming version of entire file"),
+ NULL,
+ resolve_text_conflict
+ },
+
+ {
+ svn_client_conflict_option_working_text,
+ N_("accept working copy version of entire file"),
+ NULL,
+ resolve_text_conflict
+ },
+
+ {
+ svn_client_conflict_option_incoming_new_text_for_conflicted_hunks_only,
+ N_("accept incoming version of all text conflicts in file"),
+ NULL,
+ resolve_text_conflict
+ },
+
+ {
+ svn_client_conflict_option_working_text_for_conflicted_hunks_only,
+ N_("accept working copy version of all text conflicts in file"),
+ NULL,
+ resolve_text_conflict
+ },
+
+};
+
+/* Resolver options for a binary file conflict */
+static const svn_client_conflict_option_t binary_conflict_options[] =
+{
+ {
+ svn_client_conflict_option_postpone,
+ N_("mark the conflict to be resolved later"),
+ NULL,
+ resolve_postpone
+ },
+
+ {
+ svn_client_conflict_option_incoming_new_text,
+ N_("accept incoming version of binary file"),
+ NULL,
+ resolve_text_conflict
+ },
+
+ {
+ svn_client_conflict_option_working_text,
+ N_("accept working copy version of binary file"),
+ NULL,
+ resolve_text_conflict
+ },
+
+};
+
+/* Resolver options for a property conflict */
+static const svn_client_conflict_option_t prop_conflict_options[] =
+{
+ {
+ svn_client_conflict_option_postpone,
+ N_("mark the conflict to be resolved later"),
+ NULL,
+ resolve_postpone
+ },
+
+ {
+ svn_client_conflict_option_incoming_new_text,
+ N_("accept incoming version of entire property value"),
+ NULL,
+ resolve_prop_conflict
+ },
+
+ {
+ svn_client_conflict_option_working_text,
+ N_("accept working copy version of entire property value"),
+ NULL,
+ resolve_prop_conflict
+ },
+
+};
+
+/* Resolver options for a tree conflict */
+static const svn_client_conflict_option_t tree_conflict_options[] =
+{
+ {
+ svn_client_conflict_option_postpone,
+ N_("mark the conflict to be resolved later"),
+ NULL,
+ resolve_postpone
+ },
+
+ {
+ /* ### Use 'working text' for now since libsvn_wc does not know another
+ * ### choice to resolve to working yet. */
+ svn_client_conflict_option_working_text,
+ N_("accept current working copy state"),
+ NULL,
+ resolve_tree_conflict
+ },
+
+};
+
+static svn_error_t *
+assert_text_conflict(svn_client_conflict_t *conflict, apr_pool_t *scratch_pool)
+{
+ svn_boolean_t text_conflicted;
+
+ SVN_ERR(svn_client_conflict_get_conflicted(&text_conflicted, NULL, NULL,
+ conflict, scratch_pool,
+ scratch_pool));
+
+ SVN_ERR_ASSERT(text_conflicted); /* ### return proper error? */
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+assert_prop_conflict(svn_client_conflict_t *conflict, apr_pool_t *scratch_pool)
+{
+ apr_array_header_t *props_conflicted;
+
+ SVN_ERR(svn_client_conflict_get_conflicted(NULL, &props_conflicted, NULL,
+ conflict, scratch_pool,
+ scratch_pool));
+
+ /* ### return proper error? */
+ SVN_ERR_ASSERT(props_conflicted && props_conflicted->nelts > 0);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t *
+assert_tree_conflict(svn_client_conflict_t *conflict, apr_pool_t *scratch_pool)
+{
+ svn_boolean_t tree_conflicted;
+
+ SVN_ERR(svn_client_conflict_get_conflicted(NULL, NULL, &tree_conflicted,
+ conflict, scratch_pool,
+ scratch_pool));
+
+ SVN_ERR_ASSERT(tree_conflicted); /* ### return proper error? */
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_conflict_text_get_resolution_options(apr_array_header_t **options,
+ svn_client_conflict_t
*conflict,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ const char *mime_type;
+ int i;
+
+ SVN_ERR(assert_text_conflict(conflict, scratch_pool));
+
+ *options = apr_array_make(result_pool, ARRAY_LEN(text_conflict_options),
+ sizeof(svn_client_conflict_option_t *));
+
+ mime_type = svn_client_conflict_text_get_mime_type(conflict);
+ if (mime_type && svn_mime_type_is_binary(mime_type))
+ {
+ for (i = 0; i < ARRAY_LEN(binary_conflict_options); i++)
+ {
+ APR_ARRAY_PUSH((*options), const svn_client_conflict_option_t *) =
+ &binary_conflict_options[i];
+ }
+ }
+ else
+ {
+ for (i = 0; i < ARRAY_LEN(text_conflict_options); i++)
+ {
+ APR_ARRAY_PUSH((*options), const svn_client_conflict_option_t *) =
+ &text_conflict_options[i];
+ }
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_conflict_prop_get_resolution_options(apr_array_header_t **options,
+ svn_client_conflict_t
*conflict,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ int i;
+
+ SVN_ERR(assert_prop_conflict(conflict, scratch_pool));
+
+ *options = apr_array_make(result_pool, ARRAY_LEN(prop_conflict_options),
+ sizeof(svn_client_conflict_option_t *));
+ for (i = 0; i < ARRAY_LEN(prop_conflict_options); i++)
+ {
+ APR_ARRAY_PUSH((*options), const svn_client_conflict_option_t *) =
+ &prop_conflict_options[i];
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_conflict_tree_get_resolution_options(apr_array_header_t **options,
+ svn_client_conflict_t
*conflict,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ int i;
+
+ SVN_ERR(assert_tree_conflict(conflict, scratch_pool));
+
+ *options = apr_array_make(result_pool, ARRAY_LEN(tree_conflict_options),
+ sizeof(svn_client_conflict_option_t *));
+ for (i = 0; i < ARRAY_LEN(tree_conflict_options); i++)
+ {
+ APR_ARRAY_PUSH((*options), const svn_client_conflict_option_t *) =
+ &tree_conflict_options[i];
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_client_conflict_option_id_t
+svn_client_conflict_option_get_id(svn_client_conflict_option_t *option)
+{
+ return option->id;
+}
+
+svn_error_t *
+svn_client_conflict_option_describe(const char **description,
+ svn_client_conflict_option_t *option,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ *description = apr_pstrdup(result_pool, option->description);
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_conflict_resolve(svn_client_conflict_t *conflict,
+ svn_client_conflict_option_t *option,
+ apr_pool_t *scratch_pool)
+{
+ SVN_ERR(option->do_resolve_func(option, conflict, scratch_pool));
+
+ return SVN_NO_ERROR;
+}
+
+/* Return the legacy conflict descriptor which is wrapped by CONFLICT. */
+static const svn_wc_conflict_description2_t *
+get_conflict_desc2_t(const svn_client_conflict_t *conflict)
+{
+ if (conflict->legacy_text_conflict)
+ return conflict->legacy_text_conflict;
+
+ if (conflict->legacy_tree_conflict)
+ return conflict->legacy_tree_conflict;
+
+ if (conflict->legacy_prop_conflict)
+ return conflict->legacy_prop_conflict;
+
+ return NULL;
+}
+
+svn_wc_conflict_kind_t
+svn_client_conflict_get_kind(const svn_client_conflict_t *conflict)
+{
+ return get_conflict_desc2_t(conflict)->kind;
+}
+
+svn_error_t *
+svn_client_conflict_get_conflicted(svn_boolean_t *text_conflicted,
+ apr_array_header_t **props_conflicted,
+ svn_boolean_t *tree_conflicted,
+ svn_client_conflict_t *conflict,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ if (text_conflicted)
+ *text_conflicted = (conflict->legacy_text_conflict != NULL);
+
+ if (props_conflicted)
+ {
+ if (conflict->legacy_prop_conflict)
+ {
+ *props_conflicted = apr_array_make(result_pool, 1,
+ sizeof(const char*));
+ APR_ARRAY_PUSH((*props_conflicted), const char *) =
+ conflict->legacy_prop_conflict->property_name;
+ }
+ else
+ SVN_ERR(svn_hash_keys(props_conflicted, conflict->prop_conflicts,
+ result_pool));
+ }
+
+ if (tree_conflicted)
+ *tree_conflicted = (conflict->legacy_tree_conflict != NULL);
+
+ return SVN_NO_ERROR;
+}
+
const char *
-svn_client_conflict_get_local_abspath(
- const svn_wc_conflict_description2_t *conflict)
+svn_client_conflict_get_local_abspath(const svn_client_conflict_t *conflict)
{
return conflict->local_abspath;
}
svn_wc_operation_t
-svn_client_conflict_get_operation(
- const svn_wc_conflict_description2_t *conflict)
+svn_client_conflict_get_operation(const svn_client_conflict_t *conflict)
{
- return conflict->operation;
+ return get_conflict_desc2_t(conflict)->operation;
}
svn_wc_conflict_action_t
-svn_client_conflict_get_incoming_change(
- const svn_wc_conflict_description2_t *conflict)
+svn_client_conflict_get_incoming_change(const svn_client_conflict_t *conflict)
{
- return conflict->action;
+ return get_conflict_desc2_t(conflict)->action;
}
svn_wc_conflict_reason_t
-svn_client_conflict_get_local_change(
- const svn_wc_conflict_description2_t *conflict)
+svn_client_conflict_get_local_change(const svn_client_conflict_t *conflict)
+{
+ return get_conflict_desc2_t(conflict)->reason;
+}
+
+svn_error_t *
+svn_client_conflict_get_repos_info(const char **repos_root_url,
+ const char **repos_uuid,
+ const svn_client_conflict_t *conflict,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ if (repos_root_url)
+ {
+ if (get_conflict_desc2_t(conflict)->src_left_version)
+ *repos_root_url =
+ get_conflict_desc2_t(conflict)->src_left_version->repos_url;
+ else if (get_conflict_desc2_t(conflict)->src_right_version)
+ *repos_root_url =
+ get_conflict_desc2_t(conflict)->src_right_version->repos_url;
+ else
+ *repos_root_url = NULL;
+ }
+
+ if (repos_uuid)
+ {
+ if (get_conflict_desc2_t(conflict)->src_left_version)
+ *repos_uuid =
+ get_conflict_desc2_t(conflict)->src_left_version->repos_uuid;
+ else if (get_conflict_desc2_t(conflict)->src_right_version)
+ *repos_uuid =
+ get_conflict_desc2_t(conflict)->src_right_version->repos_uuid;
+ else
+ *repos_uuid = NULL;
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_conflict_get_incoming_old_repos_location(
+ const char **incoming_old_repos_relpath,
+ svn_revnum_t *incoming_old_pegrev,
+ svn_node_kind_t *incoming_old_node_kind,
+ const svn_client_conflict_t *conflict,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ if (incoming_old_repos_relpath)
+ {
+ if (get_conflict_desc2_t(conflict)->src_left_version)
+ *incoming_old_repos_relpath =
+ get_conflict_desc2_t(conflict)->src_left_version->path_in_repos;
+ else
+ *incoming_old_repos_relpath = NULL;
+ }
+
+ if (incoming_old_pegrev)
+ {
+ if (get_conflict_desc2_t(conflict)->src_left_version)
+ *incoming_old_pegrev =
+ get_conflict_desc2_t(conflict)->src_left_version->peg_rev;
+ else
+ *incoming_old_pegrev = SVN_INVALID_REVNUM;
+ }
+
+ if (incoming_old_node_kind)
+ {
+ if (get_conflict_desc2_t(conflict)->src_left_version)
+ *incoming_old_node_kind =
+ get_conflict_desc2_t(conflict)->src_left_version->node_kind;
+ else
+ *incoming_old_node_kind = svn_node_none;
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_client_conflict_get_incoming_new_repos_location(
+ const char **incoming_new_repos_relpath,
+ svn_revnum_t *incoming_new_pegrev,
+ svn_node_kind_t *incoming_new_node_kind,
+ const svn_client_conflict_t *conflict,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
{
- return conflict->reason;
+ if (incoming_new_repos_relpath)
+ {
+ if (get_conflict_desc2_t(conflict)->src_right_version)
+ *incoming_new_repos_relpath =
+ get_conflict_desc2_t(conflict)->src_right_version->path_in_repos;
+ else
+ *incoming_new_repos_relpath = NULL;
+ }
+
+ if (incoming_new_pegrev)
+ {
+ if (get_conflict_desc2_t(conflict)->src_right_version)
+ *incoming_new_pegrev =
+ get_conflict_desc2_t(conflict)->src_right_version->peg_rev;
+ else
+ *incoming_new_pegrev = SVN_INVALID_REVNUM;
+ }
+
+ if (incoming_new_node_kind)
+ {
+ if (get_conflict_desc2_t(conflict)->src_right_version)
+ *incoming_new_node_kind =
+ get_conflict_desc2_t(conflict)->src_right_version->node_kind;
+ else
+ *incoming_new_node_kind = svn_node_none;
+ }
+
+ return SVN_NO_ERROR;
+}
+
+svn_node_kind_t
+svn_client_conflict_tree_get_victim_node_kind(
+ const svn_client_conflict_t *conflict)
+{
+ SVN_ERR_ASSERT_NO_RETURN(svn_client_conflict_get_kind(conflict)
+ == svn_wc_conflict_kind_tree);
+
+ return get_conflict_desc2_t(conflict)->node_kind;
+}
+
+const char *
+svn_client_conflict_prop_get_propname(const svn_client_conflict_t *conflict)
+{
+ SVN_ERR_ASSERT_NO_RETURN(svn_client_conflict_get_kind(conflict)
+ == svn_wc_conflict_kind_property);
+
+ return get_conflict_desc2_t(conflict)->property_name;
+}
+
+svn_error_t *
+svn_client_conflict_prop_get_propvals(const svn_string_t **base_propval,
+ const svn_string_t **working_propval,
+ const svn_string_t
**incoming_old_propval,
+ const svn_string_t
**incoming_new_propval,
+ const svn_client_conflict_t *conflict,
+ apr_pool_t *result_pool)
+{
+ SVN_ERR_ASSERT(svn_client_conflict_get_kind(conflict) ==
+ svn_wc_conflict_kind_property);
+
+ if (base_propval)
+ *base_propval =
+ svn_string_dup(get_conflict_desc2_t(conflict)->prop_value_base,
+ result_pool);
+
+ if (working_propval)
+ *working_propval =
+ svn_string_dup(get_conflict_desc2_t(conflict)->prop_value_working,
+ result_pool);
+
+ if (incoming_old_propval)
+ *incoming_old_propval =
+ svn_string_dup(get_conflict_desc2_t(conflict)->prop_value_incoming_old,
+ result_pool);
+
+ if (incoming_new_propval)
+ *incoming_new_propval =
+ svn_string_dup(get_conflict_desc2_t(conflict)->prop_value_incoming_new,
+ result_pool);
+
+ return SVN_NO_ERROR;
+}
+
+const char *
+svn_client_conflict_prop_get_reject_abspath(
+ const svn_client_conflict_t *conflict)
+{
+ SVN_ERR_ASSERT_NO_RETURN(svn_client_conflict_get_kind(conflict)
+ == svn_wc_conflict_kind_property);
+
+ /* svn_wc_conflict_description2_t stores this path in 'their_abspath' */
+ return get_conflict_desc2_t(conflict)->their_abspath;
+}
+
+const char *
+svn_client_conflict_text_get_mime_type(const svn_client_conflict_t *conflict)
+{
+ SVN_ERR_ASSERT_NO_RETURN(svn_client_conflict_get_kind(conflict)
+ == svn_wc_conflict_kind_text);
+
+ return get_conflict_desc2_t(conflict)->mime_type;
+}
+
+svn_error_t *
+svn_client_conflict_text_get_contents(const char **base_abspath,
+ const char **working_abspath,
+ const char **incoming_old_abspath,
+ const char **incoming_new_abspath,
+ const svn_client_conflict_t *conflict,
+ apr_pool_t *result_pool,
+ apr_pool_t *scratch_pool)
+{
+ SVN_ERR_ASSERT(svn_client_conflict_get_kind(conflict)
+ == svn_wc_conflict_kind_text);
+
+ if (base_abspath)
+ {
+ if (svn_client_conflict_get_operation(conflict) ==
+ svn_wc_operation_merge)
+ *base_abspath = NULL; /* ### WC base contents not available yet */
+ else /* update/switch */
+ *base_abspath = get_conflict_desc2_t(conflict)->base_abspath;
+ }
+
+ if (working_abspath)
+ *working_abspath = get_conflict_desc2_t(conflict)->my_abspath;
+
+ if (incoming_old_abspath)
+ *incoming_old_abspath = get_conflict_desc2_t(conflict)->base_abspath;
+
+ if (incoming_new_abspath)
+ *incoming_new_abspath = get_conflict_desc2_t(conflict)->their_abspath;
+
+ return SVN_NO_ERROR;
}
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs.c
URL:
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs.c?rev=1688213&r1=1688212&r2=1688213&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs.c (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs.c Mon Jun 29
13:42:10 2015
@@ -134,6 +134,18 @@ fs_serialized_init(svn_fs_t *fs, apr_poo
return SVN_NO_ERROR;
}
+svn_error_t *
+svn_fs_fs__initialize_shared_data(svn_fs_t *fs,
+ svn_mutex__t *common_pool_lock,
+ apr_pool_t *pool,
+ apr_pool_t *common_pool)
+{
+ SVN_MUTEX__WITH_LOCK(common_pool_lock,
+ fs_serialized_init(fs, common_pool, pool));
+
+ return SVN_NO_ERROR;
+}
+
/* This function is provided for Subversion 1.0.x compatibility. It
@@ -480,28 +492,19 @@ fs_hotcopy(svn_fs_t *src_fs,
apr_pool_t *pool,
apr_pool_t *common_pool)
{
- /* Open the source repo as usual. */
SVN_ERR(fs_open(src_fs, src_path, common_pool_lock, pool, common_pool));
- if (cancel_func)
- SVN_ERR(cancel_func(cancel_baton));
- /* Test target repo when in INCREMENTAL mode, initialize it when not.
- * For this, we need our FS internal data structures to be temporarily
- * available. */
+ SVN_ERR(svn_fs__check_fs(dst_fs, FALSE));
SVN_ERR(initialize_fs_struct(dst_fs));
- SVN_ERR(svn_fs_fs__hotcopy_prepare_target(src_fs, dst_fs, dst_path,
- incremental, pool));
- uninitialize_fs_struct(dst_fs);
-
- /* Now, the destination repo should open just fine. */
- SVN_ERR(fs_open(dst_fs, dst_path, common_pool_lock, pool, common_pool));
- if (cancel_func)
- SVN_ERR(cancel_func(cancel_baton));
-
- /* Now, we may copy data as needed ... */
- return svn_fs_fs__hotcopy(src_fs, dst_fs, incremental,
- notify_func, notify_baton,
- cancel_func, cancel_baton, pool);
+
+ /* In INCREMENTAL mode, svn_fs_fs__hotcopy() will open DST_FS.
+ Otherwise, it's not an FS yet --- possibly just an empty dir --- so
+ can't be opened.
+ */
+ return svn_fs_fs__hotcopy(src_fs, dst_fs, src_path, dst_path,
+ incremental, notify_func, notify_baton,
+ cancel_func, cancel_baton, common_pool_lock,
+ pool, common_pool);
}
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs.h
URL:
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs.h?rev=1688213&r1=1688212&r2=1688213&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs.h (original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs.h Mon Jun 29
13:42:10 2015
@@ -82,8 +82,6 @@ extern "C" {
/* Names of special files and file extensions for transactions */
#define PATH_CHANGES "changes" /* Records changes made so far */
#define PATH_TXN_PROPS "props" /* Transaction properties */
-#define PATH_TXN_PROPS_FINAL "props-final" /* Final transaction properties
- before moving to revprops */
#define PATH_NEXT_IDS "next-ids" /* Next temporary ID assignments */
#define PATH_PREFIX_NODE "node." /* Prefix for node filename */
#define PATH_EXT_TXN ".txn" /* Extension of txn dir */
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs_fs.c
URL:
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs_fs.c?rev=1688213&r1=1688212&r2=1688213&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs_fs.c
(original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs_fs.c Mon Jun
29 13:42:10 2015
@@ -415,75 +415,6 @@ svn_fs_fs__with_all_locks(svn_fs_t *fs,
return svn_error_trace(with_lock(lock_baton, pool));
}
-/* Set *READ_ONLY to TRUE, if the (lock) file at PATH is read-only.
- Should that file not exist, try to create an empty one at PATH.
- If that fails due to insufficient access rights, set *READ_ONLY
- to TRUE as well. Use SCRATCH_POOL for temporary allocations.
- */
-static svn_error_t *
-is_read_only(svn_boolean_t *read_only,
- const char *path,
- apr_pool_t *scratch_pool)
-{
- apr_finfo_t finfo;
-
- svn_error_t *err
- = svn_io_stat(&finfo, path, SVN__APR_FINFO_READONLY, scratch_pool);
- if (err && APR_STATUS_IS_ENOENT(err->apr_err))
- {
- /* No lock file? Try to create one.
- If that is not allowed, the repo can't be written to.
- Report it as r/o in that case. */
- svn_error_clear(err);
-
- /* This file creation is racy (see further below). */
- err = svn_io_file_create_empty(path, scratch_pool);
- if (err && APR_STATUS_IS_EACCES(err->apr_err))
- {
- /* File creation is not allowed. */
- svn_error_clear(err);
- *read_only = TRUE;
- return SVN_NO_ERROR;
- }
-
- /* Don't leak ... */
- svn_error_clear(err);
-
- /* At this point, there should either be a file or something pretty
- bad happened. In the latter case, this will fail with some error. */
- SVN_ERR(svn_io_stat(&finfo, path, SVN__APR_FINFO_READONLY,
- scratch_pool));
- }
-
- SVN_ERR(svn_io__is_finfo_read_only(read_only, &finfo, scratch_pool));
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_fs_fs__is_read_only(svn_boolean_t *read_only,
- svn_fs_t *fs,
- apr_pool_t *scratch_pool)
-{
- fs_fs_data_t *ffd = fs->fsap_data;
-
- *read_only = FALSE;
- SVN_ERR(is_read_only(read_only,
- svn_fs_fs__path_lock(fs, scratch_pool),
- scratch_pool));
-
- if (ffd->format >= SVN_FS_FS__MIN_TXN_CURRENT_FORMAT && !*read_only)
- SVN_ERR(is_read_only(read_only,
- svn_fs_fs__path_txn_current_lock(fs, scratch_pool),
- scratch_pool));
-
- if (ffd->format >= SVN_FS_FS__MIN_PACK_LOCK_FORMAT && !*read_only)
- SVN_ERR(is_read_only(read_only,
- svn_fs_fs__path_pack_lock(fs, scratch_pool),
- scratch_pool));
-
- return SVN_NO_ERROR;
-}
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs_fs.h
URL:
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs_fs.h?rev=1688213&r1=1688212&r2=1688213&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs_fs.h
(original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/fs_fs.h Mon Jun
29 13:42:10 2015
@@ -39,6 +39,15 @@ svn_error_t *svn_fs_fs__open(svn_fs_t *f
const char *path,
apr_pool_t *pool);
+/* Initialize parts of the FS data that are being shared across multiple
+ filesystem objects. Use COMMON_POOL for process-wide and POOL for
+ temporary allocations. Use COMMON_POOL_LOCK to ensure that the
+ initialization is serialized. */
+svn_error_t *svn_fs_fs__initialize_shared_data(svn_fs_t *fs,
+ svn_mutex__t *common_pool_lock,
+ apr_pool_t *pool,
+ apr_pool_t *common_pool);
+
/* Upgrade the fsfs filesystem FS. Indicate progress via the optional
* NOTIFY_FUNC callback using NOTIFY_BATON. The optional CANCEL_FUNC
* will periodically be called with CANCEL_BATON to allow for preemption.
@@ -215,21 +224,6 @@ svn_fs_fs__with_all_locks(svn_fs_t *fs,
void *baton,
apr_pool_t *pool);
-/* Set *READ_ONLY to TRUE, if we can't write to FS (create txns, commit or
- pack). If *READ_ONLY is FALSE, we expect that the on-disk permissions
- allow for any write operation.
-
- Note that we check the access rights for the current user and that a
- read-only repository may still be writable for other users.
-
- Furthermore, we expect OS access rights to be set consistently on all
- files and folders. Therefore, *READ_ONLY==FALSE is no guarantee that
- a write will actually succeed. */
-svn_error_t *
-svn_fs_fs__is_read_only(svn_boolean_t *read_only,
- svn_fs_t *fs,
- apr_pool_t *scratch_pool);
-
/* Find the value of the property named PROPNAME in transaction TXN.
Return the contents in *VALUE_P. The contents will be allocated
from POOL. */
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/hotcopy.c
URL:
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/hotcopy.c?rev=1688213&r1=1688212&r2=1688213&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/hotcopy.c
(original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/hotcopy.c Mon
Jun 29 13:42:10 2015
@@ -982,6 +982,10 @@ hotcopy_body(void *baton, apr_pool_t *po
if (kind == svn_node_file)
{
SVN_ERR(svn_sqlite__hotcopy(src_subdir, dst_subdir, pool));
+
+ /* The source might have r/o flags set on it - which would be
+ carried over to the copy. */
+ SVN_ERR(svn_io_set_file_read_write(dst_subdir, FALSE, pool));
SVN_ERR(svn_fs_fs__del_rep_reference(dst_fs, src_youngest, pool));
}
}
@@ -991,76 +995,33 @@ hotcopy_body(void *baton, apr_pool_t *po
SVN_ERR(svn_io_dir_file_copy(src_fs->path, dst_fs->path,
PATH_TXN_CURRENT, pool));
- return SVN_NO_ERROR;
-}
-
-/* Wrapper around hotcopy_body taking out all necessary source repository
- * locks.
- */
-static svn_error_t *
-hotcopy_locking_src_body(void *baton, apr_pool_t *pool)
-{
- struct hotcopy_body_baton *hbb = baton;
- fs_fs_data_t *src_ffd = hbb->src_fs->fsap_data;
-
- /* Hotcopying while packing is racy and can lead to hotcopy failure.
- Therefore, we try to block packing while we are copying data. */
- if (src_ffd->format >= SVN_FS_FS__MIN_PACK_LOCK_FORMAT)
- {
- svn_boolean_t read_only;
- SVN_ERR(svn_fs_fs__is_read_only(&read_only, hbb->src_fs, pool));
- if (!read_only)
- return svn_error_trace(svn_fs_fs__with_pack_lock(hbb->src_fs,
- hotcopy_body,
- baton, pool));
- }
+ /* Hotcopied FS is complete. Stamp it with a format file. */
+ SVN_ERR(svn_fs_fs__write_format(dst_fs, TRUE, pool));
- /* Fall-back code: Just copy. This may fail with ENOENT if the source
- repo is being packed at the same time. */
- return svn_error_trace(hotcopy_body(baton, pool));
+ return SVN_NO_ERROR;
}
-/* Create an empty filesystem at DST_FS at DST_PATH with the same
- * configuration as SRC_FS (uuid, format, and other parameters).
- * After creation DST_FS has no revisions, not even revision zero. */
-static svn_error_t *
-hotcopy_create_empty_dest(svn_fs_t *src_fs,
- svn_fs_t *dst_fs,
- const char *dst_path,
- apr_pool_t *pool)
+svn_error_t *
+svn_fs_fs__hotcopy(svn_fs_t *src_fs,
+ svn_fs_t *dst_fs,
+ const char *src_path,
+ const char *dst_path,
+ svn_boolean_t incremental,
+ svn_fs_hotcopy_notify_t notify_func,
+ void *notify_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ svn_mutex__t *common_pool_lock,
+ apr_pool_t *pool,
+ apr_pool_t *common_pool)
{
- fs_fs_data_t *src_ffd = src_fs->fsap_data;
+ struct hotcopy_body_baton hbb;
- /* Create the DST_FS repository with the same layout as SRC_FS. */
- SVN_ERR(svn_fs_fs__create_file_tree(dst_fs, dst_path, src_ffd->format,
- src_ffd->max_files_per_dir,
- src_ffd->use_log_addressing,
- pool));
-
- /* Copy the UUID. Hotcopy destination receives a new instance ID, but
- * has the same filesystem UUID as the source. */
- SVN_ERR(svn_fs_fs__set_uuid(dst_fs, src_fs->uuid, NULL, pool));
-
- /* Remove revision 0 contents. Otherwise, it may not get overwritten
- * due to having a newer timestamp. */
- SVN_ERR(hotcopy_remove_file(svn_fs_fs__path_rev(dst_fs, 0, pool), pool));
- SVN_ERR(hotcopy_remove_file(svn_fs_fs__path_revprops(dst_fs, 0, pool),
- pool));
-
- /* This filesystem is ready. Stamp it with a format number. Fail if
- * the 'format' file should already exist. */
- SVN_ERR(svn_fs_fs__write_format(dst_fs, FALSE, pool));
+ if (cancel_func)
+ SVN_ERR(cancel_func(cancel_baton));
- return SVN_NO_ERROR;
-}
+ SVN_ERR(svn_fs_fs__open(src_fs, src_path, pool));
-svn_error_t *
-svn_fs_fs__hotcopy_prepare_target(svn_fs_t *src_fs,
- svn_fs_t *dst_fs,
- const char *dst_path,
- svn_boolean_t incremental,
- apr_pool_t *pool)
-{
if (incremental)
{
const char *dst_format_abspath;
@@ -1072,39 +1033,51 @@ svn_fs_fs__hotcopy_prepare_target(svn_fs
SVN_ERR(svn_io_check_path(dst_format_abspath, &dst_format_kind, pool));
if (dst_format_kind == svn_node_none)
{
- /* Destination doesn't exist yet. Perform a normal hotcopy to a
- * empty destination using the same configuration as the source. */
- SVN_ERR(hotcopy_create_empty_dest(src_fs, dst_fs, dst_path, pool));
- }
- else
- {
- /* Check the existing repository. */
- SVN_ERR(svn_fs_fs__open(dst_fs, dst_path, pool));
- SVN_ERR(hotcopy_incremental_check_preconditions(src_fs, dst_fs,
- pool));
+ /* No destination? Fallback to a non-incremental hotcopy. */
+ incremental = FALSE;
}
}
+
+ if (incremental)
+ {
+ /* Check the existing repository. */
+ SVN_ERR(svn_fs_fs__open(dst_fs, dst_path, pool));
+ SVN_ERR(hotcopy_incremental_check_preconditions(src_fs, dst_fs, pool));
+
+ SVN_ERR(svn_fs_fs__initialize_shared_data(dst_fs, common_pool_lock,
+ pool, common_pool));
+ SVN_ERR(svn_fs_fs__initialize_caches(dst_fs, pool));
+ }
else
{
/* Start out with an empty destination using the same configuration
* as the source. */
- SVN_ERR(hotcopy_create_empty_dest(src_fs, dst_fs, dst_path, pool));
- }
+ fs_fs_data_t *src_ffd = src_fs->fsap_data;
- return SVN_NO_ERROR;
-}
+ /* Create the DST_FS repository with the same layout as SRC_FS. */
+ SVN_ERR(svn_fs_fs__create_file_tree(dst_fs, dst_path, src_ffd->format,
+ src_ffd->max_files_per_dir,
+ src_ffd->use_log_addressing,
+ pool));
+
+ /* Copy the UUID. Hotcopy destination receives a new instance ID, but
+ * has the same filesystem UUID as the source. */
+ SVN_ERR(svn_fs_fs__set_uuid(dst_fs, src_fs->uuid, NULL, pool));
+
+ /* Remove revision 0 contents. Otherwise, it may not get overwritten
+ * due to having a newer timestamp. */
+ SVN_ERR(hotcopy_remove_file(svn_fs_fs__path_rev(dst_fs, 0, pool),
+ pool));
+ SVN_ERR(hotcopy_remove_file(svn_fs_fs__path_revprops(dst_fs, 0, pool),
+ pool));
+
+ SVN_ERR(svn_fs_fs__initialize_shared_data(dst_fs, common_pool_lock,
+ pool, common_pool));
+ SVN_ERR(svn_fs_fs__initialize_caches(dst_fs, pool));
+ }
-svn_error_t *
-svn_fs_fs__hotcopy(svn_fs_t *src_fs,
- svn_fs_t *dst_fs,
- svn_boolean_t incremental,
- svn_fs_hotcopy_notify_t notify_func,
- void *notify_baton,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *pool)
-{
- struct hotcopy_body_baton hbb;
+ if (cancel_func)
+ SVN_ERR(cancel_func(cancel_baton));
hbb.src_fs = src_fs;
hbb.dst_fs = dst_fs;
@@ -1113,8 +1086,15 @@ svn_fs_fs__hotcopy(svn_fs_t *src_fs,
hbb.notify_baton = notify_baton;
hbb.cancel_func = cancel_func;
hbb.cancel_baton = cancel_baton;
- SVN_ERR(svn_fs_fs__with_all_locks(dst_fs, hotcopy_locking_src_body, &hbb,
- pool));
+
+ /* Lock the destination in the incremental mode. For a non-incremental
+ * hotcopy, don't take any locks. In that case the destination cannot be
+ * opened until the hotcopy finishes, and we don't have to worry about
+ * concurrency. */
+ if (incremental)
+ SVN_ERR(svn_fs_fs__with_all_locks(dst_fs, hotcopy_body, &hbb, pool));
+ else
+ SVN_ERR(hotcopy_body(&hbb, pool));
return SVN_NO_ERROR;
}
Modified: subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/hotcopy.h
URL:
http://svn.apache.org/viewvc/subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/hotcopy.h?rev=1688213&r1=1688212&r2=1688213&view=diff
==============================================================================
--- subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/hotcopy.h
(original)
+++ subversion/branches/move-tracking-2/subversion/libsvn_fs_fs/hotcopy.h Mon
Jun 29 13:42:10 2015
@@ -25,27 +25,23 @@
#include "fs.h"
-/* Create an empty copy of the fsfs filesystem SRC_FS into a new DST_FS at
- * DST_PATH. If INCREMENTAL is TRUE, perform a few pre-checks only if
- * a repo already exists at DST_PATH. Use POOL for temporary allocations. */
-svn_error_t *
-svn_fs_fs__hotcopy_prepare_target(svn_fs_t *src_fs,
- svn_fs_t *dst_fs,
- const char *dst_path,
- svn_boolean_t incremental,
- apr_pool_t *pool);
-
-/* Copy the fsfs filesystem SRC_FS into DST_FS. If INCREMENTAL is TRUE, do
- * not re-copy data which already exists in DST_FS. Indicate progress via
- * the optional NOTIFY_FUNC callback using NOTIFY_BATON. Use POOL for
- * temporary allocations. */
+/* Copy the fsfs filesystem SRC_FS at SRC_PATH into a new copy DST_FS at
+ * DST_PATH. If INCREMENTAL is TRUE, do not re-copy data which already
+ * exists in DST_FS. Indicate progress via the optional NOTIFY_FUNC
+ * callback using NOTIFY_BATON. Use COMMON_POOL for process-wide and
+ * POOL for temporary allocations. Use COMMON_POOL_LOCK to ensure
+ * that the initialization of the shared data is serialized. */
svn_error_t * svn_fs_fs__hotcopy(svn_fs_t *src_fs,
svn_fs_t *dst_fs,
+ const char *src_path,
+ const char *dst_path,
svn_boolean_t incremental,
svn_fs_hotcopy_notify_t notify_func,
void *notify_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
- apr_pool_t *pool);
+ svn_mutex__t *common_pool_lock,
+ apr_pool_t *pool,
+ apr_pool_t *common_pool);
#endif