diff options
Diffstat (limited to 'subversion/libsvn_delta')
-rw-r--r-- | subversion/libsvn_delta/branch.c | 2 | ||||
-rw-r--r-- | subversion/libsvn_delta/branch_compat.c | 54 | ||||
-rw-r--r-- | subversion/libsvn_delta/compat.c | 50 | ||||
-rw-r--r-- | subversion/libsvn_delta/debug_editor.c | 159 | ||||
-rw-r--r-- | subversion/libsvn_delta/deprecated.c | 73 | ||||
-rw-r--r-- | subversion/libsvn_delta/element.c | 4 | ||||
-rw-r--r-- | subversion/libsvn_delta/libsvn_delta.pc.in | 8 | ||||
-rw-r--r-- | subversion/libsvn_delta/path_driver.c | 313 |
8 files changed, 421 insertions, 242 deletions
diff --git a/subversion/libsvn_delta/branch.c b/subversion/libsvn_delta/branch.c index 95355d44650d4..57cdea7ce0747 100644 --- a/subversion/libsvn_delta/branch.c +++ b/subversion/libsvn_delta/branch.c @@ -157,7 +157,7 @@ branch_txn_delete_branch(svn_branch__txn_t *txn, if (strcmp(b->bid, bid) == 0) { - svn_sort__array_delete(txn->priv->branches, i, 1); + SVN_ERR(svn_sort__array_delete2(txn->priv->branches, i, 1)); break; } } diff --git a/subversion/libsvn_delta/branch_compat.c b/subversion/libsvn_delta/branch_compat.c index dac0e191cf24a..635b31a5eb683 100644 --- a/subversion/libsvn_delta/branch_compat.c +++ b/subversion/libsvn_delta/branch_compat.c @@ -875,6 +875,8 @@ drive_ev1_props(const char *repos_relpath, */ static svn_error_t * apply_change(void **dir_baton, + const svn_delta_editor_t *editor, + void *edit_baton, void *parent_baton, void *callback_baton, const char *ev1_relpath, @@ -905,7 +907,7 @@ apply_change(void **dir_baton, /* Only property edits are allowed on the root. */ SVN_ERR_ASSERT(change->action == RESTRUCTURE_NONE); SVN_ERR(drive_ev1_props(ev1_relpath, change, base_props, - eb->deditor, *dir_baton, scratch_pool)); + editor, *dir_baton, scratch_pool)); /* No further action possible for the root. */ return SVN_NO_ERROR; @@ -913,8 +915,8 @@ apply_change(void **dir_baton, if (change->action == RESTRUCTURE_DELETE) { - SVN_ERR(eb->deditor->delete_entry(ev1_relpath, change->deleting_rev, - parent_baton, scratch_pool)); + SVN_ERR(editor->delete_entry(ev1_relpath, change->deleting_rev, + parent_baton, scratch_pool)); /* No futher action possible for this node. */ return SVN_NO_ERROR; @@ -927,11 +929,11 @@ apply_change(void **dir_baton, if (change->action == RESTRUCTURE_ADD_ABSENT) { if (change->kind == svn_node_dir) - SVN_ERR(eb->deditor->absent_directory(ev1_relpath, parent_baton, - scratch_pool)); - else if (change->kind == svn_node_file) - SVN_ERR(eb->deditor->absent_file(ev1_relpath, parent_baton, + SVN_ERR(editor->absent_directory(ev1_relpath, parent_baton, scratch_pool)); + else if (change->kind == svn_node_file) + SVN_ERR(editor->absent_file(ev1_relpath, parent_baton, + scratch_pool)); else SVN_ERR_MALFUNCTION(); @@ -948,8 +950,8 @@ apply_change(void **dir_baton, /* Do we have an old node to delete first? If so, delete it. */ if (change->deleting) - SVN_ERR(eb->deditor->delete_entry(ev1_relpath, change->deleting_rev, - parent_baton, scratch_pool)); + SVN_ERR(editor->delete_entry(ev1_relpath, change->deleting_rev, + parent_baton, scratch_pool)); /* If it's a copy, determine the copy source location. */ if (change->copyfrom_path) @@ -974,13 +976,13 @@ apply_change(void **dir_baton, } if (change->kind == svn_node_dir) - SVN_ERR(eb->deditor->add_directory(ev1_relpath, parent_baton, - copyfrom_url, copyfrom_rev, - result_pool, dir_baton)); - else if (change->kind == svn_node_file) - SVN_ERR(eb->deditor->add_file(ev1_relpath, parent_baton, + SVN_ERR(editor->add_directory(ev1_relpath, parent_baton, copyfrom_url, copyfrom_rev, - result_pool, &file_baton)); + result_pool, dir_baton)); + else if (change->kind == svn_node_file) + SVN_ERR(editor->add_file(ev1_relpath, parent_baton, + copyfrom_url, copyfrom_rev, + result_pool, &file_baton)); else SVN_ERR_MALFUNCTION(); } @@ -993,13 +995,13 @@ apply_change(void **dir_baton, when we fetch the base properties.) */ if (change->kind == svn_node_dir) - SVN_ERR(eb->deditor->open_directory(ev1_relpath, parent_baton, - change->changing_rev, - result_pool, dir_baton)); - else if (change->kind == svn_node_file) - SVN_ERR(eb->deditor->open_file(ev1_relpath, parent_baton, + SVN_ERR(editor->open_directory(ev1_relpath, parent_baton, change->changing_rev, - result_pool, &file_baton)); + result_pool, dir_baton)); + else if (change->kind == svn_node_file) + SVN_ERR(editor->open_file(ev1_relpath, parent_baton, + change->changing_rev, + result_pool, &file_baton)); else SVN_ERR_MALFUNCTION(); } @@ -1007,10 +1009,10 @@ apply_change(void **dir_baton, /* Apply any properties in CHANGE to the node. */ if (change->kind == svn_node_dir) SVN_ERR(drive_ev1_props(ev1_relpath, change, base_props, - eb->deditor, *dir_baton, scratch_pool)); + editor, *dir_baton, scratch_pool)); else SVN_ERR(drive_ev1_props(ev1_relpath, change, base_props, - eb->deditor, file_baton, scratch_pool)); + editor, file_baton, scratch_pool)); /* Send the text content delta, if new text content is provided. */ if (change->contents_text) @@ -1023,7 +1025,7 @@ apply_change(void **dir_baton, scratch_pool); /* ### would be nice to have a BASE_CHECKSUM, but hey: this is the ### shim code... */ - SVN_ERR(eb->deditor->apply_textdelta(file_baton, NULL, scratch_pool, + SVN_ERR(editor->apply_textdelta(file_baton, NULL, scratch_pool, &handler, &handler_baton)); /* ### it would be nice to send a true txdelta here, but whatever. */ SVN_ERR(svn_txdelta_send_stream(read_stream, handler, handler_baton, @@ -1033,7 +1035,7 @@ apply_change(void **dir_baton, if (file_baton) { - SVN_ERR(eb->deditor->close_file(file_baton, NULL, scratch_pool)); + SVN_ERR(editor->close_file(file_baton, NULL, scratch_pool)); } return SVN_NO_ERROR; @@ -1740,7 +1742,7 @@ drive_changes(svn_branch__txn_priv_t *eb, /* Apply the appropriate Ev1 change to each Ev1-relative path. */ paths = get_unsorted_paths(eb->changes, scratch_pool); - SVN_ERR(svn_delta_path_driver2(eb->deditor, eb->dedit_baton, + SVN_ERR(svn_delta_path_driver3(eb->deditor, eb->dedit_baton, paths, TRUE /*sort*/, apply_change, (void *)eb, scratch_pool)); diff --git a/subversion/libsvn_delta/compat.c b/subversion/libsvn_delta/compat.c index c89e9367cd370..817e23eb18194 100644 --- a/subversion/libsvn_delta/compat.c +++ b/subversion/libsvn_delta/compat.c @@ -1577,6 +1577,8 @@ drive_ev1_props(const struct editor_baton *eb, /* Conforms to svn_delta_path_driver_cb_func_t */ static svn_error_t * apply_change(void **dir_baton, + const svn_delta_editor_t *deditor, + void *dedit_baton, void *parent_baton, void *callback_baton, const char *ev1_relpath, @@ -1614,8 +1616,8 @@ apply_change(void **dir_baton, if (change->action == RESTRUCTURE_DELETE) { - SVN_ERR(eb->deditor->delete_entry(ev1_relpath, change->deleting, - parent_baton, scratch_pool)); + SVN_ERR(deditor->delete_entry(ev1_relpath, change->deleting, + parent_baton, scratch_pool)); /* No futher action possible for this node. */ return SVN_NO_ERROR; @@ -1627,11 +1629,11 @@ apply_change(void **dir_baton, if (change->action == RESTRUCTURE_ADD_ABSENT) { if (change->kind == svn_node_dir) - SVN_ERR(eb->deditor->absent_directory(ev1_relpath, parent_baton, - scratch_pool)); + SVN_ERR(deditor->absent_directory(ev1_relpath, parent_baton, + scratch_pool)); else - SVN_ERR(eb->deditor->absent_file(ev1_relpath, parent_baton, - scratch_pool)); + SVN_ERR(deditor->absent_file(ev1_relpath, parent_baton, + scratch_pool)); /* No further action possible for this node. */ return SVN_NO_ERROR; @@ -1645,8 +1647,8 @@ apply_change(void **dir_baton, /* Do we have an old node to delete first? */ if (SVN_IS_VALID_REVNUM(change->deleting)) - SVN_ERR(eb->deditor->delete_entry(ev1_relpath, change->deleting, - parent_baton, scratch_pool)); + SVN_ERR(deditor->delete_entry(ev1_relpath, change->deleting, + parent_baton, scratch_pool)); /* Are we copying the node from somewhere? */ if (change->copyfrom_path) @@ -1669,24 +1671,24 @@ apply_change(void **dir_baton, } if (change->kind == svn_node_dir) - SVN_ERR(eb->deditor->add_directory(ev1_relpath, parent_baton, - copyfrom_url, copyfrom_rev, - result_pool, dir_baton)); + SVN_ERR(deditor->add_directory(ev1_relpath, parent_baton, + copyfrom_url, copyfrom_rev, + result_pool, dir_baton)); else - SVN_ERR(eb->deditor->add_file(ev1_relpath, parent_baton, - copyfrom_url, copyfrom_rev, - result_pool, &file_baton)); + SVN_ERR(deditor->add_file(ev1_relpath, parent_baton, + copyfrom_url, copyfrom_rev, + result_pool, &file_baton)); } else { if (change->kind == svn_node_dir) - SVN_ERR(eb->deditor->open_directory(ev1_relpath, parent_baton, - change->changing, - result_pool, dir_baton)); + SVN_ERR(deditor->open_directory(ev1_relpath, parent_baton, + change->changing, + result_pool, dir_baton)); else - SVN_ERR(eb->deditor->open_file(ev1_relpath, parent_baton, - change->changing, - result_pool, &file_baton)); + SVN_ERR(deditor->open_file(ev1_relpath, parent_baton, + change->changing, + result_pool, &file_baton)); } /* Apply any properties in CHANGE to the node. */ @@ -1703,8 +1705,8 @@ apply_change(void **dir_baton, /* ### would be nice to have a BASE_CHECKSUM, but hey: this is the ### shim code... */ - SVN_ERR(eb->deditor->apply_textdelta(file_baton, NULL, scratch_pool, - &handler, &handler_baton)); + SVN_ERR(deditor->apply_textdelta(file_baton, NULL, scratch_pool, + &handler, &handler_baton)); SVN_ERR(svn_stream_open_readonly(&contents, change->contents_abspath, scratch_pool, scratch_pool)); /* ### it would be nice to send a true txdelta here, but whatever. */ @@ -1718,7 +1720,7 @@ apply_change(void **dir_baton, const char *digest = svn_checksum_to_cstring(change->checksum, scratch_pool); - SVN_ERR(eb->deditor->close_file(file_baton, digest, scratch_pool)); + SVN_ERR(deditor->close_file(file_baton, digest, scratch_pool)); } return SVN_NO_ERROR; @@ -1747,7 +1749,7 @@ drive_changes(const struct editor_baton *eb, /* Get a sorted list of Ev1-relative paths. */ paths = get_sorted_paths(eb->changes, eb->base_relpath, scratch_pool); - SVN_ERR(svn_delta_path_driver2(eb->deditor, eb->dedit_baton, paths, + SVN_ERR(svn_delta_path_driver3(eb->deditor, eb->dedit_baton, paths, FALSE, apply_change, (void *)eb, scratch_pool)); diff --git a/subversion/libsvn_delta/debug_editor.c b/subversion/libsvn_delta/debug_editor.c index 5f26936d621b1..c5dbc9b0321b5 100644 --- a/subversion/libsvn_delta/debug_editor.c +++ b/subversion/libsvn_delta/debug_editor.c @@ -71,9 +71,11 @@ set_target_revision(void *edit_baton, SVN_ERR(svn_stream_printf(eb->out, pool, "set_target_revision : %ld\n", target_revision)); - return eb->wrapped_editor->set_target_revision(eb->wrapped_edit_baton, - target_revision, - pool); + if (eb->wrapped_editor) + SVN_ERR(eb->wrapped_editor->set_target_revision(eb->wrapped_edit_baton, + target_revision, + pool)); + return SVN_NO_ERROR; } static svn_error_t * @@ -90,10 +92,11 @@ open_root(void *edit_baton, base_revision)); eb->indent_level++; - SVN_ERR(eb->wrapped_editor->open_root(eb->wrapped_edit_baton, - base_revision, - pool, - &dir_baton->wrapped_dir_baton)); + if (eb->wrapped_editor) + SVN_ERR(eb->wrapped_editor->open_root(eb->wrapped_edit_baton, + base_revision, + pool, + &dir_baton->wrapped_dir_baton)); dir_baton->edit_baton = edit_baton; @@ -115,10 +118,12 @@ delete_entry(const char *path, SVN_ERR(svn_stream_printf(eb->out, pool, "delete_entry : %s:%ld\n", path, base_revision)); - return eb->wrapped_editor->delete_entry(path, - base_revision, - pb->wrapped_dir_baton, - pool); + if (eb->wrapped_editor) + SVN_ERR(eb->wrapped_editor->delete_entry(path, + base_revision, + pb->wrapped_dir_baton, + pool)); + return SVN_NO_ERROR; } static svn_error_t * @@ -139,12 +144,13 @@ add_directory(const char *path, path, copyfrom_path, copyfrom_revision)); eb->indent_level++; - SVN_ERR(eb->wrapped_editor->add_directory(path, - pb->wrapped_dir_baton, - copyfrom_path, - copyfrom_revision, - pool, - &b->wrapped_dir_baton)); + if (eb->wrapped_editor) + SVN_ERR(eb->wrapped_editor->add_directory(path, + pb->wrapped_dir_baton, + copyfrom_path, + copyfrom_revision, + pool, + &b->wrapped_dir_baton)); b->edit_baton = eb; *child_baton = b; @@ -168,11 +174,12 @@ open_directory(const char *path, path, base_revision)); eb->indent_level++; - SVN_ERR(eb->wrapped_editor->open_directory(path, - pb->wrapped_dir_baton, - base_revision, - pool, - &db->wrapped_dir_baton)); + if (eb->wrapped_editor) + SVN_ERR(eb->wrapped_editor->open_directory(path, + pb->wrapped_dir_baton, + base_revision, + pool, + &db->wrapped_dir_baton)); db->edit_baton = eb; *child_baton = db; @@ -199,12 +206,13 @@ add_file(const char *path, eb->indent_level++; - SVN_ERR(eb->wrapped_editor->add_file(path, - pb->wrapped_dir_baton, - copyfrom_path, - copyfrom_revision, - pool, - &fb->wrapped_file_baton)); + if (eb->wrapped_editor) + SVN_ERR(eb->wrapped_editor->add_file(path, + pb->wrapped_dir_baton, + copyfrom_path, + copyfrom_revision, + pool, + &fb->wrapped_file_baton)); fb->edit_baton = eb; *file_baton = fb; @@ -229,11 +237,12 @@ open_file(const char *path, eb->indent_level++; - SVN_ERR(eb->wrapped_editor->open_file(path, - pb->wrapped_dir_baton, - base_revision, - pool, - &fb->wrapped_file_baton)); + if (eb->wrapped_editor) + SVN_ERR(eb->wrapped_editor->open_file(path, + pb->wrapped_dir_baton, + base_revision, + pool, + &fb->wrapped_file_baton)); fb->edit_baton = eb; *file_baton = fb; @@ -255,11 +264,38 @@ apply_textdelta(void *file_baton, SVN_ERR(svn_stream_printf(eb->out, pool, "apply_textdelta : %s\n", base_checksum)); - SVN_ERR(eb->wrapped_editor->apply_textdelta(fb->wrapped_file_baton, - base_checksum, - pool, - handler, - handler_baton)); + if (eb->wrapped_editor) + SVN_ERR(eb->wrapped_editor->apply_textdelta(fb->wrapped_file_baton, + base_checksum, + pool, + handler, + handler_baton)); + + return SVN_NO_ERROR; +} + +static svn_error_t * +apply_textdelta_stream(const struct svn_delta_editor_t *editor, + void *file_baton, + const char *base_checksum, + svn_txdelta_stream_open_func_t open_func, + void *open_baton, + apr_pool_t *scratch_pool) +{ + struct file_baton *fb = file_baton; + struct edit_baton *eb = fb->edit_baton; + + SVN_ERR(write_indent(eb, scratch_pool)); + SVN_ERR(svn_stream_printf(eb->out, scratch_pool, + "apply_textdelta_stream : %s\n", + base_checksum)); + + if (eb->wrapped_editor) + SVN_ERR(eb->wrapped_editor->apply_textdelta_stream(eb->wrapped_editor, + fb->wrapped_file_baton, + base_checksum, + open_func, open_baton, + scratch_pool)); return SVN_NO_ERROR; } @@ -278,8 +314,9 @@ close_file(void *file_baton, SVN_ERR(svn_stream_printf(eb->out, pool, "close_file : %s\n", text_checksum)); - SVN_ERR(eb->wrapped_editor->close_file(fb->wrapped_file_baton, - text_checksum, pool)); + if (eb->wrapped_editor) + SVN_ERR(eb->wrapped_editor->close_file(fb->wrapped_file_baton, + text_checksum, pool)); return SVN_NO_ERROR; } @@ -295,8 +332,9 @@ absent_file(const char *path, SVN_ERR(write_indent(eb, pool)); SVN_ERR(svn_stream_printf(eb->out, pool, "absent_file : %s\n", path)); - SVN_ERR(eb->wrapped_editor->absent_file(path, fb->wrapped_file_baton, - pool)); + if (eb->wrapped_editor) + SVN_ERR(eb->wrapped_editor->absent_file(path, fb->wrapped_file_baton, + pool)); return SVN_NO_ERROR; } @@ -312,8 +350,9 @@ close_directory(void *dir_baton, SVN_ERR(write_indent(eb, pool)); SVN_ERR(svn_stream_printf(eb->out, pool, "close_directory\n")); - SVN_ERR(eb->wrapped_editor->close_directory(db->wrapped_dir_baton, - pool)); + if (eb->wrapped_editor) + SVN_ERR(eb->wrapped_editor->close_directory(db->wrapped_dir_baton, + pool)); return SVN_NO_ERROR; } @@ -330,8 +369,9 @@ absent_directory(const char *path, SVN_ERR(svn_stream_printf(eb->out, pool, "absent_directory : %s\n", path)); - SVN_ERR(eb->wrapped_editor->absent_directory(path, db->wrapped_dir_baton, - pool)); + if (eb->wrapped_editor) + SVN_ERR(eb->wrapped_editor->absent_directory(path, db->wrapped_dir_baton, + pool)); return SVN_NO_ERROR; } @@ -349,10 +389,11 @@ change_file_prop(void *file_baton, SVN_ERR(svn_stream_printf(eb->out, pool, "change_file_prop : %s -> %s\n", name, value ? value->data : "<deleted>")); - SVN_ERR(eb->wrapped_editor->change_file_prop(fb->wrapped_file_baton, - name, - value, - pool)); + if (eb->wrapped_editor) + SVN_ERR(eb->wrapped_editor->change_file_prop(fb->wrapped_file_baton, + name, + value, + pool)); return SVN_NO_ERROR; } @@ -370,10 +411,11 @@ change_dir_prop(void *dir_baton, SVN_ERR(svn_stream_printf(eb->out, pool, "change_dir_prop : %s -> %s\n", name, value ? value->data : "<deleted>")); - SVN_ERR(eb->wrapped_editor->change_dir_prop(db->wrapped_dir_baton, - name, - value, - pool)); + if (eb->wrapped_editor) + SVN_ERR(eb->wrapped_editor->change_dir_prop(db->wrapped_dir_baton, + name, + value, + pool)); return SVN_NO_ERROR; } @@ -387,7 +429,8 @@ close_edit(void *edit_baton, SVN_ERR(write_indent(eb, pool)); SVN_ERR(svn_stream_printf(eb->out, pool, "close_edit\n")); - SVN_ERR(eb->wrapped_editor->close_edit(eb->wrapped_edit_baton, pool)); + if (eb->wrapped_editor) + SVN_ERR(eb->wrapped_editor->close_edit(eb->wrapped_edit_baton, pool)); return SVN_NO_ERROR; } @@ -401,7 +444,8 @@ abort_edit(void *edit_baton, SVN_ERR(write_indent(eb, pool)); SVN_ERR(svn_stream_printf(eb->out, pool, "abort_edit\n")); - SVN_ERR(eb->wrapped_editor->abort_edit(eb->wrapped_edit_baton, pool)); + if (eb->wrapped_editor) + SVN_ERR(eb->wrapped_editor->abort_edit(eb->wrapped_edit_baton, pool)); return SVN_NO_ERROR; } @@ -414,7 +458,7 @@ svn_delta__get_debug_editor(const svn_delta_editor_t **editor, const char *prefix, apr_pool_t *pool) { - svn_delta_editor_t *tree_editor = apr_palloc(pool, sizeof(*tree_editor)); + svn_delta_editor_t *tree_editor = svn_delta_default_editor(pool); struct edit_baton *eb = apr_palloc(pool, sizeof(*eb)); apr_file_t *errfp; svn_stream_t *out; @@ -436,6 +480,7 @@ svn_delta__get_debug_editor(const svn_delta_editor_t **editor, tree_editor->add_file = add_file; tree_editor->open_file = open_file; tree_editor->apply_textdelta = apply_textdelta; + tree_editor->apply_textdelta_stream = apply_textdelta_stream; tree_editor->change_file_prop = change_file_prop; tree_editor->close_file = close_file; tree_editor->absent_file = absent_file; diff --git a/subversion/libsvn_delta/deprecated.c b/subversion/libsvn_delta/deprecated.c index 41712440baf48..f00c410cc6eca 100644 --- a/subversion/libsvn_delta/deprecated.c +++ b/subversion/libsvn_delta/deprecated.c @@ -30,6 +30,79 @@ #include "svn_sorts.h" +struct path_driver_2_to_3_baton_t +{ + svn_delta_path_driver_cb_func_t callback_func; + void *callback_baton; + svn_boolean_t slash_prefix; +}; + +/* Convert from a newer to older callback + */ +static svn_error_t * +path_driver_2_to_3_func(void **dir_baton, + const svn_delta_editor_t *editor, + void *edit_baton, + void *parent_baton, + void *callback_baton, + const char *path, + apr_pool_t *pool) +{ + struct path_driver_2_to_3_baton_t *b = callback_baton; + + if (b->slash_prefix) + path = apr_pstrcat(pool, "/", path, SVN_VA_NULL); + + /* Just drop the 'editor' parameters */ + SVN_ERR(b->callback_func(dir_baton, parent_baton, + b->callback_baton, + path, pool)); + return SVN_NO_ERROR; +} + +svn_error_t * +svn_delta_path_driver2(const svn_delta_editor_t *editor, + void *edit_baton, + const apr_array_header_t *paths, + svn_boolean_t sort_paths, + svn_delta_path_driver_cb_func_t callback_func, + void *callback_baton, + apr_pool_t *pool) +{ + struct path_driver_2_to_3_baton_t b; + int i; + + b.callback_func = callback_func; + b.callback_baton = callback_baton; + b.slash_prefix = FALSE; + + /* Remove any '/' prefix from incoming paths. Arrange to add a '/' + prefix to all paths for the callback, if any incoming path had one. */ + for (i = 0; i < paths->nelts; i++) + { + const char *path = APR_ARRAY_IDX(paths, i, const char *); + + if (path[0] == '/') + { + /* Re-allocate the array and note that we found a '/' prefix. */ + if (!b.slash_prefix) + { + paths = apr_array_copy(pool, paths); + b.slash_prefix = TRUE; + } + + /* Modify each array element that had a '/' prefix */ + APR_ARRAY_IDX(paths, i, const char *) = path + 1; + } + } + + SVN_ERR(svn_delta_path_driver3(editor, edit_baton, + paths, sort_paths, + path_driver_2_to_3_func, &b, + pool)); + return SVN_NO_ERROR; +} + svn_error_t * svn_delta_path_driver(const svn_delta_editor_t *editor, void *edit_baton, diff --git a/subversion/libsvn_delta/element.c b/subversion/libsvn_delta/element.c index be7b2171b9b46..798296412bb82 100644 --- a/subversion/libsvn_delta/element.c +++ b/subversion/libsvn_delta/element.c @@ -375,14 +375,12 @@ svn_element__tree_get(const svn_element__tree_t *tree, return svn_eid__hash_get(tree->e_map, eid); } -svn_error_t * +void svn_element__tree_set(svn_element__tree_t *tree, int eid, const svn_element__content_t *element) { svn_eid__hash_set(tree->e_map, eid, element); - - return SVN_NO_ERROR; } void diff --git a/subversion/libsvn_delta/libsvn_delta.pc.in b/subversion/libsvn_delta/libsvn_delta.pc.in index b96e6ab3c282f..9759e74e21695 100644 --- a/subversion/libsvn_delta/libsvn_delta.pc.in +++ b/subversion/libsvn_delta/libsvn_delta.pc.in @@ -6,7 +6,7 @@ includedir=@includedir@ Name: libsvn_delta Description: Subversion Delta Library Version: @PACKAGE_VERSION@ -Requires: apr-util-@SVN_APR_MAJOR_VERSION@ apr-@SVN_APR_MAJOR_VERSION@ -Requires.private: libsvn_subr -Libs: -L${libdir} -lsvn_delta @SVN_ZLIB_LIBS@ -Cflags: -I${includedir} +Requires: apr-util-@SVN_APR_MAJOR_VERSION@, apr-@SVN_APR_MAJOR_VERSION@ +Requires.private: libsvn_subr +Libs: -L${libdir} -lsvn_delta-1 @SVN_ZLIB_LIBS@ +Cflags: -I${includedir}/subversion-1 diff --git a/subversion/libsvn_delta/path_driver.c b/subversion/libsvn_delta/path_driver.c index c1f3e07b818a7..5840cc7f29099 100644 --- a/subversion/libsvn_delta/path_driver.c +++ b/subversion/libsvn_delta/path_driver.c @@ -31,7 +31,6 @@ #include "svn_dirent_uri.h" #include "svn_path.h" #include "svn_sorts.h" -#include "private/svn_fspath.h" #include "private/svn_sorts_private.h" @@ -45,6 +44,22 @@ typedef struct dir_stack_t } dir_stack_t; +/* Push onto dir_stack a new item allocated in POOL and containing + * DIR_BATON and POOL. + */ +static void +push_dir_stack_item(apr_array_header_t *db_stack, + void *dir_baton, + apr_pool_t *pool) +{ + dir_stack_t *item = apr_pcalloc(pool, sizeof(*item)); + + item->dir_baton = dir_baton; + item->pool = pool; + APR_ARRAY_PUSH(db_stack, dir_stack_t *) = item; +} + + /* Call EDITOR's open_directory() function with the PATH argument, then * add the resulting dir baton to the dir baton stack. */ @@ -72,10 +87,7 @@ open_dir(apr_array_header_t *db_stack, &db)); /* Now add the dir baton to the stack. */ - item = apr_pcalloc(subpool, sizeof(*item)); - item->dir_baton = db; - item->pool = subpool; - APR_ARRAY_PUSH(db_stack, dir_stack_t *) = item; + push_dir_stack_item(db_stack, db, subpool); return SVN_NO_ERROR; } @@ -131,168 +143,215 @@ count_components(const char *path) /*** Public interfaces ***/ svn_error_t * -svn_delta_path_driver2(const svn_delta_editor_t *editor, +svn_delta_path_driver3(const svn_delta_editor_t *editor, void *edit_baton, - const apr_array_header_t *paths, + const apr_array_header_t *relpaths, svn_boolean_t sort_paths, - svn_delta_path_driver_cb_func_t callback_func, + svn_delta_path_driver_cb_func2_t callback_func, void *callback_baton, apr_pool_t *pool) { - apr_array_header_t *db_stack = apr_array_make(pool, 4, sizeof(void *)); - const char *last_path = NULL; - int i = 0; - void *parent_db = NULL, *db = NULL; - const char *path; + svn_delta_path_driver_state_t *state; + int i; apr_pool_t *subpool, *iterpool; - dir_stack_t *item; /* Do nothing if there are no paths. */ - if (! paths->nelts) + if (! relpaths->nelts) return SVN_NO_ERROR; subpool = svn_pool_create(pool); iterpool = svn_pool_create(pool); /* sort paths if necessary */ - if (sort_paths && paths->nelts > 1) + if (sort_paths && relpaths->nelts > 1) { - apr_array_header_t *sorted = apr_array_copy(subpool, paths); + apr_array_header_t *sorted = apr_array_copy(subpool, relpaths); svn_sort__array(sorted, svn_sort_compare_paths); - paths = sorted; + relpaths = sorted; } - item = apr_pcalloc(subpool, sizeof(*item)); - - /* If the root of the edit is also a target path, we want to call - the callback function to let the user open the root directory and - do what needs to be done. Otherwise, we'll do the open_root() - ourselves. */ - path = APR_ARRAY_IDX(paths, 0, const char *); - if (svn_path_is_empty(path)) - { - SVN_ERR(callback_func(&db, NULL, callback_baton, path, subpool)); - last_path = path; - i++; - } - else - { - SVN_ERR(editor->open_root(edit_baton, SVN_INVALID_REVNUM, subpool, &db)); - } - item->pool = subpool; - item->dir_baton = db; - APR_ARRAY_PUSH(db_stack, void *) = item; + SVN_ERR(svn_delta_path_driver_start(&state, + editor, edit_baton, + callback_func, callback_baton, + pool)); /* Now, loop over the commit items, traversing the URL tree and driving the editor. */ - for (; i < paths->nelts; i++) + for (i = 0; i < relpaths->nelts; i++) { - const char *pdir; - const char *common = ""; - size_t common_len; + const char *relpath; /* Clear the iteration pool. */ svn_pool_clear(iterpool); /* Get the next path. */ - path = APR_ARRAY_IDX(paths, i, const char *); - - /*** Step A - Find the common ancestor of the last path and the - current one. For the first iteration, this is just the - empty string. ***/ - if (i > 0) - common = (last_path[0] == '/') - ? svn_fspath__get_longest_ancestor(last_path, path, iterpool) - : svn_relpath_get_longest_ancestor(last_path, path, iterpool); - common_len = strlen(common); - - /*** Step B - Close any directories between the last path and - the new common ancestor, if any need to be closed. - Sometimes there is nothing to do here (like, for the first - iteration, or when the last path was an ancestor of the - current one). ***/ - if ((i > 0) && (strlen(last_path) > common_len)) - { - const char *rel = last_path + (common_len ? (common_len + 1) : 0); - int count = count_components(rel); - while (count--) - { - SVN_ERR(pop_stack(db_stack, editor)); - } - } + relpath = APR_ARRAY_IDX(relpaths, i, const char *); - /*** Step C - Open any directories between the common ancestor - and the parent of the current path. ***/ - if (*path == '/') - pdir = svn_fspath__dirname(path, iterpool); - else - pdir = svn_relpath_dirname(path, iterpool); + SVN_ERR(svn_delta_path_driver_step(state, relpath, iterpool)); + } - if (strlen(pdir) > common_len) - { - const char *piece = pdir + common_len + 1; - - while (1) - { - const char *rel = pdir; - - /* Find the first separator. */ - piece = strchr(piece, '/'); - - /* Calculate REL as the portion of PDIR up to (but not - including) the location to which PIECE is pointing. */ - if (piece) - rel = apr_pstrmemdup(iterpool, pdir, piece - pdir); - - /* Open the subdirectory. */ - SVN_ERR(open_dir(db_stack, editor, rel, pool)); - - /* If we found a '/', advance our PIECE pointer to - character just after that '/'. Otherwise, we're - done. */ - if (piece) - piece++; - else - break; - } - } + /* Destroy the iteration subpool. */ + svn_pool_destroy(iterpool); - /*** Step D - Tell our caller to handle the current path. ***/ - item = APR_ARRAY_IDX(db_stack, db_stack->nelts - 1, void *); - parent_db = item->dir_baton; - subpool = svn_pool_create(pool); - SVN_ERR(callback_func(&db, parent_db, callback_baton, path, subpool)); - if (db) + SVN_ERR(svn_delta_path_driver_finish(state, pool)); + + return SVN_NO_ERROR; +} + +struct svn_delta_path_driver_state_t +{ + const svn_delta_editor_t *editor; + void *edit_baton; + svn_delta_path_driver_cb_func2_t callback_func; + void *callback_baton; + apr_array_header_t *db_stack; + const char *last_path; + apr_pool_t *pool; /* at least the lifetime of the entire drive */ +}; + +svn_error_t * +svn_delta_path_driver_start(svn_delta_path_driver_state_t **state_p, + const svn_delta_editor_t *editor, + void *edit_baton, + svn_delta_path_driver_cb_func2_t callback_func, + void *callback_baton, + apr_pool_t *pool) +{ + svn_delta_path_driver_state_t *state = apr_pcalloc(pool, sizeof(*state)); + + state->editor = editor; + state->edit_baton = edit_baton; + state->callback_func = callback_func; + state->callback_baton = callback_baton; + state->db_stack = apr_array_make(pool, 4, sizeof(void *)); + state->last_path = NULL; + state->pool = pool; + + *state_p = state; + return SVN_NO_ERROR; +} + +svn_error_t * +svn_delta_path_driver_step(svn_delta_path_driver_state_t *state, + const char *relpath, + apr_pool_t *scratch_pool) +{ + const char *pdir; + const char *common = ""; + size_t common_len; + apr_pool_t *subpool; + dir_stack_t *item; + void *parent_db, *db; + + SVN_ERR_ASSERT(svn_relpath_is_canonical(relpath)); + + /* If the first target path is not the root of the edit, we must first + call open_root() ourselves. (If the first target path is the root of + the edit, then we expect the user's callback to do so.) */ + if (!state->last_path && !svn_path_is_empty(relpath)) + { + subpool = svn_pool_create(state->pool); + SVN_ERR(state->editor->open_root(state->edit_baton, SVN_INVALID_REVNUM, + subpool, &db)); + push_dir_stack_item(state->db_stack, db, subpool); + } + + /*** Step A - Find the common ancestor of the last path and the + current one. For the first iteration, this is just the + empty string. ***/ + if (state->last_path) + common = svn_relpath_get_longest_ancestor(state->last_path, relpath, + scratch_pool); + common_len = strlen(common); + + /*** Step B - Close any directories between the last path and + the new common ancestor, if any need to be closed. + Sometimes there is nothing to do here (like, for the first + iteration, or when the last path was an ancestor of the + current one). ***/ + if ((state->last_path) && (strlen(state->last_path) > common_len)) + { + const char *rel = state->last_path + (common_len ? (common_len + 1) : 0); + int count = count_components(rel); + while (count--) { - item = apr_pcalloc(subpool, sizeof(*item)); - item->dir_baton = db; - item->pool = subpool; - APR_ARRAY_PUSH(db_stack, void *) = item; + SVN_ERR(pop_stack(state->db_stack, state->editor)); } - else + } + + /*** Step C - Open any directories between the common ancestor + and the parent of the current path. ***/ + pdir = svn_relpath_dirname(relpath, scratch_pool); + + if (strlen(pdir) > common_len) + { + const char *piece = pdir + common_len + 1; + + while (1) { - svn_pool_destroy(subpool); + const char *rel = pdir; + + /* Find the first separator. */ + piece = strchr(piece, '/'); + + /* Calculate REL as the portion of PDIR up to (but not + including) the location to which PIECE is pointing. */ + if (piece) + rel = apr_pstrmemdup(scratch_pool, pdir, piece - pdir); + + /* Open the subdirectory. */ + SVN_ERR(open_dir(state->db_stack, state->editor, rel, state->pool)); + + /* If we found a '/', advance our PIECE pointer to + character just after that '/'. Otherwise, we're + done. */ + if (piece) + piece++; + else + break; } + } - /*** Step E - Save our state for the next iteration. If our - caller opened or added PATH as a directory, that becomes - our LAST_PATH. Otherwise, we use PATH's parent - directory. ***/ - - /* NOTE: The variable LAST_PATH needs to outlive the loop. */ - if (db) - last_path = path; /* lives in a pool outside our control. */ - else - last_path = apr_pstrdup(pool, pdir); /* duping into POOL. */ + /*** Step D - Tell our caller to handle the current path. ***/ + if (state->db_stack->nelts) + { + item = APR_ARRAY_IDX(state->db_stack, state->db_stack->nelts - 1, void *); + parent_db = item->dir_baton; + } + else + parent_db = NULL; + db = NULL; /* predictable behaviour for callbacks that don't set it */ + subpool = svn_pool_create(state->pool); + SVN_ERR(state->callback_func(&db, + state->editor, state->edit_baton, parent_db, + state->callback_baton, + relpath, subpool)); + if (db) + { + push_dir_stack_item(state->db_stack, db, subpool); + } + else + { + svn_pool_destroy(subpool); } - /* Destroy the iteration subpool. */ - svn_pool_destroy(iterpool); + /*** Step E - Save our state for the next iteration. If our + caller opened or added PATH as a directory, that becomes + our LAST_PATH. Otherwise, we use PATH's parent + directory. ***/ + state->last_path = apr_pstrdup(state->pool, db ? relpath : pdir); + + return SVN_NO_ERROR; +} +svn_error_t * +svn_delta_path_driver_finish(svn_delta_path_driver_state_t *state, + apr_pool_t *scratch_pool) +{ /* Close down any remaining open directory batons. */ - while (db_stack->nelts) + while (state->db_stack->nelts) { - SVN_ERR(pop_stack(db_stack, editor)); + SVN_ERR(pop_stack(state->db_stack, state->editor)); } return SVN_NO_ERROR; |