You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by st...@apache.org on 2012/06/16 14:57:36 UTC
svn commit: r1350917 - in /subversion/trunk/subversion: include/svn_wc.h
libsvn_wc/conflicts.c svn/notify.c
Author: stsp
Date: Sat Jun 16 12:57:36 2012
New Revision: 1350917
URL: http://svn.apache.org/viewvc?rev=1350917&view=rev
Log:
Make the conflict resolver send a conflict summary to the caller, before
invoking the conflict callback.
This will eventually allow 'svn' to print the conflict summary before the
interactive conflict resolution callback is invoked. This summary is currently
printed after the callback was invoked on each conflict, which isn't helpful.
This commit has no visible behaviour change yet, as this would require all
operations to delay conflict callback invocation, which has currently been
implemented only for 'update'.
* subversion/include/svn_wc.h
(svn_wc_notify_action_t): Add svn_wc_notify_conflict_summary action.
This currently sends the number of text, property, and tree conflicts in
the working copy. We might extend this later, but for now the goal is to
move the current 'svn' conflict stats collecting into the conflict resolver.
(svn_wc_notify_t): Add text_conflicts, prop_conflicts, and tree_conflicts
counters for use during an svn_wc_notify_conflict_summary notification.
* subversion/libsvn_wc/conflicts.c
(conflict_status_walker_baton): Remove.
(conflict_status_walker): Replaced by ...
(gather_conflict_stats): ... this function, which only gathers conflict
statistics and the list of conflicted paths.
(gather_conflict_stats_baton): New baton for above status walker callback.
(resolve_conflicts_on_node): New function, contains the guts of the former
conflict_status_walker() callback.
(svn_wc__resolve_conflicts): Gather conflict stats via the status walker,
send a conflict summary via the notification mechanism, and then invoke
the interactive conflict callback on each conflicted path found during
the status walk.
* subversion/svn/notify.c
(notify): Handle the new conflict summary notification. For now, this only
saves the resolver's conflict stats in the notify baton for later use.
In the future, when all operations delay invocation of the conflict callback,
we can rid of svn_cl__print_conflict_stats() and print the stats here.
Modified:
subversion/trunk/subversion/include/svn_wc.h
subversion/trunk/subversion/libsvn_wc/conflicts.c
subversion/trunk/subversion/svn/notify.c
Modified: subversion/trunk/subversion/include/svn_wc.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_wc.h?rev=1350917&r1=1350916&r2=1350917&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_wc.h (original)
+++ subversion/trunk/subversion/include/svn_wc.h Sat Jun 16 12:57:36 2012
@@ -1227,7 +1227,11 @@ typedef enum svn_wc_notify_action_t
/** Operation failed because a node is obstructed.
* @since New in 1.8. */
- svn_wc_notify_failed_obstruction
+ svn_wc_notify_failed_obstruction,
+
+ /** Summary of conflicts in the working copy.
+ * @since New in 1.8. */
+ svn_wc_notify_conflict_summary
} svn_wc_notify_action_t;
@@ -1413,6 +1417,12 @@ typedef struct svn_wc_notify_t {
* @since New in 1.7 */
svn_linenum_t hunk_fuzz;
+ /** Number of conflicts per kind, for conflict summary notification.
+ * @since New in 1.8 */
+ unsigned int text_conflicts;
+ unsigned int prop_conflicts;
+ unsigned int tree_conflicts;
+
/* NOTE: Add new fields at the end to preserve binary compatibility.
Also, if you add fields here, you have to update svn_wc_create_notify
and svn_wc_dup_notify. */
Modified: subversion/trunk/subversion/libsvn_wc/conflicts.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/conflicts.c?rev=1350917&r1=1350916&r2=1350917&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/conflicts.c (original)
+++ subversion/trunk/subversion/libsvn_wc/conflicts.c Sat Jun 16 12:57:36 2012
@@ -358,41 +358,87 @@ svn_wc__resolve_text_conflict(svn_wc__db
scratch_pool));
}
-
-/* Baton for conflict_status_walker */
-struct conflict_status_walker_baton
-{
+/* Baton for gather_conflict_stats() */
+struct gather_conflict_stats_baton {
svn_wc__db_t *db;
- svn_boolean_t resolve_text;
- const char *resolve_prop;
- svn_boolean_t resolve_tree;
- svn_wc_conflict_choice_t conflict_choice;
- svn_wc_conflict_resolver_func2_t conflict_func;
- void *conflict_baton;
- svn_cancel_func_t cancel_func;
- void *cancel_baton;
- svn_wc_notify_func2_t notify_func;
- void *notify_baton;
-};
+ apr_array_header_t *conflicted_paths;
+ unsigned int text_conflicts;
+ unsigned int prop_conflicts;
+ unsigned int tree_conflicts;
+ apr_pool_t *pool;
+} gather_conflict_stats_baton;
-/* Implements svn_wc_status4_t to walk all conflicts to resolve */
+
+/* Implements svn_wc_status4_t to walk all conflicts to resolve.
+ * Gathers conflicts for the purpose of sending a conflict summary
+ * and then process conflicts in turn. */
static svn_error_t *
-conflict_status_walker(void *baton,
- const char *local_abspath,
- const svn_wc_status3_t *status,
- apr_pool_t *scratch_pool)
+gather_conflict_stats(void *baton,
+ const char *local_abspath,
+ const svn_wc_status3_t *status,
+ apr_pool_t *scratch_pool)
{
- struct conflict_status_walker_baton *cswb = baton;
- svn_wc__db_t *db = cswb->db;
-
+ struct gather_conflict_stats_baton *b = baton;
const apr_array_header_t *conflicts;
- apr_pool_t *iterpool;
int i;
- svn_boolean_t resolved = FALSE;
if (!status->conflicted)
return SVN_NO_ERROR;
+ APR_ARRAY_PUSH(b->conflicted_paths,
+ const char *) = apr_pstrdup(b->pool, local_abspath);
+
+ SVN_ERR(svn_wc__db_read_conflicts(&conflicts, b->db, local_abspath,
+ scratch_pool, scratch_pool));
+ for (i = 0; i < conflicts->nelts; i++)
+ {
+ const svn_wc_conflict_description2_t *cd;
+
+ cd = APR_ARRAY_IDX(conflicts, i, const svn_wc_conflict_description2_t *);
+ switch (cd->kind)
+ {
+ case svn_wc_conflict_kind_text:
+ b->text_conflicts++;
+ break;
+ case svn_wc_conflict_kind_property:
+ b->prop_conflicts++;
+ break;
+ case svn_wc_conflict_kind_tree:
+ b->tree_conflicts++;
+ break;
+ default:
+ return svn_error_createf(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE,
+ NULL, _("Unkown conflict kind %d"),
+ cd->kind);
+ }
+ }
+
+ return SVN_NO_ERROR;
+}
+
+
+/* Give the conflict callback a go at resolving all conflicts at LOCAL_ABSPATH.
+ * All parameters as in svn_wc__resolve_conflicts(). */
+static svn_error_t *
+resolve_conflicts_on_node(const char *local_abspath,
+ svn_wc__db_t *db,
+ svn_boolean_t resolve_text,
+ const char *resolve_prop,
+ svn_boolean_t resolve_tree,
+ svn_wc_conflict_choice_t conflict_choice,
+ svn_wc_conflict_resolver_func2_t conflict_func,
+ void *conflict_baton,
+ svn_cancel_func_t cancel_func,
+ void *cancel_baton,
+ svn_wc_notify_func2_t notify_func,
+ void *notify_baton,
+ apr_pool_t *scratch_pool)
+{
+ const apr_array_header_t *conflicts;
+ svn_boolean_t resolved = FALSE;
+ int i;
+ apr_pool_t *iterpool;
+
iterpool = svn_pool_create(scratch_pool);
SVN_ERR(svn_wc__db_read_conflicts(&conflicts, db, local_abspath,
@@ -402,7 +448,7 @@ conflict_status_walker(void *baton,
{
const svn_wc_conflict_description2_t *cd;
svn_boolean_t did_resolve;
- svn_wc_conflict_choice_t my_choice = cswb->conflict_choice;
+ svn_wc_conflict_choice_t my_choice = conflict_choice;
cd = APR_ARRAY_IDX(conflicts, i, const svn_wc_conflict_description2_t *);
@@ -412,13 +458,13 @@ conflict_status_walker(void *baton,
{
svn_wc_conflict_result_t *result;
- if (!cswb->conflict_func)
+ if (!conflict_func)
return svn_error_create(SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE, NULL,
_("No conflict-callback and no "
"pre-defined conflict-choice provided"));
- SVN_ERR(cswb->conflict_func(&result, cd, cswb->conflict_baton,
- iterpool, iterpool));
+ SVN_ERR(conflict_func(&result, cd, conflict_baton,
+ iterpool, iterpool));
my_choice = result->choice;
}
@@ -430,7 +476,7 @@ conflict_status_walker(void *baton,
switch (cd->kind)
{
case svn_wc_conflict_kind_tree:
- if (!cswb->resolve_tree)
+ if (!resolve_tree)
break;
/* For now, we only clear tree conflict information and resolve
@@ -455,26 +501,27 @@ conflict_status_walker(void *baton,
FALSE /* resolve_props */,
TRUE /* resolve_tree */,
my_choice,
- cswb->cancel_func,
- cswb->cancel_baton,
+ cancel_func,
+ cancel_baton,
iterpool));
resolved = TRUE;
break;
case svn_wc_conflict_kind_text:
- if (!cswb->resolve_text)
+ if (!resolve_text)
break;
SVN_ERR(resolve_conflict_on_node(&did_resolve,
db,
local_abspath,
TRUE /* resolve_text */,
+
FALSE /* resolve_props */,
FALSE /* resolve_tree */,
my_choice,
- cswb->cancel_func,
- cswb->cancel_baton,
+ cancel_func,
+ cancel_baton,
iterpool));
if (did_resolve)
@@ -482,13 +529,13 @@ conflict_status_walker(void *baton,
break;
case svn_wc_conflict_kind_property:
- if (!cswb->resolve_prop)
+ if (!resolve_prop)
break;
/* ### this is bogus. resolve_conflict_on_node() does not handle
### individual property resolution. */
- if (*cswb->resolve_prop != '\0' &&
- strcmp(cswb->resolve_prop, cd->property_name) != 0)
+ if (*resolve_prop != '\0' &&
+ strcmp(resolve_prop, cd->property_name) != 0)
{
break; /* Skip this property conflict */
}
@@ -502,8 +549,8 @@ conflict_status_walker(void *baton,
TRUE /* resolve_props */,
FALSE /* resolve_tree */,
my_choice,
- cswb->cancel_func,
- cswb->cancel_baton,
+ cancel_func,
+ cancel_baton,
iterpool));
if (did_resolve)
@@ -517,12 +564,12 @@ conflict_status_walker(void *baton,
}
/* Notify */
- if (cswb->notify_func && resolved)
- cswb->notify_func(cswb->notify_baton,
- svn_wc_create_notify(local_abspath,
- svn_wc_notify_resolved,
- iterpool),
- iterpool);
+ if (notify_func && resolved)
+ notify_func(notify_baton,
+ svn_wc_create_notify(local_abspath,
+ svn_wc_notify_resolved,
+ iterpool),
+ iterpool);
svn_pool_destroy(iterpool);
@@ -547,7 +594,9 @@ svn_wc__resolve_conflicts(svn_wc_context
{
svn_kind_t kind;
svn_boolean_t conflicted;
- struct conflict_status_walker_baton cswb;
+ struct gather_conflict_stats_baton gcsb;
+ int i;
+ apr_pool_t *iterpool;
/* ### the underlying code does NOT support resolving individual
### properties. bail out if the caller tries it. */
@@ -572,21 +621,14 @@ svn_wc__resolve_conflicts(svn_wc_context
else if (depth == svn_depth_unknown)
depth = svn_depth_infinity;
- cswb.db = wc_ctx->db;
- cswb.resolve_text = resolve_text;
- cswb.resolve_prop = resolve_prop;
- cswb.resolve_tree = resolve_tree;
- cswb.conflict_choice = conflict_choice;
-
- cswb.conflict_func = conflict_func;
- cswb.conflict_baton = conflict_baton;
-
- cswb.cancel_func = cancel_func;
- cswb.cancel_baton = cancel_baton;
-
- cswb.notify_func = notify_func;
- cswb.notify_baton = notify_baton;
+ gcsb.db = wc_ctx->db;
+ gcsb.conflicted_paths = apr_array_make(scratch_pool, 0, sizeof(const char *));
+ gcsb.text_conflicts = 0;
+ gcsb.prop_conflicts = 0;
+ gcsb.tree_conflicts = 0;
+ gcsb.pool = scratch_pool;
+ /* Gather conflicts within LOCAL_ABSPATH. */
SVN_ERR(svn_wc_walk_status(wc_ctx,
local_abspath,
depth,
@@ -594,10 +636,42 @@ svn_wc__resolve_conflicts(svn_wc_context
FALSE /* no_ignore */,
TRUE /* ignore_text_mods */,
NULL /* ignore_patterns */,
- conflict_status_walker, &cswb,
+ gather_conflict_stats, &gcsb,
cancel_func, cancel_baton,
scratch_pool));
+ /* Send a conflict summary notification. */
+ if (notify_func)
+ {
+ svn_wc_notify_t *notify;
+
+ notify = svn_wc_create_notify(local_abspath,
+ svn_wc_notify_conflict_summary,
+ scratch_pool),
+ notify->text_conflicts = gcsb.text_conflicts;
+ notify->prop_conflicts = gcsb.prop_conflicts;
+ notify->tree_conflicts = gcsb.tree_conflicts;
+ notify_func(notify_baton, notify, scratch_pool);
+ }
+
+ /* Give the conflict callback a go at resolving conflicts. */
+ iterpool = svn_pool_create(scratch_pool);
+ for (i = 0; i < gcsb.conflicted_paths->nelts; i++)
+ {
+ const char *conflicted_path;
+
+ svn_pool_clear(iterpool);
+ conflicted_path = APR_ARRAY_IDX(gcsb.conflicted_paths, i, const char *);
+ SVN_ERR(resolve_conflicts_on_node(conflicted_path, wc_ctx->db,
+ resolve_text, resolve_prop,
+ resolve_tree, conflict_choice,
+ conflict_func, conflict_baton,
+ cancel_func, cancel_baton,
+ notify_func, notify_baton,
+ iterpool));
+ }
+ svn_pool_destroy(iterpool);
+
return SVN_NO_ERROR;
}
Modified: subversion/trunk/subversion/svn/notify.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/notify.c?rev=1350917&r1=1350916&r2=1350917&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/notify.c (original)
+++ subversion/trunk/subversion/svn/notify.c Sat Jun 16 12:57:36 2012
@@ -982,6 +982,15 @@ notify(void *baton, const svn_wc_notify_
goto print_error;
break;
+ case svn_wc_notify_conflict_summary:
+ /* Once all operations invoke the interactive conflict resolution after
+ * they've completed, we can run svn_cl__print_conflict_stats() here.
+ * For now, allow the resolver to override stats we've gathered. */
+ nb->text_conflicts = n->text_conflicts;
+ nb->prop_conflicts = n->prop_conflicts;
+ nb->tree_conflicts = n->tree_conflicts;
+ break;
+
default:
break;
}
RE: svn commit: r1350917 - in /subversion/trunk/subversion: include/svn_wc.h libsvn_wc/conflicts.c svn/notify.c
Posted by Bert Huijben <be...@qqmail.nl>.
> -----Original Message-----
> From: stsp@apache.org [mailto:stsp@apache.org]
> Sent: zaterdag 16 juni 2012 14:58
> To: commits@subversion.apache.org
> Subject: svn commit: r1350917 - in /subversion/trunk/subversion:
> include/svn_wc.h libsvn_wc/conflicts.c svn/notify.c
>
> Author: stsp
> Date: Sat Jun 16 12:57:36 2012
> New Revision: 1350917
>
> URL: http://svn.apache.org/viewvc?rev=1350917&view=rev
> Log:
> Make the conflict resolver send a conflict summary to the caller, before
> invoking the conflict callback.
>
> This will eventually allow 'svn' to print the conflict summary before the
> interactive conflict resolution callback is invoked. This summary is currently
> printed after the callback was invoked on each conflict, which isn't helpful.
>
> This commit has no visible behaviour change yet, as this would require all
> operations to delay conflict callback invocation, which has currently been
> implemented only for 'update'.
Why does libsvn_wc do the counting of the conflicts?
All the conflicts are already notified to the notification callback, so the counting itself could just be handled by svn (as far as I know the only client that uses these conflict stats in this way).
If some higher layer (such as libsvn_client) combines operations, the calculations done by libsvn_wc won't provide the necessary results.
I think we have some precedent of providing notification actions where we need these notifications, but I don't think libsvn_wc should do the counting.
Maybe the notification could be used more generic as something like _before_conflict_resolving, or something.
Bert