Hi tree-conflicts folks,
could you please scroll over this and see if you can remotely relate to what
is going on there? Branch tree-conflicts-notify, r33855.
Particularly, I see that right after calling check_tree_conflict(), I can't
get the tree-conflict state by doing
[[[
/* Find out whether it's a tree conflict victim. */
if (tree_conflicted_p != NULL)
{
svn_wc_conflict_description_t *conflict;
SVN_ERR_ASSERT(adm_access != NULL);
path = svn_path_join(dir_path, entry->name, subpool);
SVN_ERR(svn_wc_get_tree_conflict(&conflict, path, adm_access, subpool));
*tree_conflicted_p = (conflict != NULL);
}
]]]
(I try to do that in svn_wc_conflicted_p2(), called from
subversion/libsvn_wc/update_editor.c, e.g. line 2721 on the branch),
apparently because the tree-conflict reporting is loggy?
If you guys know how best to get the tree-conflicted state of a node, let me
know. At the moment I'm making check_tree_conflict() return a value to
explicitly indicate a conflict to the caller. But it would be nice to have
svn_wc_conflicted_p2() work as advertised on the branch.
Thanks,
~Neels
--
Neels Hofmeyr -- elego Software Solutions GmbH
Gustav-Meyer-Allee 25 / Gebäude 12, 13355 Berlin, Germany
phone: +49 30 23458696 mobile: +49 177 2345869 fax: +49 30 23458695
http://www.elegosoft.com | Geschäftsführer: Olaf Wagner | Sitz: Berlin
Handelsreg: Amtsgericht Charlottenburg HRB 77719 | USt-IdNr: DE163214194
attached mail follows:
Author: neels
Date: Wed Oct 22 18:04:30 2008
New Revision: 33855
Log:
On branch: tree-conflicts-notify
*** This is just a start. Don't waste too much time reviewing it! ***
*** Some parts of this may be misguided and go away again. ***
First looking specifically at `update', try to make as many cases as
possible show a tree-conflict on the victim and not its parent dir.
Some API enhancements, internal and public, all around svn_wc_notify_t.
* subversion/include/svn_wc.h
(svn_wc_conflict_action_t, svn_wc_conflict_reason_t): Move these enums
further up in the file, because we need them in svn_wc_notify_t.
(svn_wc_notify_t): Add fields to this struct to separate tree-conflict
information from text- and prop-conflict information.
### Do we really need all of it?
(svn_wc_conflicted_p2): Change the signature of this function to
be able to return the per-victim tree-conflict state.
Also cosmetically add a missing _p to a pointer argument name.
### Might not be implemented properly yet, and also might change again.
* subversion/libsvn_wc/util.c (svn_wc_create_notify): Fill in defaults for
the new fields in svn_wc_notify_t.
* subversion/svn/notify.c
(notify): Assemble and print the new tree-conflicts information in
svn_wc_notify_t. Make a conscious decision to only count text
conflicts when the node type is not a directory (although a directory
should never show a text-conflict anymore).
* subversion/libsvn_wc/update_editor.c
(check_tree_conflict): Add a *RESULT argument that returns to the caller
the type of the tree-conflict raised and logged, if any.
(do_entry_deletion, add_directory, open_directory, close_directory,
add_file, open_file): Apply new usage of check_tree_conflict() and
svn_wc_conflicted_p2(), (attempt to) explicitly notify about a tree-
conflict using the new fields in svn_wc_notify_t, and to skip all
other action if encountered.
* subversion/libsvn_wc/questions.c
(svn_wc_text_modified_p): (Attempt to) implement the API change of
svn_wc_conflicted_p2(), returning the per-victim tree-conflict state.
### Might not be implemented properly yet, and also might change again.
(svn_wc_conflicted_p): Apply API change of svn_wc_conflicted_p2().
* subversion/libsvn_client/externals.c (switch_file_external):
Apply API change of svn_wc_conflicted_p2() and try to use it.
* subversion/libsvn_client/commit_util.c (harvest_committables):
Apply API change of svn_wc_conflicted_p2() and try to use it.
* subversion/libsvn_wc/adm_ops.c (resolve_conflict_on_entry):
Apply API change of svn_wc_conflicted_p2() and try to use it.
* subversion/libsvn_wc/status.c (assemble_status):
Apply API change of svn_wc_conflicted_p2(), no usage change.
* subversion/tests/cmdline/svntest/actions.py
(deep_trees_conflicts_after_tree_del): New structure containing an expected
test result template.
### Unfinished.
* subversion/tests/cmdline/update_tests.py
(conflicts_after_tree_del): New global shortcut.
(tree_conflicts_on_update_1_1): Attempt at expecting new notification style.
### This needs a deeper py test framework change to work.
Modified:
branches/tree-conflicts-notify/subversion/include/svn_wc.h
branches/tree-conflicts-notify/subversion/libsvn_client/commit_util.c
branches/tree-conflicts-notify/subversion/libsvn_client/externals.c
branches/tree-conflicts-notify/subversion/libsvn_wc/adm_ops.c
branches/tree-conflicts-notify/subversion/libsvn_wc/questions.c
branches/tree-conflicts-notify/subversion/libsvn_wc/status.c
branches/tree-conflicts-notify/subversion/libsvn_wc/update_editor.c
branches/tree-conflicts-notify/subversion/libsvn_wc/util.c
branches/tree-conflicts-notify/subversion/svn/notify.c
branches/tree-conflicts-notify/subversion/tests/cmdline/svntest/actions.py
branches/tree-conflicts-notify/subversion/tests/cmdline/update_tests.py
Modified: branches/tree-conflicts-notify/subversion/include/svn_wc.h
URL: http://svn.collab.net/viewvc/svn/branches/tree-conflicts-notify/subversion/include/svn_wc.h?pathrev=33855&r1=33854&r2=33855
==============================================================================
--- branches/tree-conflicts-notify/subversion/include/svn_wc.h Wed Oct 22 17:20:29 2008 (r33854)
+++ branches/tree-conflicts-notify/subversion/include/svn_wc.h Wed Oct 22 18:04:30 2008 (r33855)
@@ -884,6 +884,41 @@ typedef enum svn_wc_notify_lock_state_t
} svn_wc_notify_lock_state_t;
+
+/* These two enums were originally found further down in this
+ * file, in the section called "Interactive conflict handling",
+ * but they were added to svn_wc_notify_t and needed up here.
+ */
+
+/** The type of action being attempted on an object.
+ *
+ * @since New in 1.5.
+ */
+typedef enum svn_wc_conflict_action_t
+{
+ svn_wc_conflict_action_edit, /* attempting to change text or props */
+ svn_wc_conflict_action_add, /* attempting to add object */
+ svn_wc_conflict_action_delete /* attempting to delete object */
+
+} svn_wc_conflict_action_t;
+
+
+/** The pre-existing condition which is causing a state of conflict.
+ *
+ * @since New in 1.5.
+ */
+typedef enum svn_wc_conflict_reason_t
+{
+ svn_wc_conflict_reason_edited, /* local edits are already present */
+ svn_wc_conflict_reason_obstructed, /* another object is in the way */
+ svn_wc_conflict_reason_deleted, /* object is already schedule-delete */
+ svn_wc_conflict_reason_added, /* object is already added or schedule-add */
+ svn_wc_conflict_reason_missing, /* object is unknown or missing */
+ svn_wc_conflict_reason_unversioned /* object is unversioned */
+
+} svn_wc_conflict_reason_t;
+
+
/**
* Structure used in the @c svn_wc_notify_func2_t function.
*
@@ -965,6 +1000,22 @@ typedef struct svn_wc_notify_t {
* displayed for an operation. @since New in 1.6 */
const char *path_prefix;
+ /** Whether @c path is a victim of a tree-conflict.
+ * @since New in 1.6 */
+ svn_boolean_t is_tree_conflict_victim;
+
+ /** If IS_TREE_CONFLICT_VICTIM is TRUE, this supplies the corresponding
+ * conflict action, i.e. what subversion tried to do but couldn't because
+ * it encountered a tree-conflict.
+ * @since New in 1.6 */
+ svn_wc_conflict_action_t tree_conflict_action;
+
+ /** If IS_TREE_CONFLICT_VICTIM is TRUE, this supplies the corresponding
+ * conflict reason, i.e. what is found in the working copy or the target
+ * and prevents an action that subversion wanted to carry out.
+ * @since New in 1.6 */
+ svn_wc_conflict_reason_t tree_conflict_reason;
+
/* 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. */
@@ -1096,34 +1147,6 @@ typedef svn_error_t *(*svn_wc_get_file_t
*
*/
-/** The type of action being attempted on an object.
- *
- * @since New in 1.5.
- */
-typedef enum svn_wc_conflict_action_t
-{
- svn_wc_conflict_action_edit, /* attempting to change text or props */
- svn_wc_conflict_action_add, /* attempting to add object */
- svn_wc_conflict_action_delete /* attempting to delete object */
-
-} svn_wc_conflict_action_t;
-
-
-/** The pre-existing condition which is causing a state of conflict.
- *
- * @since New in 1.5.
- */
-typedef enum svn_wc_conflict_reason_t
-{
- svn_wc_conflict_reason_edited, /* local edits are already present */
- svn_wc_conflict_reason_obstructed, /* another object is in the way */
- svn_wc_conflict_reason_deleted, /* object is already schedule-delete */
- svn_wc_conflict_reason_added, /* object is already added or schedule-add */
- svn_wc_conflict_reason_missing, /* object is unknown or missing */
- svn_wc_conflict_reason_unversioned /* object is unversioned */
-
-} svn_wc_conflict_reason_t;
-
/** The type of conflict being described by an @c
* svn_wc_conflict_description_t (see below).
@@ -2144,12 +2167,18 @@ svn_wc_entry_dup(const svn_wc_entry_t *e
/** Given a @a dir_path under version control, decide if one of its
* entries (@a entry) is in state of conflict; return the answers in
- * @a text_conflicted_p, @a prop_conflicted_p and @a
- * has_tree_conflicted_children.
+ * @a text_conflicted_p, @a prop_conflicted_p, @a tree_conflicted_p and
+ * @a has_tree_conflicted_children_p.
+ *
+ * Only @a tree_conflicted_p and @a has_tree_conflicted_children_p can
+ * be NULL, in which case no answer is supplied, repsectively.
+ *
+ * An @a adm_access is (only) needed to determine @a tree_conflicted_p.
+ * If @a tree_conflicted_p is NULL, @a adm_access may be NULL as well.
*
* If @a entry is the THIS_DIR entry of @a dir_path, and this directory
* currently contains one or more tree-conflicted children, then set
- * @a *has_tree_conflicted_children to true, else set it to false.
+ * @a *has_tree_conflicted_children_p to true, else set it to false.
*
* If the @a entry mentions that a text conflict file (.rej suffix)
* exists, but it cannot be found, assume the text conflict has been
@@ -2160,6 +2189,9 @@ svn_wc_entry_dup(const svn_wc_entry_t *e
* conflicts have been resolved by the user and return FALSE in
* @a *prop_conflicted_p.
*
+ * @a *tree_conflicted_p and @a *has_tree_conflicted_children_p are
+ * not auto-resolved in this fashion, an explicit `resolved' is needed.
+ *
* The @a entry is not updated.
*
* @since New in 1.6.
@@ -2167,9 +2199,11 @@ svn_wc_entry_dup(const svn_wc_entry_t *e
svn_error_t *
svn_wc_conflicted_p2(svn_boolean_t *text_conflicted_p,
svn_boolean_t *prop_conflicted_p,
- svn_boolean_t *has_tree_conflicted_children,
+ svn_boolean_t *tree_conflicted_p,
+ svn_boolean_t *has_tree_conflicted_children_p,
const char *dir_path,
const svn_wc_entry_t *entry,
+ svn_wc_adm_access_t *adm_access,
apr_pool_t *pool);
/** Like svn_wc_conflicted_p2, but without the capability to
Modified: branches/tree-conflicts-notify/subversion/libsvn_client/commit_util.c
URL: http://svn.collab.net/viewvc/svn/branches/tree-conflicts-notify/subversion/libsvn_client/commit_util.c?pathrev=33855&r1=33854&r2=33855
==============================================================================
--- branches/tree-conflicts-notify/subversion/libsvn_client/commit_util.c Wed Oct 22 17:20:29 2008 (r33854)
+++ branches/tree-conflicts-notify/subversion/libsvn_client/commit_util.c Wed Oct 22 18:04:30 2008 (r33855)
@@ -318,31 +318,25 @@ harvest_committables(apr_hash_t *committ
APR_HASH_KEY_STRING))))
{
entry = e;
- SVN_ERR(svn_wc_conflicted_p2(&tc, &pc, &treec, path, entry, pool));
+ SVN_ERR(svn_wc_conflicted_p2(&tc, &pc, &treec, NULL, path, entry,
+ adm_access, pool));
}
/* No new entry? Just check the parent's pointer for
conflicts. */
else
{
- SVN_ERR(svn_wc_conflicted_p2(&tc, &pc, &treec, p_path, entry,
- pool));
+ SVN_ERR(svn_wc_conflicted_p2(&tc, &pc, &treec, NULL, p_path, entry,
+ adm_access, pool));
}
}
/* If this is not a directory, check for conflicts using the
- parent's path. */
+ parent's path, passing this node's entry. */
else
{
- /* ### Maybe the tree-conflict test should be a separate function. */
- svn_boolean_t dummy;
- const svn_wc_entry_t *p_entry;
-
- SVN_ERR(svn_wc_entry(&p_entry, p_path, adm_access, TRUE, pool));
- SVN_ERR(svn_wc_conflicted_p2(&dummy, &dummy, &treec, p_path,
- p_entry, pool));
-
- SVN_ERR(svn_wc_conflicted_p2(&tc, &pc, &dummy, p_path, entry, pool));
+ SVN_ERR(svn_wc_conflicted_p2(&tc, &pc, &treec, NULL, p_path, entry,
+ adm_access, pool));
}
/* Bail now if any conflicts exist for the ENTRY. */
Modified: branches/tree-conflicts-notify/subversion/libsvn_client/externals.c
URL: http://svn.collab.net/viewvc/svn/branches/tree-conflicts-notify/subversion/libsvn_client/externals.c?pathrev=33855&r1=33854&r2=33855
==============================================================================
--- branches/tree-conflicts-notify/subversion/libsvn_client/externals.c Wed Oct 22 17:20:29 2008 (r33854)
+++ branches/tree-conflicts-notify/subversion/libsvn_client/externals.c Wed Oct 22 18:04:30 2008 (r33855)
@@ -376,7 +376,7 @@ switch_file_external(const char *path,
apr_file_t *f;
svn_boolean_t text_conflicted;
svn_boolean_t prop_conflicted;
- svn_boolean_t has_tree_conflicted_children;
+ svn_boolean_t tree_conflicted;
/* Check for a conflict on the containing directory. Because a
switch is done on the added file later, it will leave a
@@ -386,9 +386,10 @@ switch_file_external(const char *path,
SVN_ERR(svn_wc__entry_versioned(&anchor_dir_entry, anchor,
target_adm_access, FALSE, subpool));
SVN_ERR(svn_wc_conflicted_p2(&text_conflicted, &prop_conflicted,
- &has_tree_conflicted_children,
- anchor, anchor_dir_entry, subpool));
- if (text_conflicted || prop_conflicted)
+ &tree_conflicted, NULL, anchor,
+ anchor_dir_entry, target_adm_access,
+ subpool));
+ if (text_conflicted || prop_conflicted || tree_conflicted)
return svn_error_createf
(SVN_ERR_WC_FOUND_CONFLICT, 0,
_("The file external from '%s' cannot be written to '%s' while "
Modified: branches/tree-conflicts-notify/subversion/libsvn_wc/adm_ops.c
URL: http://svn.collab.net/viewvc/svn/branches/tree-conflicts-notify/subversion/libsvn_wc/adm_ops.c?pathrev=33855&r1=33854&r2=33855
==============================================================================
--- branches/tree-conflicts-notify/subversion/libsvn_wc/adm_ops.c Wed Oct 22 17:20:29 2008 (r33854)
+++ branches/tree-conflicts-notify/subversion/libsvn_wc/adm_ops.c Wed Oct 22 18:04:30 2008 (r33855)
@@ -2917,9 +2917,9 @@ resolve_conflict_on_entry(const char *pa
the successful resolution. */
svn_boolean_t text_conflict, prop_conflict, tree_conflict;
SVN_ERR(svn_wc_conflicted_p2(&text_conflict, &prop_conflict,
- &tree_conflict,
+ &tree_conflict, NULL,
svn_wc_adm_access_path(conflict_dir),
- entry, pool));
+ entry, conflict_dir, pool));
if ((! (resolve_text && text_conflict))
&& (! (resolve_props && prop_conflict))
&& (! (resolve_tree && tree_conflict)))
Modified: branches/tree-conflicts-notify/subversion/libsvn_wc/questions.c
URL: http://svn.collab.net/viewvc/svn/branches/tree-conflicts-notify/subversion/libsvn_wc/questions.c?pathrev=33855&r1=33854&r2=33855
==============================================================================
--- branches/tree-conflicts-notify/subversion/libsvn_wc/questions.c Wed Oct 22 17:20:29 2008 (r33854)
+++ branches/tree-conflicts-notify/subversion/libsvn_wc/questions.c Wed Oct 22 18:04:30 2008 (r33855)
@@ -542,9 +542,11 @@ svn_wc_text_modified_p(svn_boolean_t *mo
svn_error_t *
svn_wc_conflicted_p2(svn_boolean_t *text_conflicted_p,
svn_boolean_t *prop_conflicted_p,
- svn_boolean_t *has_tree_conflicted_children,
+ svn_boolean_t *tree_conflicted_p,
+ svn_boolean_t *has_tree_conflicted_children_p,
const char *dir_path,
const svn_wc_entry_t *entry,
+ svn_wc_adm_access_t *adm_access,
apr_pool_t *pool)
{
const char *path;
@@ -553,7 +555,10 @@ svn_wc_conflicted_p2(svn_boolean_t *text
*text_conflicted_p = FALSE;
*prop_conflicted_p = FALSE;
- *has_tree_conflicted_children = FALSE;
+ if (tree_conflicted_p != NULL)
+ *tree_conflicted_p = FALSE;
+ if (has_tree_conflicted_children_p != NULL)
+ *has_tree_conflicted_children_p = FALSE;
/* Look for any text conflict, exercising only as much effort as
necessary to obtain a definitive answer. This only applies to
@@ -594,11 +599,23 @@ svn_wc_conflicted_p2(svn_boolean_t *text
*prop_conflicted_p = TRUE;
}
- /* Check for tree conflicts (only "this-dir" entries have tree conflicts). */
- if ((strcmp(entry->name, SVN_WC_ENTRY_THIS_DIR) == 0)
+ /* Find out whether it's a tree conflict victim. */
+ if (tree_conflicted_p != NULL)
+ {
+ svn_wc_conflict_description_t *conflict;
+ SVN_ERR_ASSERT(adm_access != NULL);
+ path = svn_path_join(dir_path, entry->name, subpool);
+ SVN_ERR(svn_wc_get_tree_conflict(&conflict, path, adm_access, subpool));
+ *tree_conflicted_p = (conflict != NULL);
+ }
+
+ /* Check for contained tree conflicts (only "this-dir" entries
+ * contain tree conflicts). */
+ if ((has_tree_conflicted_children_p != NULL) &&
+ (strcmp(entry->name, SVN_WC_ENTRY_THIS_DIR) == 0)
&& entry->tree_conflict_data)
{
- *has_tree_conflicted_children = TRUE;
+ *has_tree_conflicted_children_p = TRUE;
}
svn_pool_destroy(subpool);
@@ -612,10 +629,8 @@ svn_wc_conflicted_p(svn_boolean_t *text_
const svn_wc_entry_t *entry,
apr_pool_t *pool)
{
- svn_boolean_t has_tree_conflicted_children;
return svn_wc_conflicted_p2(text_conflicted_p, prop_conflicted_p,
- &has_tree_conflicted_children, dir_path, entry,
- pool);
+ NULL, NULL, dir_path, entry, NULL, pool);
}
Modified: branches/tree-conflicts-notify/subversion/libsvn_wc/status.c
URL: http://svn.collab.net/viewvc/svn/branches/tree-conflicts-notify/subversion/libsvn_wc/status.c?pathrev=33855&r1=33854&r2=33855
==============================================================================
--- branches/tree-conflicts-notify/subversion/libsvn_wc/status.c Wed Oct 22 17:20:29 2008 (r33854)
+++ branches/tree-conflicts-notify/subversion/libsvn_wc/status.c Wed Oct 22 18:04:30 2008 (r33855)
@@ -426,7 +426,7 @@ assemble_status(svn_wc_status2_t **statu
if (entry->prejfile || entry->conflict_old ||
entry->conflict_new || entry->conflict_wrk)
{
- svn_boolean_t text_conflict_p, prop_conflict_p, dummy;
+ svn_boolean_t text_conflict_p, prop_conflict_p;
const char *parent_dir;
if (entry->kind == svn_node_dir)
@@ -438,7 +438,8 @@ assemble_status(svn_wc_status2_t **statu
marked it as resolved by deleting the artifact files, so check
for that. */
SVN_ERR(svn_wc_conflicted_p2(&text_conflict_p, &prop_conflict_p,
- &dummy, parent_dir, entry, pool));
+ NULL, &has_tree_conflicted_children,
+ parent_dir, entry, adm_access, pool));
if (text_conflict_p)
final_text_status = svn_wc_status_conflicted;
Modified: branches/tree-conflicts-notify/subversion/libsvn_wc/update_editor.c
URL: http://svn.collab.net/viewvc/svn/branches/tree-conflicts-notify/subversion/libsvn_wc/update_editor.c?pathrev=33855&r1=33854&r2=33855
==============================================================================
--- branches/tree-conflicts-notify/subversion/libsvn_wc/update_editor.c Wed Oct 22 17:20:29 2008 (r33854)
+++ branches/tree-conflicts-notify/subversion/libsvn_wc/update_editor.c Wed Oct 22 18:04:30 2008 (r33855)
@@ -1199,6 +1199,10 @@ tree_has_local_mods(svn_boolean_t *modif
* schedule-delete etc.), or NULL if FULL_PATH is unversioned.
* PARENT_ADM_ACCESS is the admin access baton of FULL_PATH's parent
* directory.
+ *
+ * *RESULT returns the conflict reason if a tree conflict was detected.
+ * If no conflict was detected, *RESULT will be
+ * (svn_wc_conflict_reason_t)(-1).
*/
static svn_error_t *
check_tree_conflict(struct edit_baton *eb,
@@ -1207,9 +1211,12 @@ check_tree_conflict(struct edit_baton *e
const svn_wc_entry_t *entry,
svn_wc_adm_access_t *parent_adm_access,
svn_wc_conflict_action_t action,
+ svn_wc_conflict_reason_t *result,
apr_pool_t *pool)
{
svn_wc_conflict_reason_t reason = (svn_wc_conflict_reason_t)(-1);
+ if (result != NULL)
+ *result = reason;
/* Test whether ACTION conflicts with the state of ENTRY.
* If so, set REASON to an appropriate value. */
@@ -1309,6 +1316,11 @@ check_tree_conflict(struct edit_baton *e
parent_adm_access, pool));
}
+ /* return the resulting conflict reason (if any, and if the
+ * result is asked for by the caller). */
+ if (result != NULL)
+ *result = reason;
+
return SVN_NO_ERROR;
}
@@ -1328,6 +1340,7 @@ do_entry_deletion(struct edit_baton *eb,
const svn_wc_entry_t *entry;
const char *full_path = svn_path_join(eb->anchor, path, pool);
svn_stringbuf_t *log_item = svn_stringbuf_create("", pool);
+ svn_wc_conflict_reason_t conflict_reason;
SVN_ERR(svn_wc_adm_retrieve(&adm_access, eb->adm_access,
parent_path, pool));
@@ -1335,7 +1348,25 @@ do_entry_deletion(struct edit_baton *eb,
SVN_ERR(svn_wc__entry_versioned(&entry, full_path, adm_access, FALSE, pool));
SVN_ERR(check_tree_conflict(eb, log_item, full_path, entry, adm_access,
- svn_wc_conflict_action_delete, pool));
+ svn_wc_conflict_action_delete,
+ &conflict_reason, pool));
+
+ /* If this raised a tree-conflict, notify and bail out. */
+ if (conflict_reason != (svn_wc_conflict_reason_t)(-1))
+ {
+ if (eb->notify_func)
+ {
+ svn_wc_notify_t *notify = svn_wc_create_notify(
+ full_path,
+ svn_wc_notify_update_delete,
+ pool);
+ notify->is_tree_conflict_victim = TRUE;
+ notify->tree_conflict_action = svn_wc_conflict_action_delete;
+ notify->tree_conflict_reason = conflict_reason;
+ (*eb->notify_func)(eb->notify_baton, notify, pool);
+ }
+ return SVN_NO_ERROR;
+ }
SVN_ERR(svn_wc__loggy_delete_entry(&log_item, adm_access, full_path,
pool));
@@ -1447,6 +1478,7 @@ add_directory(const char *path,
struct edit_baton *eb = pb->edit_baton;
struct dir_baton *db;
svn_node_kind_t kind;
+ svn_wc_conflict_reason_t conflict_reason = (svn_wc_conflict_reason_t)(-1);
SVN_ERR(make_dir_baton(&db, path, eb, pb, TRUE, pool));
*child_baton = db;
@@ -1570,7 +1602,8 @@ add_directory(const char *path,
/* Raise a tree conflict if this directory is already present. */
SVN_ERR(check_tree_conflict(eb, pb->log_accum, db->path, entry,
parent_adm_access,
- svn_wc_conflict_action_add, pool));
+ svn_wc_conflict_action_add,
+ &conflict_reason, pool));
/*
return svn_error_createf
@@ -1702,6 +1735,12 @@ add_directory(const char *path,
svn_wc_notify_exists : svn_wc_notify_update_add,
pool);
notify->kind = svn_node_dir;
+ if (conflict_reason != (svn_wc_conflict_reason_t)(-1))
+ {
+ notify->is_tree_conflict_victim = TRUE;
+ notify->tree_conflict_action = svn_wc_conflict_action_add;
+ notify->tree_conflict_reason = svn_wc_conflict_reason_added;
+ }
(*eb->notify_func)(eb->notify_baton, notify, pool);
}
@@ -1748,16 +1787,16 @@ open_directory(const char *path,
all flags. */
svn_boolean_t text_conflicted;
svn_boolean_t prop_conflicted;
- svn_boolean_t has_tree_conflicted_children;
+ svn_boolean_t tree_conflicted;
db->ambient_depth = entry->depth;
db->was_incomplete = entry->incomplete;
SVN_ERR(svn_wc_conflicted_p2(&text_conflicted, &prop_conflicted,
- &has_tree_conflicted_children, db->path,
- entry, pool));
+ &tree_conflicted, NULL,
+ db->path, entry, adm_access, pool));
SVN_ERR_ASSERT(! text_conflicted);
- if (prop_conflicted || has_tree_conflicted_children)
+ if (prop_conflicted || tree_conflicted)
{
db->bump_info->skipped = TRUE;
apr_hash_set(eb->skipped_paths, apr_pstrdup(eb->pool, db->path),
@@ -1767,7 +1806,16 @@ open_directory(const char *path,
svn_wc_notify_t *notify
= svn_wc_create_notify(db->path, svn_wc_notify_skip, pool);
notify->kind = svn_node_dir;
- notify->prop_state = svn_wc_notify_state_conflicted;
+ notify->prop_state = prop_conflicted
+ ? svn_wc_notify_state_conflicted
+ : svn_wc_notify_state_unknown;
+ if (tree_conflicted)
+ {
+ notify->is_tree_conflict_victim = FALSE;
+ notify->tree_conflict_action = svn_wc_conflict_action_edit;
+ /* ### TODO: This is wrong: */
+ notify->tree_conflict_reason = svn_wc_conflict_reason_edited;
+ }
(*eb->notify_func)(eb->notify_baton, notify, pool);
}
return SVN_NO_ERROR;
@@ -1777,7 +1825,7 @@ open_directory(const char *path,
/* Raise a tree conflict if scheduled for deletion or similar. */
SVN_ERR(check_tree_conflict(eb, pb->log_accum, db->path, entry,
parent_adm_access, svn_wc_conflict_action_edit,
- pool));
+ NULL, pool));
/* Mark directory as being at target_revision and URL, but incomplete. */
tmp_entry.revision = *(eb->target_revision);
@@ -1877,7 +1925,7 @@ close_directory(void *dir_baton,
apr_hash_t *base_props = NULL, *working_props = NULL;
svn_wc_adm_access_t *adm_access;
const svn_wc_entry_t *entry;
- svn_boolean_t has_tree_conflicted_children;
+ svn_boolean_t tree_conflicted;
svn_boolean_t text_conflicted, prop_conflicted; /* Dummies (never read). */
SVN_ERR(svn_categorize_props(db->propchanges, &entry_props, &wc_props,
@@ -2012,8 +2060,8 @@ close_directory(void *dir_baton,
/* Check for tree conflicts in this directory. */
SVN_ERR(svn_wc_entry(&entry, db->path, adm_access, TRUE, db->pool));
SVN_ERR(svn_wc_conflicted_p2(&text_conflicted, &prop_conflicted,
- &has_tree_conflicted_children, db->path, entry,
- db->pool));
+ &tree_conflicted, NULL, db->path, entry,
+ adm_access, db->pool));
/* Notify of any prop changes on this directory -- but do nothing
if it's an added or skipped directory, because notification has already
@@ -2031,9 +2079,7 @@ close_directory(void *dir_baton,
pool);
notify->kind = svn_node_dir;
notify->prop_state = prop_state;
- notify->content_state = has_tree_conflicted_children
- ? svn_wc_notify_state_conflicted
- : svn_wc_notify_state_unknown;
+ notify->is_tree_conflict_victim = tree_conflicted;
(*db->edit_baton->notify_func)(db->edit_baton->notify_baton,
notify, pool);
}
@@ -2488,6 +2534,7 @@ add_file(const char *path,
svn_node_kind_t kind;
svn_wc_adm_access_t *adm_access;
apr_pool_t *subpool;
+ svn_wc_conflict_reason_t conflict_reason;
if (copyfrom_path || SVN_IS_VALID_REVNUM(copyfrom_rev))
{
@@ -2519,7 +2566,28 @@ add_file(const char *path,
/* Raise a tree conflict if there's already something versioned here. */
SVN_ERR(check_tree_conflict(eb, pb->log_accum, path, entry, adm_access,
- svn_wc_conflict_action_add, pool));
+ svn_wc_conflict_action_add, &conflict_reason,
+ pool));
+
+ /* If a tree-conflict was raised, notify and bail out, furthermore
+ * skip this addition. */
+ if (conflict_reason != (svn_wc_conflict_reason_t)(-1))
+ {
+ fb->skipped = TRUE;
+ if (eb->notify_func)
+ {
+ const char *full_path = svn_path_join(eb->anchor, path, pool);
+ svn_wc_notify_t *notify = svn_wc_create_notify(
+ full_path,
+ svn_wc_notify_update_add,
+ pool);
+ notify->is_tree_conflict_victim = TRUE;
+ notify->tree_conflict_action = svn_wc_conflict_action_delete;
+ notify->tree_conflict_reason = conflict_reason;
+ (*eb->notify_func)(eb->notify_baton, notify, pool);
+ }
+ return SVN_NO_ERROR;
+ }
/* When adding, there should be nothing with this name unless unversioned
obstructions are permitted or the obstruction is scheduled for addition
@@ -2608,7 +2676,8 @@ open_file(const char *path,
svn_wc_adm_access_t *adm_access;
svn_boolean_t text_conflicted;
svn_boolean_t prop_conflicted;
- svn_boolean_t has_tree_conflicted_children;
+ svn_boolean_t caused_tree_conflict;
+ svn_wc_conflict_reason_t conflict_reason;
/* the file_pool can stick around for a *long* time, so we want to use
a subpool for any temporary allocations. */
@@ -2640,16 +2709,22 @@ open_file(const char *path,
* See also notes/tree-conflicts/detection.txt
*/
SVN_ERR(check_tree_conflict(eb, pb->log_accum, fb->path, entry, adm_access,
- svn_wc_conflict_action_edit, pool));
+ svn_wc_conflict_action_edit, &conflict_reason,
+ pool));
/* It is interesting to note: everything below is just validation. We
aren't actually doing any "work" or fetching any persistent data. */
- /* If the file is in conflict, don't mess with it. */
+ /* If the file is in conflict, don't mess with it.
+ * Btw, the tree conflict information is not available from this
+ * function yet, using the result above instead. */
SVN_ERR(svn_wc_conflicted_p2(&text_conflicted, &prop_conflicted,
- &has_tree_conflicted_children, pb->path, entry,
- pool));
- if (text_conflicted || prop_conflicted)
+ NULL, NULL, pb->path, entry,
+ adm_access, pool));
+
+ caused_tree_conflict = (conflict_reason != (svn_wc_conflict_reason_t)(-1));
+
+ if (text_conflicted || prop_conflicted || caused_tree_conflict)
{
fb->skipped = TRUE;
apr_hash_set(eb->skipped_paths, apr_pstrdup(eb->pool, fb->path),
@@ -2657,14 +2732,28 @@ open_file(const char *path,
if (eb->notify_func)
{
svn_wc_notify_t *notify
- = svn_wc_create_notify(fb->path, svn_wc_notify_skip, pool);
+ = svn_wc_create_notify(fb->path,
+ caused_tree_conflict
+ ? svn_wc_notify_update_update
+ : svn_wc_notify_skip,
+ pool);
notify->kind = svn_node_file;
+
notify->content_state = text_conflicted
? svn_wc_notify_state_conflicted
: svn_wc_notify_state_unknown;
+
notify->prop_state = prop_conflicted
? svn_wc_notify_state_conflicted
: svn_wc_notify_state_unknown;
+
+ if (caused_tree_conflict)
+ {
+ notify->is_tree_conflict_victim = caused_tree_conflict;
+ notify->tree_conflict_action = svn_wc_conflict_action_edit;
+ notify->tree_conflict_reason = conflict_reason;
+ }
+
(*eb->notify_func)(eb->notify_baton, notify, pool);
}
}
Modified: branches/tree-conflicts-notify/subversion/libsvn_wc/util.c
URL: http://svn.collab.net/viewvc/svn/branches/tree-conflicts-notify/subversion/libsvn_wc/util.c?pathrev=33855&r1=33854&r2=33855
==============================================================================
--- branches/tree-conflicts-notify/subversion/libsvn_wc/util.c Wed Oct 22 17:20:29 2008 (r33854)
+++ branches/tree-conflicts-notify/subversion/libsvn_wc/util.c Wed Oct 22 18:04:30 2008 (r33855)
@@ -129,6 +129,9 @@ svn_wc_create_notify(const char *path,
ret->changelist_name = NULL;
ret->merge_range = NULL;
ret->path_prefix = NULL;
+ ret->is_tree_conflict_victim = FALSE;
+ ret->tree_conflict_action = (svn_wc_conflict_action_t)(-1);
+ ret->tree_conflict_reason = (svn_wc_conflict_reason_t)(-1);
return ret;
}
Modified: branches/tree-conflicts-notify/subversion/svn/notify.c
URL: http://svn.collab.net/viewvc/svn/branches/tree-conflicts-notify/subversion/svn/notify.c?pathrev=33855&r1=33854&r2=33855
==============================================================================
--- branches/tree-conflicts-notify/subversion/svn/notify.c Wed Oct 22 17:20:29 2008 (r33854)
+++ branches/tree-conflicts-notify/subversion/svn/notify.c Wed Oct 22 18:04:30 2008 (r33855)
@@ -118,7 +118,8 @@ static void
notify(void *baton, const svn_wc_notify_t *n, apr_pool_t *pool)
{
struct notify_baton *nb = baton;
- char statchar_buf[5] = " ";
+ char statchar_buf[4] = " ";
+ char tree_conflict_char_buf[8] = " ";
const char *path_local = n->path;
svn_error_t *err;
@@ -137,6 +138,54 @@ notify(void *baton, const svn_wc_notify_
path_local = svn_path_local_style(path_local, pool);
+ if (n->is_tree_conflict_victim)
+ {
+ nb->in_external ? nb->ext_tree_conflicts++
+ : nb->tree_conflicts++;
+
+ memcpy(tree_conflict_char_buf, "C( -> )", 7);
+
+ switch (n->tree_conflict_action){
+ case svn_wc_conflict_action_add:
+ tree_conflict_char_buf[2] = 'A';
+ break;
+ case svn_wc_conflict_action_edit:
+ tree_conflict_char_buf[2] = 'M';
+ break;
+ case svn_wc_conflict_action_delete:
+ tree_conflict_char_buf[2] = 'D';
+ break;
+ default:
+ tree_conflict_char_buf[2] = '#';
+ break;
+ }
+
+ switch (n->tree_conflict_action){
+ case svn_wc_conflict_reason_added:
+ tree_conflict_char_buf[5] = 'A';
+ break;
+ case svn_wc_conflict_reason_edited:
+ tree_conflict_char_buf[5] = 'M';
+ break;
+ case svn_wc_conflict_reason_deleted:
+ tree_conflict_char_buf[5] = 'D';
+ break;
+ case svn_wc_conflict_reason_unversioned:
+ tree_conflict_char_buf[5] = '?';
+ break;
+ case svn_wc_conflict_reason_obstructed:
+ tree_conflict_char_buf[5] = '~';
+ break;
+ case svn_wc_conflict_reason_missing:
+ tree_conflict_char_buf[5] = '!';
+ break;
+ default:
+ tree_conflict_char_buf[5] = '#';
+ break;
+ }
+
+ }
+
switch (n->action)
{
case svn_wc_notify_skip:
@@ -159,13 +208,15 @@ notify(void *baton, const svn_wc_notify_
case svn_wc_notify_update_delete:
nb->received_some_change = TRUE;
- if ((err = svn_cmdline_printf(pool, "D %s\n", path_local)))
+ if ((err = svn_cmdline_printf(pool, "D %s %s\n", tree_conflict_char_buf,
+ path_local)))
goto print_error;
break;
case svn_wc_notify_update_replace:
nb->received_some_change = TRUE;
- if ((err = svn_cmdline_printf(pool, "R %s\n", path_local)))
+ if ((err = svn_cmdline_printf(pool, "R %s %s\n", tree_conflict_char_buf,
+ path_local)))
goto print_error;
break;
@@ -173,21 +224,18 @@ notify(void *baton, const svn_wc_notify_
nb->received_some_change = TRUE;
if (n->content_state == svn_wc_notify_state_conflicted)
{
- /* TODO: This needs to be adjusted once we report
- * tree conflict victims, instead of their parent
- * directories, on update/merge. */
- if (n->kind == svn_node_dir)
- nb->in_external ? nb->ext_tree_conflicts++
- : nb->tree_conflicts++;
- else
- nb->in_external ? nb->ext_text_conflicts++
- : nb->text_conflicts++;
- if ((err = svn_cmdline_printf(pool, "C %s\n", path_local)))
+ nb->in_external ? nb->ext_text_conflicts++
+ : nb->text_conflicts++;
+ if ((err = svn_cmdline_printf(pool, "C %s %s\n",
+ tree_conflict_char_buf,
+ path_local)))
goto print_error;
}
else
{
- if ((err = svn_cmdline_printf(pool, "A %s\n", path_local)))
+ if ((err = svn_cmdline_printf(pool, "A %s %s\n",
+ tree_conflict_char_buf,
+ path_local)))
goto print_error;
}
break;
@@ -196,15 +244,8 @@ notify(void *baton, const svn_wc_notify_
nb->received_some_change = TRUE;
if (n->content_state == svn_wc_notify_state_conflicted)
{
- /* TODO: This needs to be adjusted once we report
- * tree conflict victims, instead of their parent
- * directories, on update/merge. */
- if (n->kind == svn_node_dir)
- nb->in_external ? nb->ext_tree_conflicts++
- : nb->tree_conflicts++;
- else
- nb->in_external ? nb->ext_text_conflicts++
- : nb->text_conflicts++;
+ nb->in_external ? nb->ext_text_conflicts++
+ : nb->text_conflicts++;
statchar_buf[0] = 'C';
}
else
@@ -219,7 +260,9 @@ notify(void *baton, const svn_wc_notify_
else if (n->prop_state == svn_wc_notify_state_merged)
statchar_buf[1] = 'G';
- if ((err = svn_cmdline_printf(pool, "%s %s\n", statchar_buf, path_local)))
+ if ((err = svn_cmdline_printf(pool, "%s%s %s\n", statchar_buf,
+ tree_conflict_char_buf,
+ path_local)))
goto print_error;
break;
@@ -255,13 +298,15 @@ notify(void *baton, const svn_wc_notify_
is a binary addition. */
if (n->mime_type && (svn_mime_type_is_binary(n->mime_type)))
{
- if ((err = svn_cmdline_printf(pool, "A (bin) %s\n",
+ if ((err = svn_cmdline_printf(pool, "A %s(bin) %s\n",
+ tree_conflict_char_buf,
path_local)))
goto print_error;
}
else
{
- if ((err = svn_cmdline_printf(pool, "A %s\n",
+ if ((err = svn_cmdline_printf(pool, "A %s %s\n",
+ tree_conflict_char_buf,
path_local)))
goto print_error;
}
@@ -269,7 +314,8 @@ notify(void *baton, const svn_wc_notify_
case svn_wc_notify_delete:
nb->received_some_change = TRUE;
- if ((err = svn_cmdline_printf(pool, "D %s\n",
+ if ((err = svn_cmdline_printf(pool, "D %s %s\n",
+ tree_conflict_char_buf,
path_local)))
goto print_error;
break;
@@ -278,15 +324,8 @@ notify(void *baton, const svn_wc_notify_
{
if (n->content_state == svn_wc_notify_state_conflicted)
{
- /* TODO: This needs to be adjusted once we report
- * tree conflict victims, instead of their parent
- * directories, on update/merge. */
- if (n->kind == svn_node_dir)
- nb->in_external ? nb->ext_tree_conflicts++
- : nb->tree_conflicts++;
- else
- nb->in_external ? nb->ext_text_conflicts++
- : nb->text_conflicts++;
+ nb->in_external ? nb->ext_text_conflicts++
+ : nb->text_conflicts++;
statchar_buf[0] = 'C';
}
else if (n->kind == svn_node_file)
@@ -311,14 +350,17 @@ notify(void *baton, const svn_wc_notify_
if (n->lock_state == svn_wc_notify_lock_state_unlocked)
statchar_buf[2] = 'B';
- if (statchar_buf[0] != ' ' || statchar_buf[1] != ' ')
+ if (statchar_buf[0] != ' ' || statchar_buf[1] != ' '
+ || n->is_tree_conflict_victim)
nb->received_some_change = TRUE;
if (statchar_buf[0] != ' ' || statchar_buf[1] != ' '
- || statchar_buf[2] != ' ')
+ || statchar_buf[2] != ' ' || n->is_tree_conflict_victim)
{
- if ((err = svn_cmdline_printf(pool, "%s %s\n",
- statchar_buf, path_local)))
+ if ((err = svn_cmdline_printf(pool, "%s%s %s\n",
+ statchar_buf,
+ tree_conflict_char_buf,
+ path_local)))
goto print_error;
}
}
Modified: branches/tree-conflicts-notify/subversion/tests/cmdline/svntest/actions.py
URL: http://svn.collab.net/viewvc/svn/branches/tree-conflicts-notify/subversion/tests/cmdline/svntest/actions.py?pathrev=33855&r1=33854&r2=33855
==============================================================================
--- branches/tree-conflicts-notify/subversion/tests/cmdline/svntest/actions.py Wed Oct 22 17:20:29 2008 (r33854)
+++ branches/tree-conflicts-notify/subversion/tests/cmdline/svntest/actions.py Wed Oct 22 18:04:30 2008 (r33855)
@@ -1768,6 +1768,18 @@ deep_trees_after_tree_del = wc.State('',
})
+# The items that should be reported conflicted in a tree-conflict that
+# involves deep_trees_tree_del.
+deep_trees_conflicts_after_tree_del = wc.State('', {
+ 'F/alpha' : Item(status=' C'),
+ 'D/D1' : Item(status=' C'),
+ 'DF/D1' : Item(status=' C'),
+ 'DD/D1' : Item(status=' C'),
+ 'DDF/D1' : Item(status=' C'),
+ 'DDD/D1' : Item(status=' C'),
+ })
+
+
class DeepTreesTestCase:
Modified: branches/tree-conflicts-notify/subversion/tests/cmdline/update_tests.py
URL: http://svn.collab.net/viewvc/svn/branches/tree-conflicts-notify/subversion/tests/cmdline/update_tests.py?pathrev=33855&r1=33854&r2=33855
==============================================================================
--- branches/tree-conflicts-notify/subversion/tests/cmdline/update_tests.py Wed Oct 22 17:20:29 2008 (r33854)
+++ branches/tree-conflicts-notify/subversion/tests/cmdline/update_tests.py Wed Oct 22 18:04:30 2008 (r33855)
@@ -3969,6 +3969,7 @@ leaf_del = svntest.actions.deep_trees_le
state_after_leaf_edit = svntest.actions.deep_trees_after_leaf_edit
state_after_leaf_del = svntest.actions.deep_trees_after_leaf_del
state_after_tree_del = svntest.actions.deep_trees_after_tree_del
+conflicts_after_tree_del = svntest.actions.deep_trees_conflicts_after_tree_del
DeepTreesTestCase = svntest.actions.DeepTreesTestCase
@@ -3979,21 +3980,15 @@ def tree_conflicts_on_update_1_1(sbox):
# use case 1, as in notes/tree-conflicts/use-cases.txt
# 1.1) local tree delete, incoming leaf edit
- expected_output = wc.State('', {
- 'F' : Item(status='C '),
- 'D' : Item(status='C '),
- 'DF' : Item(status='C '),
- 'DD' : Item(status='C '),
- 'DDF' : Item(status='C '),
- 'DDD' : Item(status='C '),
- })
+ expected_output = conflicts_after_tree_del;
expected_disk = state_after_tree_del
- expected_status = state_after_tree_del.copy()
+ expected_status = conflicts_after_tree_del.copy()
expected_status.add({ '' : Item(status=' ') }) # also set root's attributes
expected_status.tweak(wc_rev=3)
- expected_status.tweak('F', 'D', 'DF', 'DD', 'DDF', 'DDD', status='C ')
+ expected_status.tweak('F/alpha', 'D/D1', 'DF/D1', 'DD/D1', 'DDF/D1', 'DDD/D1',
+ status=' C')
svntest.actions.deep_trees_run_tests_scheme_for_update(sbox,
[ DeepTreesTestCase("local_tree_del_incoming_leaf_edit",
---------------------------------------------------------------------
To unsubscribe, e-mail: svn-unsubscribe_at_subversion.tigris.org
For additional commands, e-mail: svn-help_at_subversion.tigris.org
Received on 2008-10-23 10:32:45 CEST