aboutsummaryrefslogtreecommitdiff
path: root/subversion/libsvn_subr/cmdline.c
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-02-13 13:04:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-02-13 13:04:04 +0000
commit8f67d37de16f4d4a3c64b754a079789ce8ad1b25 (patch)
treef70a7f1a49f2036e84a115da7b6b718d2c702e41 /subversion/libsvn_subr/cmdline.c
parentbbee6e0814d5875b85b81f26fd4ca7a28b6f9570 (diff)
Diffstat (limited to 'subversion/libsvn_subr/cmdline.c')
-rw-r--r--subversion/libsvn_subr/cmdline.c101
1 files changed, 89 insertions, 12 deletions
diff --git a/subversion/libsvn_subr/cmdline.c b/subversion/libsvn_subr/cmdline.c
index d1aad71b234a..bc27788ec03a 100644
--- a/subversion/libsvn_subr/cmdline.c
+++ b/subversion/libsvn_subr/cmdline.c
@@ -39,9 +39,15 @@
#include <apr.h> /* for STDIN_FILENO */
#include <apr_errno.h> /* for apr_strerror */
+#include <apr_version.h>
+#if APR_VERSION_AT_LEAST(1,5,0)
#include <apr_escape.h>
+#else
+#include "private/svn_dep_compat.h"
+#endif
#include <apr_general.h> /* for apr_initialize/apr_terminate */
#include <apr_strings.h> /* for apr_snprintf */
+#include <apr_env.h> /* for apr_env_get */
#include <apr_pools.h>
#include <apr_signal.h>
@@ -1235,38 +1241,84 @@ svn_cmdline__be_interactive(svn_boolean_t non_interactive,
/* Helper for the edit_externally functions. Set *EDITOR to some path to an
- editor binary. Sources to search include: the EDITOR_CMD argument
- (if not NULL), $SVN_EDITOR, the runtime CONFIG variable (if CONFIG
+ 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_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)
- e = getenv("SVN_EDITOR");
+ {
+ 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, SVN_CONFIG_SECTION_HELPERS,
+ 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)
- e = getenv("VISUAL");
+ {
+ status = apr_env_get((char**)&e, "VISUAL", pool);
+ if (status || ! *e)
+ {
+ e = NULL;
+ }
+ }
if (! e)
- e = getenv("EDITOR");
+ {
+ 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. */
@@ -1400,13 +1452,17 @@ svn_cmdline__edit_file_externally(const char *path,
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));
+ SVN_ERR(find_editor_binary(&editor, editor_cmd, config, pool));
apr_err = apr_filepath_get(&old_cwd, APR_FILEPATH_NATIVE, pool);
if (apr_err)
@@ -1423,10 +1479,18 @@ svn_cmdline__edit_file_externally(const char *path,
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. */
- cmd = apr_psprintf(pool, "%s %s", editor, escape_path(pool, file_name));
+#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)
@@ -1458,6 +1522,9 @@ svn_cmdline__edit_string_externally(svn_string_t **edited_contents /* UTF-8! */,
{
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;
@@ -1471,7 +1538,7 @@ svn_cmdline__edit_string_externally(svn_string_t **edited_contents /* UTF-8! */,
int sys_err;
svn_boolean_t remove_file = TRUE;
- SVN_ERR(find_editor_binary(&editor, editor_cmd, config));
+ SVN_ERR(find_editor_binary(&editor, editor_cmd, config, pool));
/* Convert file contents from UTF-8/LF if desired. */
if (as_text)
@@ -1581,13 +1648,18 @@ svn_cmdline__edit_string_externally(svn_string_t **edited_contents /* UTF-8! */,
goto cleanup;
/* Prepare the editor command line. */
- err = svn_utf_cstring_from_utf8(&tmpfile_native, tmpfile_name, pool);
+ err = svn_utf_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. */
- cmd = apr_psprintf(pool, "%s %s", editor, escape_path(pool, tmpfile_native));
+#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. */
@@ -1598,7 +1670,12 @@ svn_cmdline__edit_string_externally(svn_string_t **edited_contents /* UTF-8! */,
}
/* 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)
{
/* Extracting any meaning from sys_err is platform specific, so just