diff options
Diffstat (limited to 'subversion/libsvn_ra_svn/editorp.c')
-rw-r--r-- | subversion/libsvn_ra_svn/editorp.c | 243 |
1 files changed, 141 insertions, 102 deletions
diff --git a/subversion/libsvn_ra_svn/editorp.c b/subversion/libsvn_ra_svn/editorp.c index c7fc69b..cc1d8ab 100644 --- a/subversion/libsvn_ra_svn/editorp.c +++ b/subversion/libsvn_ra_svn/editorp.c @@ -28,6 +28,7 @@ #include <apr_general.h> #include <apr_strings.h> +#include "svn_hash.h" #include "svn_types.h" #include "svn_string.h" #include "svn_error.h" @@ -39,6 +40,7 @@ #include "svn_private_config.h" #include "private/svn_fspath.h" +#include "private/svn_editor.h" #include "ra_svn.h" @@ -121,14 +123,23 @@ static ra_svn_baton_t *ra_svn_make_baton(svn_ra_svn_conn_t *conn, /* Check for an early error status report from the consumer. If we * get one, abort the edit and return the error. */ -static svn_error_t *check_for_error(ra_svn_edit_baton_t *eb, apr_pool_t *pool) +static svn_error_t * +check_for_error_internal(ra_svn_edit_baton_t *eb, apr_pool_t *pool) { SVN_ERR_ASSERT(!eb->got_status); + + /* reset TX counter */ + eb->conn->written_since_error_check = 0; + + /* if we weren't asked to always check, wait for at least the next TX */ + eb->conn->may_check_for_error = eb->conn->error_check_interval == 0; + + /* any incoming data? */ if (svn_ra_svn__input_waiting(eb->conn, pool)) { eb->got_status = TRUE; - SVN_ERR(svn_ra_svn_write_cmd(eb->conn, pool, "abort-edit", "")); - SVN_ERR(svn_ra_svn_read_cmd_response(eb->conn, pool, "")); + SVN_ERR(svn_ra_svn__write_cmd_abort_edit(eb->conn, pool)); + SVN_ERR(svn_ra_svn__read_cmd_response(eb->conn, pool, "")); /* We shouldn't get here if the consumer is doing its job. */ return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Successful edit status returned too soon")); @@ -136,13 +147,21 @@ static svn_error_t *check_for_error(ra_svn_edit_baton_t *eb, apr_pool_t *pool) return SVN_NO_ERROR; } +static svn_error_t * +check_for_error(ra_svn_edit_baton_t *eb, apr_pool_t *pool) +{ + return eb->conn->may_check_for_error + ? check_for_error_internal(eb, pool) + : SVN_NO_ERROR; +} + static svn_error_t *ra_svn_target_rev(void *edit_baton, svn_revnum_t rev, apr_pool_t *pool) { ra_svn_edit_baton_t *eb = edit_baton; SVN_ERR(check_for_error(eb, pool)); - SVN_ERR(svn_ra_svn_write_cmd(eb->conn, pool, "target-rev", "r", rev)); + SVN_ERR(svn_ra_svn__write_cmd_target_rev(eb->conn, pool, rev)); return SVN_NO_ERROR; } @@ -153,8 +172,7 @@ static svn_error_t *ra_svn_open_root(void *edit_baton, svn_revnum_t rev, const char *token = make_token('d', eb, pool); SVN_ERR(check_for_error(eb, pool)); - SVN_ERR(svn_ra_svn_write_cmd(eb->conn, pool, "open-root", "(?r)c", rev, - token)); + SVN_ERR(svn_ra_svn__write_cmd_open_root(eb->conn, pool, rev, token)); *root_baton = ra_svn_make_baton(eb->conn, pool, eb, token); return SVN_NO_ERROR; } @@ -165,8 +183,8 @@ static svn_error_t *ra_svn_delete_entry(const char *path, svn_revnum_t rev, ra_svn_baton_t *b = parent_baton; SVN_ERR(check_for_error(b->eb, pool)); - SVN_ERR(svn_ra_svn_write_cmd(b->conn, pool, "delete-entry", "c(?r)c", - path, rev, b->token)); + SVN_ERR(svn_ra_svn__write_cmd_delete_entry(b->conn, pool, + path, rev, b->token)); return SVN_NO_ERROR; } @@ -181,8 +199,8 @@ static svn_error_t *ra_svn_add_dir(const char *path, void *parent_baton, SVN_ERR_ASSERT((copy_path && SVN_IS_VALID_REVNUM(copy_rev)) || (!copy_path && !SVN_IS_VALID_REVNUM(copy_rev))); SVN_ERR(check_for_error(b->eb, pool)); - SVN_ERR(svn_ra_svn_write_cmd(b->conn, pool, "add-dir", "ccc(?cr)", path, - b->token, token, copy_path, copy_rev)); + SVN_ERR(svn_ra_svn__write_cmd_add_dir(b->conn, pool, path, b->token, + token, copy_path, copy_rev)); *child_baton = ra_svn_make_baton(b->conn, pool, b->eb, token); return SVN_NO_ERROR; } @@ -195,8 +213,8 @@ static svn_error_t *ra_svn_open_dir(const char *path, void *parent_baton, const char *token = make_token('d', b->eb, pool); SVN_ERR(check_for_error(b->eb, pool)); - SVN_ERR(svn_ra_svn_write_cmd(b->conn, pool, "open-dir", "ccc(?r)", - path, b->token, token, rev)); + SVN_ERR(svn_ra_svn__write_cmd_open_dir(b->conn, pool, path, b->token, + token, rev)); *child_baton = ra_svn_make_baton(b->conn, pool, b->eb, token); return SVN_NO_ERROR; } @@ -208,8 +226,8 @@ static svn_error_t *ra_svn_change_dir_prop(void *dir_baton, const char *name, ra_svn_baton_t *b = dir_baton; SVN_ERR(check_for_error(b->eb, pool)); - SVN_ERR(svn_ra_svn_write_cmd(b->conn, pool, "change-dir-prop", "cc(?s)", - b->token, name, value)); + SVN_ERR(svn_ra_svn__write_cmd_change_dir_prop(b->conn, pool, b->token, + name, value)); return SVN_NO_ERROR; } @@ -218,7 +236,7 @@ static svn_error_t *ra_svn_close_dir(void *dir_baton, apr_pool_t *pool) ra_svn_baton_t *b = dir_baton; SVN_ERR(check_for_error(b->eb, pool)); - SVN_ERR(svn_ra_svn_write_cmd(b->conn, pool, "close-dir", "c", b->token)); + SVN_ERR(svn_ra_svn__write_cmd_close_dir(b->conn, pool, b->token)); return SVN_NO_ERROR; } @@ -233,8 +251,7 @@ static svn_error_t *ra_svn_absent_dir(const char *path, return SVN_NO_ERROR; SVN_ERR(check_for_error(b->eb, pool)); - SVN_ERR(svn_ra_svn_write_cmd(b->conn, pool, "absent-dir", "cc", path, - b->token)); + SVN_ERR(svn_ra_svn__write_cmd_absent_dir(b->conn, pool, path, b->token)); return SVN_NO_ERROR; } @@ -251,8 +268,8 @@ static svn_error_t *ra_svn_add_file(const char *path, SVN_ERR_ASSERT((copy_path && SVN_IS_VALID_REVNUM(copy_rev)) || (!copy_path && !SVN_IS_VALID_REVNUM(copy_rev))); SVN_ERR(check_for_error(b->eb, pool)); - SVN_ERR(svn_ra_svn_write_cmd(b->conn, pool, "add-file", "ccc(?cr)", path, - b->token, token, copy_path, copy_rev)); + SVN_ERR(svn_ra_svn__write_cmd_add_file(b->conn, pool, path, b->token, + token, copy_path, copy_rev)); *file_baton = ra_svn_make_baton(b->conn, pool, b->eb, token); return SVN_NO_ERROR; } @@ -267,8 +284,8 @@ static svn_error_t *ra_svn_open_file(const char *path, const char *token = make_token('c', b->eb, pool); SVN_ERR(check_for_error(b->eb, b->pool)); - SVN_ERR(svn_ra_svn_write_cmd(b->conn, pool, "open-file", "ccc(?r)", - path, b->token, token, rev)); + SVN_ERR(svn_ra_svn__write_cmd_open_file(b->conn, pool, path, b->token, + token, rev)); *file_baton = ra_svn_make_baton(b->conn, pool, b->eb, token); return SVN_NO_ERROR; } @@ -282,8 +299,8 @@ static svn_error_t *ra_svn_svndiff_handler(void *baton, const char *data, SVN_ERR(check_for_error(b->eb, b->pool)); str.data = data; str.len = *len; - return svn_ra_svn_write_cmd(b->conn, b->pool, "textdelta-chunk", "cs", - b->token, &str); + return svn_ra_svn__write_cmd_textdelta_chunk(b->conn, b->pool, + b->token, &str); } static svn_error_t *ra_svn_svndiff_close_handler(void *baton) @@ -291,8 +308,7 @@ static svn_error_t *ra_svn_svndiff_close_handler(void *baton) ra_svn_baton_t *b = baton; SVN_ERR(check_for_error(b->eb, b->pool)); - SVN_ERR(svn_ra_svn_write_cmd(b->conn, b->pool, "textdelta-end", "c", - b->token)); + SVN_ERR(svn_ra_svn__write_cmd_textdelta_end(b->conn, b->pool, b->token)); return SVN_NO_ERROR; } @@ -307,8 +323,8 @@ static svn_error_t *ra_svn_apply_textdelta(void *file_baton, /* Tell the other side we're starting a text delta. */ SVN_ERR(check_for_error(b->eb, pool)); - SVN_ERR(svn_ra_svn_write_cmd(b->conn, pool, "apply-textdelta", "c(?c)", - b->token, base_checksum)); + SVN_ERR(svn_ra_svn__write_cmd_apply_textdelta(b->conn, pool, b->token, + base_checksum)); /* Transform the window stream to an svndiff stream. Reuse the * file baton for the stream handler, since it has all the @@ -337,8 +353,8 @@ static svn_error_t *ra_svn_change_file_prop(void *file_baton, ra_svn_baton_t *b = file_baton; SVN_ERR(check_for_error(b->eb, pool)); - SVN_ERR(svn_ra_svn_write_cmd(b->conn, pool, "change-file-prop", "cc(?s)", - b->token, name, value)); + SVN_ERR(svn_ra_svn__write_cmd_change_file_prop(b->conn, pool, + b->token, name, value)); return SVN_NO_ERROR; } @@ -349,8 +365,8 @@ static svn_error_t *ra_svn_close_file(void *file_baton, ra_svn_baton_t *b = file_baton; SVN_ERR(check_for_error(b->eb, pool)); - SVN_ERR(svn_ra_svn_write_cmd(b->conn, pool, "close-file", "c(?c)", - b->token, text_checksum)); + SVN_ERR(svn_ra_svn__write_cmd_close_file(b->conn, pool, + b->token, text_checksum)); return SVN_NO_ERROR; } @@ -365,8 +381,7 @@ static svn_error_t *ra_svn_absent_file(const char *path, return SVN_NO_ERROR; SVN_ERR(check_for_error(b->eb, pool)); - SVN_ERR(svn_ra_svn_write_cmd(b->conn, pool, "absent-file", "cc", path, - b->token)); + SVN_ERR(svn_ra_svn__write_cmd_absent_file(b->conn, pool, path, b->token)); return SVN_NO_ERROR; } @@ -377,11 +392,11 @@ static svn_error_t *ra_svn_close_edit(void *edit_baton, apr_pool_t *pool) SVN_ERR_ASSERT(!eb->got_status); eb->got_status = TRUE; - SVN_ERR(svn_ra_svn_write_cmd(eb->conn, pool, "close-edit", "")); - err = svn_ra_svn_read_cmd_response(eb->conn, pool, ""); + SVN_ERR(svn_ra_svn__write_cmd_close_edit(eb->conn, pool)); + err = svn_ra_svn__read_cmd_response(eb->conn, pool, ""); if (err) { - svn_error_clear(svn_ra_svn_write_cmd(eb->conn, pool, "abort-edit", "")); + svn_error_clear(svn_ra_svn__write_cmd_abort_edit(eb->conn, pool)); return err; } if (eb->callback) @@ -395,8 +410,8 @@ static svn_error_t *ra_svn_abort_edit(void *edit_baton, apr_pool_t *pool) if (eb->got_status) return SVN_NO_ERROR; - SVN_ERR(svn_ra_svn_write_cmd(eb->conn, pool, "abort-edit", "")); - SVN_ERR(svn_ra_svn_read_cmd_response(eb->conn, pool, "")); + SVN_ERR(svn_ra_svn__write_cmd_abort_edit(eb->conn, pool)); + SVN_ERR(svn_ra_svn__read_cmd_response(eb->conn, pool, "")); return SVN_NO_ERROR; } @@ -435,6 +450,11 @@ void svn_ra_svn_get_editor(const svn_delta_editor_t **editor, *editor = ra_svn_editor; *edit_baton = eb; + + svn_error_clear(svn_editor__insert_shims(editor, edit_baton, *editor, + *edit_baton, NULL, NULL, + conn->shim_callbacks, + pool, pool)); } /* --- DRIVING AN EDITOR --- */ @@ -453,7 +473,7 @@ static ra_svn_token_entry_t *store_token(ra_svn_driver_state_t *ds, entry->is_file = is_file; entry->dstream = NULL; entry->pool = pool; - apr_hash_set(ds->tokens, entry->token, APR_HASH_KEY_STRING, entry); + svn_hash_sets(ds->tokens, entry->token, entry); return entry; } @@ -461,7 +481,7 @@ static svn_error_t *lookup_token(ra_svn_driver_state_t *ds, const char *token, svn_boolean_t is_file, ra_svn_token_entry_t **entry) { - *entry = apr_hash_get(ds->tokens, token, APR_HASH_KEY_STRING); + *entry = svn_hash_gets(ds->tokens, token); if (!*entry || (*entry)->is_file != is_file) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, _("Invalid file or dir token during edit")); @@ -475,7 +495,7 @@ static svn_error_t *ra_svn_handle_target_rev(svn_ra_svn_conn_t *conn, { svn_revnum_t rev; - SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "r", &rev)); + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "r", &rev)); SVN_CMD_ERR(ds->editor->set_target_revision(ds->edit_baton, rev, pool)); return SVN_NO_ERROR; } @@ -490,7 +510,7 @@ static svn_error_t *ra_svn_handle_open_root(svn_ra_svn_conn_t *conn, const char *token; void *root_baton; - SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "(?r)c", &rev, &token)); + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "(?r)c", &rev, &token)); subpool = svn_pool_create(ds->pool); SVN_CMD_ERR(ds->editor->open_root(ds->edit_baton, rev, subpool, &root_baton)); @@ -507,7 +527,8 @@ static svn_error_t *ra_svn_handle_delete_entry(svn_ra_svn_conn_t *conn, svn_revnum_t rev; ra_svn_token_entry_t *entry; - SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c(?r)c", &path, &rev, &token)); + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?r)c", + &path, &rev, &token)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); path = svn_relpath_canonicalize(path, pool); SVN_CMD_ERR(ds->editor->delete_entry(path, rev, entry->baton, pool)); @@ -525,8 +546,8 @@ static svn_error_t *ra_svn_handle_add_dir(svn_ra_svn_conn_t *conn, apr_pool_t *subpool; void *child_baton; - SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "ccc(?cr)", &path, &token, - &child_token, ©_path, ©_rev)); + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "ccc(?cr)", &path, &token, + &child_token, ©_path, ©_rev)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); subpool = svn_pool_create(entry->pool); path = svn_relpath_canonicalize(path, pool); @@ -558,8 +579,8 @@ static svn_error_t *ra_svn_handle_open_dir(svn_ra_svn_conn_t *conn, apr_pool_t *subpool; void *child_baton; - SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "ccc(?r)", &path, &token, - &child_token, &rev)); + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "ccc(?r)", &path, &token, + &child_token, &rev)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); subpool = svn_pool_create(entry->pool); path = svn_relpath_canonicalize(path, pool); @@ -578,8 +599,8 @@ static svn_error_t *ra_svn_handle_change_dir_prop(svn_ra_svn_conn_t *conn, svn_string_t *value; ra_svn_token_entry_t *entry; - SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "cc(?s)", &token, &name, - &value)); + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "cc(?s)", &token, &name, + &value)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); SVN_CMD_ERR(ds->editor->change_dir_prop(entry->baton, name, value, entry->pool)); @@ -595,12 +616,12 @@ static svn_error_t *ra_svn_handle_close_dir(svn_ra_svn_conn_t *conn, ra_svn_token_entry_t *entry; /* Parse and look up the directory token. */ - SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c", &token)); + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c", &token)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); /* Close the directory and destroy the baton. */ SVN_CMD_ERR(ds->editor->close_directory(entry->baton, pool)); - apr_hash_set(ds->tokens, token, APR_HASH_KEY_STRING, NULL); + svn_hash_sets(ds->tokens, token, NULL); svn_pool_destroy(entry->pool); return SVN_NO_ERROR; } @@ -615,7 +636,7 @@ static svn_error_t *ra_svn_handle_absent_dir(svn_ra_svn_conn_t *conn, ra_svn_token_entry_t *entry; /* Parse parameters and look up the directory token. */ - SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "cc", &path, &token)); + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "cc", &path, &token)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); /* Call the editor. */ @@ -632,8 +653,8 @@ static svn_error_t *ra_svn_handle_add_file(svn_ra_svn_conn_t *conn, svn_revnum_t copy_rev; ra_svn_token_entry_t *entry, *file_entry; - SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "ccc(?cr)", &path, &token, - &file_token, ©_path, ©_rev)); + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "ccc(?cr)", &path, &token, + &file_token, ©_path, ©_rev)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); ds->file_refs++; path = svn_relpath_canonicalize(path, pool); @@ -663,8 +684,8 @@ static svn_error_t *ra_svn_handle_open_file(svn_ra_svn_conn_t *conn, svn_revnum_t rev; ra_svn_token_entry_t *entry, *file_entry; - SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "ccc(?r)", &path, &token, - &file_token, &rev)); + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "ccc(?r)", &path, &token, + &file_token, &rev)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); ds->file_refs++; path = svn_relpath_canonicalize(path, pool); @@ -686,8 +707,8 @@ static svn_error_t *ra_svn_handle_apply_textdelta(svn_ra_svn_conn_t *conn, char *base_checksum; /* Parse arguments and look up the token. */ - SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c(?c)", - &token, &base_checksum)); + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?c)", + &token, &base_checksum)); SVN_ERR(lookup_token(ds, token, TRUE, &entry)); if (entry->dstream) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, @@ -709,7 +730,7 @@ static svn_error_t *ra_svn_handle_textdelta_chunk(svn_ra_svn_conn_t *conn, svn_string_t *str; /* Parse arguments and look up the token. */ - SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "cs", &token, &str)); + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "cs", &token, &str)); SVN_ERR(lookup_token(ds, token, TRUE, &entry)); if (!entry->dstream) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, @@ -727,7 +748,7 @@ static svn_error_t *ra_svn_handle_textdelta_end(svn_ra_svn_conn_t *conn, ra_svn_token_entry_t *entry; /* Parse arguments and look up the token. */ - SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c", &token)); + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c", &token)); SVN_ERR(lookup_token(ds, token, TRUE, &entry)); if (!entry->dstream) return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL, @@ -747,8 +768,8 @@ static svn_error_t *ra_svn_handle_change_file_prop(svn_ra_svn_conn_t *conn, svn_string_t *value; ra_svn_token_entry_t *entry; - SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "cc(?s)", &token, &name, - &value)); + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "cc(?s)", &token, &name, + &value)); SVN_ERR(lookup_token(ds, token, TRUE, &entry)); SVN_CMD_ERR(ds->editor->change_file_prop(entry->baton, name, value, pool)); return SVN_NO_ERROR; @@ -764,13 +785,13 @@ static svn_error_t *ra_svn_handle_close_file(svn_ra_svn_conn_t *conn, const char *text_checksum; /* Parse arguments and look up the file token. */ - SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "c(?c)", - &token, &text_checksum)); + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "c(?c)", + &token, &text_checksum)); SVN_ERR(lookup_token(ds, token, TRUE, &entry)); /* Close the file and destroy the baton. */ SVN_CMD_ERR(ds->editor->close_file(entry->baton, text_checksum, pool)); - apr_hash_set(ds->tokens, token, APR_HASH_KEY_STRING, NULL); + svn_hash_sets(ds->tokens, token, NULL); if (--ds->file_refs == 0) svn_pool_clear(ds->file_pool); return SVN_NO_ERROR; @@ -786,7 +807,7 @@ static svn_error_t *ra_svn_handle_absent_file(svn_ra_svn_conn_t *conn, ra_svn_token_entry_t *entry; /* Parse parameters and look up the parent directory token. */ - SVN_ERR(svn_ra_svn_parse_tuple(params, pool, "cc", &path, &token)); + SVN_ERR(svn_ra_svn__parse_tuple(params, pool, "cc", &path, &token)); SVN_ERR(lookup_token(ds, token, FALSE, &entry)); /* Call the editor. */ @@ -803,7 +824,7 @@ static svn_error_t *ra_svn_handle_close_edit(svn_ra_svn_conn_t *conn, ds->done = TRUE; if (ds->aborted) *ds->aborted = FALSE; - return svn_ra_svn_write_cmd_response(conn, pool, ""); + return svn_ra_svn__write_cmd_response(conn, pool, ""); } static svn_error_t *ra_svn_handle_abort_edit(svn_ra_svn_conn_t *conn, @@ -815,7 +836,7 @@ static svn_error_t *ra_svn_handle_abort_edit(svn_ra_svn_conn_t *conn, if (ds->aborted) *ds->aborted = TRUE; SVN_CMD_ERR(ds->editor->abort_edit(ds->edit_baton, pool)); - return svn_ra_svn_write_cmd_response(conn, pool, ""); + return svn_ra_svn__write_cmd_response(conn, pool, ""); } static svn_error_t *ra_svn_handle_finish_replay(svn_ra_svn_conn_t *conn, @@ -839,25 +860,25 @@ static const struct { const apr_array_header_t *params, ra_svn_driver_state_t *ds); } ra_svn_edit_cmds[] = { - { "target-rev", ra_svn_handle_target_rev }, - { "open-root", ra_svn_handle_open_root }, - { "delete-entry", ra_svn_handle_delete_entry }, + { "change-file-prop", ra_svn_handle_change_file_prop }, + { "open-file", ra_svn_handle_open_file }, + { "apply-textdelta", ra_svn_handle_apply_textdelta }, + { "textdelta-chunk", ra_svn_handle_textdelta_chunk }, + { "close-file", ra_svn_handle_close_file }, { "add-dir", ra_svn_handle_add_dir }, { "open-dir", ra_svn_handle_open_dir }, { "change-dir-prop", ra_svn_handle_change_dir_prop }, + { "delete-entry", ra_svn_handle_delete_entry }, { "close-dir", ra_svn_handle_close_dir }, { "absent-dir", ra_svn_handle_absent_dir }, { "add-file", ra_svn_handle_add_file }, - { "open-file", ra_svn_handle_open_file }, - { "apply-textdelta", ra_svn_handle_apply_textdelta }, - { "textdelta-chunk", ra_svn_handle_textdelta_chunk }, { "textdelta-end", ra_svn_handle_textdelta_end }, - { "change-file-prop", ra_svn_handle_change_file_prop }, - { "close-file", ra_svn_handle_close_file }, { "absent-file", ra_svn_handle_absent_file }, - { "close-edit", ra_svn_handle_close_edit }, { "abort-edit", ra_svn_handle_abort_edit }, { "finish-replay", ra_svn_handle_finish_replay }, + { "target-rev", ra_svn_handle_target_rev }, + { "open-root", ra_svn_handle_open_root }, + { "close-edit", ra_svn_handle_close_edit }, { NULL } }; @@ -870,7 +891,7 @@ static svn_error_t *blocked_write(svn_ra_svn_conn_t *conn, apr_pool_t *pool, /* We blocked trying to send an error. Read and discard an editing * command in order to avoid deadlock. */ - SVN_ERR(svn_ra_svn_read_tuple(conn, pool, "wl", &cmd, ¶ms)); + SVN_ERR(svn_ra_svn__read_tuple(conn, pool, "wl", &cmd, ¶ms)); if (strcmp(cmd, "abort-edit") == 0) { ds->done = TRUE; @@ -906,30 +927,47 @@ svn_error_t *svn_ra_svn_drive_editor2(svn_ra_svn_conn_t *conn, while (!state.done) { svn_pool_clear(subpool); - SVN_ERR(svn_ra_svn_read_tuple(conn, subpool, "wl", &cmd, ¶ms)); - for (i = 0; ra_svn_edit_cmds[i].cmd; i++) - { - if (strcmp(cmd, ra_svn_edit_cmds[i].cmd) == 0) - break; - } - if (ra_svn_edit_cmds[i].cmd) - err = (*ra_svn_edit_cmds[i].handler)(conn, subpool, params, &state); - else if (strcmp(cmd, "failure") == 0) + if (editor) { - /* While not really an editor command this can occur when - reporter->finish_report() fails before the first editor command */ - if (aborted) - *aborted = TRUE; - err = svn_ra_svn__handle_failure_status(params, pool); - return svn_error_compose_create( - err, - editor->abort_edit(edit_baton, subpool)); + SVN_ERR(svn_ra_svn__read_tuple(conn, subpool, "wl", &cmd, ¶ms)); + for (i = 0; ra_svn_edit_cmds[i].cmd; i++) + if (strcmp(cmd, ra_svn_edit_cmds[i].cmd) == 0) + break; + + if (ra_svn_edit_cmds[i].cmd) + err = (*ra_svn_edit_cmds[i].handler)(conn, subpool, params, &state); + else if (strcmp(cmd, "failure") == 0) + { + /* While not really an editor command this can occur when + reporter->finish_report() fails before the first editor + command */ + if (aborted) + *aborted = TRUE; + err = svn_ra_svn__handle_failure_status(params, pool); + return svn_error_compose_create( + err, + editor->abort_edit(edit_baton, subpool)); + } + else + { + err = svn_error_createf(SVN_ERR_RA_SVN_UNKNOWN_CMD, NULL, + _("Unknown editor command '%s'"), cmd); + err = svn_error_create(SVN_ERR_RA_SVN_CMD_ERR, err, NULL); + } } else { - err = svn_error_createf(SVN_ERR_RA_SVN_UNKNOWN_CMD, NULL, - _("Unknown command '%s'"), cmd); - err = svn_error_create(SVN_ERR_RA_SVN_CMD_ERR, err, NULL); + const char* command = NULL; + SVN_ERR(svn_ra_svn__read_command_only(conn, subpool, &command)); + if (strcmp(command, "close-edit") == 0) + { + state.done = TRUE; + if (aborted) + *aborted = FALSE; + err = svn_ra_svn__write_cmd_response(conn, pool, ""); + } + else + err = NULL; } if (err && err->apr_err == SVN_ERR_RA_SVN_CMD_ERR) @@ -939,14 +977,15 @@ svn_error_t *svn_ra_svn_drive_editor2(svn_ra_svn_conn_t *conn, if (!state.done) { /* Abort the edit and use non-blocking I/O to write the error. */ - svn_error_clear(editor->abort_edit(edit_baton, subpool)); + if (editor) + svn_error_clear(editor->abort_edit(edit_baton, subpool)); svn_ra_svn__set_block_handler(conn, blocked_write, &state); } - write_err = svn_ra_svn_write_cmd_failure( + write_err = svn_ra_svn__write_cmd_failure( conn, subpool, svn_ra_svn__locate_real_error_child(err)); if (!write_err) - write_err = svn_ra_svn_flush(conn, subpool); + write_err = svn_ra_svn__flush(conn, subpool); svn_ra_svn__set_block_handler(conn, NULL, NULL); svn_error_clear(err); SVN_ERR(write_err); @@ -973,7 +1012,7 @@ svn_error_t *svn_ra_svn_drive_editor2(svn_ra_svn_conn_t *conn, while (!state.done) { svn_pool_clear(subpool); - err = svn_ra_svn_read_tuple(conn, subpool, "wl", &cmd, ¶ms); + err = svn_ra_svn__read_tuple(conn, subpool, "wl", &cmd, ¶ms); if (err && err->apr_err == SVN_ERR_RA_SVN_CONNECTION_CLOSED) { /* Other side disconnected; that's no error. */ |