You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2013/01/27 00:11:36 UTC

svn commit: r1438990 - in /subversion/trunk/subversion: include/private/svn_wc_private.h libsvn_client/repos_diff.c libsvn_wc/diff_editor.c

Author: rhuijben
Date: Sat Jan 26 23:11:35 2013
New Revision: 1438990

URL: http://svn.apache.org/viewvc?rev=1438990&view=rev
Log:
Add an absent handler to the libsvn_wc diff processor to diff callback wrapper.

* subversion/include/private/svn_wc_private.h
  (svn_wc__diff_state_absent_t): New typedef.

* subversion/libsvn_client/repos_diff.c
  (edit_baton): Extract state handling members to their own struct.
  (send_delete_notify): Remove function. Integrate code in its only caller.
  (absent_directory,
   absent_file): Call node_absent on the diff processor instead of notifying
     directly.

  (diff_notify_baton_t): New struct.
  (diff_state_handle,
   diff_state_close): Use diff_notify_baton_t. Fold send_delete_notify code.
  (diff_state_absent): New function.

  (svn_client__get_diff_editor): Update caller.

* subversion/libsvn_wc/diff_editor.c
  (wc_diff_wrap_baton_t): Add callback.
  (wrap_node_absent): New function.
  (svn_wc__wrap_diff_callbacks): Update initialization.

Modified:
    subversion/trunk/subversion/include/private/svn_wc_private.h
    subversion/trunk/subversion/libsvn_client/repos_diff.c
    subversion/trunk/subversion/libsvn_wc/diff_editor.c

Modified: subversion/trunk/subversion/include/private/svn_wc_private.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_wc_private.h?rev=1438990&r1=1438989&r2=1438990&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_wc_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_wc_private.h Sat Jan 26 23:11:35 2013
@@ -1701,6 +1701,15 @@ typedef svn_error_t *
                                       void *state_baton,
                                       apr_pool_t *scratch_pool);
 
+/** Callback for the svn_diff_tree_processor_t wrapper, to allow handling
+ *  absent nodes.
+ *
+ * Probably only necessary while transitioning to svn_diff_tree_processor_t
+ */
+typedef svn_error_t *
+        (*svn_wc__diff_state_absent_t)(const char *relpath,
+                                       void *state_baton,
+                                       apr_pool_t *scratch_pool);
 
 /** Obtains a diff processor that will drive the diff callbacks when it
  * is invoked. The state arguments will be handled by the state processor
@@ -1712,6 +1721,7 @@ svn_wc__wrap_diff_callbacks(svn_diff_tre
                             void *callback_baton,
                             svn_wc__diff_state_handle_t state_handle,
                             svn_wc__diff_state_close_t state_close,
+                            svn_wc__diff_state_absent_t state_absent,
                             void *state_baton,
                             apr_pool_t *result_pool,
                             apr_pool_t *scratch_pool);

Modified: subversion/trunk/subversion/libsvn_client/repos_diff.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_client/repos_diff.c?rev=1438990&r1=1438989&r2=1438990&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_client/repos_diff.c (original)
+++ subversion/trunk/subversion/libsvn_client/repos_diff.c Sat Jan 26 23:11:35 2013
@@ -77,15 +77,6 @@ struct edit_baton {
   /* Empty hash used for adds. */
   apr_hash_t *empty_hash;
 
-  /* Hash used to check replaced paths. Key is path relative CWD,
-   * Value is *deleted_path_notify_t.
-   * All allocations are from edit_baton's pool. */
-  apr_hash_t *deleted_paths;
-
-  /* If the func is non-null, send notifications of actions. */
-  svn_wc_notify_func2_t notify_func;
-  void *notify_baton;
-
   /* TRUE if the operation needs to walk deleted dirs on the "old" side.
      FALSE otherwise. */
   svn_boolean_t walk_deleted_repos_dirs;
@@ -392,43 +383,6 @@ remove_non_prop_changes(apr_hash_t *pris
     }
 }
 
-/* Send outstanding deletes for everything below PATH */
-static svn_error_t *
-send_delete_notify(struct edit_baton *eb,
-                   const char *path,
-                   apr_pool_t *scratch_pool)
-{
-  apr_hash_index_t *hi;
-
-  if (! eb->notify_func)
-    return SVN_NO_ERROR;
-
-  for (hi = apr_hash_first(scratch_pool, eb->deleted_paths); hi;
-       hi = apr_hash_next(hi))
-    {
-      svn_wc_notify_t *notify;
-      const char *deleted_path = svn__apr_hash_index_key(hi);
-      deleted_path_notify_t *dpn = svn__apr_hash_index_val(hi);
-
-      /* Ignore paths which are not children of bb->path.  (There
-         should be none due to editor ordering constraints, but
-         ra_serf drops the ball here -- see issue #3802 for
-         details.) */
-      if (! svn_relpath_skip_ancestor(path, deleted_path))
-        continue;
-
-      notify = svn_wc_create_notify(deleted_path, dpn->action, scratch_pool);
-      notify->kind = dpn->kind;
-      notify->content_state = notify->prop_state = dpn->state;
-      notify->lock_state = svn_wc_notify_lock_state_inapplicable;
-      (*eb->notify_func)(eb->notify_baton, notify, scratch_pool);
-      apr_hash_set(eb->deleted_paths, deleted_path,
-                   APR_HASH_KEY_STRING, NULL);
-    }
-  return SVN_NO_ERROR;
-}
-
-
 /* Get the empty file associated with the edit baton. This is cached so
  * that it can be reused, all empty files are the same.
  */
@@ -1186,18 +1140,7 @@ absent_directory(const char *path,
   struct dir_baton *pb = parent_baton;
   struct edit_baton *eb = pb->edit_baton;
 
-  /* ### TODO: Raise a tree-conflict?? I sure hope not.*/
-
-  if (eb->notify_func)
-    {
-      svn_wc_notify_t *notify
-        = svn_wc_create_notify(path, svn_wc_notify_skip, pool);
-
-      notify->kind = svn_node_dir;
-      notify->content_state = notify->prop_state
-        = svn_wc_notify_state_missing;
-      (*eb->notify_func)(eb->notify_baton, notify, pool);
-    }
+  SVN_ERR(eb->processor->node_absent(path, pb->pdb, eb->processor, pool));
 
   return SVN_NO_ERROR;
 }
@@ -1213,18 +1156,7 @@ absent_file(const char *path,
   struct dir_baton *pb = parent_baton;
   struct edit_baton *eb = pb->edit_baton;
 
-  /* ### TODO: Raise a tree-conflict?? I sure hope not.*/
-
-  if (eb->notify_func)
-    {
-      svn_wc_notify_t *notify
-        = svn_wc_create_notify(path, svn_wc_notify_skip, pool);
-
-      notify->kind = svn_node_file;
-      notify->content_state = notify->prop_state
-        = svn_wc_notify_state_missing;
-      (*eb->notify_func)(eb->notify_baton, notify, pool);
-    }
+  SVN_ERR(eb->processor->node_absent(path, pb->pdb, eb->processor, pool));
 
   return SVN_NO_ERROR;
 }
@@ -1328,6 +1260,21 @@ fetch_base_func(const char **filename,
   return SVN_NO_ERROR;
 }
 
+/* Baton for diff_state_* functions */
+struct diff_notify_baton_t
+{
+  /* Hash used to check replaced paths. Key is path relative CWD,
+   * Value is *deleted_path_notify_t.
+   * All allocations are from edit_baton's pool. */
+  apr_hash_t *deleted_paths;
+
+  /* If the func is non-null, send notifications of actions. */
+  svn_wc_notify_func2_t notify_func;
+  void *notify_baton;
+
+  apr_pool_t *pool;
+};
+
 /** Callback for the svn_diff_tree_processor_t wrapper, to allow handling
  *  notifications like how the repos diff in libsvn_client does.
  *
@@ -1345,11 +1292,11 @@ diff_state_handle(svn_boolean_t tree_con
                   void *state_baton,
                   apr_pool_t *scratch_pool)
 {
-  struct edit_baton *eb = state_baton;
+  struct diff_notify_baton_t *dnb = state_baton;
   svn_wc_notify_state_t notify_content_state = svn_wc_notify_state_inapplicable;
   svn_wc_notify_state_t notify_prop_state = svn_wc_notify_state_inapplicable;
 
-  if (! eb->notify_func)
+  if (! dnb->notify_func)
     return SVN_NO_ERROR;
 
   if ((for_delete && before_operation && !tree_conflicted)
@@ -1361,11 +1308,9 @@ diff_state_handle(svn_boolean_t tree_con
       const char *deleted_path;
       deleted_path_notify_t *dpn;
       svn_wc_notify_action_t action;
-      svn_node_kind_t notify_kind = (kind == svn_kind_dir) ? svn_node_dir
-                                                           : svn_node_file;
 
-      deleted_path = apr_pstrdup(eb->pool, relpath);
-      dpn = apr_pcalloc(eb->pool, sizeof(*dpn));
+      deleted_path = apr_pstrdup(dnb->pool, relpath);
+      dpn = apr_pcalloc(dnb->pool, sizeof(*dpn));
 
       if (!tree_conflicted
           && state
@@ -1381,7 +1326,7 @@ diff_state_handle(svn_boolean_t tree_con
       dpn->action = tree_conflicted ? svn_wc_notify_tree_conflict : action;
       dpn->state = state ? *state : svn_wc_notify_state_inapplicable;
       dpn->tree_conflicted = tree_conflicted;
-      apr_hash_set(eb->deleted_paths, deleted_path, APR_HASH_KEY_STRING, dpn);
+      apr_hash_set(dnb->deleted_paths, deleted_path, APR_HASH_KEY_STRING, dpn);
 
       return SVN_NO_ERROR;
     }
@@ -1392,18 +1337,18 @@ diff_state_handle(svn_boolean_t tree_con
       deleted_path_notify_t *dpn;
       svn_node_kind_t notify_kind;
 
-      apr_hash_set(eb->deleted_paths, relpath,
+      apr_hash_set(dnb->deleted_paths, relpath,
                    APR_HASH_KEY_STRING, NULL);
 
       notify = svn_wc_create_notify(relpath, svn_wc_notify_tree_conflict,
                                     scratch_pool);
 
-      dpn = apr_hash_get(eb->deleted_paths, relpath, APR_HASH_KEY_STRING);
+      dpn = apr_hash_get(dnb->deleted_paths, relpath, APR_HASH_KEY_STRING);
       if (dpn)
         {
           /* If any was found, we will handle the pending 'deleted path
           * notification' (DPN) here. Remove it from the list. */
-          apr_hash_set(eb->deleted_paths, relpath,
+          apr_hash_set(dnb->deleted_paths, relpath,
               APR_HASH_KEY_STRING, NULL);
 
           /* the pending delete might be on a different node kind. */
@@ -1411,7 +1356,7 @@ diff_state_handle(svn_boolean_t tree_con
         }
 
       notify->kind = notify_kind;
-      (*eb->notify_func)(eb->notify_baton, notify, scratch_pool);
+      (*dnb->notify_func)(dnb->notify_baton, notify, scratch_pool);
       return SVN_NO_ERROR;
     }
 
@@ -1439,7 +1384,7 @@ diff_state_handle(svn_boolean_t tree_con
       notify->kind = (kind == svn_kind_dir) ? svn_node_dir : svn_node_file;
       notify->content_state = notify_content_state;
       notify->prop_state = notify_prop_state;
-      (*eb->notify_func)(eb->notify_baton, notify, scratch_pool);
+      (*dnb->notify_func)(dnb->notify_baton, notify, scratch_pool);
       return SVN_NO_ERROR;
     }
 
@@ -1460,12 +1405,12 @@ diff_state_handle(svn_boolean_t tree_con
 
     /* Find out if a pending delete notification for this path is
     * still around. */
-    dpn = apr_hash_get(eb->deleted_paths, relpath, APR_HASH_KEY_STRING);
+    dpn = apr_hash_get(dnb->deleted_paths, relpath, APR_HASH_KEY_STRING);
     if (dpn)
       {
         /* If any was found, we will handle the pending 'deleted path
         * notification' (DPN) here. Remove it from the list. */
-        apr_hash_set(eb->deleted_paths, relpath,
+        apr_hash_set(dnb->deleted_paths, relpath,
                      APR_HASH_KEY_STRING, NULL);
 
         /* the pending delete might be on a different node kind. */
@@ -1480,7 +1425,7 @@ diff_state_handle(svn_boolean_t tree_con
     notify->kind = notify_kind;
     notify->content_state = notify_content_state;
     notify->prop_state = notify_prop_state;
-    (*eb->notify_func)(eb->notify_baton, notify, scratch_pool);
+    (*dnb->notify_func)(dnb->notify_baton, notify, scratch_pool);
   }
 
   return SVN_NO_ERROR;
@@ -1492,12 +1437,55 @@ diff_state_close(const char *relpath,
                  void *state_baton,
                  apr_pool_t *scratch_pool)
 {
-  struct edit_baton *eb = state_baton;
-  SVN_ERR(send_delete_notify(eb, relpath, scratch_pool));
+  struct diff_notify_baton_t *dnb = state_baton;
+  apr_hash_index_t *hi;
+
+  if (! dnb->notify_func)
+    return SVN_NO_ERROR;
+
+  for (hi = apr_hash_first(scratch_pool, dnb->deleted_paths); hi;
+       hi = apr_hash_next(hi))
+    {
+      svn_wc_notify_t *notify;
+      const char *deleted_path = svn__apr_hash_index_key(hi);
+      deleted_path_notify_t *dpn = svn__apr_hash_index_val(hi);
+
+      /* Ignore paths which are not children of bb->path.  (There
+         should be none due to editor ordering constraints, but
+         ra_serf drops the ball here -- see issue #3802 for
+         details.) */
+      if (! svn_relpath_skip_ancestor(relpath, deleted_path))
+        continue;
 
+      notify = svn_wc_create_notify(deleted_path, dpn->action, scratch_pool);
+      notify->kind = dpn->kind;
+      notify->content_state = notify->prop_state = dpn->state;
+      notify->lock_state = svn_wc_notify_lock_state_inapplicable;
+      (*dnb->notify_func)(dnb->notify_baton, notify, scratch_pool);
+      apr_hash_set(dnb->deleted_paths, deleted_path,
+                   APR_HASH_KEY_STRING, NULL);
+    }
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+diff_state_absent(const char *relpath,
+                  void *state_baton,
+                  apr_pool_t *scratch_pool)
+{
+  struct diff_notify_baton_t *dnb = state_baton;
+
+  if (dnb->notify_func)
+    {
+      svn_wc_notify_t *notify
+        = svn_wc_create_notify(relpath, svn_wc_notify_skip, scratch_pool);
+
+      notify->kind = svn_node_file;
+      (*dnb->notify_func)(dnb->notify_baton, notify, scratch_pool);
+    }
+
+  return SVN_NO_ERROR;
+}
 
 /* Create a repository diff editor and baton.  */
 svn_error_t *
@@ -1519,17 +1507,24 @@ svn_client__get_diff_editor(const svn_de
   apr_pool_t *editor_pool = svn_pool_create(result_pool);
   svn_delta_editor_t *tree_editor = svn_delta_default_editor(editor_pool);
   struct edit_baton *eb = apr_pcalloc(editor_pool, sizeof(*eb));
+  struct diff_notify_baton_t *dnb = apr_pcalloc(editor_pool, sizeof(*eb));
   svn_delta_shim_callbacks_t *shim_callbacks =
                                 svn_delta_shim_callbacks_default(editor_pool);
 
   eb->pool = editor_pool;
   eb->depth = depth;
 
+  dnb->pool = editor_pool;
+  dnb->deleted_paths = apr_hash_make(eb->pool);
+  dnb->notify_func = notify_func;
+  dnb->notify_baton = notify_baton;
+
   SVN_ERR(svn_wc__wrap_diff_callbacks(&eb->processor,
                                       diff_callbacks, diff_cmd_baton,
                                       diff_state_handle,
                                       diff_state_close,
-                                      eb,
+                                      diff_state_absent,
+                                      dnb,
                                       result_pool, result_pool));
 
   eb->ra_session = ra_session;
@@ -1537,9 +1532,6 @@ svn_client__get_diff_editor(const svn_de
   eb->revision = revision;
   eb->empty_file = NULL;
   eb->empty_hash = apr_hash_make(eb->pool);
-  eb->deleted_paths = apr_hash_make(eb->pool);
-  eb->notify_func = notify_func;
-  eb->notify_baton = notify_baton;
   eb->walk_deleted_repos_dirs = walk_deleted_dirs;
   eb->text_deltas = text_deltas;
   eb->cancel_func = cancel_func;

Modified: subversion/trunk/subversion/libsvn_wc/diff_editor.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/diff_editor.c?rev=1438990&r1=1438989&r2=1438990&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/diff_editor.c (original)
+++ subversion/trunk/subversion/libsvn_wc/diff_editor.c Sat Jan 26 23:11:35 2013
@@ -1969,6 +1969,7 @@ typedef struct wc_diff_wrap_baton_t
   void *callback_baton;
   svn_wc__diff_state_handle_t state_handle;
   svn_wc__diff_state_close_t state_close;
+  svn_wc__diff_state_absent_t state_absent;
   void *state_baton;
 
   apr_pool_t *result_pool;
@@ -2393,12 +2394,28 @@ wrap_file_changed(const char *relpath,
   return SVN_NO_ERROR;
 }
 
+static svn_error_t *
+wrap_node_absent(const char *relpath,
+                 void *dir_baton,
+                 const svn_diff_tree_processor_t *processor,
+                 apr_pool_t *scratch_pool)
+{
+  wc_diff_wrap_baton_t *wb = processor->baton;
+  if (wb->state_absent)
+    SVN_ERR(wb->state_absent(relpath,
+                             wb->state_baton,
+                             scratch_pool));
+  return SVN_NO_ERROR;
+}
+
+
 svn_error_t *
 svn_wc__wrap_diff_callbacks(svn_diff_tree_processor_t **diff_processor,
                             const svn_wc_diff_callbacks4_t *callbacks,
                             void *callback_baton,
                             svn_wc__diff_state_handle_t state_handler,
                             svn_wc__diff_state_close_t state_close,
+                            svn_wc__diff_state_absent_t state_absent,
                             void *state_baton,
                             apr_pool_t *result_pool,
                             apr_pool_t *scratch_pool)
@@ -2413,6 +2430,7 @@ svn_wc__wrap_diff_callbacks(svn_diff_tre
   wrap_baton->callback_baton = callback_baton;
   wrap_baton->state_handle = state_handler;
   wrap_baton->state_close = state_close;
+  wrap_baton->state_absent = state_absent;
   wrap_baton->state_baton = state_baton;
   wrap_baton->empty_file = NULL;
 
@@ -2430,6 +2448,8 @@ svn_wc__wrap_diff_callbacks(svn_diff_tre
   processor->file_changed  = wrap_file_changed;
   /*processor->file_closed   = wrap_file_closed*/; /* Not needed */
 
+  processor->node_absent   = wrap_node_absent;
+
   *diff_processor = processor;
   return SVN_NO_ERROR;
 }