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 2018/11/07 12:30:11 UTC
svn commit: r1846002 [33/44] - in /subversion/branches/ra-git: ./ build/
build/ac-macros/ build/generator/ build/generator/swig/
build/generator/templates/ build/generator/util/ build/win32/
contrib/client-side/ contrib/client-side/svn_load_dirs/ contr...
Modified: subversion/branches/ra-git/subversion/svnlook/svnlook.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svnlook/svnlook.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/svnlook/svnlook.c (original)
+++ subversion/branches/ra-git/subversion/svnlook/svnlook.c Wed Nov 7 12:30:06 2018
@@ -212,110 +212,144 @@ static const apr_getopt_option_t options
/* Array of available subcommands.
* The entire list must be terminated with an entry of nulls.
*/
-static const svn_opt_subcommand_desc2_t cmd_table[] =
+static const svn_opt_subcommand_desc3_t cmd_table[] =
{
- {"author", subcommand_author, {0},
- N_("usage: svnlook author REPOS_PATH\n\n"
- "Print the author.\n"),
+ {"author", subcommand_author, {0}, {N_(
+ "usage: svnlook author REPOS_PATH\n"
+ "\n"), N_(
+ "Print the author.\n"
+ )},
{'r', 't'} },
- {"cat", subcommand_cat, {0},
- N_("usage: svnlook cat REPOS_PATH FILE_PATH\n\n"
- "Print the contents of a file. Leading '/' on FILE_PATH is optional.\n"),
+ {"cat", subcommand_cat, {0}, {N_(
+ "usage: svnlook cat REPOS_PATH FILE_PATH\n"
+ "\n"), N_(
+ "Print the contents of a file. Leading '/' on FILE_PATH is optional.\n"
+ )},
{'r', 't'} },
- {"changed", subcommand_changed, {0},
- N_("usage: svnlook changed REPOS_PATH\n\n"
- "Print the paths that were changed.\n"),
+ {"changed", subcommand_changed, {0}, {N_(
+ "usage: svnlook changed REPOS_PATH\n"
+ "\n"), N_(
+ "Print the paths that were changed.\n"
+ )},
{'r', 't', svnlook__copy_info} },
- {"date", subcommand_date, {0},
- N_("usage: svnlook date REPOS_PATH\n\n"
- "Print the datestamp.\n"),
+ {"date", subcommand_date, {0}, {N_(
+ "usage: svnlook date REPOS_PATH\n"
+ "\n"), N_(
+ "Print the datestamp.\n"
+ )},
{'r', 't'} },
- {"diff", subcommand_diff, {0},
- N_("usage: svnlook diff REPOS_PATH\n\n"
- "Print GNU-style diffs of changed files and properties.\n"),
+ {"diff", subcommand_diff, {0}, {N_(
+ "usage: svnlook diff REPOS_PATH\n"
+ "\n"), N_(
+ "Print GNU-style diffs of changed files and properties.\n"
+ )},
{'r', 't', svnlook__no_diff_deleted, svnlook__no_diff_added,
svnlook__diff_copy_from, svnlook__diff_cmd, 'x',
svnlook__ignore_properties, svnlook__properties_only} },
- {"dirs-changed", subcommand_dirschanged, {0},
- N_("usage: svnlook dirs-changed REPOS_PATH\n\n"
+ {"dirs-changed", subcommand_dirschanged, {0}, {N_(
+ "usage: svnlook dirs-changed REPOS_PATH\n"
+ "\n"), N_(
"Print the directories that were themselves changed (property edits)\n"
- "or whose file children were changed.\n"),
+ "or whose file children were changed.\n"
+ )},
{'r', 't'} },
- {"filesize", subcommand_filesize, {0},
- N_("usage: svnlook filesize REPOS_PATH PATH_IN_REPOS\n\n"
+ {"filesize", subcommand_filesize, {0}, {N_(
+ "usage: svnlook filesize REPOS_PATH PATH_IN_REPOS\n"
+ "\n"), N_(
"Print the size (in bytes) of the file located at PATH_IN_REPOS as\n"
- "it is represented in the repository.\n"),
+ "it is represented in the repository.\n"
+ )},
{'r', 't'} },
- {"help", subcommand_help, {"?", "h"},
- N_("usage: svnlook help [SUBCOMMAND...]\n\n"
- "Describe the usage of this program or its subcommands.\n"),
+ {"help", subcommand_help, {"?", "h"}, {N_(
+ "usage: svnlook help [SUBCOMMAND...]\n"
+ "\n"), N_(
+ "Describe the usage of this program or its subcommands.\n"
+ )},
{0} },
- {"history", subcommand_history, {0},
- N_("usage: svnlook history REPOS_PATH [PATH_IN_REPOS]\n\n"
+ {"history", subcommand_history, {0}, {N_(
+ "usage: svnlook history REPOS_PATH [PATH_IN_REPOS]\n"
+ "\n"), N_(
"Print information about the history of a path in the repository (or\n"
- "the root directory if no path is supplied).\n"),
+ "the root directory if no path is supplied).\n"
+ )},
{'r', svnlook__show_ids, 'l'} },
- {"info", subcommand_info, {0},
- N_("usage: svnlook info REPOS_PATH\n\n"
- "Print the author, datestamp, log message size, and log message.\n"),
+ {"info", subcommand_info, {0}, {N_(
+ "usage: svnlook info REPOS_PATH\n"
+ "\n"), N_(
+ "Print the author, datestamp, log message size, and log message.\n"
+ )},
{'r', 't'} },
- {"lock", subcommand_lock, {0},
- N_("usage: svnlook lock REPOS_PATH PATH_IN_REPOS\n\n"
- "If a lock exists on a path in the repository, describe it.\n"),
+ {"lock", subcommand_lock, {0}, {N_(
+ "usage: svnlook lock REPOS_PATH PATH_IN_REPOS\n"
+ "\n"), N_(
+ "If a lock exists on a path in the repository, describe it.\n"
+ )},
{0} },
- {"log", subcommand_log, {0},
- N_("usage: svnlook log REPOS_PATH\n\n"
- "Print the log message.\n"),
+ {"log", subcommand_log, {0}, {N_(
+ "usage: svnlook log REPOS_PATH\n"
+ "\n"), N_(
+ "Print the log message.\n"
+ )},
{'r', 't'} },
- {"propget", subcommand_pget, {"pget", "pg"},
- N_("usage: 1. svnlook propget REPOS_PATH PROPNAME PATH_IN_REPOS\n"
+ {"propget", subcommand_pget, {"pget", "pg"}, {N_(
+ "usage: 1. svnlook propget REPOS_PATH PROPNAME PATH_IN_REPOS\n"
" "
/* The line above is actually needed, so do NOT delete it! */
- " 2. svnlook propget --revprop REPOS_PATH PROPNAME\n\n"
+ " 2. svnlook propget --revprop REPOS_PATH PROPNAME\n"
+ "\n"), N_(
"Print the raw value of a property on a path in the repository.\n"
- "With --revprop, print the raw value of a revision property.\n"),
+ "With --revprop, print the raw value of a revision property.\n"
+ )},
{'r', 't', 'v', svnlook__revprop_opt, svnlook__show_inherited_props} },
- {"proplist", subcommand_plist, {"plist", "pl"},
- N_("usage: 1. svnlook proplist REPOS_PATH PATH_IN_REPOS\n"
+ {"proplist", subcommand_plist, {"plist", "pl"}, {N_(
+ "usage: 1. svnlook proplist REPOS_PATH PATH_IN_REPOS\n"
" "
/* The line above is actually needed, so do NOT delete it! */
- " 2. svnlook proplist --revprop REPOS_PATH\n\n"
+ " 2. svnlook proplist --revprop REPOS_PATH\n"
+ "\n"), N_(
"List the properties of a path in the repository, or\n"
"with the --revprop option, revision properties.\n"
- "With -v, show the property values too.\n"),
+ "With -v, show the property values too.\n"
+ )},
{'r', 't', 'v', svnlook__revprop_opt, svnlook__xml_opt,
svnlook__show_inherited_props} },
- {"tree", subcommand_tree, {0},
- N_("usage: svnlook tree REPOS_PATH [PATH_IN_REPOS]\n\n"
+ {"tree", subcommand_tree, {0}, {N_(
+ "usage: svnlook tree REPOS_PATH [PATH_IN_REPOS]\n"
+ "\n"), N_(
"Print the tree, starting at PATH_IN_REPOS (if supplied, at the root\n"
- "of the tree otherwise), optionally showing node revision ids.\n"),
+ "of the tree otherwise), optionally showing node revision ids.\n"
+ )},
{'r', 't', 'N', svnlook__show_ids, svnlook__full_paths, 'M'} },
- {"uuid", subcommand_uuid, {0},
- N_("usage: svnlook uuid REPOS_PATH\n\n"
- "Print the repository's UUID.\n"),
+ {"uuid", subcommand_uuid, {0}, {N_(
+ "usage: svnlook uuid REPOS_PATH\n"
+ "\n"), N_(
+ "Print the repository's UUID.\n"
+ )},
{0} },
- {"youngest", subcommand_youngest, {0},
- N_("usage: svnlook youngest REPOS_PATH\n\n"
- "Print the youngest revision number.\n"),
+ {"youngest", subcommand_youngest, {0}, {N_(
+ "usage: svnlook youngest REPOS_PATH\n"
+ "\n"), N_(
+ "Print the youngest revision number.\n"
+ )},
{svnlook__no_newline} },
- { NULL, NULL, {0}, NULL, {0} }
+ { NULL, NULL, {0}, {NULL}, {0} }
};
@@ -2222,7 +2256,7 @@ subcommand_help(apr_getopt_t *os, void *
version_footer = svn_stringbuf_create(fs_desc_start, pool);
SVN_ERR(svn_fs_print_modules(version_footer, pool));
- SVN_ERR(svn_opt_print_help4(os, "svnlook",
+ SVN_ERR(svn_opt_print_help5(os, "svnlook",
opt_state ? opt_state->version : FALSE,
opt_state ? opt_state->quiet : FALSE,
opt_state ? opt_state->verbose : FALSE,
@@ -2437,7 +2471,7 @@ sub_main(int *exit_code, int argc, const
svn_error_t *err;
apr_status_t apr_err;
- const svn_opt_subcommand_desc2_t *subcommand = NULL;
+ const svn_opt_subcommand_desc3_t *subcommand = NULL;
struct svnlook_opt_state opt_state;
apr_getopt_t *os;
int opt_id;
@@ -2505,8 +2539,12 @@ sub_main(int *exit_code, int argc, const
break;
case 'M':
- opt_state.memory_cache_size
- = 0x100000 * apr_strtoi64(opt_arg, NULL, 0);
+ {
+ apr_uint64_t sz_val;
+ SVN_ERR(svn_cstring_atoui64(&sz_val, opt_arg));
+
+ opt_state.memory_cache_size = 0x100000 * sz_val;
+ }
break;
case 'N':
@@ -2630,7 +2668,7 @@ sub_main(int *exit_code, int argc, const
just typos/mistakes. Whatever the case, the subcommand to
actually run is subcommand_help(). */
if (opt_state.help)
- subcommand = svn_opt_get_canonical_subcommand2(cmd_table, "help");
+ subcommand = svn_opt_get_canonical_subcommand3(cmd_table, "help");
/* If we're not running the `help' subcommand, then look for a
subcommand in the first argument. */
@@ -2641,8 +2679,8 @@ sub_main(int *exit_code, int argc, const
if (opt_state.version)
{
/* Use the "help" subcommand to handle the "--version" option. */
- static const svn_opt_subcommand_desc2_t pseudo_cmd =
- { "--version", subcommand_help, {0}, "",
+ static const svn_opt_subcommand_desc3_t pseudo_cmd =
+ { "--version", subcommand_help, {0}, {""},
{svnlook__version, /* must accept its own option */
'q', 'v',
} };
@@ -2661,21 +2699,21 @@ sub_main(int *exit_code, int argc, const
}
else
{
- const char *first_arg = os->argv[os->ind++];
- subcommand = svn_opt_get_canonical_subcommand2(cmd_table, first_arg);
+ const char *first_arg;
+
+ SVN_ERR(svn_utf_cstring_to_utf8(&first_arg, os->argv[os->ind++],
+ pool));
+ subcommand = svn_opt_get_canonical_subcommand3(cmd_table, first_arg);
if (subcommand == NULL)
{
- const char *first_arg_utf8;
- SVN_ERR(svn_utf_cstring_to_utf8(&first_arg_utf8, first_arg,
- pool));
svn_error_clear(
svn_cmdline_fprintf(stderr, pool,
_("Unknown subcommand: '%s'\n"),
- first_arg_utf8));
+ first_arg));
SVN_ERR(subcommand_help(NULL, NULL, pool));
/* Be kind to people who try 'svnlook verify'. */
- if (strcmp(first_arg_utf8, "verify") == 0)
+ if (strcmp(first_arg, "verify") == 0)
{
svn_error_clear(
svn_cmdline_fprintf(stderr, pool,
@@ -2758,11 +2796,11 @@ sub_main(int *exit_code, int argc, const
if (opt_id == 'h' || opt_id == '?')
continue;
- if (! svn_opt_subcommand_takes_option3(subcommand, opt_id, NULL))
+ if (! svn_opt_subcommand_takes_option4(subcommand, opt_id, NULL))
{
const char *optstr;
const apr_getopt_option_t *badopt =
- svn_opt_get_option_from_code2(opt_id, options_table, subcommand,
+ svn_opt_get_option_from_code3(opt_id, options_table, subcommand,
pool);
svn_opt_format_option(&optstr, badopt, FALSE, pool);
if (subcommand->name[0] == '-')
Modified: subversion/branches/ra-git/subversion/svnmucc/svnmucc.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svnmucc/svnmucc.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/svnmucc/svnmucc.c (original)
+++ subversion/branches/ra-git/subversion/svnmucc/svnmucc.c Wed Nov 7 12:30:06 2018
@@ -297,6 +297,7 @@ help(FILE *stream, apr_pool_t *pool)
" -F [--file] ARG : read log message from file ARG\n"
" -u [--username] ARG : commit the changes as username ARG\n"
" -p [--password] ARG : use ARG as the password\n"
+ " --password-from-stdin : read password from stdin\n"
" -U [--root-url] ARG : interpret all action URLs relative to ARG\n"
" -r [--revision] ARG : use revision ARG as baseline for changes\n"
" --with-revprop ARG : set revision property in the following format:\n"
@@ -341,7 +342,7 @@ display_version(apr_pool_t *pool)
version_footer = svn_stringbuf_create(ra_desc_start, pool);
SVN_ERR(svn_ra_print_modules(version_footer, pool));
- SVN_ERR(svn_opt_print_help4(NULL, "svnmucc", TRUE, FALSE, FALSE,
+ SVN_ERR(svn_opt_print_help5(NULL, "svnmucc", TRUE, FALSE, FALSE,
version_footer->data,
NULL, NULL, NULL, NULL, NULL, pool));
@@ -480,13 +481,15 @@ sub_main(int *exit_code, int argc, const
non_interactive_opt,
force_interactive_opt,
trust_server_cert_opt,
- trust_server_cert_failures_opt
+ trust_server_cert_failures_opt,
+ password_from_stdin_opt
};
static const apr_getopt_option_t options[] = {
{"message", 'm', 1, ""},
{"file", 'F', 1, ""},
{"username", 'u', 1, ""},
{"password", 'p', 1, ""},
+ {"password-from-stdin", password_from_stdin_opt, 0, ""},
{"root-url", 'U', 1, ""},
{"revision", 'r', 1, ""},
{"with-revprop", with_revprop_opt, 1, ""},
@@ -527,10 +530,14 @@ sub_main(int *exit_code, int argc, const
svn_client_ctx_t *ctx;
struct log_message_baton lmb;
int i;
+ svn_boolean_t read_pass_from_stdin = FALSE;
/* Check library versions */
SVN_ERR(check_lib_versions());
+ /* Initialize the RA library. */
+ SVN_ERR(svn_ra_initialize(pool));
+
config_options = apr_array_make(pool, 0,
sizeof(svn_cmdline__config_argument_t*));
@@ -558,9 +565,9 @@ sub_main(int *exit_code, int argc, const
break;
case 'F':
{
- const char *arg_utf8;
- SVN_ERR(svn_utf_cstring_to_utf8(&arg_utf8, arg, pool));
- SVN_ERR(svn_stringbuf_from_file2(&filedata, arg, pool));
+ const char *filename;
+ SVN_ERR(svn_utf_cstring_to_utf8(&filename, arg, pool));
+ SVN_ERR(svn_stringbuf_from_file2(&filedata, filename, pool));
}
break;
case 'u':
@@ -569,6 +576,9 @@ sub_main(int *exit_code, int argc, const
case 'p':
password = apr_pstrdup(pool, arg);
break;
+ case password_from_stdin_opt:
+ read_pass_from_stdin = TRUE;
+ break;
case 'U':
SVN_ERR(svn_utf_cstring_to_utf8(&root_url, arg, pool));
if (! svn_path_is_url(root_url))
@@ -595,7 +605,7 @@ sub_main(int *exit_code, int argc, const
SVN_ERR(svn_opt_parse_revprop(&revprops, arg, pool));
break;
case 'X':
- extra_args_file = apr_pstrdup(pool, arg);
+ SVN_ERR(svn_utf_cstring_to_utf8(&extra_args_file, arg, pool));
break;
case non_interactive_opt:
non_interactive = TRUE;
@@ -669,27 +679,33 @@ sub_main(int *exit_code, int argc, const
"--non-interactive"));
}
+ /* --password-from-stdin can only be used with --non-interactive */
+ if (read_pass_from_stdin && !non_interactive)
+ {
+ return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ _("--password-from-stdin requires "
+ "--non-interactive"));
+ }
+
+
/* Copy the rest of our command-line arguments to an array,
UTF-8-ing them along the way. */
action_args = apr_array_make(pool, opts->argc, sizeof(const char *));
while (opts->ind < opts->argc)
{
- const char *arg = opts->argv[opts->ind++];
- SVN_ERR(svn_utf_cstring_to_utf8(&APR_ARRAY_PUSH(action_args,
- const char *),
- arg, pool));
+ const char *arg;
+
+ SVN_ERR(svn_utf_cstring_to_utf8(&arg, opts->argv[opts->ind++], pool));
+ APR_ARRAY_PUSH(action_args, const char *) = arg;
}
/* If there are extra arguments in a supplementary file, tack those
on, too (again, in UTF8 form). */
if (extra_args_file)
{
- const char *extra_args_file_utf8;
svn_stringbuf_t *contents, *contents_utf8;
- SVN_ERR(svn_utf_cstring_to_utf8(&extra_args_file_utf8,
- extra_args_file, pool));
- SVN_ERR(svn_stringbuf_from_file2(&contents, extra_args_file_utf8, pool));
+ SVN_ERR(svn_stringbuf_from_file2(&contents, extra_args_file, pool));
SVN_ERR(svn_utf_stringbuf_to_utf8(&contents_utf8, contents, pool));
svn_cstring_split_append(action_args, contents_utf8->data, "\n\r",
FALSE, pool);
@@ -721,6 +737,12 @@ sub_main(int *exit_code, int argc, const
"svnmucc: ", "--config-option"));
}
+ /* Get password from stdin if necessary */
+ if (read_pass_from_stdin)
+ {
+ SVN_ERR(svn_cmdline__stdin_readline(&password, pool, pool));
+ }
+
SVN_ERR(svn_client_create_context2(&ctx, cfg_hash, pool));
cfg_config = svn_hash_gets(cfg_hash, SVN_CONFIG_CATEGORY_CONFIG);
Modified: subversion/branches/ra-git/subversion/svnrdump/dump_editor.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/svnrdump/dump_editor.c?rev=1846002&r1=1846001&r2=1846002&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/svnrdump/dump_editor.c (original)
+++ subversion/branches/ra-git/subversion/svnrdump/dump_editor.c Wed Nov 7 12:30:06 2018
@@ -22,951 +22,28 @@
* ====================================================================
*/
-#include "svn_hash.h"
-#include "svn_pools.h"
-#include "svn_repos.h"
-#include "svn_path.h"
+#include "svn_types.h"
#include "svn_props.h"
-#include "svn_subst.h"
-#include "svn_dirent_uri.h"
+#include "svn_ra.h"
+#include "svn_io.h"
+#include "svn_delta.h"
#include "private/svn_repos_private.h"
-#include "private/svn_subr_private.h"
-#include "private/svn_dep_compat.h"
#include "private/svn_editor.h"
#include "svnrdump.h"
#include <assert.h>
-#define ARE_VALID_COPY_ARGS(p,r) ((p) && SVN_IS_VALID_REVNUM(r))
-
-
-/* A directory baton used by all directory-related callback functions
- * in the dump editor. */
-struct dir_baton
-{
- struct dump_edit_baton *eb;
-
- /* Pool for per-directory allocations */
- apr_pool_t *pool;
-
- /* the path to this directory */
- const char *repos_relpath; /* a relpath */
-
- /* Copyfrom info for the node, if any. */
- const char *copyfrom_path; /* a relpath */
- svn_revnum_t copyfrom_rev;
-
- /* Headers accumulated so far for this directory */
- svn_repos__dumpfile_headers_t *headers;
-
- /* Properties which were modified during change_dir_prop. */
- apr_hash_t *props;
-
- /* Properties which were deleted during change_dir_prop. */
- apr_hash_t *deleted_props;
-
- /* Hash of paths that need to be deleted, though some -might- be
- replaced. Maps const char * paths to this dir_baton. Note that
- they're full paths, because that's what the editor driver gives
- us, although they're all really within this directory. */
- apr_hash_t *deleted_entries;
-
- /* Flag to trigger dumping props. */
- svn_boolean_t dump_props;
-};
-
-/* A file baton used by all file-related callback functions in the dump
- * editor */
-struct file_baton
-{
- struct dump_edit_baton *eb;
-
- /* Pool for per-file allocations */
- apr_pool_t *pool;
-
- /* the path to this file */
- const char *repos_relpath; /* a relpath */
-
- /* Properties which were modified during change_file_prop. */
- apr_hash_t *props;
-
- /* Properties which were deleted during change_file_prop. */
- apr_hash_t *deleted_props;
-
- /* The checksum of the file the delta is being applied to */
- const char *base_checksum;
-
- /* Copy state and source information (if any). */
- svn_boolean_t is_copy;
- const char *copyfrom_path;
- svn_revnum_t copyfrom_rev;
-
- /* The action associate with this node. */
- enum svn_node_action action;
-
- /* Flags to trigger dumping props and text. */
- svn_boolean_t dump_text;
- svn_boolean_t dump_props;
-};
/* The baton used by the dump editor. */
struct dump_edit_baton {
- /* The output stream we write the dumpfile to */
- svn_stream_t *stream;
-
/* A backdoor ra session to fetch additional information during the edit. */
svn_ra_session_t *ra_session;
- /* The repository relpath of the anchor of the editor when driven
- via the RA update mechanism; NULL otherwise. (When the editor is
- driven via the RA "replay" mechanism instead, the editor is
- always anchored at the repository, we don't need to prepend an
- anchor path to the dumped node paths, and open_root() doesn't
- need to manufacture directory additions.) */
- const char *update_anchor_relpath;
-
- /* Pool for per-revision allocations */
- apr_pool_t *pool;
-
- /* Temporary file used for textdelta application along with its
- absolute path; these two variables should be allocated in the
- per-edit-session pool */
- const char *delta_abspath;
- apr_file_t *delta_file;
-
/* The revision we're currently dumping. */
svn_revnum_t current_revision;
-
- /* The baton of the directory node whose block of
- dump stream data has not been fully completed; NULL if there's no
- such item. */
- struct dir_baton *pending_db;
};
-/* Make a directory baton to represent the directory at PATH (relative
- * to the EDIT_BATON).
- *
- * COPYFROM_PATH/COPYFROM_REV are the path/revision against which this
- * directory should be compared for changes. If the copyfrom
- * information is valid, the directory will be compared against its
- * copy source.
- *
- * PB is the directory baton of this directory's parent, or NULL if
- * this is the top-level directory of the edit.
- *
- * Perform all allocations in POOL. */
-static struct dir_baton *
-make_dir_baton(const char *path,
- const char *copyfrom_path,
- svn_revnum_t copyfrom_rev,
- void *edit_baton,
- struct dir_baton *pb,
- apr_pool_t *pool)
-{
- struct dump_edit_baton *eb = edit_baton;
- struct dir_baton *new_db = apr_pcalloc(pool, sizeof(*new_db));
- const char *repos_relpath;
-
- /* Construct the full path of this node. */
- if (pb)
- repos_relpath = svn_relpath_canonicalize(path, pool);
- else
- repos_relpath = "";
-
- /* Strip leading slash from copyfrom_path so that the path is
- canonical and svn_relpath_join can be used */
- if (copyfrom_path)
- copyfrom_path = svn_relpath_canonicalize(copyfrom_path, pool);
-
- new_db->eb = eb;
- new_db->pool = pool;
- new_db->repos_relpath = repos_relpath;
- new_db->copyfrom_path = copyfrom_path
- ? svn_relpath_canonicalize(copyfrom_path, pool)
- : NULL;
- new_db->copyfrom_rev = copyfrom_rev;
- new_db->headers = NULL;
- new_db->props = apr_hash_make(pool);
- new_db->deleted_props = apr_hash_make(pool);
- new_db->deleted_entries = apr_hash_make(pool);
-
- return new_db;
-}
-
-/* Make a file baton to represent the directory at PATH (relative to
- * PB->eb). PB is the directory baton of this directory's parent, or
- * NULL if this is the top-level directory of the edit. Perform all
- * allocations in POOL. */
-static struct file_baton *
-make_file_baton(const char *path,
- struct dir_baton *pb,
- apr_pool_t *pool)
-{
- struct file_baton *new_fb = apr_pcalloc(pool, sizeof(*new_fb));
-
- new_fb->eb = pb->eb;
- new_fb->pool = pool;
- new_fb->repos_relpath = svn_relpath_canonicalize(path, pool);
- new_fb->props = apr_hash_make(pool);
- new_fb->deleted_props = apr_hash_make(pool);
- new_fb->is_copy = FALSE;
- new_fb->copyfrom_path = NULL;
- new_fb->copyfrom_rev = SVN_INVALID_REVNUM;
- new_fb->action = svn_node_action_change;
-
- return new_fb;
-}
-
-/* Append to HEADERS the required headers, and set *CONTENT to the property
- * content section, to represent the property delta of PROPS/DELETED_PROPS.
- */
-static svn_error_t *
-get_props_content(svn_repos__dumpfile_headers_t *headers,
- svn_stringbuf_t **content,
- apr_hash_t *props,
- apr_hash_t *deleted_props,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- svn_stream_t *content_stream;
- apr_hash_t *normal_props;
-
- *content = svn_stringbuf_create_empty(result_pool);
-
- content_stream = svn_stream_from_stringbuf(*content, scratch_pool);
-
- SVN_ERR(svn_rdump__normalize_props(&normal_props, props, scratch_pool));
- SVN_ERR(svn_hash_write_incremental(normal_props, deleted_props,
- content_stream, "PROPS-END",
- scratch_pool));
- SVN_ERR(svn_stream_close(content_stream));
-
- /* Prop-delta: true */
- svn_repos__dumpfile_header_push(
- headers, SVN_REPOS_DUMPFILE_PROP_DELTA, "true");
-
- return SVN_NO_ERROR;
-}
-
-/* A special case of dump_node(), for a delete record.
- *
- * The only thing special about this version is it only writes one blank
- * line, not two, after the headers. Why? Historical precedent for the
- * case where a delete record is used as part of a (delete + add-with-history)
- * in implementing a replacement.
- */
-static svn_error_t *
-dump_node_delete(svn_stream_t *stream,
- const char *node_relpath,
- apr_pool_t *pool)
-{
- svn_repos__dumpfile_headers_t *headers
- = svn_repos__dumpfile_headers_create(pool);
-
- assert(svn_relpath_is_canonical(node_relpath));
-
- /* Node-path: ... */
- svn_repos__dumpfile_header_push(
- headers, SVN_REPOS_DUMPFILE_NODE_PATH, node_relpath);
-
- /* Node-action: delete */
- svn_repos__dumpfile_header_push(
- headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "delete");
-
- SVN_ERR(svn_repos__dump_node_record(stream, headers,
- NULL, FALSE, 0, /* props & text */
- FALSE /*content_length_always*/, pool));
- return SVN_NO_ERROR;
-}
-
-/* Set *HEADERS_P to contain some headers for the node at PATH of type KIND.
- *
- * ACTION describes what is happening to the node (see enum
- * svn_node_action).
- *
- * If the node was itself copied, IS_COPY is TRUE and the
- * path/revision of the copy source are in COPYFROM_PATH/COPYFROM_REV.
- * If IS_COPY is FALSE, yet COPYFROM_PATH/COPYFROM_REV are valid, this
- * node is part of a copied subtree.
- *
- * Iff ACTION is svn_node_action_replace and IS_COPY, then first write a
- * complete deletion record to the dump stream.
- *
- * If ACTION is svn_node_action_delete, then the node record will be
- * complete. (The caller may want to write two blank lines after the
- * header block.)
- */
-static svn_error_t *
-dump_node(svn_repos__dumpfile_headers_t **headers_p,
- struct dump_edit_baton *eb,
- const char *repos_relpath,
- struct dir_baton *db,
- struct file_baton *fb,
- enum svn_node_action action,
- svn_boolean_t is_copy,
- const char *copyfrom_path,
- svn_revnum_t copyfrom_rev,
- apr_pool_t *pool)
-{
- const char *node_relpath = repos_relpath;
- svn_repos__dumpfile_headers_t *headers
- = svn_repos__dumpfile_headers_create(pool);
-
- assert(svn_relpath_is_canonical(repos_relpath));
- assert(!copyfrom_path || svn_relpath_is_canonical(copyfrom_path));
- assert(! (db && fb));
-
- /* Add the edit root relpath prefix if necessary. */
- if (eb->update_anchor_relpath)
- node_relpath = svn_relpath_join(eb->update_anchor_relpath,
- node_relpath, pool);
-
- /* Node-path: ... */
- svn_repos__dumpfile_header_push(
- headers, SVN_REPOS_DUMPFILE_NODE_PATH, node_relpath);
-
- /* Node-kind: "file" | "dir" */
- if (fb)
- svn_repos__dumpfile_header_push(
- headers, SVN_REPOS_DUMPFILE_NODE_KIND, "file");
- else if (db)
- svn_repos__dumpfile_header_push(
- headers, SVN_REPOS_DUMPFILE_NODE_KIND, "dir");
-
-
- /* Write the appropriate Node-action header */
- switch (action)
- {
- case svn_node_action_change:
- /* We are here after a change_file_prop or change_dir_prop. They
- set up whatever dump_props they needed to- nothing to
- do here but print node action information.
-
- Node-action: change. */
- svn_repos__dumpfile_header_push(
- headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "change");
- break;
-
- case svn_node_action_delete:
- /* Node-action: delete */
- svn_repos__dumpfile_header_push(
- headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "delete");
- break;
-
- case svn_node_action_replace:
- if (! is_copy)
- {
- /* Node-action: replace */
- svn_repos__dumpfile_header_push(
- headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "replace");
-
- /* Wait for a change_*_prop to be called before dumping
- anything */
- if (fb)
- fb->dump_props = TRUE;
- else if (db)
- db->dump_props = TRUE;
- break;
- }
- else
- {
- /* More complex case: is_copy is true, and copyfrom_path/
- copyfrom_rev are present: delete the original, and then re-add
- it */
- /* ### Why not write a 'replace' record? Don't know. */
-
- /* ### Unusually, we end this 'delete' node record with only a single
- blank line after the header block -- no extra blank line. */
- SVN_ERR(dump_node_delete(eb->stream, repos_relpath, pool));
-
- /* The remaining action is a non-replacing add-with-history */
- /* action = svn_node_action_add; */
- }
- /* FALL THROUGH to 'add' */
-
- case svn_node_action_add:
- /* Node-action: add */
- svn_repos__dumpfile_header_push(
- headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "add");
-
- if (is_copy)
- {
- /* Node-copyfrom-rev / Node-copyfrom-path */
- svn_repos__dumpfile_header_pushf(
- headers, SVN_REPOS_DUMPFILE_NODE_COPYFROM_REV, "%ld", copyfrom_rev);
- svn_repos__dumpfile_header_push(
- headers, SVN_REPOS_DUMPFILE_NODE_COPYFROM_PATH, copyfrom_path);
- }
- else
- {
- /* fb->dump_props (for files) is handled in close_file()
- which is called immediately.
-
- However, directories are not closed until all the work
- inside them has been done; db->dump_props (for directories)
- is handled (via dump_pending()) in all the functions that
- can possibly be called after add_directory():
-
- - add_directory()
- - open_directory()
- - delete_entry()
- - close_directory()
- - add_file()
- - open_file()
-
- change_dir_prop() is a special case. */
- if (fb)
- fb->dump_props = TRUE;
- else if (db)
- db->dump_props = TRUE;
- }
-
- break;
- }
-
- /* Return the headers so far. We don't necessarily have all the headers
- yet -- there may be property-related and content length headers to
- come, if this was not a 'delete' record. */
- *headers_p = headers;
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-dump_mkdir(struct dump_edit_baton *eb,
- const char *repos_relpath,
- apr_pool_t *pool)
-{
- svn_stringbuf_t *prop_content;
- svn_repos__dumpfile_headers_t *headers
- = svn_repos__dumpfile_headers_create(pool);
-
- /* Node-path: ... */
- svn_repos__dumpfile_header_push(
- headers, SVN_REPOS_DUMPFILE_NODE_PATH, repos_relpath);
-
- /* Node-kind: dir */
- svn_repos__dumpfile_header_push(
- headers, SVN_REPOS_DUMPFILE_NODE_KIND, "dir");
-
- /* Node-action: add */
- svn_repos__dumpfile_header_push(
- headers, SVN_REPOS_DUMPFILE_NODE_ACTION, "add");
-
- /* Dump the (empty) property block. */
- SVN_ERR(get_props_content(headers, &prop_content,
- apr_hash_make(pool), apr_hash_make(pool),
- pool, pool));
- SVN_ERR(svn_repos__dump_node_record(eb->stream, headers, prop_content,
- FALSE, 0, FALSE /*content_length_always*/,
- pool));
-
- /* Newlines to tie it all off. */
- SVN_ERR(svn_stream_puts(eb->stream, "\n\n"));
-
- return SVN_NO_ERROR;
-}
-
-/* Dump pending headers and properties for the directory EB->pending_db (if
- * not null), to allow starting the dump of a child node */
-static svn_error_t *
-dump_pending_dir(struct dump_edit_baton *eb,
- apr_pool_t *scratch_pool)
-{
- struct dir_baton *db = eb->pending_db;
- svn_stringbuf_t *prop_content = NULL;
-
- if (! db)
- return SVN_NO_ERROR;
-
- /* Some pending properties to dump? */
- if (db->dump_props)
- {
- SVN_ERR(get_props_content(db->headers, &prop_content,
- db->props, db->deleted_props,
- scratch_pool, scratch_pool));
- }
- SVN_ERR(svn_repos__dump_node_record(eb->stream, db->headers, prop_content,
- FALSE, 0, FALSE /*content_length_always*/,
- scratch_pool));
-
- /* No text is going to be dumped. Write a couple of newlines and
- wait for the next node/ revision. */
- SVN_ERR(svn_stream_puts(eb->stream, "\n\n"));
-
- if (db->dump_props)
- {
- /* Cleanup so that data is never dumped twice. */
- apr_hash_clear(db->props);
- apr_hash_clear(db->deleted_props);
- db->dump_props = FALSE;
- }
-
- /* Anything that was pending is pending no longer. */
- eb->pending_db = NULL;
-
- return SVN_NO_ERROR;
-}
-
-
-
-/*** Editor Function Implementations ***/
-
-static svn_error_t *
-open_root(void *edit_baton,
- svn_revnum_t base_revision,
- apr_pool_t *pool,
- void **root_baton)
-{
- struct dump_edit_baton *eb = edit_baton;
- struct dir_baton *new_db = NULL;
-
- /* Clear the per-revision pool after each revision */
- svn_pool_clear(eb->pool);
-
- if (eb->update_anchor_relpath)
- {
- int i;
- const char *parent_path = eb->update_anchor_relpath;
- apr_array_header_t *dirs_to_add =
- apr_array_make(pool, 4, sizeof(const char *));
- apr_pool_t *iterpool = svn_pool_create(pool);
-
- while (! svn_path_is_empty(parent_path))
- {
- APR_ARRAY_PUSH(dirs_to_add, const char *) = parent_path;
- parent_path = svn_relpath_dirname(parent_path, pool);
- }
-
- for (i = dirs_to_add->nelts; i; --i)
- {
- const char *dir_to_add =
- APR_ARRAY_IDX(dirs_to_add, i - 1, const char *);
-
- svn_pool_clear(iterpool);
-
- /* For parents of the source directory, we just manufacture
- the adds ourselves. */
- if (i > 1)
- {
- SVN_ERR(dump_mkdir(eb, dir_to_add, iterpool));
- }
- else
- {
- /* ... but for the source directory itself, we'll defer
- to letting the typical plumbing handle this task. */
- new_db = make_dir_baton(NULL, NULL, SVN_INVALID_REVNUM,
- edit_baton, NULL, pool);
- SVN_ERR(dump_node(&new_db->headers,
- eb, new_db->repos_relpath, new_db,
- NULL, svn_node_action_add, FALSE,
- NULL, SVN_INVALID_REVNUM, pool));
-
- /* Remember that we've started but not yet finished
- handling this directory. */
- eb->pending_db = new_db;
- }
- }
- svn_pool_destroy(iterpool);
- }
-
- if (! new_db)
- {
- new_db = make_dir_baton(NULL, NULL, SVN_INVALID_REVNUM,
- edit_baton, NULL, pool);
- }
-
- *root_baton = new_db;
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-delete_entry(const char *path,
- svn_revnum_t revision,
- void *parent_baton,
- apr_pool_t *pool)
-{
- struct dir_baton *pb = parent_baton;
-
- SVN_ERR(dump_pending_dir(pb->eb, pool));
-
- /* We don't dump this deletion immediate. Rather, we add this path
- to the deleted_entries of the parent directory baton. That way,
- we can tell (later) an addition from a replacement. All the real
- deletions get handled in close_directory(). */
- svn_hash_sets(pb->deleted_entries, apr_pstrdup(pb->pool, path), pb);
-
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-add_directory(const char *path,
- void *parent_baton,
- const char *copyfrom_path,
- svn_revnum_t copyfrom_rev,
- apr_pool_t *pool,
- void **child_baton)
-{
- struct dir_baton *pb = parent_baton;
- void *was_deleted;
- struct dir_baton *new_db;
- svn_boolean_t is_copy;
-
- SVN_ERR(dump_pending_dir(pb->eb, pool));
-
- new_db = make_dir_baton(path, copyfrom_path, copyfrom_rev, pb->eb,
- pb, pb->pool);
-
- /* This might be a replacement -- is the path already deleted? */
- was_deleted = svn_hash_gets(pb->deleted_entries, path);
-
- /* Detect an add-with-history */
- is_copy = ARE_VALID_COPY_ARGS(copyfrom_path, copyfrom_rev);
-
- /* Dump the node */
- SVN_ERR(dump_node(&new_db->headers,
- pb->eb, new_db->repos_relpath, new_db, NULL,
- was_deleted ? svn_node_action_replace : svn_node_action_add,
- is_copy,
- is_copy ? new_db->copyfrom_path : NULL,
- is_copy ? copyfrom_rev : SVN_INVALID_REVNUM,
- pool));
-
- if (was_deleted)
- /* Delete the path, it's now been dumped */
- svn_hash_sets(pb->deleted_entries, path, NULL);
-
- /* Remember that we've started, but not yet finished handling this
- directory. */
- pb->eb->pending_db = new_db;
-
- *child_baton = new_db;
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-open_directory(const char *path,
- void *parent_baton,
- svn_revnum_t base_revision,
- apr_pool_t *pool,
- void **child_baton)
-{
- struct dir_baton *pb = parent_baton;
- struct dir_baton *new_db;
- const char *copyfrom_path = NULL;
- svn_revnum_t copyfrom_rev = SVN_INVALID_REVNUM;
-
- SVN_ERR(dump_pending_dir(pb->eb, pool));
-
- /* If the parent directory has explicit comparison path and rev,
- record the same for this one. */
- if (ARE_VALID_COPY_ARGS(pb->copyfrom_path, pb->copyfrom_rev))
- {
- copyfrom_path = svn_relpath_join(pb->copyfrom_path,
- svn_relpath_basename(path, NULL),
- pb->pool);
- copyfrom_rev = pb->copyfrom_rev;
- }
-
- new_db = make_dir_baton(path, copyfrom_path, copyfrom_rev, pb->eb, pb,
- pb->pool);
-
- *child_baton = new_db;
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-close_directory(void *dir_baton,
- apr_pool_t *pool)
-{
- struct dir_baton *db = dir_baton;
- apr_hash_index_t *hi;
- svn_boolean_t this_pending;
-
- /* Remember if this directory is the one currently pending. */
- this_pending = (db->eb->pending_db == db);
-
- SVN_ERR(dump_pending_dir(db->eb, pool));
-
- /* If this directory was pending, then dump_pending() should have
- taken care of all the props and such. Of course, the only way
- that would be the case is if this directory was added/replaced.
-
- Otherwise, if stuff for this directory has already been written
- out (at some point in the past, prior to our handling other
- nodes), we might need to generate a second "change" record just
- to carry the information we've since learned about the
- directory. */
- if ((! this_pending) && (db->dump_props))
- {
- SVN_ERR(dump_node(&db->headers,
- db->eb, db->repos_relpath, db, NULL,
- svn_node_action_change, FALSE,
- NULL, SVN_INVALID_REVNUM, pool));
- db->eb->pending_db = db;
- SVN_ERR(dump_pending_dir(db->eb, pool));
- }
-
- /* Dump the deleted directory entries */
- for (hi = apr_hash_first(pool, db->deleted_entries); hi;
- hi = apr_hash_next(hi))
- {
- const char *path = apr_hash_this_key(hi);
-
- SVN_ERR(dump_node_delete(db->eb->stream, path, pool));
- /* This deletion record is complete -- write an extra newline */
- SVN_ERR(svn_stream_puts(db->eb->stream, "\n"));
- }
-
- /* ### should be unnecessary */
- apr_hash_clear(db->deleted_entries);
-
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-add_file(const char *path,
- void *parent_baton,
- const char *copyfrom_path,
- svn_revnum_t copyfrom_rev,
- apr_pool_t *pool,
- void **file_baton)
-{
- struct dir_baton *pb = parent_baton;
- struct file_baton *fb;
- void *was_deleted;
-
- SVN_ERR(dump_pending_dir(pb->eb, pool));
-
- /* Make the file baton. */
- fb = make_file_baton(path, pb, pool);
-
- /* This might be a replacement -- is the path already deleted? */
- was_deleted = svn_hash_gets(pb->deleted_entries, path);
-
- /* Detect add-with-history. */
- if (ARE_VALID_COPY_ARGS(copyfrom_path, copyfrom_rev))
- {
- fb->copyfrom_path = svn_relpath_canonicalize(copyfrom_path, fb->pool);
- fb->copyfrom_rev = copyfrom_rev;
- fb->is_copy = TRUE;
- }
- fb->action = was_deleted ? svn_node_action_replace : svn_node_action_add;
-
- /* Delete the path, it's now been dumped. */
- if (was_deleted)
- svn_hash_sets(pb->deleted_entries, path, NULL);
-
- *file_baton = fb;
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-open_file(const char *path,
- void *parent_baton,
- svn_revnum_t ancestor_revision,
- apr_pool_t *pool,
- void **file_baton)
-{
- struct dir_baton *pb = parent_baton;
- struct file_baton *fb;
-
- SVN_ERR(dump_pending_dir(pb->eb, pool));
-
- /* Make the file baton. */
- fb = make_file_baton(path, pb, pool);
-
- /* If the parent directory has explicit copyfrom path and rev,
- record the same for this one. */
- if (ARE_VALID_COPY_ARGS(pb->copyfrom_path, pb->copyfrom_rev))
- {
- fb->copyfrom_path = svn_relpath_join(pb->copyfrom_path,
- svn_relpath_basename(path, NULL),
- pb->pool);
- fb->copyfrom_rev = pb->copyfrom_rev;
- }
-
- *file_baton = fb;
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-change_dir_prop(void *parent_baton,
- const char *name,
- const svn_string_t *value,
- apr_pool_t *pool)
-{
- struct dir_baton *db = parent_baton;
- svn_boolean_t this_pending;
-
- /* This directory is not pending, but something else is, so handle
- the "something else". */
- this_pending = (db->eb->pending_db == db);
- if (! this_pending)
- SVN_ERR(dump_pending_dir(db->eb, pool));
-
- if (svn_property_kind2(name) != svn_prop_regular_kind)
- return SVN_NO_ERROR;
-
- if (value)
- svn_hash_sets(db->props,
- apr_pstrdup(db->pool, name),
- svn_string_dup(value, db->pool));
- else
- svn_hash_sets(db->deleted_props, apr_pstrdup(db->pool, name), "");
-
- /* Make sure we eventually output the props */
- db->dump_props = TRUE;
-
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-change_file_prop(void *file_baton,
- const char *name,
- const svn_string_t *value,
- apr_pool_t *pool)
-{
- struct file_baton *fb = file_baton;
-
- if (svn_property_kind2(name) != svn_prop_regular_kind)
- return SVN_NO_ERROR;
-
- if (value)
- svn_hash_sets(fb->props,
- apr_pstrdup(fb->pool, name),
- svn_string_dup(value, fb->pool));
- else
- svn_hash_sets(fb->deleted_props, apr_pstrdup(fb->pool, name), "");
-
- /* Dump the property headers and wait; close_file might need
- to write text headers too depending on whether
- apply_textdelta is called */
- fb->dump_props = TRUE;
-
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-apply_textdelta(void *file_baton, const char *base_checksum,
- apr_pool_t *pool,
- svn_txdelta_window_handler_t *handler,
- void **handler_baton)
-{
- struct file_baton *fb = file_baton;
- struct dump_edit_baton *eb = fb->eb;
- svn_stream_t *delta_filestream;
-
- /* Use a temporary file to measure the Text-content-length */
- delta_filestream = svn_stream_from_aprfile2(eb->delta_file, TRUE, pool);
-
- /* Prepare to write the delta to the delta_filestream */
- svn_txdelta_to_svndiff3(handler, handler_baton,
- delta_filestream, 0,
- SVN_DELTA_COMPRESSION_LEVEL_DEFAULT, pool);
-
- /* Record that there's text to be dumped, and its base checksum. */
- fb->dump_text = TRUE;
- fb->base_checksum = apr_pstrdup(fb->pool, base_checksum);
-
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-close_file(void *file_baton,
- const char *text_checksum,
- apr_pool_t *pool)
-{
- struct file_baton *fb = file_baton;
- struct dump_edit_baton *eb = fb->eb;
- svn_filesize_t text_content_length = 0;
- svn_stringbuf_t *propstring = NULL;
- svn_repos__dumpfile_headers_t *headers;
-
- SVN_ERR(dump_pending_dir(eb, pool));
-
- /* Start dumping this node, by collecting some basic headers for it. */
- SVN_ERR(dump_node(&headers, eb, fb->repos_relpath, NULL, fb,
- fb->action, fb->is_copy, fb->copyfrom_path,
- fb->copyfrom_rev, pool));
-
- /* Some pending properties to dump? We'll dump just the headers for
- now, then dump the actual propchange content only after dumping
- the text headers too (if present). */
- if (fb->dump_props)
- {
- SVN_ERR(get_props_content(headers, &propstring,
- fb->props, fb->deleted_props,
- pool, pool));
- }
-
- /* Dump the text headers */
- if (fb->dump_text)
- {
- /* Text-delta: true */
- svn_repos__dumpfile_header_push(
- headers, SVN_REPOS_DUMPFILE_TEXT_DELTA, "true");
-
- SVN_ERR(svn_io_file_size_get(&text_content_length, eb->delta_file,
- pool));
-
- if (fb->base_checksum)
- /* Text-delta-base-md5: */
- svn_repos__dumpfile_header_push(
- headers, SVN_REPOS_DUMPFILE_TEXT_DELTA_BASE_MD5, fb->base_checksum);
-
- /* Text-content-md5: 82705804337e04dcd0e586bfa2389a7f */
- svn_repos__dumpfile_header_push(
- headers, SVN_REPOS_DUMPFILE_TEXT_CONTENT_MD5, text_checksum);
- }
-
- /* Dump the headers and props now */
- SVN_ERR(svn_repos__dump_node_record(eb->stream, headers, propstring,
- fb->dump_text, text_content_length,
- FALSE /*content_length_always*/,
- pool));
-
- if (fb->dump_props)
- {
- /* Cleanup */
- fb->dump_props = FALSE;
- apr_hash_clear(fb->props);
- apr_hash_clear(fb->deleted_props);
- }
-
- /* Dump the text */
- if (fb->dump_text)
- {
- /* Seek to the beginning of the delta file, map it to a stream,
- and copy the stream to eb->stream. Then close the stream and
- truncate the file so we can reuse it for the next textdelta
- application. Note that the file isn't created, opened or
- closed here */
- svn_stream_t *delta_filestream;
- apr_off_t offset = 0;
-
- SVN_ERR(svn_io_file_seek(eb->delta_file, APR_SET, &offset, pool));
- delta_filestream = svn_stream_from_aprfile2(eb->delta_file, TRUE, pool);
- SVN_ERR(svn_stream_copy3(delta_filestream, eb->stream, NULL, NULL, pool));
-
- /* Cleanup */
- SVN_ERR(svn_stream_close(delta_filestream));
- SVN_ERR(svn_io_file_trunc(eb->delta_file, 0, pool));
- }
-
- /* Write a couple of blank lines for matching output with `svnadmin
- dump` */
- SVN_ERR(svn_stream_puts(eb->stream, "\n\n"));
-
- return SVN_NO_ERROR;
-}
-
-static svn_error_t *
-close_edit(void *edit_baton, apr_pool_t *pool)
-{
- return SVN_NO_ERROR;
-}
-
static svn_error_t *
fetch_base_func(const char **filename,
void *baton,
@@ -1085,47 +162,21 @@ svn_rdump__get_dump_editor(const svn_del
apr_pool_t *pool)
{
struct dump_edit_baton *eb;
- svn_delta_editor_t *de;
svn_delta_shim_callbacks_t *shim_callbacks =
svn_delta_shim_callbacks_default(pool);
eb = apr_pcalloc(pool, sizeof(struct dump_edit_baton));
- eb->stream = stream;
eb->ra_session = ra_session;
- eb->update_anchor_relpath = update_anchor_relpath;
eb->current_revision = revision;
- eb->pending_db = NULL;
-
- /* Create a special per-revision pool */
- eb->pool = svn_pool_create(pool);
- /* Open a unique temporary file for all textdelta applications in
- this edit session. The file is automatically closed and cleaned
- up when the edit session is done. */
- SVN_ERR(svn_io_open_unique_file3(&(eb->delta_file), &(eb->delta_abspath),
- NULL, svn_io_file_del_on_close, pool, pool));
-
- de = svn_delta_default_editor(pool);
- de->open_root = open_root;
- de->delete_entry = delete_entry;
- de->add_directory = add_directory;
- de->open_directory = open_directory;
- de->close_directory = close_directory;
- de->change_dir_prop = change_dir_prop;
- de->change_file_prop = change_file_prop;
- de->apply_textdelta = apply_textdelta;
- de->add_file = add_file;
- de->open_file = open_file;
- de->close_file = close_file;
- de->close_edit = close_edit;
-
- /* Set the edit_baton and editor. */
- *edit_baton = eb;
- *editor = de;
+ SVN_ERR(svn_repos__get_dump_editor(editor, edit_baton,
+ stream, update_anchor_relpath, pool));
/* Wrap this editor in a cancellation editor. */
SVN_ERR(svn_delta_get_cancellation_editor(cancel_func, cancel_baton,
- de, eb, editor, edit_baton, pool));
+ *editor, *edit_baton,
+ editor, edit_baton,
+ pool));
shim_callbacks->fetch_base_func = fetch_base_func;
shim_callbacks->fetch_props_func = fetch_props_func;