From 913eccd30f27eb0ef923f9bf0d8a3e1602b37fb4 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Mon, 1 Feb 2016 21:26:20 +0100 Subject: [PATCH] builder: Add shell source This lets you run shell commands to modify the source --- builder/Makefile.am.inc | 2 + builder/builder-source-shell.c | 217 +++++++++++++++++++++++++++++++++ builder/builder-source-shell.h | 40 ++++++ builder/builder-source.c | 5 + 4 files changed, 264 insertions(+) create mode 100644 builder/builder-source-shell.c create mode 100644 builder/builder-source-shell.h diff --git a/builder/Makefile.am.inc b/builder/Makefile.am.inc index 014907cf..918baa8e 100644 --- a/builder/Makefile.am.inc +++ b/builder/Makefile.am.inc @@ -22,6 +22,8 @@ xdg_app_builder_SOURCES = \ builder/builder-source-file.h \ builder/builder-source-script.c \ builder/builder-source-script.h \ + builder/builder-source-shell.c \ + builder/builder-source-shell.h \ builder/builder-source-patch.c \ builder/builder-source-patch.h \ builder/builder-context.c \ diff --git a/builder/builder-source-shell.c b/builder/builder-source-shell.c new file mode 100644 index 00000000..dcc489f5 --- /dev/null +++ b/builder/builder-source-shell.c @@ -0,0 +1,217 @@ +/* builder-source-shell.c + * + * Copyright (C) 2015 Red Hat, Inc + * + * This file is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Authors: + * Alexander Larsson + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "builder-utils.h" +#include "builder-source-shell.h" + +struct BuilderSourceShell { + BuilderSource parent; + + char **commands; +}; + +typedef struct { + BuilderSourceClass parent_class; +} BuilderSourceShellClass; + +G_DEFINE_TYPE (BuilderSourceShell, builder_source_shell, BUILDER_TYPE_SOURCE); + +enum { + PROP_0, + PROP_COMMANDS, + LAST_PROP +}; + +static void +builder_source_shell_finalize (GObject *object) +{ + BuilderSourceShell *self = (BuilderSourceShell *)object; + + g_strfreev (self->commands); + + G_OBJECT_CLASS (builder_source_shell_parent_class)->finalize (object); +} + +static void +builder_source_shell_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + BuilderSourceShell *self = BUILDER_SOURCE_SHELL (object); + + switch (prop_id) + { + case PROP_COMMANDS: + g_value_set_boxed (value, self->commands); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +builder_source_shell_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + BuilderSourceShell *self = BUILDER_SOURCE_SHELL (object); + gchar **tmp; + + switch (prop_id) + { + case PROP_COMMANDS: + tmp = self->commands; + self->commands = g_strdupv (g_value_get_boxed (value)); + g_strfreev (tmp); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static gboolean +builder_source_shell_download (BuilderSource *source, + gboolean update_vcs, + BuilderContext *context, + GError **error) +{ + return TRUE; +} + +static gboolean +run_script (BuilderContext *context, + GFile *source_dir, + const gchar *script, + GError **error) +{ + GFile *app_dir = builder_context_get_app_dir (context); + g_autoptr(GSubprocessLauncher) launcher = NULL; + g_autoptr(GSubprocess) subp = NULL; + g_autoptr(GPtrArray) args = NULL; + g_autofree char *commandline = NULL; + g_autofree char *source_dir_path = g_file_get_path (source_dir); + g_autofree char *source_dir_path_canonical = NULL; + + args = g_ptr_array_new_with_free_func (g_free); + g_ptr_array_add (args, g_strdup ("xdg-app")); + g_ptr_array_add (args, g_strdup ("build")); + + source_dir_path_canonical = canonicalize_file_name (source_dir_path); + + g_ptr_array_add (args, g_strdup ("--nofilesystem=host")); + g_ptr_array_add (args, g_strdup_printf ("--filesystem=%s", source_dir_path_canonical)); + + g_ptr_array_add (args, g_file_get_path (app_dir)); + g_ptr_array_add (args, g_strdup ("/bin/sh")); + g_ptr_array_add (args, g_strdup ("-c")); + g_ptr_array_add (args, g_strdup (script)); + g_ptr_array_add (args, NULL); + + commandline = g_strjoinv (" ", (char **) args->pdata); + g_print ("Running: %s\n", commandline); + + launcher = g_subprocess_launcher_new (0); + + g_subprocess_launcher_set_cwd (launcher, source_dir_path_canonical); + + subp = g_subprocess_launcher_spawnv (launcher, (const gchar * const *) args->pdata, error); + g_ptr_array_free (args, TRUE); + + if (subp == NULL || + !g_subprocess_wait_check (subp, NULL, error)) + return FALSE; + + return TRUE; +} + + +static gboolean +builder_source_shell_extract (BuilderSource *source, + GFile *dest, + BuilderContext *context, + GError **error) +{ + BuilderSourceShell *self = BUILDER_SOURCE_SHELL (source); + int i; + + if (self->commands) + { + for (i = 0; self->commands[i] != NULL; i++) + { + if (!run_script (context, + dest, self->commands[i], error)) + return FALSE; + } + } + + + return TRUE; +} + +static void +builder_source_shell_checksum (BuilderSource *source, + BuilderCache *cache, + BuilderContext *context) +{ + BuilderSourceShell *self = BUILDER_SOURCE_SHELL (source); + + builder_cache_checksum_strv (cache, self->commands); +} + +static void +builder_source_shell_class_init (BuilderSourceShellClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + BuilderSourceClass *source_class = BUILDER_SOURCE_CLASS (klass); + + object_class->finalize = builder_source_shell_finalize; + object_class->get_property = builder_source_shell_get_property; + object_class->set_property = builder_source_shell_set_property; + + source_class->download = builder_source_shell_download; + source_class->extract = builder_source_shell_extract; + source_class->checksum = builder_source_shell_checksum; + + g_object_class_install_property (object_class, + PROP_COMMANDS, + g_param_spec_boxed ("commands", + "", + "", + G_TYPE_STRV, + G_PARAM_READWRITE)); +} + +static void +builder_source_shell_init (BuilderSourceShell *self) +{ +} diff --git a/builder/builder-source-shell.h b/builder/builder-source-shell.h new file mode 100644 index 00000000..8de51d3e --- /dev/null +++ b/builder/builder-source-shell.h @@ -0,0 +1,40 @@ +/* + * Copyright © 2015 Red Hat, Inc + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Authors: + * Alexander Larsson + */ + +#ifndef __BUILDER_SOURCE_SHELL_H__ +#define __BUILDER_SOURCE_SHELL_H__ + +#include "builder-source.h" + +G_BEGIN_DECLS + +typedef struct BuilderSourceShell BuilderSourceShell; + +#define BUILDER_TYPE_SOURCE_SHELL (builder_source_shell_get_type()) +#define BUILDER_SOURCE_SHELL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUILDER_TYPE_SOURCE_SHELL, BuilderSourceShell)) +#define BUILDER_IS_SOURCE_SHELL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUILDER_TYPE_SOURCE_SHELL)) + +GType builder_source_shell_get_type (void); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(BuilderSourceShell, g_object_unref) + +G_END_DECLS + +#endif /* __BUILDER_SOURCE_SHELL_H__ */ diff --git a/builder/builder-source.c b/builder/builder-source.c index 7ab242dd..bf7b2de6 100644 --- a/builder/builder-source.c +++ b/builder/builder-source.c @@ -35,6 +35,7 @@ #include "builder-source-bzr.h" #include "builder-source-file.h" #include "builder-source-script.h" +#include "builder-source-shell.h" static void serializable_iface_init (JsonSerializableIface *serializable_iface); @@ -175,6 +176,8 @@ builder_source_to_json (BuilderSource *self) type = "file"; else if (BUILDER_IS_SOURCE_SCRIPT (self)) type = "script"; + else if (BUILDER_IS_SOURCE_SHELL (self)) + type = "shell"; else if (BUILDER_IS_SOURCE_PATCH (self)) type = "patch"; else if (BUILDER_IS_SOURCE_GIT (self)) @@ -204,6 +207,8 @@ builder_source_from_json (JsonNode *node) return (BuilderSource *)json_gobject_deserialize (BUILDER_TYPE_SOURCE_FILE, node); if (strcmp (type, "script") == 0) return (BuilderSource *)json_gobject_deserialize (BUILDER_TYPE_SOURCE_SCRIPT, node); + if (strcmp (type, "shell") == 0) + return (BuilderSource *)json_gobject_deserialize (BUILDER_TYPE_SOURCE_SHELL, node); if (strcmp (type, "patch") == 0) return (BuilderSource *)json_gobject_deserialize (BUILDER_TYPE_SOURCE_PATCH, node); if (strcmp (type, "git") == 0)