Kaydet (Commit) b032f2e2 authored tarafından Colomban Wendling's avatar Colomban Wendling

Merge pull request #426 from techee/run_script_tmp

Create geany_run_script.sh in the temporary directory instead of the
working directory.
...@@ -3022,8 +3022,9 @@ The Terminal field of the tools preferences tab requires a command to ...@@ -3022,8 +3022,9 @@ The Terminal field of the tools preferences tab requires a command to
execute the terminal program and to pass it the name of the Geany run execute the terminal program and to pass it the name of the Geany run
script that it should execute in a Bourne compatible shell (eg /bin/sh). script that it should execute in a Bourne compatible shell (eg /bin/sh).
The marker "%c" is substituted with the name of the Geany run script, The marker "%c" is substituted with the name of the Geany run script,
which is created in the working directory set in the Build commands which is created in the temporary directory and which changes the working
dialog, see `Build menu commands dialog`_ for details. directory to the directory set in the Build commands dialog, see
`Build menu commands dialog`_ for details.
As an example the default (Linux) command is:: As an example the default (Linux) command is::
......
...@@ -91,9 +91,9 @@ typedef struct RunInfo ...@@ -91,9 +91,9 @@ typedef struct RunInfo
static RunInfo *run_info; static RunInfo *run_info;
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
static const gchar RUN_SCRIPT_CMD[] = "geany_run_script.bat"; static const gchar RUN_SCRIPT_CMD[] = "geany_run_script_XXXXXX.bat";
#else #else
static const gchar RUN_SCRIPT_CMD[] = "./geany_run_script.sh"; static const gchar RUN_SCRIPT_CMD[] = "geany_run_script_XXXXXX.sh";
#endif #endif
/* pack group (<8) and command (<32) into a user_data pointer */ /* pack group (<8) and command (<32) into a user_data pointer */
...@@ -128,7 +128,7 @@ static guint build_items_count = 9; ...@@ -128,7 +128,7 @@ static guint build_items_count = 9;
static void build_exit_cb(GPid child_pid, gint status, gpointer user_data); static void build_exit_cb(GPid child_pid, gint status, gpointer user_data);
static gboolean build_iofunc(GIOChannel *ioc, GIOCondition cond, gpointer data); static gboolean build_iofunc(GIOChannel *ioc, GIOCondition cond, gpointer data);
#endif #endif
static gboolean build_create_shellscript(const gchar *fname, const gchar *working_dir, const gchar *cmd, gboolean autoclose, GError **error); static gchar *build_create_shellscript(const gchar *working_dir, const gchar *cmd, gboolean autoclose, GError **error);
static GPid build_spawn_cmd(GeanyDocument *doc, const gchar *cmd, const gchar *dir); static GPid build_spawn_cmd(GeanyDocument *doc, const gchar *cmd, const gchar *dir);
static void set_stop_button(gboolean stop); static void set_stop_button(gboolean stop);
static void run_exit_cb(GPid child_pid, gint status, gpointer user_data); static void run_exit_cb(GPid child_pid, gint status, gpointer user_data);
...@@ -879,54 +879,49 @@ static GPid build_spawn_cmd(GeanyDocument *doc, const gchar *cmd, const gchar *d ...@@ -879,54 +879,49 @@ static GPid build_spawn_cmd(GeanyDocument *doc, const gchar *cmd, const gchar *d
} }
/* Returns: NULL if there was an error, or the working directory the script was created in. /* Returns: NULL if there was an error, or the command to be executed. If Geany is
* vte_cmd_nonscript is the location of a string which is filled with the command to be used * set to use a run script, the returned value is a path to the script that runs
* when vc->skip_run_script is set, otherwise it will be set to NULL */ * the command; otherwise the command itself is returned. working_dir is a pointer
static gchar *prepare_run_script(GeanyDocument *doc, gchar **vte_cmd_nonscript, guint cmdindex) * to the working directory from which the command is executed. Both strings are
* in the locale encoding. */
static gchar *prepare_run_cmd(GeanyDocument *doc, gchar **working_dir, guint cmdindex)
{ {
GeanyBuildCommand *cmd = NULL; GeanyBuildCommand *cmd = NULL;
gchar *working_dir = NULL;
const gchar *cmd_working_dir; const gchar *cmd_working_dir;
gboolean autoclose = FALSE; gboolean autoclose = FALSE;
gboolean result = FALSE; gchar *cmd_string_utf8, *working_dir_utf8, *run_cmd, *cmd_string;
gchar *tmp;
gchar *cmd_string;
GError *error = NULL; GError *error = NULL;
if (vte_cmd_nonscript != NULL)
*vte_cmd_nonscript = NULL;
cmd = get_build_cmd(doc, GEANY_GBG_EXEC, cmdindex, NULL); cmd = get_build_cmd(doc, GEANY_GBG_EXEC, cmdindex, NULL);
cmd_string = build_replace_placeholder(doc, cmd->command); cmd_string_utf8 = build_replace_placeholder(doc, cmd->command);
cmd_working_dir = cmd->working_dir; cmd_working_dir = cmd->working_dir;
if (EMPTY(cmd_working_dir)) if (EMPTY(cmd_working_dir))
cmd_working_dir = "%d"; cmd_working_dir = "%d";
working_dir = build_replace_placeholder(doc, cmd_working_dir); /* in utf-8 */ working_dir_utf8 = build_replace_placeholder(doc, cmd_working_dir);
*working_dir = utils_get_locale_from_utf8(working_dir_utf8);
/* only test whether working dir exists, don't change it or else Windows support will break /* only test whether working dir exists, don't change it or else Windows support will break
* (gspawn-win32-helper.exe is used by GLib and must be in $PATH which means current working * (gspawn-win32-helper.exe is used by GLib and must be in $PATH which means current working
* dir where geany.exe was started from, so we can't change it) */ * dir where geany.exe was started from, so we can't change it) */
if (EMPTY(working_dir) || ! g_file_test(working_dir, G_FILE_TEST_EXISTS) || if (EMPTY(*working_dir) || ! g_file_test(*working_dir, G_FILE_TEST_EXISTS) ||
! g_file_test(working_dir, G_FILE_TEST_IS_DIR)) ! g_file_test(*working_dir, G_FILE_TEST_IS_DIR))
{ {
ui_set_statusbar(TRUE, _("Failed to change the working directory to \"%s\""), ui_set_statusbar(TRUE, _("Failed to change the working directory to \"%s\""),
!EMPTY(working_dir) ? working_dir : "<NULL>" ); !EMPTY(working_dir_utf8) ? working_dir_utf8 : "<NULL>" );
utils_free_pointers(2, cmd_string, working_dir, NULL); utils_free_pointers(3, cmd_string_utf8, working_dir_utf8, *working_dir, NULL);
return NULL; return NULL;
} }
cmd_string = utils_get_locale_from_utf8(cmd_string_utf8);
#ifdef HAVE_VTE #ifdef HAVE_VTE
if (vte_info.have_vte && vc->run_in_vte) if (vte_info.have_vte && vc->run_in_vte)
{ {
if (vc->skip_run_script) if (vc->skip_run_script)
{ {
if (vte_cmd_nonscript != NULL) utils_free_pointers(2, cmd_string_utf8, working_dir_utf8, NULL);
*vte_cmd_nonscript = cmd_string; return cmd_string;
else
g_free(cmd_string);
return working_dir;
} }
else else
/* don't wait for user input at the end of script when we are running in VTE */ /* don't wait for user input at the end of script when we are running in VTE */
...@@ -934,38 +929,31 @@ static gchar *prepare_run_script(GeanyDocument *doc, gchar **vte_cmd_nonscript, ...@@ -934,38 +929,31 @@ static gchar *prepare_run_script(GeanyDocument *doc, gchar **vte_cmd_nonscript,
} }
#endif #endif
/* RUN_SCRIPT_CMD should be ok in UTF8 without converting in locale because it run_cmd = build_create_shellscript(*working_dir, cmd_string, autoclose, &error);
* contains no umlauts */ if (!run_cmd)
tmp = g_build_filename(working_dir, RUN_SCRIPT_CMD, NULL);
result = build_create_shellscript(tmp, working_dir, cmd_string, autoclose, &error);
if (! result)
{ {
ui_set_statusbar(TRUE, _("Failed to execute \"%s\" (start-script could not be created: %s)"), ui_set_statusbar(TRUE, _("Failed to execute \"%s\" (start-script could not be created: %s)"),
!EMPTY(cmd_string) ? cmd_string : NULL, error->message); !EMPTY(cmd_string_utf8) ? cmd_string_utf8 : NULL, error->message);
g_error_free(error); g_error_free(error);
g_free(*working_dir);
} }
utils_free_pointers(2, cmd_string, tmp, NULL); utils_free_pointers(3, cmd_string_utf8, working_dir_utf8, cmd_string, NULL);
return run_cmd;
if (result)
return working_dir;
g_free(working_dir);
return NULL;
} }
static GPid build_run_cmd(GeanyDocument *doc, guint cmdindex) static GPid build_run_cmd(GeanyDocument *doc, guint cmdindex)
{ {
gchar *working_dir; gchar *working_dir;
gchar *vte_cmd_nonscript = NULL; gchar *run_cmd = NULL;
GError *error = NULL; GError *error = NULL;
if (! DOC_VALID(doc) || doc->file_name == NULL) if (! DOC_VALID(doc) || doc->file_name == NULL)
return (GPid) 0; return (GPid) 0;
working_dir = prepare_run_script(doc, &vte_cmd_nonscript, cmdindex); run_cmd = prepare_run_cmd(doc, &working_dir, cmdindex);
if (working_dir == NULL) if (run_cmd == NULL)
return (GPid) 0; return (GPid) 0;
run_info[cmdindex].file_type_id = doc->file_type->id; run_info[cmdindex].file_type_id = doc->file_type->id;
...@@ -975,28 +963,23 @@ static GPid build_run_cmd(GeanyDocument *doc, guint cmdindex) ...@@ -975,28 +963,23 @@ static GPid build_run_cmd(GeanyDocument *doc, guint cmdindex)
{ {
gchar *vte_cmd; gchar *vte_cmd;
/* VTE expects commands in UTF-8 */
SETPTR(run_cmd, utils_get_utf8_from_locale(run_cmd));
SETPTR(working_dir, utils_get_utf8_from_locale(working_dir));
if (vc->skip_run_script) if (vc->skip_run_script)
{ vte_cmd = g_strconcat(run_cmd, "\n", NULL);
SETPTR(vte_cmd_nonscript, utils_get_utf8_from_locale(vte_cmd_nonscript));
vte_cmd = g_strconcat(vte_cmd_nonscript, "\n", NULL);
g_free(vte_cmd_nonscript);
}
else else
vte_cmd = g_strconcat("\n/bin/sh ", RUN_SCRIPT_CMD, "\n", NULL); vte_cmd = g_strconcat("\n/bin/sh ", run_cmd, "\n", NULL);
/* change into current directory if it is not done by default */ vte_cwd(working_dir, TRUE);
if (! vc->follow_path)
{
/* we need to convert the working_dir back to UTF-8 because the VTE expects it */
gchar *utf8_working_dir = utils_get_utf8_from_locale(working_dir);
vte_cwd(utf8_working_dir, TRUE);
g_free(utf8_working_dir);
}
if (! vte_send_cmd(vte_cmd)) if (! vte_send_cmd(vte_cmd))
{ {
ui_set_statusbar(FALSE, ui_set_statusbar(FALSE,
_("Could not execute the file in the VTE because it probably contains a command.")); _("Could not execute the file in the VTE because it probably contains a command."));
geany_debug("Could not execute the file in the VTE because it probably contains a command."); geany_debug("Could not execute the file in the VTE because it probably contains a command.");
if (!vc->skip_run_script)
g_unlink(run_cmd);
} }
/* show the VTE */ /* show the VTE */
...@@ -1025,8 +1008,7 @@ static GPid build_run_cmd(GeanyDocument *doc, guint cmdindex) ...@@ -1025,8 +1008,7 @@ static GPid build_run_cmd(GeanyDocument *doc, guint cmdindex)
_("Could not parse terminal command \"%s\" " _("Could not parse terminal command \"%s\" "
"(check Terminal tool setting in Preferences)"), tool_prefs.term_cmd); "(check Terminal tool setting in Preferences)"), tool_prefs.term_cmd);
run_info[cmdindex].pid = (GPid) 1; run_info[cmdindex].pid = (GPid) 1;
script_path = g_build_filename(working_dir, RUN_SCRIPT_CMD, NULL); g_unlink(run_cmd);
g_unlink(script_path);
goto free_strings; goto free_strings;
} }
...@@ -1044,14 +1026,13 @@ static GPid build_run_cmd(GeanyDocument *doc, guint cmdindex) ...@@ -1044,14 +1026,13 @@ static GPid build_run_cmd(GeanyDocument *doc, guint cmdindex)
_("Could not find terminal \"%s\" " _("Could not find terminal \"%s\" "
"(check path for Terminal tool setting in Preferences)"), tool_prefs.term_cmd); "(check path for Terminal tool setting in Preferences)"), tool_prefs.term_cmd);
run_info[cmdindex].pid = (GPid) 1; run_info[cmdindex].pid = (GPid) 1;
script_path = g_build_filename(working_dir, RUN_SCRIPT_CMD, NULL); g_unlink(run_cmd);
g_unlink(script_path);
goto free_strings; goto free_strings;
} }
for (i = 0; i < argv_len; i++) for (i = 0; i < argv_len; i++)
{ {
utils_str_replace_all(&(argv[i]), "%c", RUN_SCRIPT_CMD); utils_str_replace_all(&(argv[i]), "%c", run_cmd);
} }
if (! g_spawn_async(working_dir, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, if (! g_spawn_async(working_dir, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD,
...@@ -1060,8 +1041,7 @@ static GPid build_run_cmd(GeanyDocument *doc, guint cmdindex) ...@@ -1060,8 +1041,7 @@ static GPid build_run_cmd(GeanyDocument *doc, guint cmdindex)
geany_debug("g_spawn_async() failed: %s", error->message); geany_debug("g_spawn_async() failed: %s", error->message);
ui_set_statusbar(TRUE, _("Process failed (%s)"), error->message); ui_set_statusbar(TRUE, _("Process failed (%s)"), error->message);
g_error_free(error); g_error_free(error);
script_path = g_build_filename(working_dir, RUN_SCRIPT_CMD, NULL); g_unlink(run_cmd);
g_unlink(script_path);
error = NULL; error = NULL;
run_info[cmdindex].pid = (GPid) 0; run_info[cmdindex].pid = (GPid) 0;
} }
...@@ -1079,6 +1059,7 @@ static GPid build_run_cmd(GeanyDocument *doc, guint cmdindex) ...@@ -1079,6 +1059,7 @@ static GPid build_run_cmd(GeanyDocument *doc, guint cmdindex)
} }
g_free(working_dir); g_free(working_dir);
g_free(run_cmd);
return run_info[cmdindex].pid; return run_info[cmdindex].pid;
} }
...@@ -1270,36 +1251,28 @@ static void run_exit_cb(GPid child_pid, gint status, gpointer user_data) ...@@ -1270,36 +1251,28 @@ static void run_exit_cb(GPid child_pid, gint status, gpointer user_data)
} }
static void set_file_error_from_errno(GError **error, gint err, const gchar *prefix)
{
g_set_error(error, G_FILE_ERROR, g_file_error_from_errno(err), "%s%s%s",
prefix ? prefix : "", prefix ? ": " : "", g_strerror(err));
}
/* write a little shellscript to call the executable (similar to anjuta_launcher but "internal") /* write a little shellscript to call the executable (similar to anjuta_launcher but "internal")
* fname is the full file name (including path) for the script to create */ * working_dir and cmd are both in the locale encoding
static gboolean build_create_shellscript(const gchar *fname, const gchar *working_dir, const gchar *cmd, gboolean autoclose, GError **error) * it returns the full file name (including path) of the created script in the locale encoding */
static gchar *build_create_shellscript(const gchar *working_dir, const gchar *cmd, gboolean autoclose, GError **error)
{ {
FILE *fp; gint fd;
gchar *str; gchar *str, *fname;
gboolean success = TRUE; gboolean success = TRUE;
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
gchar *expanded_cmd; gchar *expanded_cmd;
#else #else
gchar *escaped_dir; gchar *escaped_dir;
#endif #endif
fd = g_file_open_tmp (RUN_SCRIPT_CMD, &fname, error);
if (fd < 0)
return NULL;
close(fd);
fp = g_fopen(fname, "w");
if (! fp)
{
set_file_error_from_errno(error, errno, "Failed to create file");
return FALSE;
}
#ifdef G_OS_WIN32 #ifdef G_OS_WIN32
/* Expand environment variables like %blah%. */ /* Expand environment variables like %blah%. */
expanded_cmd = win32_expand_environment_variables(cmd); expanded_cmd = win32_expand_environment_variables(cmd);
str = g_strdup_printf("%s\n\n%s\ndel \"%%0\"\n\npause\n", expanded_cmd, (autoclose) ? "" : "pause"); str = g_strdup_printf("cd \"%s\"\n\n%s\n\n%s\ndel \"%%0\"\n\npause\n", working_dir, expanded_cmd, (autoclose) ? "" : "pause");
g_free(expanded_cmd); g_free(expanded_cmd);
#else #else
escaped_dir = g_strescape(working_dir, NULL); escaped_dir = g_strescape(working_dir, NULL);
...@@ -1311,29 +1284,31 @@ static gboolean build_create_shellscript(const gchar *fname, const gchar *workin ...@@ -1311,29 +1284,31 @@ static gboolean build_create_shellscript(const gchar *fname, const gchar *workin
g_free(escaped_dir); g_free(escaped_dir);
#endif #endif
if (fputs(str, fp) < 0) if (!g_file_set_contents(fname, str, -1, error))
{
set_file_error_from_errno(error, errno, "Failed to write file");
success = FALSE; success = FALSE;
}
g_free(str); g_free(str);
if (fclose(fp) != 0)
{
if (error && ! *error) /* don't set error twice */
set_file_error_from_errno(error, errno, "Failed to close file");
success = FALSE;
}
#ifdef __APPLE__ #ifdef __APPLE__
if (g_chmod(fname, 0777) != 0) if (success && g_chmod(fname, 0777) != 0)
{ {
if (error && ! *error) /* don't set error twice */ if (error)
set_file_error_from_errno(error, errno, "Failed to make file executable"); {
gint errsv = errno;
g_set_error(error, G_FILE_ERROR, g_file_error_from_errno(errsv),
"Failed to make file executable: %s", g_strerror(errsv));
}
success = FALSE; success = FALSE;
} }
#endif #endif
return success; if (!success)
{
g_unlink(fname);
g_free(fname);
fname = NULL;
}
return fname;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment