app: when called with --quit, GIMP exit code will report batch failure.

If you call GIMP with batch commands and ask it to quit immediately, you
are likely interested by failure information. For this reason, let's now
report exit code other than success, but only in such case. In
particular, even if the batch commands fail, but GIMP is not set to exit
immediately, we continue reporting SUCCESS run at the very end (when
exiting interactively).

Note that I hardcode a few exit values, as standardly found on Linux
(but not using headers which may not be found on all platforms; in
particular, Windows apparently doesn't use any standard code other than
0 for success, from what my searches return).

Additionally, when several commands are requested, GIMP will now stop at
the first failing and will return its error code, and print a message on
stderr to easily report the failed command for easier debugging.
This commit is contained in:
Jehan 2022-04-16 02:25:03 +02:00
parent 1f74b4fede
commit 5831f5ef4e
5 changed files with 87 additions and 39 deletions

View File

@ -161,7 +161,7 @@ app_exit (gint status)
exit (status);
}
void
gint
app_run (const gchar *full_prog_name,
const gchar **filenames,
GFile *alternate_system_gimprc,
@ -194,6 +194,7 @@ app_run (const gchar *full_prog_name,
GFile *gimpdir;
const gchar *abort_message;
GError *font_error = NULL;
gint retval = EXIT_SUCCESS;
if (filenames && filenames[0] && ! filenames[1] &&
g_file_test (filenames[0], G_FILE_TEST_IS_DIR))
@ -424,7 +425,7 @@ app_run (const gchar *full_prog_name,
}
if (run_loop)
gimp_batch_run (gimp, batch_interpreter, batch_commands);
retval = gimp_batch_run (gimp, batch_interpreter, batch_commands);
if (quit)
{
@ -434,6 +435,13 @@ app_run (const gchar *full_prog_name,
g_signal_emit_by_name (gimp, "exit", TRUE, &cb_retval);
}
else
{
/* Only take into account the batch commands' success when we
* return immediately.
*/
retval = EXIT_SUCCESS;
}
if (run_loop)
g_main_loop_run (loop);
@ -455,6 +463,8 @@ app_run (const gchar *full_prog_name,
gimp_debug_instances ();
gegl_exit ();
return retval;
}

View File

@ -30,7 +30,7 @@ void app_abort (gboolean no_interface,
const gchar *abort_message) G_GNUC_NORETURN;
void app_exit (gint status) G_GNUC_NORETURN;
void app_run (const gchar *full_prog_name,
gint app_run (const gchar *full_prog_name,
const gchar **filenames,
GFile *alternate_system_gimprc,
GFile *alternate_gimprc,

View File

@ -42,22 +42,23 @@
static void gimp_batch_exit_after_callback (Gimp *gimp) G_GNUC_NORETURN;
static void gimp_batch_run_cmd (Gimp *gimp,
static gint gimp_batch_run_cmd (Gimp *gimp,
const gchar *proc_name,
GimpProcedure *procedure,
GimpRunMode run_mode,
const gchar *cmd);
void
gint
gimp_batch_run (Gimp *gimp,
const gchar *batch_interpreter,
const gchar **batch_commands)
{
gulong exit_id;
gint retval = EXIT_SUCCESS;
if (! batch_commands || ! batch_commands[0])
return;
return retval;
exit_id = g_signal_connect_after (gimp, "exit",
G_CALLBACK (gimp_batch_exit_after_callback),
@ -86,9 +87,10 @@ gimp_batch_run (Gimp *gimp,
GimpProcedure *procedure = gimp_pdb_lookup_procedure (gimp->pdb,
proc_name);
retval = 69; /* EX_UNAVAILABLE - service unavailable (sysexits.h) */
if (procedure)
gimp_batch_run_cmd (gimp, proc_name, procedure,
GIMP_RUN_NONINTERACTIVE, NULL);
retval = gimp_batch_run_cmd (gimp, proc_name, procedure,
GIMP_RUN_NONINTERACTIVE, NULL);
else
g_message (_("The batch interpreter '%s' is not available. "
"Batch mode disabled."), proc_name);
@ -98,13 +100,27 @@ gimp_batch_run (Gimp *gimp,
GimpProcedure *eval_proc = gimp_pdb_lookup_procedure (gimp->pdb,
batch_interpreter);
retval = 69; /* EX_UNAVAILABLE - service unavailable (sysexits.h) */
if (eval_proc)
{
gint i;
retval = EXIT_SUCCESS;
for (i = 0; batch_commands[i]; i++)
gimp_batch_run_cmd (gimp, batch_interpreter, eval_proc,
GIMP_RUN_NONINTERACTIVE, batch_commands[i]);
{
retval = gimp_batch_run_cmd (gimp, batch_interpreter, eval_proc,
GIMP_RUN_NONINTERACTIVE, batch_commands[i]);
/* In case of several commands, stop and return last
* failed command.
*/
if (retval != EXIT_SUCCESS)
{
g_printerr ("Stopping at failing batch command [%d]: %s\n",
i, batch_commands[i]);
break;
}
}
}
else
{
@ -114,6 +130,8 @@ gimp_batch_run (Gimp *gimp,
}
g_signal_handler_disconnect (gimp, exit_id);
return retval;
}
@ -141,7 +159,7 @@ GIMP_IS_PARAM_SPEC_RUN_MODE (GParamSpec *pspec)
pspec->value_type == GIMP_TYPE_RUN_MODE);
}
static void
static gint
gimp_batch_run_cmd (Gimp *gimp,
const gchar *proc_name,
GimpProcedure *procedure,
@ -150,8 +168,9 @@ gimp_batch_run_cmd (Gimp *gimp,
{
GimpValueArray *args;
GimpValueArray *return_vals;
GError *error = NULL;
gint i = 0;
GError *error = NULL;
gint i = 0;
gint retval = EXIT_SUCCESS;
args = gimp_procedure_get_arguments (procedure);
@ -176,6 +195,11 @@ gimp_batch_run_cmd (Gimp *gimp,
switch (g_value_get_enum (gimp_value_array_index (return_vals, 0)))
{
case GIMP_PDB_EXECUTION_ERROR:
/* Using Linux's standard exit code as found in /usr/include/sysexits.h
* Since other platforms may not have the header, I simply
* hardcode the few cases.
*/
retval = 70; /* EX_SOFTWARE - internal software error */
if (error)
{
g_printerr ("batch command experienced an execution error:\n"
@ -188,6 +212,7 @@ gimp_batch_run_cmd (Gimp *gimp,
break;
case GIMP_PDB_CALLING_ERROR:
retval = 64; /* EX_USAGE - command line usage error */
if (error)
{
g_printerr ("batch command experienced a calling error:\n"
@ -200,8 +225,20 @@ gimp_batch_run_cmd (Gimp *gimp,
break;
case GIMP_PDB_SUCCESS:
retval = EXIT_SUCCESS;
g_printerr ("batch command executed successfully\n");
break;
case GIMP_PDB_CANCEL:
/* Not in sysexits.h, but usually used for 'Script terminated by
* Control-C'. See: https://tldp.org/LDP/abs/html/exitcodes.html
*/
retval = 130;
break;
case GIMP_PDB_PASS_THROUGH:
retval = EXIT_FAILURE; /* Catchall. */
break;
}
gimp_value_array_unref (return_vals);
@ -210,5 +247,5 @@ gimp_batch_run_cmd (Gimp *gimp,
if (error)
g_error_free (error);
return;
return retval;
}

View File

@ -19,7 +19,7 @@
#define __GIMP_BATCH_H__
void gimp_batch_run (Gimp *gimp,
gint gimp_batch_run (Gimp *gimp,
const gchar *batch_interpreter,
const gchar **batch_commands);

View File

@ -539,6 +539,7 @@ main (int argc,
GFile *user_gimprc_file = NULL;
GOptionGroup *gimp_group = NULL;
gchar *backtrace_file = NULL;
gint retval;
gint i;
#ifdef ENABLE_WIN32_DEBUG_CONSOLE
@ -787,29 +788,29 @@ main (int argc,
if (user_gimprc)
user_gimprc_file = g_file_new_for_commandline_arg (user_gimprc);
app_run (argv[0],
filenames,
system_gimprc_file,
user_gimprc_file,
session_name,
batch_interpreter,
batch_commands,
quit,
as_new,
no_interface,
no_data,
no_fonts,
no_splash,
be_verbose,
use_shm,
use_cpu_accel,
console_messages,
use_debug_handler,
show_playground,
show_debug_menu,
stack_trace_mode,
pdb_compat_mode,
backtrace_file);
retval = app_run (argv[0],
filenames,
system_gimprc_file,
user_gimprc_file,
session_name,
batch_interpreter,
batch_commands,
quit,
as_new,
no_interface,
no_data,
no_fonts,
no_splash,
be_verbose,
use_shm,
use_cpu_accel,
console_messages,
use_debug_handler,
show_playground,
show_debug_menu,
stack_trace_mode,
pdb_compat_mode,
backtrace_file);
g_free (backtrace_file);
@ -820,7 +821,7 @@ main (int argc,
g_option_context_free (context);
return EXIT_SUCCESS;
return retval;
}