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;
}