Another reason to do this in libsvn_wc is that we need to retry resolving conflicts, as some conflicts might be in the way of others. The global retry as implemented here also has the side effect of hiding certain error types around these retries. (See changes of the libsvn wc version)
Just providing the error that we can't resolve everything, while hiding the specific error reason why was one of the errors I found. Specializing the depth empty status walk at least allows access to all the error messages.
Bert
Sent from Surface
From: Bert Huijben
Sent: Saturday, June 27, 2015 11:00 PM
To: commits_at_subversion.apache.org, dev_at_subversion.apache.org
The problem you describe in the conflict walker of libsvn_wc is already fixed in the 1.9 codebase. And if not we should fix it there.
A bigger problem was that it even forgot to report new conflicts deep below the current node, in case the node type changed. But all of that was already fixed before 1.9.0-rc1.
(The fixes were part of the big catchup merge, after the initial branch)
The restart of the walk as implemented here was an intermediate version of the libsvn_wc version, but one that didn't catch all of the problems… as new conflicts may also appear outside the tree that is walked for conflicts. Catching new conflicts via the notify handler works much better.
Trying to fix this in libsvn_client is very hard, as you don’t know where to apply the working copy lock (especially on moves). Libsvn_wc has the code to do that, but I don't see a usage of that in your code here.
Bert
Sent from Surface
From: Stefan Sperling
Sent: Saturday, June 27, 2015 12:35 PM
To: commits_at_subversion.apache.org
Author: stsp
Date: Sat Jun 27 10:35:42 2015
New Revision: 1687906
URL: http://svn.apache.org/r1687906
Log:
Add a conflict walker to the new svn_client_conflict API.
Contrary to our current libsvn_wc conflict walker, this walker guarantees
that new conflicts created during conflict resolution (which can happen
when resolving tree conflicts) are visited as well. The libsvn_wc walker
will visit such new conflicts only if they happen to be created in parts
of the working copy which the walker has not yet visited.
* subversion/include/svn_client.h
(svn_client_conflict_walk_func_t, svn_client_conflict_walk): Declare.
* subversion/libsvn_client/resolved.c
(svn_client_conflict_walk): Implement.
Modified:
subversion/trunk/subversion/include/svn_client.h
subversion/trunk/subversion/libsvn_client/resolved.c
Modified: subversion/trunk/subversion/include/svn_client.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_client.h?rev=1687906&r1=1687905&r2=1687906&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_client.h (original)
+++ subversion/trunk/subversion/include/svn_client.h Sat Jun 27 10:35:42 2015
@@ -4411,6 +4411,37 @@ svn_client_conflict_from_wc_description2
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.
Modified: subversion/trunk/subversion/libsvn_client/resolved.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/resolved.c?rev=1687906&r1=1687905&r2=1687906&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/resolved.c (original)
+++ subversion/trunk/subversion/libsvn_client/resolved.c Sat Jun 27 10:35:42 2015
@@ -257,6 +257,77 @@ svn_client_conflict_from_wc_description2
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;
+ b.conflicts_found = 0;
+
+ /* ### 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
+ {
+ 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,
Received on 2015-06-27 23:13:59 CEST