[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

[Fwd: svn commit: r33855 - in branches/tree-conflicts-notify/subversion: include libsvn_client libsvn_wc svn tests/cmdline tests/cmdline/svntest]

From: Neels J. Hofmeyr <neels_at_elego.de>
Date: Thu, 23 Oct 2008 10:32:04 +0200

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

This is an archived mail posted to the Subversion Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.