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



commit 5831f5ef4e792cf0d9e2acac32f0d52e796634cb
Author: Jehan <jehan girinstud io>
Date:   Sat Apr 16 02:25:03 2022 +0200

    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.

 app/app.c             | 14 ++++++++++--
 app/app.h             |  2 +-
 app/core/gimp-batch.c | 59 +++++++++++++++++++++++++++++++++++++++++----------
 app/core/gimp-batch.h |  2 +-
 app/main.c            | 49 +++++++++++++++++++++---------------------
 5 files changed, 87 insertions(+), 39 deletions(-)
---
diff --git a/app/app.c b/app/app.c
index 3ac2828faf..e9d18e6461 100644
--- a/app/app.c
+++ b/app/app.c
@@ -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;
 }
 
 
diff --git a/app/app.h b/app/app.h
index ca9fb07150..f11672efaf 100644
--- a/app/app.h
+++ b/app/app.h
@@ -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,
diff --git a/app/core/gimp-batch.c b/app/core/gimp-batch.c
index 6dfa5ea551..059be443e8 100644
--- a/app/core/gimp-batch.c
+++ b/app/core/gimp-batch.c
@@ -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;
 }
diff --git a/app/core/gimp-batch.h b/app/core/gimp-batch.h
index 3e6945cc3f..1c6e4dfd4a 100644
--- a/app/core/gimp-batch.h
+++ b/app/core/gimp-batch.h
@@ -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);
 
diff --git a/app/main.c b/app/main.c
index af44052e30..2a0c41e23c 100644
--- a/app/main.c
+++ b/app/main.c
@@ -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;
 }
 
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]