[gnome-builder/wip/gtk4-port: 1605/1774] libide/foundry: do variable expansion at the source




commit efaa584bcddc2bec7f091e849f9460cb473c6852
Author: Christian Hergert <chergert redhat com>
Date:   Wed Jun 22 15:45:39 2022 -0700

    libide/foundry: do variable expansion at the source
    
    We want to do this when extracting the run command, not when dealing with
    run contexts, which is far too late.
    
    Additionally, we probably need to do similar from shellcmd when executing
    commands using keyboard shortcuts.

 src/libide/foundry/ide-run-context.c | 38 +-----------------------
 src/libide/foundry/ide-run-manager.c | 57 ++++++++++++++++++++++++++++++++----
 2 files changed, 53 insertions(+), 42 deletions(-)
---
diff --git a/src/libide/foundry/ide-run-context.c b/src/libide/foundry/ide-run-context.c
index 21111224e..aa8ff08c6 100644
--- a/src/libide/foundry/ide-run-context.c
+++ b/src/libide/foundry/ide-run-context.c
@@ -707,39 +707,6 @@ ide_run_context_callback_layer (IdeRunContext       *self,
   return ret;
 }
 
-static char *
-ide_run_context_expand_cwd (IdeRunContext *self)
-{
-  g_autoptr(GString) str = NULL;
-  const char *envval;
-  const char *cwd;
-
-  g_assert (IDE_IS_RUN_CONTEXT (self));
-
-  if (!(cwd = ide_run_context_get_cwd (self)))
-    return NULL;
-
-  str = g_string_new (cwd);
-
-  if ((envval = ide_run_context_getenv (self, "BUILDDIR")))
-    g_string_replace (str, "$BUILDDIR", envval, 0);
-
-  if ((envval = ide_run_context_getenv (self, "SRCDIR")))
-    g_string_replace (str, "$SRCDIR", envval, 0);
-
-  if ((envval = ide_run_context_getenv (self, "HOME")))
-    g_string_replace (str, "$HOME", envval, 0);
-  else
-    g_string_replace (str, "$HOME", g_get_home_dir (), 0);
-
-  if ((envval = ide_run_context_getenv (self, "USER")))
-    g_string_replace (str, "$USER", envval, 0);
-  else
-    g_string_replace (str, "$USER", g_get_user_name (), 0);
-
-  return ide_path_expand (str->str);
-}
-
 /**
  * ide_run_context_end:
  * @self: a #IdeRunContext
@@ -752,7 +719,6 @@ ide_run_context_end (IdeRunContext  *self,
                      GError        **error)
 {
   g_autoptr(IdeSubprocessLauncher) launcher = NULL;
-  g_autofree char *cwd = NULL;
 
   g_return_val_if_fail (IDE_IS_RUN_CONTEXT (self), NULL);
   g_return_val_if_fail (self->ended == FALSE, NULL);
@@ -769,13 +735,11 @@ ide_run_context_end (IdeRunContext  *self,
         return FALSE;
     }
 
-  cwd = ide_run_context_expand_cwd (self);
-
   launcher = ide_subprocess_launcher_new (0);
 
   ide_subprocess_launcher_set_argv (launcher, ide_run_context_get_argv (self));
   ide_subprocess_launcher_set_environ (launcher, ide_run_context_get_environ (self));
-  ide_subprocess_launcher_set_cwd (launcher, cwd);
+  ide_subprocess_launcher_set_cwd (launcher, ide_run_context_get_cwd (self));
 
   return g_steal_pointer (&launcher);
 }
diff --git a/src/libide/foundry/ide-run-manager.c b/src/libide/foundry/ide-run-manager.c
index f2621e8d7..3ddc9bbac 100644
--- a/src/libide/foundry/ide-run-manager.c
+++ b/src/libide/foundry/ide-run-manager.c
@@ -24,6 +24,7 @@
 
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
+#include <unistd.h>
 
 #include <libpeas/peas.h>
 #include <libpeas/peas-autocleanups.h>
@@ -764,16 +765,51 @@ ide_run_manager_run_subprocess_wait_check_cb (GObject      *object,
   IDE_EXIT;
 }
 
+
+static char *
+expand_variables (IdePipeline *pipeline,
+                  const char  *spec)
+{
+  g_autoptr(GString) str = g_string_new (spec);
+  static char uidstr[32];
+  const struct {
+    const char *needle;
+    const char *replacement;
+  } replacements[] = {
+    { "$BUILDDIR", ide_pipeline_get_builddir (pipeline) },
+    { "$SRCDIR", ide_pipeline_get_srcdir (pipeline) },
+    { "$HOME", g_get_home_dir () },
+    { "$USER", g_get_user_name () },
+    { "$UID", uidstr },
+  };
+
+  if (uidstr[0] == 0)
+    g_snprintf (uidstr, sizeof uidstr, "%u", getuid ());
+
+  if (strchr (str->str, '$') != NULL)
+    {
+      for (guint i = 0; i < G_N_ELEMENTS (replacements); i++)
+        g_string_replace (str,
+                          replacements[i].needle,
+                          replacements[i].replacement,
+                          0);
+    }
+
+  return g_string_free (g_steal_pointer (&str), FALSE);
+}
+
 static void
 ide_run_manager_prepare_run_context (IdeRunManager *self,
                                      IdeRunContext *run_context,
-                                     IdeRunCommand *run_command)
+                                     IdeRunCommand *run_command,
+                                     IdePipeline   *pipeline)
 {
   IDE_ENTRY;
 
   g_assert (IDE_IS_RUN_MANAGER (self));
   g_assert (IDE_IS_RUN_CONTEXT (run_context));
   g_assert (IDE_IS_RUN_COMMAND (run_command));
+  g_assert (IDE_IS_PIPELINE (pipeline));
 
   /* The very first thing we need to do is allow the current run handler
    * to inject any command wrapper it needs. This might be something like
@@ -798,15 +834,26 @@ ide_run_manager_prepare_run_context (IdeRunManager *self,
     const char *cwd = ide_run_command_get_cwd (run_command);
 
     if (cwd != NULL)
-      ide_run_context_set_cwd (run_context, cwd);
+      {
+        g_autofree char *expand1 = expand_variables (pipeline, cwd);
+        g_autofree char *expand2 = ide_path_expand (expand1);
+
+        ide_run_context_set_cwd (run_context, expand2);
+      }
   }
 
   /* Setup command arguments */
   {
     const char * const *argv = ide_run_command_get_argv (run_command);
 
-    if (argv != NULL && argv[0] != NULL)
-      ide_run_context_append_args (run_context, argv);
+    if (argv != NULL)
+      {
+        for (guint i = 0; argv[i]; i++)
+          {
+            g_autofree char *expanded = expand_variables (pipeline, argv[i]);
+            ide_run_context_append_argv (run_context, expanded);
+          }
+      }
   }
 
   /* Setup command environment */
@@ -892,7 +939,7 @@ ide_run_manager_run_deploy_cb (GObject      *object,
   run_context = ide_run_context_new ();
   setup_pipeline_environment (run_context, pipeline);
   ide_deploy_strategy_prepare_run_context (deploy_strategy, pipeline, run_context);
-  ide_run_manager_prepare_run_context (self, run_context, self->current_run_command);
+  ide_run_manager_prepare_run_context (self, run_context, self->current_run_command, pipeline);
 
   /* Now spawn the subprocess or bail if there was a failure to build command */
   if (!(subprocess = ide_run_context_spawn (run_context, &error)))


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