Author: rinrab
Date: Thu May 29 11:41:35 2025
New Revision: 1925930
URL: http://svn.apache.org/viewvc?rev=1925930&view=rev
Log:
On the 'utf8-cmdline-prototype' branch: sync with trunk.
Added:
subversion/branches/utf8-cmdline-prototype/subversion/libsvn_subr/cmdline_editor.c
- copied unchanged from r1925929,
subversion/trunk/subversion/libsvn_subr/cmdline_editor.c
subversion/branches/utf8-cmdline-prototype/subversion/libsvn_subr/opt_revision.c
- copied unchanged from r1925929,
subversion/trunk/subversion/libsvn_subr/opt_revision.c
subversion/branches/utf8-cmdline-prototype/subversion/libsvn_subr/opt_subcommand.c
- copied unchanged from r1925929,
subversion/trunk/subversion/libsvn_subr/opt_subcommand.c
Modified:
subversion/branches/utf8-cmdline-prototype/ (props changed)
subversion/branches/utf8-cmdline-prototype/subversion/libsvn_subr/cmdline.c
subversion/branches/utf8-cmdline-prototype/subversion/libsvn_subr/opt.c
Propchange: subversion/branches/utf8-cmdline-prototype/
------------------------------------------------------------------------------
Merged /subversion/trunk:r1925915-1925929
Modified:
subversion/branches/utf8-cmdline-prototype/subversion/libsvn_subr/cmdline.c
URL:
http://svn.apache.org/viewvc/subversion/branches/utf8-cmdline-prototype/subversion/libsvn_subr/cmdline.c?rev=1925930&r1=1925929&r2=1925930&view=diff
==============================================================================
--- subversion/branches/utf8-cmdline-prototype/subversion/libsvn_subr/cmdline.c
(original)
+++ subversion/branches/utf8-cmdline-prototype/subversion/libsvn_subr/cmdline.c
Thu May 29 11:41:35 2025
@@ -1240,522 +1240,6 @@ svn_cmdline__be_interactive(svn_boolean_
}
-/* Helper for the edit_externally functions. Set *EDITOR to some path to an
- editor binary, in native C string on Unix/Linux platforms and in UTF-8
- string on Windows platform. Sources to search include: the EDITOR_CMD
- argument (if not NULL), $SVN_EDITOR, the runtime CONFIG variable (if CONFIG
- is not NULL), $VISUAL, $EDITOR. Return
- SVN_ERR_CL_NO_EXTERNAL_EDITOR if no binary can be found. */
-static svn_error_t *
-find_editor_binary(const char **editor,
- const char *editor_cmd,
- apr_hash_t *config,
- apr_pool_t *pool)
-{
- const char *e;
- const char *e_cfg;
- struct svn_config_t *cfg;
- apr_status_t status;
-
- /* Use the editor specified on the command line via --editor-cmd, if any. */
-#ifdef WIN32
- /* On Windows, editor_cmd is transcoded to the system active code page
- because we use main() as a entry point without APR's (or our own) wrapper
- in command line tools. */
- if (editor_cmd)
- {
- SVN_ERR(svn_utf_cstring_to_utf8(&e, editor_cmd, pool));
- }
- else
- {
- e = NULL;
- }
-#else
- e = editor_cmd;
-#endif
-
- /* Otherwise look for the Subversion-specific environment variable. */
- if (! e)
- {
- status = apr_env_get((char **)&e, "SVN_EDITOR", pool);
- if (status || ! *e)
- {
- e = NULL;
- }
- }
-
- /* If not found then fall back on the config file. */
- if (! e)
- {
- cfg = config ? svn_hash_gets(config, SVN_CONFIG_CATEGORY_CONFIG) : NULL;
- svn_config_get(cfg, &e_cfg, SVN_CONFIG_SECTION_HELPERS,
- SVN_CONFIG_OPTION_EDITOR_CMD, NULL);
-#ifdef WIN32
- if (e_cfg)
- {
- /* On Windows, we assume that config values are set in system active
- code page, so we need transcode it here. */
- SVN_ERR(svn_utf_cstring_to_utf8(&e, e_cfg, pool));
- }
-#else
- e = e_cfg;
-#endif
- }
-
- /* If not found yet then try general purpose environment variables. */
- if (! e)
- {
- status = apr_env_get((char**)&e, "VISUAL", pool);
- if (status || ! *e)
- {
- e = NULL;
- }
- }
- if (! e)
- {
- status = apr_env_get((char**)&e, "EDITOR", pool);
- if (status || ! *e)
- {
- e = NULL;
- }
- }
-
-#ifdef SVN_CLIENT_EDITOR
- /* If still not found then fall back on the hard-coded default. */
- if (! e)
- e = SVN_CLIENT_EDITOR;
-#endif
-
- /* Error if there is no editor specified */
- if (e)
- {
- const char *c;
-
- for (c = e; *c; c++)
- if (!svn_ctype_isspace(*c))
- break;
-
- if (! *c)
- return svn_error_create
- (SVN_ERR_CL_NO_EXTERNAL_EDITOR, NULL,
- _("The EDITOR, SVN_EDITOR or VISUAL environment variable or "
- "'editor-cmd' run-time configuration option is empty or "
- "consists solely of whitespace. Expected a shell command."));
- }
- else
- return svn_error_create
- (SVN_ERR_CL_NO_EXTERNAL_EDITOR, NULL,
- _("None of the environment variables SVN_EDITOR, VISUAL or EDITOR are "
- "set, and no 'editor-cmd' run-time configuration option was found"));
-
- *editor = e;
- return SVN_NO_ERROR;
-}
-
-/* Wrapper around apr_pescape_shell() which also escapes whitespace. */
-static const char *
-escape_path(apr_pool_t *pool, const char *orig_path)
-{
- apr_size_t len, esc_len;
- apr_status_t status;
-
- len = strlen(orig_path);
- esc_len = 0;
-
- status = apr_escape_shell(NULL, orig_path, len, &esc_len);
-
- if (status == APR_NOTFOUND)
- {
- /* No special characters found by APR, so just surround it in double
- quotes in case there is whitespace, which APR (as of 1.6.5) doesn't
- consider special. */
- return apr_psprintf(pool, "\"%s\"", orig_path);
- }
- else
- {
-#ifdef WIN32
- const char *p;
- /* Following the advice from
-
https://docs.microsoft.com/en-us/archive/blogs/twistylittlepassagesallalike/everyone-quotes-command-line-arguments-the-wrong-way
- 1. Surround argument with double-quotes
- 2. Escape backslashes, if they're followed by a double-quote, and
double-quotes
- 3. Escape any metacharacter, including double-quotes, with ^ */
-
- /* Use APR's buffer size as an approximation for how large the escaped
- string should be, plus 4 bytes for the leading/trailing ^" */
- svn_stringbuf_t *buf = svn_stringbuf_create_ensure(esc_len + 4, pool);
- svn_stringbuf_appendcstr(buf, "^\"");
- for (p = orig_path; *p; p++)
- {
- int nr_backslash = 0;
- while (*p && *p == '\\')
- {
- nr_backslash++;
- p++;
- }
-
- if (!*p)
- /* We've reached the end of the argument, so we need 2n backslash
- characters. That will be interpreted as n backslashes and the
- final double-quote character will be interpreted as the final
- string delimiter. */
- svn_stringbuf_appendfill(buf, '\\', nr_backslash * 2);
- else if (*p == '"')
- {
- /* Double-quote as part of the argument means we need to double
- any preceding backslashes and then add one to escape the
- double-quote. */
- svn_stringbuf_appendfill(buf, '\\', nr_backslash * 2 + 1);
- svn_stringbuf_appendbyte(buf, '^');
- svn_stringbuf_appendbyte(buf, *p);
- }
- else
- {
- /* Since there's no double-quote, we just insert any backslashes
- literally. No escaping needed. */
- svn_stringbuf_appendfill(buf, '\\', nr_backslash);
- if (strchr("()%!^<>&|", *p))
- svn_stringbuf_appendbyte(buf, '^');
- svn_stringbuf_appendbyte(buf, *p);
- }
- }
- svn_stringbuf_appendcstr(buf, "^\"");
- return buf->data;
-#else
- char *path, *p, *esc_path;
-
- /* Account for whitespace, since APR doesn't */
- for (p = (char *)orig_path; *p; p++)
- if (strchr(" \t\n\r", *p))
- esc_len++;
-
- path = apr_pcalloc(pool, esc_len);
- apr_escape_shell(path, orig_path, len, NULL);
-
- p = esc_path = apr_pcalloc(pool, len + esc_len + 1);
- while (*path)
- {
- if (strchr(" \t\n\r", *path))
- *p++ = '\\';
- *p++ = *path++;
- }
-
- return esc_path;
-#endif
- }
-}
-
-svn_error_t *
-svn_cmdline__edit_file_externally(const char *path,
- const char *editor_cmd,
- apr_hash_t *config,
- apr_pool_t *pool)
-{
- const char *editor, *cmd, *base_dir, *file_name, *base_dir_apr;
- const char *file_name_local;
-#ifdef WIN32
- const WCHAR *wcmd;
-#endif
- char *old_cwd;
- int sys_err;
- apr_status_t apr_err;
-
- svn_dirent_split(&base_dir, &file_name, path, pool);
-
- SVN_ERR(find_editor_binary(&editor, editor_cmd, config, pool));
-
- apr_err = apr_filepath_get(&old_cwd, APR_FILEPATH_NATIVE, pool);
- if (apr_err)
- return svn_error_wrap_apr(apr_err, _("Can't get working directory"));
-
- /* APR doesn't like "" directories */
- if (base_dir[0] == '\0')
- base_dir_apr = ".";
- else
- SVN_ERR(svn_path_cstring_from_utf8(&base_dir_apr, base_dir, pool));
-
- apr_err = apr_filepath_set(base_dir_apr, pool);
- if (apr_err)
- return svn_error_wrap_apr
- (apr_err, _("Can't change working directory to '%s'"), base_dir);
-
- SVN_ERR(svn_path_cstring_from_utf8(&file_name_local,
- escape_path(pool, file_name), pool));
- /* editor is explicitly documented as being interpreted by the user's shell,
- and as such should already be quoted/escaped as needed. */
-#ifndef WIN32
- cmd = apr_psprintf(pool, "%s %s", editor, file_name_local);
- sys_err = system(cmd);
-#else
- cmd = apr_psprintf(pool, "\"%s %s\"", editor, file_name_local);
- SVN_ERR(svn_utf__win32_utf8_to_utf16(&wcmd, cmd, NULL, pool));
- sys_err = _wsystem(wcmd);
-#endif
-
- apr_err = apr_filepath_set(old_cwd, pool);
- if (apr_err)
- svn_handle_error2(svn_error_wrap_apr
- (apr_err, _("Can't restore working directory")),
- stderr, TRUE /* fatal */, "svn: ");
-
- if (sys_err)
- {
- const char *cmd_utf8;
-
- /* Extracting any meaning from sys_err is platform specific, so just
- use the raw value. */
- SVN_ERR(svn_path_cstring_to_utf8(&cmd_utf8, cmd, pool));
- return svn_error_createf(SVN_ERR_EXTERNAL_PROGRAM, NULL,
- _("system('%s') returned %d"),
- cmd_utf8, sys_err);
- }
-
- return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_cmdline__edit_string_externally(svn_string_t **edited_contents /* UTF-8!
*/,
- const char **tmpfile_left /* UTF-8! */,
- const char *editor_cmd,
- const char *base_dir /* UTF-8! */,
- const svn_string_t *contents /* UTF-8! */,
- const char *filename,
- apr_hash_t *config,
- svn_boolean_t as_text,
- const char *encoding,
- apr_pool_t *pool)
-{
- const char *editor;
- const char *cmd;
-#ifdef WIN32
- const WCHAR *wcmd;
-#endif
- apr_file_t *tmp_file;
- const char *tmpfile_name;
- const char *tmpfile_native;
- const char *base_dir_apr;
- svn_string_t *translated_contents;
- apr_status_t apr_err;
- apr_size_t written;
- apr_finfo_t finfo_before, finfo_after;
- svn_error_t *err = SVN_NO_ERROR;
- char *old_cwd;
- int sys_err;
- svn_boolean_t remove_file = TRUE;
-
- SVN_ERR(find_editor_binary(&editor, editor_cmd, config, pool));
-
- /* Convert file contents from UTF-8/LF if desired. */
- if (as_text)
- {
- const char *translated;
- SVN_ERR(svn_subst_translate_cstring2(contents->data, &translated,
- APR_EOL_STR, FALSE,
- NULL, FALSE, pool));
- translated_contents = svn_string_create_empty(pool);
- if (encoding)
- SVN_ERR(svn_utf_cstring_from_utf8_ex2(&translated_contents->data,
- translated, encoding, pool));
- else
- SVN_ERR(svn_utf_cstring_from_utf8(&translated_contents->data,
- translated, pool));
- translated_contents->len = strlen(translated_contents->data);
- }
- else
- translated_contents = svn_string_dup(contents, pool);
-
- /* Move to BASE_DIR to avoid getting characters that need quoting
- into tmpfile_name */
- apr_err = apr_filepath_get(&old_cwd, APR_FILEPATH_NATIVE, pool);
- if (apr_err)
- return svn_error_wrap_apr(apr_err, _("Can't get working directory"));
-
- /* APR doesn't like "" directories */
- if (base_dir[0] == '\0')
- base_dir_apr = ".";
- else
- SVN_ERR(svn_path_cstring_from_utf8(&base_dir_apr, base_dir, pool));
- apr_err = apr_filepath_set(base_dir_apr, pool);
- if (apr_err)
- {
- return svn_error_wrap_apr
- (apr_err, _("Can't change working directory to '%s'"), base_dir);
- }
-
- /*** From here on, any problems that occur require us to cd back!! ***/
-
- /* Ask the working copy for a temporary file named FILENAME-something. */
- err = svn_io_open_uniquely_named(&tmp_file, &tmpfile_name,
- "" /* dirpath */,
- filename,
- ".tmp",
- svn_io_file_del_none, pool, pool);
-
- if (err && (APR_STATUS_IS_EACCES(err->apr_err) || err->apr_err == EROFS))
- {
- const char *temp_dir_apr;
-
- svn_error_clear(err);
-
- SVN_ERR(svn_io_temp_dir(&base_dir, pool));
-
- SVN_ERR(svn_path_cstring_from_utf8(&temp_dir_apr, base_dir, pool));
- apr_err = apr_filepath_set(temp_dir_apr, pool);
- if (apr_err)
- {
- return svn_error_wrap_apr
- (apr_err, _("Can't change working directory to '%s'"), base_dir);
- }
-
- err = svn_io_open_uniquely_named(&tmp_file, &tmpfile_name,
- "" /* dirpath */,
- filename,
- ".tmp",
- svn_io_file_del_none, pool, pool);
- }
-
- if (err)
- goto cleanup2;
-
- /*** From here on, any problems that occur require us to cleanup
- the file we just created!! ***/
-
- /* Dump initial CONTENTS to TMP_FILE. */
- err = svn_io_file_write_full(tmp_file, translated_contents->data,
- translated_contents->len, &written,
- pool);
-
- err = svn_error_compose_create(err, svn_io_file_close(tmp_file, pool));
-
- /* Make sure the whole CONTENTS were written, else return an error. */
- if (err)
- goto cleanup;
-
- /* Get information about the temporary file before the user has
- been allowed to edit its contents. */
- err = svn_io_stat(&finfo_before, tmpfile_name, APR_FINFO_MTIME, pool);
- if (err)
- goto cleanup;
-
- /* Backdate the file a little bit in case the editor is very fast
- and doesn't change the size. (Use two seconds, since some
- filesystems have coarse granularity.) It's OK if this call
- fails, so we don't check its return value.*/
- err = svn_io_set_file_affected_time(finfo_before.mtime
- - apr_time_from_sec(2),
- tmpfile_name, pool);
- svn_error_clear(err);
-
- /* Stat it again to get the mtime we actually set. */
- err = svn_io_stat(&finfo_before, tmpfile_name,
- APR_FINFO_MTIME | APR_FINFO_SIZE, pool);
- if (err)
- goto cleanup;
-
- /* Prepare the editor command line. */
- err = svn_path_cstring_from_utf8(&tmpfile_native,
- escape_path(pool, tmpfile_name), pool);
- if (err)
- goto cleanup;
-
- /* editor is explicitly documented as being interpreted by the user's shell,
- and as such should already be quoted/escaped as needed. */
-#ifndef WIN32
- cmd = apr_psprintf(pool, "%s %s", editor, tmpfile_native);
-#else
- cmd = apr_psprintf(pool, "\"%s %s\"", editor, tmpfile_native);
-#endif
-
- /* If the caller wants us to leave the file around, return the path
- of the file we'll use, and make a note not to destroy it. */
- if (tmpfile_left)
- {
- *tmpfile_left = svn_dirent_join(base_dir, tmpfile_name, pool);
- remove_file = FALSE;
- }
-
- /* Now, run the editor command line. */
-#ifndef WIN32
- sys_err = system(cmd);
-#else
- SVN_ERR(svn_utf__win32_utf8_to_utf16(&wcmd, cmd, NULL, pool));
- sys_err = _wsystem(wcmd);
-#endif
- if (sys_err != 0)
- {
- const char *cmd_utf8;
-
- /* Extracting any meaning from sys_err is platform specific, so just
- use the raw value. */
- SVN_ERR(svn_path_cstring_to_utf8(&cmd_utf8, cmd, pool));
- err = svn_error_createf(SVN_ERR_EXTERNAL_PROGRAM, NULL,
- _("system('%s') returned %d"),
- cmd_utf8, sys_err);
- goto cleanup;
- }
-
- /* Get information about the temporary file after the assumed editing. */
- err = svn_io_stat(&finfo_after, tmpfile_name,
- APR_FINFO_MTIME | APR_FINFO_SIZE, pool);
- if (err)
- goto cleanup;
-
- /* If the file looks changed... */
- if ((finfo_before.mtime != finfo_after.mtime) ||
- (finfo_before.size != finfo_after.size))
- {
- svn_stringbuf_t *edited_contents_s;
- err = svn_stringbuf_from_file2(&edited_contents_s, tmpfile_name, pool);
- if (err)
- goto cleanup;
-
- *edited_contents = svn_stringbuf__morph_into_string(edited_contents_s);
-
- /* Translate back to UTF8/LF if desired. */
- if (as_text)
- {
- err = svn_subst_translate_string2(edited_contents, NULL, NULL,
- *edited_contents, encoding, FALSE,
- pool, pool);
- if (err)
- {
- err = svn_error_quick_wrap
- (err,
- _("Error normalizing edited contents to internal format"));
- goto cleanup;
- }
- }
- }
- else
- {
- /* No edits seem to have been made */
- *edited_contents = NULL;
- }
-
- cleanup:
- if (remove_file)
- {
- /* Remove the file from disk. */
- err = svn_error_compose_create(
- err,
- svn_io_remove_file2(tmpfile_name, FALSE, pool));
- }
-
- cleanup2:
- /* If we against all probability can't cd back, all further relative
- file references would be screwed up, so we have to abort. */
- apr_err = apr_filepath_set(old_cwd, pool);
- if (apr_err)
- {
- svn_handle_error2(svn_error_wrap_apr
- (apr_err, _("Can't restore working directory")),
- stderr, TRUE /* fatal */, "svn: ");
- }
-
- return svn_error_trace(err);
-}
-
svn_error_t *
svn_cmdline__parse_trust_options(
svn_boolean_t *trust_server_cert_unknown_ca,
Modified:
subversion/branches/utf8-cmdline-prototype/subversion/libsvn_subr/opt.c
URL:
http://svn.apache.org/viewvc/subversion/branches/utf8-cmdline-prototype/subversion/libsvn_subr/opt.c?rev=1925930&r1=1925929&r2=1925930&view=diff
==============================================================================
--- subversion/branches/utf8-cmdline-prototype/subversion/libsvn_subr/opt.c
(original)
+++ subversion/branches/utf8-cmdline-prototype/subversion/libsvn_subr/opt.c Thu
May 29 11:41:35 2025
@@ -55,752 +55,6 @@
/*** Code. ***/
-const svn_opt_subcommand_desc3_t *
-svn_opt_get_canonical_subcommand3(const svn_opt_subcommand_desc3_t *table,
- const char *cmd_name)
-{
- int i = 0;
-
- if (cmd_name == NULL)
- return NULL;
-
- while (table[i].name) {
- int j;
- if (strcmp(cmd_name, table[i].name) == 0)
- return table + i;
- for (j = 0; (j < SVN_OPT_MAX_ALIASES) && table[i].aliases[j]; j++)
- if (strcmp(cmd_name, table[i].aliases[j]) == 0)
- return table + i;
-
- i++;
- }
-
- /* If we get here, there was no matching subcommand name or alias. */
- return NULL;
-}
-
-const apr_getopt_option_t *
-svn_opt_get_option_from_code3(int code,
- const apr_getopt_option_t *option_table,
- const svn_opt_subcommand_desc3_t *command,
- apr_pool_t *pool)
-{
- apr_size_t i;
-
- for (i = 0; option_table[i].optch; i++)
- if (option_table[i].optch == code)
- {
- if (command)
- {
- int j;
-
- for (j = 0; ((j < SVN_OPT_MAX_OPTIONS) &&
- command->desc_overrides[j].optch); j++)
- if (command->desc_overrides[j].optch == code)
- {
- apr_getopt_option_t *tmpopt =
- apr_palloc(pool, sizeof(*tmpopt));
- *tmpopt = option_table[i];
- tmpopt->description = command->desc_overrides[j].desc;
- return tmpopt;
- }
- }
- return &(option_table[i]);
- }
-
- return NULL;
-}
-
-/* Like svn_opt_get_option_from_code3(), but also, if CODE appears a second
- * time in OPTION_TABLE with a different name, then set *LONG_ALIAS to that
- * second name, else set it to NULL. */
-static const apr_getopt_option_t *
-get_option_from_code3(const char **long_alias,
- int code,
- const apr_getopt_option_t *option_table,
- const svn_opt_subcommand_desc3_t *command,
- apr_pool_t *pool)
-{
- const apr_getopt_option_t *i;
- const apr_getopt_option_t *opt
- = svn_opt_get_option_from_code3(code, option_table, command, pool);
-
- /* Find a long alias in the table, if there is one. */
- *long_alias = NULL;
- for (i = option_table; i->optch; i++)
- {
- if (i->optch == code && i->name != opt->name)
- {
- *long_alias = i->name;
- break;
- }
- }
-
- return opt;
-}
-
-
-/* Print an option OPT nicely into a STRING allocated in POOL.
- * If OPT has a single-character short form, then print OPT->name (if not
- * NULL) as an alias, else print LONG_ALIAS (if not NULL) as an alias.
- * If DOC is set, include the generic documentation string of OPT,
- * localized to the current locale if a translation is available.
- */
-static void
-format_option(const char **string,
- const apr_getopt_option_t *opt,
- const char *long_alias,
- svn_boolean_t doc,
- apr_pool_t *pool)
-{
- char *opts;
-
- if (opt == NULL)
- {
- *string = "?";
- return;
- }
-
- /* We have a valid option which may or may not have a "short
- name" (a single-character alias for the long option). */
- if (opt->optch <= 255)
- opts = apr_psprintf(pool, "-%c [--%s]", opt->optch, opt->name);
- else if (long_alias)
- opts = apr_psprintf(pool, "--%s [--%s]", opt->name, long_alias);
- else
- opts = apr_psprintf(pool, "--%s", opt->name);
-
- if (opt->has_arg)
- opts = apr_pstrcat(pool, opts, _(" ARG"), SVN_VA_NULL);
-
- if (doc)
- opts = apr_psprintf(pool, "%-24s : %s", opts, _(opt->description));
-
- *string = opts;
-}
-
-void
-svn_opt_format_option(const char **string,
- const apr_getopt_option_t *opt,
- svn_boolean_t doc,
- apr_pool_t *pool)
-{
- format_option(string, opt, NULL, doc, pool);
-}
-
-
-svn_boolean_t
-svn_opt_subcommand_takes_option4(const svn_opt_subcommand_desc3_t *command,
- int option_code,
- const int *global_options)
-{
- apr_size_t i;
-
- for (i = 0; i < SVN_OPT_MAX_OPTIONS; i++)
- if (command->valid_options[i] == option_code)
- return TRUE;
-
- if (global_options)
- for (i = 0; global_options[i]; i++)
- if (global_options[i] == option_code)
- return TRUE;
-
- return FALSE;
-}
-
-
-/* Print the canonical command name for CMD, and all its aliases, to
- STREAM. If HELP is set, print CMD's help string too, in which case
- obtain option usage from OPTIONS_TABLE.
-
- Include global and experimental options iff VERBOSE is true.
- */
-static svn_error_t *
-print_command_info3(const svn_opt_subcommand_desc3_t *cmd,
- const apr_getopt_option_t *options_table,
- const int *global_options,
- svn_boolean_t help,
- svn_boolean_t verbose,
- apr_pool_t *pool,
- FILE *stream)
-{
- svn_boolean_t first_time;
- apr_size_t i;
-
- /* Print the canonical command name. */
- SVN_ERR(svn_cmdline_fputs(cmd->name, stream, pool));
-
- /* Print the list of aliases. */
- first_time = TRUE;
- for (i = 0; i < SVN_OPT_MAX_ALIASES; i++)
- {
- if (cmd->aliases[i] == NULL)
- break;
-
- if (first_time) {
- SVN_ERR(svn_cmdline_fputs(" (", stream, pool));
- first_time = FALSE;
- }
- else
- SVN_ERR(svn_cmdline_fputs(", ", stream, pool));
-
- SVN_ERR(svn_cmdline_fputs(cmd->aliases[i], stream, pool));
- }
-
- if (! first_time)
- SVN_ERR(svn_cmdline_fputs(")", stream, pool));
-
- if (help)
- {
- const apr_getopt_option_t *option;
- const char *long_alias;
- svn_boolean_t have_options = FALSE;
- svn_boolean_t have_experimental = FALSE;
-
- SVN_ERR(svn_cmdline_fprintf(stream, pool, ": "));
-
- for (i = 0; i < SVN_OPT_MAX_PARAGRAPHS && cmd->help[i]; i++)
- {
- SVN_ERR(svn_cmdline_fprintf(stream, pool, "%s", _(cmd->help[i])));
- }
-
- /* Loop over all valid option codes attached to the subcommand */
- for (i = 0; i < SVN_OPT_MAX_OPTIONS; i++)
- {
- if (cmd->valid_options[i])
- {
- if (!have_options)
- {
- SVN_ERR(svn_cmdline_fputs(_("\nValid options:\n"),
- stream, pool));
- have_options = TRUE;
- }
-
- /* convert each option code into an option */
- option = get_option_from_code3(&long_alias,
cmd->valid_options[i],
- options_table, cmd, pool);
-
- /* print the option's docstring */
- if (option && option->description)
- {
- const char *optstr;
-
- if (option->name && strncmp(option->name, "x-", 2) == 0)
- {
- if (verbose && !have_experimental)
- SVN_ERR(svn_cmdline_fputs(_("\nExperimental
options:\n"),
- stream, pool));
- have_experimental = TRUE;
- if (!verbose)
- continue;
- }
-
- format_option(&optstr, option, long_alias, TRUE, pool);
- SVN_ERR(svn_cmdline_fprintf(stream, pool, " %s\n",
- optstr));
- }
- }
- }
- /* And global options too */
- if (verbose && global_options && *global_options)
- {
- SVN_ERR(svn_cmdline_fputs(_("\nGlobal options:\n"),
- stream, pool));
- have_options = TRUE;
-
- for (i = 0; global_options[i]; i++)
- {
-
- /* convert each option code into an option */
- option = get_option_from_code3(&long_alias, global_options[i],
- options_table, cmd, pool);
-
- /* print the option's docstring */
- if (option && option->description)
- {
- const char *optstr;
- format_option(&optstr, option, long_alias, TRUE, pool);
- SVN_ERR(svn_cmdline_fprintf(stream, pool, " %s\n",
- optstr));
- }
- }
- }
-
- if (!verbose && global_options && *global_options)
- SVN_ERR(svn_cmdline_fputs(_("\n(Use '-v' to show global and
experimental options.)\n"),
- stream, pool));
- if (have_options)
- SVN_ERR(svn_cmdline_fprintf(stream, pool, "\n"));
- }
-
- return SVN_NO_ERROR;
-}
-
-/* The body for svn_opt_print_generic_help3() function with standard error
- * handling semantic. Handling of errors implemented at caller side. */
-static svn_error_t *
-print_generic_help_body3(const char *header,
- const svn_opt_subcommand_desc3_t *cmd_table,
- const apr_getopt_option_t *opt_table,
- const char *footer,
- svn_boolean_t with_experimental,
- apr_pool_t *pool, FILE *stream)
-{
- svn_boolean_t have_experimental = FALSE;
- int i;
-
- if (header)
- SVN_ERR(svn_cmdline_fputs(header, stream, pool));
-
- for (i = 0; cmd_table[i].name; i++)
- {
- if (strncmp(cmd_table[i].name, "x-", 2) == 0)
- {
- if (with_experimental && !have_experimental)
- SVN_ERR(svn_cmdline_fputs(_("\nExperimental subcommands:\n"),
- stream, pool));
- have_experimental = TRUE;
- if (!with_experimental)
- continue;
- }
- SVN_ERR(svn_cmdline_fputs(" ", stream, pool));
- SVN_ERR(print_command_info3(cmd_table + i, opt_table,
- NULL, FALSE, FALSE,
- pool, stream));
- SVN_ERR(svn_cmdline_fputs("\n", stream, pool));
- }
-
- if (have_experimental && !with_experimental)
- SVN_ERR(svn_cmdline_fputs(_("\n(Use '-v' to show experimental
subcommands.)\n"),
- stream, pool));
-
- SVN_ERR(svn_cmdline_fputs("\n", stream, pool));
-
- if (footer)
- SVN_ERR(svn_cmdline_fputs(footer, stream, pool));
-
- return SVN_NO_ERROR;
-}
-
-static void
-print_generic_help(const char *header,
- const svn_opt_subcommand_desc3_t *cmd_table,
- const apr_getopt_option_t *opt_table,
- const char *footer,
- svn_boolean_t with_experimental,
- apr_pool_t *pool, FILE *stream)
-{
- svn_error_t *err;
-
- err = print_generic_help_body3(header, cmd_table, opt_table, footer,
- with_experimental,
- pool, stream);
-
- /* Issue #3014:
- * Don't print anything on broken pipes. The pipe was likely
- * closed by the process at the other end. We expect that
- * process to perform error reporting as necessary.
- *
- * ### This assumes that there is only one error in a chain for
- * ### SVN_ERR_IO_PIPE_WRITE_ERROR. See svn_cmdline_fputs(). */
- if (err && err->apr_err != SVN_ERR_IO_PIPE_WRITE_ERROR)
- svn_handle_error2(err, stderr, FALSE, "svn: ");
- svn_error_clear(err);
-}
-
-void
-svn_opt_print_generic_help3(const char *header,
- const svn_opt_subcommand_desc3_t *cmd_table,
- const apr_getopt_option_t *opt_table,
- const char *footer,
- apr_pool_t *pool, FILE *stream)
-{
- print_generic_help(header, cmd_table, opt_table, footer,
- TRUE, pool, stream);
-}
-
-
-/* The body of svn_opt_subcommand_help4(), which see.
- *
- * VERBOSE means show also the subcommand's global and experimental options.
- */
-static void
-subcommand_help(const char *subcommand,
- const svn_opt_subcommand_desc3_t *table,
- const apr_getopt_option_t *options_table,
- const int *global_options,
- svn_boolean_t verbose,
- apr_pool_t *pool)
-{
- const svn_opt_subcommand_desc3_t *cmd =
- svn_opt_get_canonical_subcommand3(table, subcommand);
- svn_error_t *err;
-
- if (cmd)
- err = print_command_info3(cmd, options_table, global_options,
- TRUE, verbose, pool, stdout);
- else
- err = svn_cmdline_fprintf(stderr, pool,
- _("\"%s\": unknown command.\n\n"), subcommand);
-
- if (err) {
- /* Issue #3014: Don't print anything on broken pipes. */
- if (err->apr_err != SVN_ERR_IO_PIPE_WRITE_ERROR)
- svn_handle_error2(err, stderr, FALSE, "svn: ");
- svn_error_clear(err);
- }
-}
-
-void
-svn_opt_subcommand_help4(const char *subcommand,
- const svn_opt_subcommand_desc3_t *table,
- const apr_getopt_option_t *options_table,
- const int *global_options,
- apr_pool_t *pool)
-{
- subcommand_help(subcommand, table, options_table, global_options,
- TRUE, pool);
-}
-
-
-
-/*** Parsing revision and date options. ***/
-
-
-/** Parsing "X:Y"-style arguments. **/
-
-/* If WORD matches one of the special revision descriptors,
- * case-insensitively, set *REVISION accordingly:
- *
- * - For "head", set REVISION->kind to svn_opt_revision_head.
- *
- * - For "prev", set REVISION->kind to svn_opt_revision_previous.
- *
- * - For "base", set REVISION->kind to svn_opt_revision_base.
- *
- * - For "committed", set REVISION->kind to svn_opt_revision_committed.
- *
- * If match, return 0, else return -1 and don't touch REVISION.
- */
-static int
-revision_from_word(svn_opt_revision_t *revision, const char *word)
-{
- if (svn_cstring_casecmp(word, "head") == 0)
- {
- revision->kind = svn_opt_revision_head;
- }
- else if (svn_cstring_casecmp(word, "prev") == 0)
- {
- revision->kind = svn_opt_revision_previous;
- }
- else if (svn_cstring_casecmp(word, "base") == 0)
- {
- revision->kind = svn_opt_revision_base;
- }
- else if (svn_cstring_casecmp(word, "committed") == 0)
- {
- revision->kind = svn_opt_revision_committed;
- }
- else
- return -1;
-
- return 0;
-}
-
-
-/* Parse one revision specification. Return pointer to character
- after revision, or NULL if the revision is invalid. Modifies
- str, so make sure to pass a copy of anything precious. Uses
- POOL for temporary allocation. */
-static char *parse_one_rev(svn_opt_revision_t *revision, char *str,
- apr_pool_t *pool)
-{
- char *end, save;
-
- /* Allow any number of 'r's to prefix a revision number, because
- that way if a script pastes svn output into another svn command
- (like "svn log -r${REV_COPIED_FROM_OUTPUT}"), it'll Just Work,
- even when compounded.
-
- As it happens, none of our special revision words begins with
- "r". If any ever do, then this code will have to get smarter.
-
- Incidentally, this allows "r{DATE}". We could avoid that with
- some trivial code rearrangement, but it's not clear what would
- be gained by doing so. */
- while (*str == 'r')
- str++;
-
- if (*str == '{')
- {
- svn_boolean_t matched;
- apr_time_t tm;
- svn_error_t *err;
-
- /* Brackets denote a date. */
- str++;
- end = strchr(str, '}');
- if (!end)
- return NULL;
- *end = '\0';
- err = svn_parse_date(&matched, &tm, str, apr_time_now(), pool);
- if (err)
- {
- svn_error_clear(err);
- return NULL;
- }
- if (!matched)
- return NULL;
- revision->kind = svn_opt_revision_date;
- revision->value.date = tm;
- return end + 1;
- }
- else if (svn_ctype_isdigit(*str))
- {
- /* It's a number. */
- end = str + 1;
- while (svn_ctype_isdigit(*end))
- end++;
- save = *end;
- *end = '\0';
- revision->kind = svn_opt_revision_number;
- revision->value.number = SVN_STR_TO_REV(str);
- *end = save;
- return end;
- }
- else if (svn_ctype_isalpha(*str))
- {
- end = str + 1;
- while (svn_ctype_isalpha(*end))
- end++;
- save = *end;
- *end = '\0';
- if (revision_from_word(revision, str) != 0)
- return NULL;
- *end = save;
- return end;
- }
- else
- return NULL;
-}
-
-
-int
-svn_opt_parse_revision(svn_opt_revision_t *start_revision,
- svn_opt_revision_t *end_revision,
- const char *arg,
- apr_pool_t *pool)
-{
- char *left_rev, *right_rev, *end;
-
- /* Operate on a copy of the argument. */
- left_rev = apr_pstrdup(pool, arg);
-
- right_rev = parse_one_rev(start_revision, left_rev, pool);
- if (right_rev && *right_rev == ':')
- {
- right_rev++;
- end = parse_one_rev(end_revision, right_rev, pool);
- if (!end || *end != '\0')
- return -1;
- }
- else if (!right_rev || *right_rev != '\0')
- return -1;
-
- return 0;
-}
-
-
-int
-svn_opt_parse_revision_to_range(apr_array_header_t *opt_ranges,
- const char *arg,
- apr_pool_t *pool)
-{
- svn_opt_revision_range_t *range = apr_palloc(pool, sizeof(*range));
-
- range->start.kind = svn_opt_revision_unspecified;
- range->end.kind = svn_opt_revision_unspecified;
-
- if (svn_opt_parse_revision(&(range->start), &(range->end),
- arg, pool) == -1)
- return -1;
-
- APR_ARRAY_PUSH(opt_ranges, svn_opt_revision_range_t *) = range;
- return 0;
-}
-
-int svn_opt_parse_change_to_range(apr_array_header_t *opt_ranges,
- const char *arg,
- apr_pool_t *result_pool)
-{
- char *end;
- svn_revnum_t changeno, changeno_end;
- const char *s = arg;
- svn_boolean_t is_negative;
-
- /* Check for a leading minus to allow "-c -r42".
- * The is_negative flag is used to handle "-c -42" and "-c -r42".
- * The "-c r-42" case is handled by strtol() returning a
- * negative number. */
- is_negative = (*s == '-');
- if (is_negative)
- s++;
-
- /* Allow any number of 'r's to prefix a revision number. */
- while (*s == 'r')
- s++;
- changeno = changeno_end = strtol(s, &end, 10);
- if (end != s && *end == '-')
- {
- /* Negative number in range not supported with -c */
- if (changeno < 0 || is_negative)
- return -1;
-
- s = end + 1;
- while (*s == 'r')
- s++;
- changeno_end = strtol(s, &end, 10);
-
- /* Negative number in range not supported with -c */
- if (changeno_end < 0)
- return -1;
- }
-
- /* Non-numeric change argument given to -c? */
- if (end == arg || *end != '\0')
- return -1;
-
- /* There is no change 0 */
- if (changeno == 0 || changeno_end == 0)
- return -1;
-
- /* The revision number cannot contain a double minus */
- if (changeno < 0 && is_negative)
- return -1;
-
- if (is_negative)
- changeno = -changeno;
-
- /* Figure out the range:
- -c N -> -r N-1:N
- -c -N -> -r N:N-1
- -c M-N -> -r M-1:N for M < N
- -c M-N -> -r M:N-1 for M > N
- -c -M-N -> error (too confusing/no valid use case)
- */
- if (changeno > 0)
- {
- if (changeno <= changeno_end)
- changeno--;
- else
- changeno_end--;
- }
- else
- {
- changeno = -changeno;
- changeno_end = changeno - 1;
- }
-
- APR_ARRAY_PUSH(opt_ranges,
- svn_opt_revision_range_t *)
- = svn_opt__revision_range_from_revnums(changeno, changeno_end,
- result_pool);
-
- return 0;
-}
-
-svn_error_t *
-svn_opt_parse_revnum(svn_revnum_t *rev, const char *str)
-{
- /* Allow any number of 'r's to prefix a revision number. */
- while (*str == 'r')
- str++;
-
- return svn_error_trace(svn_revnum_parse(rev, str, NULL));
-}
-
-svn_error_t *
-svn_opt_resolve_revisions(svn_opt_revision_t *peg_rev,
- svn_opt_revision_t *op_rev,
- svn_boolean_t is_url,
- svn_boolean_t notice_local_mods,
- apr_pool_t *pool)
-{
- if (peg_rev->kind == svn_opt_revision_unspecified)
- {
- if (is_url)
- {
- peg_rev->kind = svn_opt_revision_head;
- }
- else
- {
- if (notice_local_mods)
- peg_rev->kind = svn_opt_revision_working;
- else
- peg_rev->kind = svn_opt_revision_base;
- }
- }
-
- if (op_rev->kind == svn_opt_revision_unspecified)
- *op_rev = *peg_rev;
-
- return SVN_NO_ERROR;
-}
-
-const char *
-svn_opt__revision_to_string(const svn_opt_revision_t *revision,
- apr_pool_t *result_pool)
-{
- switch (revision->kind)
- {
- case svn_opt_revision_unspecified:
- return "unspecified";
- case svn_opt_revision_number:
- return apr_psprintf(result_pool, "%ld", revision->value.number);
- case svn_opt_revision_date:
- /* ### svn_time_to_human_cstring()? */
- return svn_time_to_cstring(revision->value.date, result_pool);
- case svn_opt_revision_committed:
- return "committed";
- case svn_opt_revision_previous:
- return "previous";
- case svn_opt_revision_base:
- return "base";
- case svn_opt_revision_working:
- return "working";
- case svn_opt_revision_head:
- return "head";
- default:
- return NULL;
- }
-}
-
-svn_opt_revision_range_t *
-svn_opt__revision_range_create(const svn_opt_revision_t *start_revision,
- const svn_opt_revision_t *end_revision,
- apr_pool_t *result_pool)
-{
- svn_opt_revision_range_t *range = apr_palloc(result_pool, sizeof(*range));
-
- range->start = *start_revision;
- range->end = *end_revision;
- return range;
-}
-
-svn_opt_revision_range_t *
-svn_opt__revision_range_from_revnums(svn_revnum_t start_revnum,
- svn_revnum_t end_revnum,
- apr_pool_t *result_pool)
-{
- svn_opt_revision_range_t *range = apr_palloc(result_pool, sizeof(*range));
-
- range->start.kind = svn_opt_revision_number;
- range->start.value.number = start_revnum;
- range->end.kind = svn_opt_revision_number;
- range->end.value.number = end_revnum;
- return range;
-}
-
/*** Parsing arguments. ***/
@@ -1237,137 +491,3 @@ svn_opt__arg_canonicalize_path(const cha
return SVN_NO_ERROR;
}
-
-
-svn_error_t *
-svn_opt__print_version_info(const char *pgm_name,
- const char *footer,
- const svn_version_extended_t *info,
- svn_boolean_t quiet,
- svn_boolean_t verbose,
- apr_pool_t *pool)
-{
- if (quiet)
- return svn_cmdline_printf(pool, "%s\n", SVN_VER_NUMBER);
-
- SVN_ERR(svn_cmdline_printf(pool, _("%s, version %s\n"
- " compiled %s, %s on %s\n\n"),
- pgm_name, SVN_VERSION,
- svn_version_ext_build_date(info),
- svn_version_ext_build_time(info),
- svn_version_ext_build_host(info)));
- SVN_ERR(svn_cmdline_printf(pool, "%s\n", svn_version_ext_copyright(info)));
-
- if (footer)
- {
- SVN_ERR(svn_cmdline_printf(pool, "%s\n", footer));
- }
-
- if (verbose)
- {
- const apr_array_header_t *libs;
-
- SVN_ERR(svn_cmdline_fputs(_("System information:\n\n"), stdout, pool));
- SVN_ERR(svn_cmdline_printf(pool, _("* running on %s\n"),
- svn_version_ext_runtime_host(info)));
- if (svn_version_ext_runtime_osname(info))
- {
- SVN_ERR(svn_cmdline_printf(pool, _(" - %s\n"),
- svn_version_ext_runtime_osname(info)));
- }
-
- libs = svn_version_ext_linked_libs(info);
- if (libs && libs->nelts)
- {
- const svn_version_ext_linked_lib_t *lib;
- int i;
-
- SVN_ERR(svn_cmdline_fputs(_("* linked dependencies:\n"),
- stdout, pool));
- for (i = 0; i < libs->nelts; ++i)
- {
- lib = &APR_ARRAY_IDX(libs, i, svn_version_ext_linked_lib_t);
- if (lib->runtime_version)
- SVN_ERR(svn_cmdline_printf(pool,
- " - %s %s (compiled with %s)\n",
- lib->name,
- lib->runtime_version,
- lib->compiled_version));
- else
- SVN_ERR(svn_cmdline_printf(pool,
- " - %s %s (static)\n",
- lib->name,
- lib->compiled_version));
- }
- }
-
- libs = svn_version_ext_loaded_libs(info);
- if (libs && libs->nelts)
- {
- const svn_version_ext_loaded_lib_t *lib;
- int i;
-
- SVN_ERR(svn_cmdline_fputs(_("* loaded shared libraries:\n"),
- stdout, pool));
- for (i = 0; i < libs->nelts; ++i)
- {
- lib = &APR_ARRAY_IDX(libs, i, svn_version_ext_loaded_lib_t);
- if (lib->version)
- SVN_ERR(svn_cmdline_printf(pool,
- " - %s (%s)\n",
- lib->name, lib->version));
- else
- SVN_ERR(svn_cmdline_printf(pool, " - %s\n", lib->name));
- }
- }
- }
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_opt_print_help5(apr_getopt_t *os,
- const char *pgm_name,
- svn_boolean_t print_version,
- svn_boolean_t quiet,
- svn_boolean_t verbose,
- const char *version_footer,
- const char *header,
- const svn_opt_subcommand_desc3_t *cmd_table,
- const apr_getopt_option_t *option_table,
- const int *global_options,
- const char *footer,
- apr_pool_t *pool)
-{
- apr_array_header_t *targets = NULL;
-
- if (os)
- SVN_ERR(svn_opt_parse_all_args(&targets, os, pool));
-
- if (os && targets->nelts) /* help on subcommand(s) requested */
- {
- int i;
-
- for (i = 0; i < targets->nelts; i++)
- {
- subcommand_help(APR_ARRAY_IDX(targets, i, const char *),
- cmd_table, option_table, global_options,
- verbose, pool);
- }
- }
- else if (print_version) /* just --version */
- {
- SVN_ERR(svn_opt__print_version_info(pgm_name, version_footer,
- svn_version_extended(verbose, pool),
- quiet, verbose, pool));
- }
- else if (os && !targets->nelts) /* `-h', `--help', or `help' */
- print_generic_help(header, cmd_table, option_table, footer,
- verbose,
- pool, stdout);
- else /* unknown option or cmd */
- SVN_ERR(svn_cmdline_fprintf(stderr, pool,
- _("Type '%s help' for usage.\n"), pgm_name));
-
- return SVN_NO_ERROR;
-}