diff --git a/Makefile.am b/Makefile.am index 6fa61aa6..f5adccc8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -89,7 +89,6 @@ include common/Makefile.am.inc include data/Makefile.am.inc include app/Makefile.am.inc include lib/Makefile.am.inc -include builder/Makefile.am.inc include session-helper/Makefile.am.inc include system-helper/Makefile.am.inc include dbus-proxy/Makefile.am.inc diff --git a/builder/Makefile.am.inc b/builder/Makefile.am.inc deleted file mode 100644 index a9592f05..00000000 --- a/builder/Makefile.am.inc +++ /dev/null @@ -1,45 +0,0 @@ -bin_PROGRAMS += \ - flatpak-builder \ - $(NULL) - -flatpak_builder_SOURCES = \ - builder/builder-main.c \ - builder/builder-manifest.c \ - builder/builder-manifest.h \ - builder/builder-options.c \ - builder/builder-options.h \ - builder/builder-extension.c \ - builder/builder-extension.h \ - builder/builder-module.c \ - builder/builder-module.h \ - builder/builder-post-process.c \ - builder/builder-post-process.h \ - builder/builder-source.c \ - builder/builder-source.h \ - builder/builder-source-archive.c \ - builder/builder-source-archive.h \ - builder/builder-source-git.c \ - builder/builder-source-git.h \ - builder/builder-source-bzr.c \ - builder/builder-source-bzr.h \ - builder/builder-source-file.c \ - 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 \ - builder/builder-context.h \ - builder/builder-cache.c \ - builder/builder-cache.h \ - builder/builder-utils.c \ - builder/builder-utils.h \ - builder/builder-git.c \ - builder/builder-git.h \ - $(NULL) - -flatpak_builder_LDADD = $(AM_LDADD) $(BASE_LIBS) $(OSTREE_LIBS) $(JSON_LIBS) $(SOUP_LIBS) $(LIBELF_LIBS) \ - libglnx.la libflatpak-common.la -flatpak_builder_CFLAGS = $(AM_CFLAGS) $(BASE_CFLAGS) $(OSTREE_CFLAGS) $(JSON_CFLAGS) $(SOUP_CFLAGS) diff --git a/builder/builder-cache.c b/builder/builder-cache.c deleted file mode 100644 index 5924339e..00000000 --- a/builder/builder-cache.c +++ /dev/null @@ -1,1172 +0,0 @@ -/* builder-cache.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 -#include -#include "libglnx/libglnx.h" - -#include "flatpak-utils.h" -#include "builder-utils.h" -#include "builder-cache.h" -#include "builder-context.h" - -struct BuilderCache -{ - GObject parent; - BuilderContext *context; - GChecksum *checksum; - GFile *app_dir; - char *branch; - char *stage; - GHashTable *unused_stages; - char *last_parent; - OstreeRepo *repo; - gboolean disabled; - OstreeRepoDevInoCache *devino_to_csum_cache; -}; - -typedef struct -{ - GObjectClass parent_class; -} BuilderCacheClass; - -G_DEFINE_TYPE (BuilderCache, builder_cache, G_TYPE_OBJECT); - -enum { - PROP_0, - PROP_CONTEXT, - PROP_APP_DIR, - PROP_BRANCH, - LAST_PROP -}; - -#define OSTREE_GIO_FAST_QUERYINFO ("standard::name,standard::type,standard::size,standard::is-symlink,standard::symlink-target," \ - "unix::device,unix::inode,unix::mode,unix::uid,unix::gid,unix::rdev") - -static void -builder_cache_finalize (GObject *object) -{ - BuilderCache *self = (BuilderCache *) object; - - g_clear_object (&self->context); - g_clear_object (&self->app_dir); - g_clear_object (&self->repo); - g_checksum_free (self->checksum); - g_free (self->branch); - g_free (self->last_parent); - g_free (self->stage); - if (self->unused_stages) - g_hash_table_unref (self->unused_stages); - - if (self->devino_to_csum_cache) - ostree_repo_devino_cache_unref (self->devino_to_csum_cache); - - G_OBJECT_CLASS (builder_cache_parent_class)->finalize (object); -} - -static void -builder_cache_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - BuilderCache *self = BUILDER_CACHE (object); - - switch (prop_id) - { - case PROP_CONTEXT: - g_value_set_object (value, self->context); - break; - - case PROP_APP_DIR: - g_value_set_object (value, self->app_dir); - break; - - case PROP_BRANCH: - g_value_set_string (value, self->branch); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -builder_cache_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - BuilderCache *self = BUILDER_CACHE (object); - - switch (prop_id) - { - case PROP_BRANCH: - g_free (self->branch); - self->branch = g_value_dup_string (value); - break; - - case PROP_CONTEXT: - g_set_object (&self->context, g_value_get_object (value)); - break; - - case PROP_APP_DIR: - g_set_object (&self->app_dir, g_value_get_object (value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -builder_cache_class_init (BuilderCacheClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = builder_cache_finalize; - object_class->get_property = builder_cache_get_property; - object_class->set_property = builder_cache_set_property; - - g_object_class_install_property (object_class, - PROP_CONTEXT, - g_param_spec_object ("context", - "", - "", - BUILDER_TYPE_CONTEXT, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (object_class, - PROP_APP_DIR, - g_param_spec_object ("app-dir", - "", - "", - G_TYPE_FILE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (object_class, - PROP_BRANCH, - g_param_spec_string ("branch", - "", - "", - NULL, - G_PARAM_READWRITE)); -} - -static void -builder_cache_init (BuilderCache *self) -{ - self->checksum = g_checksum_new (G_CHECKSUM_SHA256); - self->devino_to_csum_cache = ostree_repo_devino_cache_new (); -} - -BuilderCache * -builder_cache_new (BuilderContext *context, - GFile *app_dir, - const char *branch) -{ - return g_object_new (BUILDER_TYPE_CACHE, - "context", context, - "app-dir", app_dir, - "branch", branch, - NULL); -} - -GChecksum * -builder_cache_get_checksum (BuilderCache *self) -{ - return self->checksum; -} - -static char * -get_ref (BuilderCache *self, const char *stage) -{ - GString *s = g_string_new (self->branch); - - g_string_append_c (s, '/'); - - while (*stage) - { - char c = *stage++; - if (g_ascii_isalnum (c) || - c == '-' || - c == '_' || - c == '.') - g_string_append_c (s, c); - else - g_string_append_printf (s, "%x", c); - } - - return g_string_free (s, FALSE); -} - -gboolean -builder_cache_open (BuilderCache *self, - GError **error) -{ - self->repo = ostree_repo_new (builder_context_get_cache_dir (self->context)); - - /* We don't need fsync on checkouts as they are transient, and we - rely on the syncfs() in the transaction commit for commits. */ - ostree_repo_set_disable_fsync (self->repo, TRUE); - - if (!g_file_query_exists (builder_context_get_cache_dir (self->context), NULL)) - { - g_autoptr(GFile) parent = g_file_get_parent (builder_context_get_cache_dir (self->context)); - - if (!flatpak_mkdir_p (parent, NULL, error)) - return FALSE; - - if (!ostree_repo_create (self->repo, OSTREE_REPO_MODE_BARE_USER, NULL, error)) - return FALSE; - } - - if (!ostree_repo_open (self->repo, NULL, error)) - return FALSE; - - /* At one point we used just the branch name as a ref, make sure to - * remove this to handle using the branch as a subdir */ - ostree_repo_set_ref_immediate (self->repo, - NULL, - self->branch, - NULL, - NULL, NULL); - - /* List all stages first so we can purge unused ones at the end */ - if (!ostree_repo_list_refs (self->repo, - self->branch, - &self->unused_stages, - NULL, error)) - return FALSE; - - return TRUE; -} - -static char * -builder_cache_get_current (BuilderCache *self) -{ - g_autoptr(GChecksum) copy = g_checksum_copy (self->checksum); - - return g_strdup (g_checksum_get_string (copy)); -} - -static gboolean -builder_cache_checkout (BuilderCache *self, const char *commit, gboolean delete_dir, GError **error) -{ - g_autoptr(GError) my_error = NULL; - OstreeRepoCheckoutMode mode = OSTREE_REPO_CHECKOUT_MODE_NONE; - OstreeRepoCheckoutAtOptions options = { 0, }; - - if (delete_dir) - { - if (!g_file_delete (self->app_dir, NULL, &my_error) && - !g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) - { - g_propagate_error (error, g_steal_pointer (&my_error)); - return FALSE; - } - - if (!flatpak_mkdir_p (self->app_dir, NULL, error)) - return FALSE; - } - - /* If rofiles-fuse is disabled, we check out without user mode, not - necessarily because we care about uids not owned by the user - (they are all from the build, so should be creatable by the user, - but because we want to force the checkout to not use - hardlinks. Hard links into the cache without rofiles-fuse are not - safe, as the build could mutate the cache. */ - if (builder_context_get_use_rofiles (self->context)) - mode = OSTREE_REPO_CHECKOUT_MODE_USER; - - options.mode = mode; - options.overwrite_mode = OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES; - options.devino_to_csum_cache = self->devino_to_csum_cache; - - if (!ostree_repo_checkout_at (self->repo, &options, - AT_FDCWD, flatpak_file_get_path_cached (self->app_dir), - commit, NULL, error)) - return FALSE; - - /* There is a bug in ostree (https://github.com/ostreedev/ostree/issues/326) that - causes it to not reset mtime to 0 in themismatching modes case. So we do that - manually */ - if (mode == OSTREE_REPO_CHECKOUT_MODE_NONE && - !flatpak_zero_mtime (AT_FDCWD, flatpak_file_get_path_cached (self->app_dir), - NULL, error)) - return FALSE; - - return TRUE; -} - -gboolean -builder_cache_has_checkout (BuilderCache *self) -{ - return self->disabled; -} - -void -builder_cache_ensure_checkout (BuilderCache *self) -{ - if (builder_cache_has_checkout (self)) - return; - - if (self->last_parent) - { - g_autoptr(GError) error = NULL; - g_print ("Everything cached, checking out from cache\n"); - - if (!builder_cache_checkout (self, self->last_parent, TRUE, &error)) - g_error ("Failed to check out cache: %s", error->message); - } - - self->disabled = TRUE; -} - -static char * -builder_cache_get_current_ref (BuilderCache *self) -{ - return get_ref (self, self->stage); -} - -gboolean -builder_cache_lookup (BuilderCache *self, - const char *stage) -{ - g_autofree char *current = NULL; - g_autofree char *commit = NULL; - g_autofree char *ref = NULL; - - g_free (self->stage); - self->stage = g_strdup (stage); - - g_hash_table_remove (self->unused_stages, stage); - - if (self->disabled) - return FALSE; - - ref = builder_cache_get_current_ref (self); - if (!ostree_repo_resolve_rev (self->repo, ref, TRUE, &commit, NULL)) - goto checkout; - - current = builder_cache_get_current (self); - - if (commit != NULL) - { - g_autoptr(GVariant) variant = NULL; - const gchar *subject; - - if (!ostree_repo_load_variant (self->repo, OSTREE_OBJECT_TYPE_COMMIT, commit, - &variant, NULL)) - goto checkout; - - g_variant_get (variant, "(a{sv}aya(say)&s&stayay)", NULL, NULL, NULL, - &subject, NULL, NULL, NULL, NULL); - - if (strcmp (subject, current) == 0) - { - g_free (self->last_parent); - self->last_parent = g_steal_pointer (&commit); - - return TRUE; - } - } - -checkout: - if (self->last_parent) - { - g_autoptr(GError) error = NULL; - g_print ("Cache miss, checking out last cache hit\n"); - - if (!builder_cache_checkout (self, self->last_parent, TRUE, &error)) - g_error ("Failed to check out cache: %s", error->message); - } - - self->disabled = TRUE; /* Don't use cache any more after first miss */ - - return FALSE; -} - -static gboolean -mtree_empty (OstreeMutableTree *mtree) -{ - GHashTable *files = ostree_mutable_tree_get_files (mtree); - GHashTable *subdirs = ostree_mutable_tree_get_subdirs (mtree); - - return - g_hash_table_size (files) == 0 && - g_hash_table_size (subdirs) == 0; -} - -/* This takes a mutable tree and an existing OstreeRepoFile, and recursively - * removes all mtree files that already exists in the OstreeRepoFile. - * This is very useful to create a commit with just the new files, which - * we can then check out in order to get a the new hardlinks to the - * cache repo. - */ -static gboolean -mtree_prune_old_files (OstreeMutableTree *mtree, - OstreeRepoFile *old, - GError **error) -{ - GHashTable *files = ostree_mutable_tree_get_files (mtree); - GHashTable *subdirs = ostree_mutable_tree_get_subdirs (mtree); - GHashTableIter iter; - gpointer key, value; - - ostree_mutable_tree_set_contents_checksum (mtree, NULL); - - if (old != NULL && !ostree_repo_file_ensure_resolved (old, error)) - return FALSE; - - g_hash_table_iter_init (&iter, files); - while (g_hash_table_iter_next (&iter, &key, &value)) - { - const char *name = key; - const char *csum = value; - int n = -1; - gboolean is_dir; - g_autoptr(GVariant) container = NULL; - gboolean same = FALSE; - - if (old) - n = ostree_repo_file_tree_find_child (old, name, &is_dir, &container); - - if (n >= 0) - { - if (!is_dir) - { - g_autoptr(GVariant) old_csum_bytes = NULL; - g_autofree char *old_csum = NULL; - - g_variant_get_child (container, n, - "(@s@ay)", NULL, &old_csum_bytes); - old_csum = ostree_checksum_from_bytes_v (old_csum_bytes); - - if (strcmp (old_csum, csum) == 0) - same = TRUE; /* Modified file */ - } - } - - if (same) - g_hash_table_iter_remove (&iter); - } - - g_hash_table_iter_init (&iter, subdirs); - while (g_hash_table_iter_next (&iter, &key, &value)) - { - const char *name = key; - OstreeMutableTree *subdir = value; - g_autoptr(GFile) old_subdir = NULL; - int n = -1; - gboolean is_dir; - - if (old) - n = ostree_repo_file_tree_find_child (old, name, &is_dir, NULL); - - if (n >= 0 && is_dir) - old_subdir = g_file_get_child (G_FILE (old), name); - - if (!mtree_prune_old_files (subdir, OSTREE_REPO_FILE (old_subdir), error)) - return FALSE; - - if (mtree_empty (subdir)) - g_hash_table_iter_remove (&iter); - } - - return TRUE; -} - -gboolean -builder_cache_commit (BuilderCache *self, - const char *body, - GError **error) -{ - g_autofree char *current = NULL; - OstreeRepoCommitModifier *modifier = NULL; - - g_autoptr(OstreeMutableTree) mtree = NULL; - g_autoptr(GFile) root = NULL; - g_autofree char *commit_checksum = NULL; - g_autofree char *new_commit_checksum = NULL; - gboolean res = FALSE; - g_autofree char *ref = NULL; - g_autoptr(GFile) last_root = NULL; - g_autoptr(GFile) new_root = NULL; - - g_print ("Committing stage %s to cache\n", self->stage); - - /* We set all mtimes to 0 during a commit, to simulate what would happen when - running via flatpak deploy (and also if we checked out from the cache). */ - if (!flatpak_zero_mtime (AT_FDCWD, flatpak_file_get_path_cached (self->app_dir), - NULL, NULL)) - return FALSE; - - if (!ostree_repo_prepare_transaction (self->repo, NULL, NULL, error)) - return FALSE; - - mtree = ostree_mutable_tree_new (); - - modifier = ostree_repo_commit_modifier_new (OSTREE_REPO_COMMIT_MODIFIER_FLAGS_SKIP_XATTRS, - NULL, NULL, NULL); - if (self->devino_to_csum_cache) - ostree_repo_commit_modifier_set_devino_cache (modifier, self->devino_to_csum_cache); - - if (!ostree_repo_write_directory_to_mtree (self->repo, self->app_dir, - mtree, modifier, NULL, error)) - goto out; - - if (!ostree_repo_write_mtree (self->repo, mtree, &root, NULL, error)) - goto out; - - current = builder_cache_get_current (self); - - if (!ostree_repo_write_commit (self->repo, self->last_parent, current, body, NULL, - OSTREE_REPO_FILE (root), - &commit_checksum, NULL, error)) - goto out; - - ref = builder_cache_get_current_ref (self); - ostree_repo_transaction_set_ref (self->repo, NULL, ref, commit_checksum); - - if (self->last_parent && - !ostree_repo_read_commit (self->repo, self->last_parent, &last_root, NULL, NULL, error)) - goto out; - - if (!mtree_prune_old_files (mtree, OSTREE_REPO_FILE (last_root), error)) - goto out; - - if (!ostree_repo_write_mtree (self->repo, mtree, &new_root, NULL, error)) - goto out; - - if (!ostree_repo_write_commit (self->repo, NULL, current, body, NULL, - OSTREE_REPO_FILE (new_root), - &new_commit_checksum, NULL, error)) - goto out; - - if (!ostree_repo_commit_transaction (self->repo, NULL, NULL, error)) - goto out; - - /* Check out the just commited cache so we hardlinks to the cache */ - if (builder_context_get_use_rofiles (self->context) && - !builder_cache_checkout (self, new_commit_checksum, FALSE, error)) - goto out; - - g_free (self->last_parent); - self->last_parent = g_steal_pointer (&commit_checksum); - - res = TRUE; - -out: - if (!res) - { - if (!ostree_repo_abort_transaction (self->repo, NULL, NULL)) - g_warning ("failed to abort transaction"); - } - if (modifier) - ostree_repo_commit_modifier_unref (modifier); - - return res; -} - -typedef struct { - dev_t dev; - ino_t ino; - char checksum[OSTREE_SHA256_STRING_LEN+1]; -} OstreeDevIno; - -static const char * -devino_cache_lookup (OstreeRepoDevInoCache *devino_to_csum_cache, - guint32 device, - guint32 inode) -{ - OstreeDevIno dev_ino_key; - OstreeDevIno *dev_ino_val; - GHashTable *cache = (GHashTable *)devino_to_csum_cache; - - if (devino_to_csum_cache == NULL) - return NULL; - - dev_ino_key.dev = device; - dev_ino_key.ino = inode; - dev_ino_val = g_hash_table_lookup (cache, &dev_ino_key); - - if (!dev_ino_val) - return NULL; - - return dev_ino_val->checksum; -} - -static gboolean -get_file_checksum (OstreeRepoDevInoCache *devino_to_csum_cache, - GFile *f, - GFileInfo *f_info, - char **out_checksum, - GCancellable *cancellable, - GError **error) -{ - g_autofree char *ret_checksum = NULL; - g_autofree guchar *csum = NULL; - - if (OSTREE_IS_REPO_FILE (f)) - { - ret_checksum = g_strdup (ostree_repo_file_get_checksum ((OstreeRepoFile*)f)); - } - else - { - const char *cached = devino_cache_lookup (devino_to_csum_cache, - g_file_info_get_attribute_uint32 (f_info, "unix::device"), - g_file_info_get_attribute_uint64 (f_info, "unix::inode")); - if (cached) - ret_checksum = g_strdup (cached); - else - { - g_autoptr(GInputStream) in = NULL; - - if (g_file_info_get_file_type (f_info) == G_FILE_TYPE_REGULAR) - { - in = (GInputStream*)g_file_read (f, cancellable, error); - if (!in) - return FALSE; - } - - if (!ostree_checksum_file_from_input (f_info, NULL, in, - OSTREE_OBJECT_TYPE_FILE, - &csum, cancellable, error)) - return FALSE; - - ret_checksum = ostree_checksum_from_bytes (csum); - } - } - - *out_checksum = g_steal_pointer (&ret_checksum); - return TRUE; -} - -static gboolean -diff_files (OstreeRepoDevInoCache *devino_to_csum_cache, - GFile *a, - GFileInfo *a_info, - GFile *b, - GFileInfo *b_info, - gboolean *was_changed, - GCancellable *cancellable, - GError **error) -{ - g_autofree char *checksum_a = NULL; - g_autofree char *checksum_b = NULL; - - if (!get_file_checksum (devino_to_csum_cache, a, a_info, &checksum_a, cancellable, error)) - return FALSE; - - if (!get_file_checksum (devino_to_csum_cache, b, b_info, &checksum_b, cancellable, error)) - return FALSE; - - *was_changed = strcmp (checksum_a, checksum_b) != 0; - - return TRUE; -} - -static gboolean -diff_add_dir_recurse (GFile *d, - GPtrArray *added, - GCancellable *cancellable, - GError **error) -{ - GError *temp_error = NULL; - g_autoptr(GFileEnumerator) dir_enum = NULL; - g_autoptr(GFile) child = NULL; - g_autoptr(GFileInfo) child_info = NULL; - - dir_enum = g_file_enumerate_children (d, OSTREE_GIO_FAST_QUERYINFO, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - cancellable, - error); - if (!dir_enum) - return FALSE; - - while ((child_info = g_file_enumerator_next_file (dir_enum, cancellable, &temp_error)) != NULL) - { - const char *name; - - name = g_file_info_get_name (child_info); - - g_clear_object (&child); - child = g_file_get_child (d, name); - - g_ptr_array_add (added, g_object_ref (child)); - - if (g_file_info_get_file_type (child_info) == G_FILE_TYPE_DIRECTORY) - { - if (!diff_add_dir_recurse (child, added, cancellable, error)) - return FALSE; - } - - g_clear_object (&child_info); - } - - if (temp_error != NULL) - { - g_propagate_error (error, temp_error); - return FALSE; - } - - return TRUE; -} - - -static gboolean -diff_dirs (OstreeRepoDevInoCache *devino_to_csum_cache, - GFile *a, - GFile *b, - GPtrArray *changed, - GCancellable *cancellable, - GError **error) -{ - GError *temp_error = NULL; - g_autoptr(GFileEnumerator) dir_enum = NULL; - g_autoptr(GFile) child_a = NULL; - g_autoptr(GFile) child_b = NULL; - g_autoptr(GFileInfo) child_a_info = NULL; - g_autoptr(GFileInfo) child_b_info = NULL; - - if (a == NULL) - { - if (!diff_add_dir_recurse (b, changed, cancellable, error)) - return FALSE; - - return TRUE; - } - - dir_enum = g_file_enumerate_children (a, OSTREE_GIO_FAST_QUERYINFO, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - cancellable, error); - if (!dir_enum) - return FALSE; - - while ((child_a_info = g_file_enumerator_next_file (dir_enum, cancellable, &temp_error)) != NULL) - { - const char *name; - GFileType child_a_type; - GFileType child_b_type; - - name = g_file_info_get_name (child_a_info); - - g_clear_object (&child_a); - child_a = g_file_get_child (a, name); - child_a_type = g_file_info_get_file_type (child_a_info); - - g_clear_object (&child_b); - child_b = g_file_get_child (b, name); - - g_clear_object (&child_b_info); - child_b_info = g_file_query_info (child_b, OSTREE_GIO_FAST_QUERYINFO, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - cancellable, - &temp_error); - if (!child_b_info) - { - if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) - { - g_clear_error (&temp_error); - /* Removed, ignore */ - } - else - { - g_propagate_error (error, temp_error); - return FALSE; - } - } - else - { - child_b_type = g_file_info_get_file_type (child_b_info); - if (child_a_type != child_b_type) - { - g_ptr_array_add (changed, g_object_ref (child_b)); - } - else - { - gboolean was_changed = FALSE; - - if (!diff_files (devino_to_csum_cache, - child_a, child_a_info, - child_b, child_b_info, - &was_changed, - cancellable, error)) - return FALSE; - - if (was_changed) - g_ptr_array_add (changed, g_object_ref (child_b)); - - if (child_a_type == G_FILE_TYPE_DIRECTORY) - { - if (!diff_dirs (devino_to_csum_cache, child_a, child_b, changed, - cancellable, error)) - return FALSE; - } - } - } - - g_clear_object (&child_a_info); - } - if (temp_error != NULL) - { - g_propagate_error (error, temp_error); - return FALSE; - } - - g_clear_object (&dir_enum); - dir_enum = g_file_enumerate_children (b, OSTREE_GIO_FAST_QUERYINFO, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - cancellable, error); - if (!dir_enum) - return FALSE; - - g_clear_object (&child_b_info); - while ((child_b_info = g_file_enumerator_next_file (dir_enum, cancellable, &temp_error)) != NULL) - { - const char *name; - - name = g_file_info_get_name (child_b_info); - - g_clear_object (&child_a); - child_a = g_file_get_child (a, name); - - g_clear_object (&child_b); - child_b = g_file_get_child (b, name); - - g_clear_object (&child_a_info); - child_a_info = g_file_query_info (child_a, OSTREE_GIO_FAST_QUERYINFO, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - cancellable, - &temp_error); - if (!child_a_info) - { - if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) - { - g_clear_error (&temp_error); - g_ptr_array_add (changed, g_object_ref (child_b)); - if (g_file_info_get_file_type (child_b_info) == G_FILE_TYPE_DIRECTORY) - { - if (!diff_add_dir_recurse (child_b, changed, cancellable, error)) - return FALSE; - } - } - else - { - g_propagate_error (error, temp_error); - return FALSE; - } - } - g_clear_object (&child_b_info); - } - if (temp_error != NULL) - { - g_propagate_error (error, temp_error); - return FALSE; - } - - return TRUE; -} - -gboolean -builder_cache_get_outstanding_changes (BuilderCache *self, - GPtrArray **changed_out, - GError **error) -{ - g_autoptr(GPtrArray) changed = g_ptr_array_new_with_free_func (g_object_unref); - g_autoptr(GPtrArray) changed_paths = g_ptr_array_new_with_free_func (g_free); - g_autoptr(GFile) last_root = NULL; - int i; - - if (self->last_parent && - !ostree_repo_read_commit (self->repo, self->last_parent, &last_root, NULL, NULL, error)) - return FALSE; - - if (!diff_dirs (self->devino_to_csum_cache, - last_root, - self->app_dir, - changed, - NULL, error)) - return FALSE; - - for (i = 0; i < changed->len; i++) - { - GFile *changed_file = g_ptr_array_index (changed, i); - char *path = g_file_get_relative_path (self->app_dir, changed_file); - g_ptr_array_add (changed_paths, path); - } - - if (changed_out) - *changed_out = g_steal_pointer (&changed_paths); - - return TRUE; -} - -static GPtrArray * -get_changes (BuilderCache *self, - GFile *from, - GFile *to, - GError **error) -{ - g_autoptr(GPtrArray) added = g_ptr_array_new_with_free_func (g_object_unref); - g_autoptr(GPtrArray) modified = g_ptr_array_new_with_free_func ((GDestroyNotify) ostree_diff_item_unref); - g_autoptr(GPtrArray) removed = g_ptr_array_new_with_free_func (g_object_unref); - g_autoptr(GPtrArray) changed_paths = g_ptr_array_new_with_free_func (g_free); - int i; - - if (!ostree_diff_dirs (OSTREE_DIFF_FLAGS_NONE, - from, - to, - modified, - removed, - added, - NULL, error)) - return NULL; - - for (i = 0; i < added->len; i++) - { - char *path = g_file_get_relative_path (to, g_ptr_array_index (added, i)); - g_ptr_array_add (changed_paths, path); - } - - for (i = 0; i < modified->len; i++) - { - OstreeDiffItem *modified_item = g_ptr_array_index (modified, i); - char *path = g_file_get_relative_path (to, modified_item->target); - g_ptr_array_add (changed_paths, path); - } - - return g_steal_pointer (&changed_paths); -} - - -GPtrArray * -builder_cache_get_all_changes (BuilderCache *self, - GError **error) -{ - g_autoptr(GFile) init_root = NULL; - g_autoptr(GFile) finish_root = NULL; - g_autofree char *init_commit = NULL; - g_autofree char *finish_commit = NULL; - g_autofree char *init_ref = get_ref (self, "init"); - g_autofree char *finish_ref = get_ref (self, "finish"); - - if (!ostree_repo_resolve_rev (self->repo, init_ref, FALSE, &init_commit, NULL)) - return FALSE; - - if (!ostree_repo_resolve_rev (self->repo, finish_ref, FALSE, &finish_commit, NULL)) - return FALSE; - - if (!ostree_repo_read_commit (self->repo, init_commit, &init_root, NULL, NULL, error)) - return NULL; - - if (!ostree_repo_read_commit (self->repo, finish_commit, &finish_root, NULL, NULL, error)) - return NULL; - - return get_changes (self, init_root, finish_root, error); -} - -GPtrArray * -builder_cache_get_changes (BuilderCache *self, - GError **error) -{ - g_autoptr(GFile) current_root = NULL; - g_autoptr(GFile) parent_root = NULL; - g_autoptr(GVariant) variant = NULL; - g_autofree char *parent_commit = NULL; - - if (!ostree_repo_read_commit (self->repo, self->last_parent, ¤t_root, NULL, NULL, error)) - return NULL; - - if (!ostree_repo_load_variant (self->repo, OSTREE_OBJECT_TYPE_COMMIT, self->last_parent, - &variant, NULL)) - return NULL; - - parent_commit = ostree_commit_get_parent (variant); - if (parent_commit != NULL) - { - if (!ostree_repo_read_commit (self->repo, parent_commit, &parent_root, NULL, NULL, error)) - return FALSE; - } - - return get_changes (self, parent_root, current_root, error); -} - -GPtrArray * -builder_cache_get_files (BuilderCache *self, - GError **error) -{ - g_autoptr(GFile) current_root = NULL; - - if (!ostree_repo_read_commit (self->repo, self->last_parent, ¤t_root, NULL, NULL, error)) - return NULL; - - return get_changes (self, NULL, current_root, error); -} - -void -builder_cache_disable_lookups (BuilderCache *self) -{ - self->disabled = TRUE; -} - -gboolean -builder_gc (BuilderCache *self, - GError **error) -{ - gint objects_total; - gint objects_pruned; - guint64 pruned_object_size_total; - GHashTableIter iter; - gpointer key, value; - - g_hash_table_iter_init (&iter, self->unused_stages); - while (g_hash_table_iter_next (&iter, &key, &value)) - { - const char *unused_stage = (const char *) key; - g_autofree char *unused_ref = get_ref (self, unused_stage); - - g_debug ("Removing unused ref %s", unused_ref); - - if (!ostree_repo_set_ref_immediate (self->repo, - NULL, - unused_ref, - NULL, - NULL, error)) - return FALSE; - } - - g_print ("Pruning cache\n"); - return ostree_repo_prune (self->repo, - OSTREE_REPO_PRUNE_FLAGS_REFS_ONLY, -1, - &objects_total, - &objects_pruned, - &pruned_object_size_total, - NULL, error); -} - -/* Only add to cache if non-empty. This means we can add - these things compatibly without invalidating the cache. - This is useful if empty means no change from what was - before */ -void -builder_cache_checksum_compat_str (BuilderCache *self, - const char *str) -{ - if (str) - builder_cache_checksum_str (self, str); -} - -void -builder_cache_checksum_str (BuilderCache *self, - const char *str) -{ - /* We include the terminating zero so that we make - * a difference between NULL and "". */ - - if (str) - g_checksum_update (self->checksum, (const guchar *) str, strlen (str) + 1); - else - /* Always add something so we can't be fooled by a sequence like - NULL, "a" turning into "a", NULL. */ - g_checksum_update (self->checksum, (const guchar *) "\1", 1); -} - -/* Only add to cache if non-empty. This means we can add - these things compatibly without invalidating the cache. - This is useful if empty means no change from what was - before */ -void -builder_cache_checksum_compat_strv (BuilderCache *self, - char **strv) -{ - if (strv != NULL && strv[0] != NULL) - builder_cache_checksum_strv (self, strv); -} - - -void -builder_cache_checksum_strv (BuilderCache *self, - char **strv) -{ - int i; - - if (strv) - { - g_checksum_update (self->checksum, (const guchar *) "\1", 1); - for (i = 0; strv[i] != NULL; i++) - builder_cache_checksum_str (self, strv[i]); - } - else - { - g_checksum_update (self->checksum, (const guchar *) "\2", 1); - } -} - -void -builder_cache_checksum_boolean (BuilderCache *self, - gboolean val) -{ - if (val) - g_checksum_update (self->checksum, (const guchar *) "\1", 1); - else - g_checksum_update (self->checksum, (const guchar *) "\0", 1); -} - -/* Only add to cache if true. This means we can add - these things compatibly without invalidating the cache. - This is useful if false means no change from what was - before */ -void -builder_cache_checksum_compat_boolean (BuilderCache *self, - gboolean val) -{ - if (val) - builder_cache_checksum_boolean (self, val); -} - -void -builder_cache_checksum_uint32 (BuilderCache *self, - guint32 val) -{ - guchar v[4]; - - v[0] = (val >> 0) & 0xff; - v[1] = (val >> 8) & 0xff; - v[2] = (val >> 16) & 0xff; - v[3] = (val >> 24) & 0xff; - g_checksum_update (self->checksum, v, 4); -} - -void -builder_cache_checksum_data (BuilderCache *self, - guint8 *data, - gsize len) -{ - g_checksum_update (self->checksum, data, len); -} diff --git a/builder/builder-cache.h b/builder/builder-cache.h deleted file mode 100644 index 5c4e54d7..00000000 --- a/builder/builder-cache.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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.1 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_CACHE_H__ -#define __BUILDER_CACHE_H__ - -#include -#include - -G_BEGIN_DECLS - -typedef struct BuilderCache BuilderCache; -typedef struct BuilderContext BuilderContext; - -#define BUILDER_TYPE_CACHE (builder_cache_get_type ()) -#define BUILDER_CACHE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUILDER_TYPE_CACHE, BuilderCache)) -#define BUILDER_IS_CACHE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUILDER_TYPE_CACHE)) - -GType builder_cache_get_type (void); - -BuilderCache *builder_cache_new (BuilderContext *context, - GFile *app_dir, - const char *branch); -void builder_cache_disable_lookups (BuilderCache *self); -gboolean builder_cache_open (BuilderCache *self, - GError **error); -GChecksum * builder_cache_get_checksum (BuilderCache *self); -gboolean builder_cache_lookup (BuilderCache *self, - const char *stage); -void builder_cache_ensure_checkout (BuilderCache *self); -gboolean builder_cache_has_checkout (BuilderCache *self); -gboolean builder_cache_commit (BuilderCache *self, - const char *body, - GError **error); -gboolean builder_cache_get_outstanding_changes (BuilderCache *self, - GPtrArray **changed_out, - GError **error); -GPtrArray *builder_cache_get_files (BuilderCache *self, - GError **error); -GPtrArray *builder_cache_get_changes (BuilderCache *self, - GError **error); -GPtrArray *builder_cache_get_all_changes (BuilderCache *self, - GError **error); -gboolean builder_gc (BuilderCache *self, - GError **error); - -void builder_cache_checksum_str (BuilderCache *self, - const char *str); -void builder_cache_checksum_compat_str (BuilderCache *self, - const char *str); -void builder_cache_checksum_strv (BuilderCache *self, - char **strv); -void builder_cache_checksum_compat_strv (BuilderCache *self, - char **strv); -void builder_cache_checksum_boolean (BuilderCache *self, - gboolean val); -void builder_cache_checksum_compat_boolean (BuilderCache *self, - gboolean val); -void builder_cache_checksum_uint32 (BuilderCache *self, - guint32 val); -void builder_cache_checksum_data (BuilderCache *self, - guint8 *data, - gsize len); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (BuilderCache, g_object_unref) - -G_END_DECLS - -#endif /* __BUILDER_CACHE_H__ */ diff --git a/builder/builder-context.c b/builder/builder-context.c deleted file mode 100644 index d7b29871..00000000 --- a/builder/builder-context.c +++ /dev/null @@ -1,904 +0,0 @@ -/* builder-context.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 -#include -#include -#include - -#include -#include "flatpak-utils.h" -#include "builder-context.h" -#include "builder-cache.h" -#include "builder-utils.h" - -struct BuilderContext -{ - GObject parent; - - GFile *app_dir; - GFile *run_dir; /* directory flatpak-builder was started from */ - GFile *base_dir; /* directory with json manifest, origin for source files */ - SoupSession *soup_session; - char *arch; - char *stop_at; - - GFile *download_dir; - GPtrArray *sources_dirs; - GPtrArray *sources_urls; - GFile *state_dir; - GFile *build_dir; - GFile *cache_dir; - GFile *checksums_dir; - GFile *ccache_dir; - GFile *rofiles_dir; - GFile *rofiles_allocated_dir; - GLnxLockFile rofiles_file_lock; - - BuilderOptions *options; - gboolean keep_build_dirs; - gboolean delete_build_dirs; - int jobs; - char **cleanup; - char **cleanup_platform; - gboolean use_ccache; - gboolean build_runtime; - gboolean build_extension; - gboolean separate_locales; - gboolean bundle_sources; - gboolean sandboxed; - gboolean rebuild_on_sdk_change; - gboolean use_rofiles; - gboolean have_rofiles; -}; - -typedef struct -{ - GObjectClass parent_class; -} BuilderContextClass; - -G_DEFINE_TYPE (BuilderContext, builder_context, G_TYPE_OBJECT); - -enum { - PROP_0, - PROP_APP_DIR, - PROP_RUN_DIR, - LAST_PROP -}; - - -static void -builder_context_finalize (GObject *object) -{ - BuilderContext *self = (BuilderContext *) object; - - g_clear_object (&self->state_dir); - g_clear_object (&self->download_dir); - g_clear_object (&self->build_dir); - g_clear_object (&self->cache_dir); - g_clear_object (&self->checksums_dir); - g_clear_object (&self->rofiles_dir); - g_clear_object (&self->ccache_dir); - g_clear_object (&self->app_dir); - g_clear_object (&self->run_dir); - g_clear_object (&self->base_dir); - g_clear_object (&self->soup_session); - g_clear_object (&self->options); - g_free (self->arch); - g_free (self->stop_at); - g_strfreev (self->cleanup); - g_strfreev (self->cleanup_platform); - glnx_release_lock_file(&self->rofiles_file_lock); - - g_clear_pointer (&self->sources_dirs, g_ptr_array_unref); - g_clear_pointer (&self->sources_urls, g_ptr_array_unref); - - G_OBJECT_CLASS (builder_context_parent_class)->finalize (object); -} - -static void -builder_context_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - BuilderContext *self = BUILDER_CONTEXT (object); - - switch (prop_id) - { - case PROP_RUN_DIR: - g_value_set_object (value, self->run_dir); - break; - - case PROP_APP_DIR: - g_value_set_object (value, self->app_dir); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -builder_context_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - BuilderContext *self = BUILDER_CONTEXT (object); - - switch (prop_id) - { - case PROP_RUN_DIR: - g_set_object (&self->run_dir, g_value_get_object (value)); - break; - - case PROP_APP_DIR: - g_set_object (&self->app_dir, g_value_get_object (value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -builder_context_constructed (GObject *object) -{ - BuilderContext *self = BUILDER_CONTEXT (object); - - self->state_dir = g_file_get_child (self->run_dir, ".flatpak-builder"); - self->download_dir = g_file_get_child (self->state_dir, "downloads"); - self->build_dir = g_file_get_child (self->state_dir, "build"); - self->cache_dir = g_file_get_child (self->state_dir, "cache"); - self->checksums_dir = g_file_get_child (self->state_dir, "checksums"); - self->ccache_dir = g_file_get_child (self->state_dir, "ccache"); -} - -static void -builder_context_class_init (BuilderContextClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->constructed = builder_context_constructed; - object_class->finalize = builder_context_finalize; - object_class->get_property = builder_context_get_property; - object_class->set_property = builder_context_set_property; - - g_object_class_install_property (object_class, - PROP_APP_DIR, - g_param_spec_object ("app-dir", - "", - "", - G_TYPE_FILE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (object_class, - PROP_RUN_DIR, - g_param_spec_object ("run-dir", - "", - "", - G_TYPE_FILE, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); -} - -static void -builder_context_init (BuilderContext *self) -{ - GLnxLockFile init = GLNX_LOCK_FILE_INIT; - g_autofree char *path = NULL; - - self->rofiles_file_lock = init; - path = g_find_program_in_path ("rofiles-fuse"); - self->have_rofiles = path != NULL; -} - -GFile * -builder_context_get_run_dir (BuilderContext *self) -{ - return self->run_dir; -} - -GFile * -builder_context_get_base_dir (BuilderContext *self) -{ - return self->base_dir; -} - -void -builder_context_set_base_dir (BuilderContext *self, - GFile *base_dir) -{ - g_set_object (&self->base_dir, base_dir); -} - -GFile * -builder_context_get_state_dir (BuilderContext *self) -{ - return self->state_dir; -} - -GFile * -builder_context_get_app_dir_raw (BuilderContext *self) -{ - return self->app_dir; -} - -GFile * -builder_context_get_app_dir (BuilderContext *self) -{ - if (self->rofiles_dir) - return self->rofiles_dir; - return self->app_dir; -} - -GFile * -builder_context_get_download_dir (BuilderContext *self) -{ - return self->download_dir; -} - -GPtrArray * -builder_context_get_sources_dirs (BuilderContext *self) -{ - return self->sources_dirs; -} - -void -builder_context_set_sources_dirs (BuilderContext *self, - GPtrArray *sources_dirs) -{ - g_clear_pointer (&self->sources_dirs, g_ptr_array_unref); - self->sources_dirs = g_ptr_array_ref (sources_dirs); -} - -GFile * -builder_context_find_in_sources_dirs_va (BuilderContext *self, - va_list args) -{ - int i; - - if (self->sources_dirs == NULL) - return NULL; - - for (i = 0; i < self->sources_dirs->len; i++) - { - GFile *dir = g_ptr_array_index (self->sources_dirs, i); - g_autoptr(GFile) local_file = NULL; - va_list args2; - - va_copy (args2, args); - local_file = flatpak_build_file_va (dir, args2); - va_end (args2); - - if (g_file_query_exists (local_file, NULL)) - return g_steal_pointer (&local_file); - } - - return NULL; -} - -GFile * -builder_context_find_in_sources_dirs (BuilderContext *self, - ...) -{ - GFile *res; - va_list args; - - va_start (args, self); - res = builder_context_find_in_sources_dirs_va (self, args); - va_end (args); - - return res; -} - -GPtrArray * -builder_context_get_sources_urls (BuilderContext *self) -{ - return self->sources_urls; -} - -void -builder_context_set_sources_urls (BuilderContext *self, - GPtrArray *sources_urls) -{ - g_clear_pointer (&self->sources_urls, g_ptr_array_unref); - self->sources_urls = g_ptr_array_ref (sources_urls); -} - -gboolean -builder_context_download_uri (BuilderContext *self, - const char *url, - GFile *dest, - char *sha256, - GError **error) -{ - int i; - g_autoptr(SoupURI) original_uri = soup_uri_new (url); - - if (original_uri == NULL) - return flatpak_fail (error, _("Could not parse URI “%s”"), url); - - g_print ("Downloading %s\n", url); - - if (self->sources_urls != NULL) - { - g_autofree char *base_name = g_path_get_basename (soup_uri_get_path (original_uri)); - g_autofree char *rel = g_build_filename ("downloads", sha256, base_name, NULL); - - for (i = 0; i < self->sources_urls->len; i++) - { - SoupURI *base_uri = g_ptr_array_index (self->sources_urls, i); - g_autoptr(SoupURI) mirror_uri = soup_uri_new_with_base (base_uri, rel); - g_autofree char *mirror_uri_str = soup_uri_to_string (mirror_uri, FALSE); - g_print ("Trying mirror %s\n", mirror_uri_str); - g_autoptr(GError) my_error = NULL; - - if (builder_download_uri (mirror_uri, - dest, - sha256, - builder_context_get_soup_session (self), - &my_error)) - return TRUE; - - if (!g_error_matches (my_error, SOUP_HTTP_ERROR, SOUP_STATUS_NOT_FOUND)) - g_warning ("Error downloading from mirror: %s\n", my_error->message); - } - } - - if (!builder_download_uri (original_uri, - dest, - sha256, - builder_context_get_soup_session (self), - error)) - return FALSE; - - return TRUE; -} - -GFile * -builder_context_get_cache_dir (BuilderContext *self) -{ - return self->cache_dir; -} - -GFile * -builder_context_get_build_dir (BuilderContext *self) -{ - return self->build_dir; -} - -char * -builder_context_get_checksum_for (BuilderContext *self, - const char *name) -{ - g_autoptr(GFile) checksum_file = g_file_get_child (self->checksums_dir, name); - g_autofree gchar *checksum = NULL; - - if (!g_file_get_contents (flatpak_file_get_path_cached (checksum_file), &checksum, NULL, NULL)) - return NULL; - - return g_steal_pointer (&checksum); -} - -void -builder_context_set_checksum_for (BuilderContext *self, - const char *name, - const char *checksum) -{ - g_autoptr(GFile) checksum_file = g_file_get_child (self->checksums_dir, name); - - if (!flatpak_mkdir_p (self->checksums_dir, - NULL, NULL)) - return; - - g_file_set_contents (flatpak_file_get_path_cached (checksum_file), checksum, -1, NULL); -} - -GFile * -builder_context_allocate_build_subdir (BuilderContext *self, - const char *name, - GError **error) -{ - g_autoptr(GError) my_error = NULL; - int count; - - if (!flatpak_mkdir_p (self->build_dir, - NULL, error)) - return NULL; - - for (count = 1; count < 1000; count++) - { - g_autofree char *buildname = NULL; - g_autoptr(GFile) subdir = NULL; - - buildname = g_strdup_printf ("%s-%d", name, count); - subdir = g_file_get_child (self->build_dir, buildname); - - if (g_file_make_directory (subdir, NULL, &my_error)) - return g_steal_pointer (&subdir); - else - { - if (!g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_EXISTS)) - { - g_propagate_error (error, g_steal_pointer (&my_error)); - return NULL; - } - g_clear_error (&my_error); - /* Already exists, try again */ - } - } - - flatpak_fail (error, "Unable to allocate build dir for %s\n", name); - return NULL; -} - -GFile * -builder_context_get_ccache_dir (BuilderContext *self) -{ - return self->ccache_dir; -} - -SoupSession * -builder_context_get_soup_session (BuilderContext *self) -{ - if (self->soup_session == NULL) - self->soup_session = flatpak_create_soup_session ("flatpak-builder " PACKAGE_VERSION); - - return self->soup_session; -} - -const char * -builder_context_get_arch (BuilderContext *self) -{ - if (self->arch == NULL) - self->arch = g_strdup (flatpak_get_arch ()); - - return (const char *) self->arch; -} - -void -builder_context_set_arch (BuilderContext *self, - const char *arch) -{ - g_free (self->arch); - self->arch = g_strdup (arch); -} - -const char * -builder_context_get_stop_at (BuilderContext *self) -{ - return self->stop_at; -} - -void -builder_context_set_stop_at (BuilderContext *self, - const char *module) -{ - g_free (self->stop_at); - self->stop_at = g_strdup (module); -} - -BuilderOptions * -builder_context_get_options (BuilderContext *self) -{ - return self->options; -} - -void -builder_context_set_options (BuilderContext *self, - BuilderOptions *option) -{ - g_set_object (&self->options, option); -} - -int -builder_context_get_jobs (BuilderContext *self) -{ - if (self->jobs == 0) - return (int) sysconf (_SC_NPROCESSORS_ONLN); - return self->jobs; -} - -void -builder_context_set_jobs (BuilderContext *self, - int jobs) -{ - self->jobs = jobs; -} - -void -builder_context_set_keep_build_dirs (BuilderContext *self, - gboolean keep_build_dirs) -{ - self->keep_build_dirs = keep_build_dirs; -} - -void -builder_context_set_delete_build_dirs (BuilderContext *self, - gboolean delete_build_dirs) -{ - self->delete_build_dirs = delete_build_dirs; -} - -void -builder_context_set_global_cleanup (BuilderContext *self, - const char **cleanup) -{ - g_strfreev (self->cleanup); - self->cleanup = g_strdupv ((char **) cleanup); -} - -const char ** -builder_context_get_global_cleanup (BuilderContext *self) -{ - return (const char **) self->cleanup; -} - -void -builder_context_set_global_cleanup_platform (BuilderContext *self, - const char **cleanup) -{ - g_strfreev (self->cleanup_platform); - self->cleanup_platform = g_strdupv ((char **) cleanup); -} - -const char ** -builder_context_get_global_cleanup_platform (BuilderContext *self) -{ - return (const char **) self->cleanup_platform; -} - -gboolean -builder_context_get_keep_build_dirs (BuilderContext *self) -{ - return self->keep_build_dirs; -} - -gboolean -builder_context_get_delete_build_dirs (BuilderContext *self) -{ - return self->delete_build_dirs; -} - -void -builder_context_set_sandboxed (BuilderContext *self, - gboolean sandboxed) -{ - self->sandboxed = sandboxed; -} - -gboolean -builder_context_get_sandboxed (BuilderContext *self) -{ - return self->sandboxed; -} - -gboolean -builder_context_get_build_runtime (BuilderContext *self) -{ - return self->build_runtime; -} - -void -builder_context_set_build_runtime (BuilderContext *self, - gboolean build_runtime) -{ - self->build_runtime = !!build_runtime; -} - -gboolean -builder_context_get_build_extension (BuilderContext *self) -{ - return self->build_extension; -} - -void -builder_context_set_build_extension (BuilderContext *self, - gboolean build_extension) -{ - self->build_extension = !!build_extension; -} - -gboolean -builder_context_get_separate_locales (BuilderContext *self) -{ - return self->separate_locales; -} - -void -builder_context_set_separate_locales (BuilderContext *self, - gboolean separate_locales) -{ - self->separate_locales = !!separate_locales; -} - -gboolean -builder_context_get_bundle_sources (BuilderContext *self) -{ - return self->bundle_sources; -} - -void -builder_context_set_bundle_sources (BuilderContext *self, - gboolean bundle_sources) -{ - self->bundle_sources = !!bundle_sources; -} - -static char *rofiles_unmount_path = NULL; - -static void -rofiles_umount_handler (int signum) -{ - char *argv[] = { "fusermount", "-u", NULL, - NULL }; - - argv[2] = rofiles_unmount_path; - g_debug ("unmounting rofiles-fuse %s", rofiles_unmount_path); - g_spawn_sync (NULL, (char **)argv, NULL, - G_SPAWN_SEARCH_PATH | G_SPAWN_CLOEXEC_PIPES | G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, - NULL, NULL, NULL, NULL, NULL, NULL); - exit (0); -} - -static void -rofiles_child_setup (gpointer user_data) -{ - struct rlimit limit; - - /* I had issues with rofiles-fuse running into EMFILE, so - lets push it as far up as we can */ - - if (getrlimit (RLIMIT_NOFILE, &limit) == 0 && - limit.rlim_max != limit.rlim_cur) - { - limit.rlim_cur = limit.rlim_max; - setrlimit (RLIMIT_NOFILE, &limit); - } -} - -gboolean -builder_context_enable_rofiles (BuilderContext *self, - GError **error) -{ - g_autoptr(GFile) rofiles_base = NULL; - g_autoptr(GFile) rofiles_dir = NULL; - g_autofree char *tmpdir_name = NULL; - char *argv[] = { "rofiles-fuse", - "-o", - "kernel_cache,entry_timeout=60,attr_timeout=60,splice_write,splice_move", - (char *)flatpak_file_get_path_cached (self->app_dir), - NULL, - NULL }; - gint exit_status; - pid_t child; - - if (!self->use_rofiles) - return TRUE; - - if (!self->have_rofiles) - { - g_warning ("rofiles-fuse not available, doing without"); - return TRUE; - } - - g_assert (self->rofiles_dir == NULL); - - if (self->rofiles_allocated_dir == NULL) - { - rofiles_base = g_file_get_child (self->state_dir, "rofiles"); - if (g_mkdir_with_parents (flatpak_file_get_path_cached (rofiles_base), 0755) != 0) - { - glnx_set_error_from_errno (error); - return FALSE; - } - - if (!flatpak_allocate_tmpdir (AT_FDCWD, - flatpak_file_get_path_cached (rofiles_base), - "rofiles-", - &tmpdir_name, NULL, - &self->rofiles_file_lock, - NULL, NULL, error)) - return FALSE; - - self->rofiles_allocated_dir = g_file_get_child (rofiles_base, tmpdir_name); - - /* Make sure we unmount the fuse fs if flatpak-builder dies unexpectedly */ - rofiles_unmount_path = (char *)flatpak_file_get_path_cached (self->rofiles_allocated_dir); - child = fork (); - if (child == -1) - { - glnx_set_error_from_errno (error); - return FALSE; - } - - if (child == 0) - { - /* In child */ - struct sigaction new_action; - - prctl (PR_SET_PDEATHSIG, SIGHUP); - - new_action.sa_handler = rofiles_umount_handler; - sigemptyset (&new_action.sa_mask); - new_action.sa_flags = 0; - sigaction (SIGHUP, &new_action, NULL); - - sigset (SIGINT, SIG_IGN); - sigset (SIGPIPE, SIG_IGN); - sigset (SIGSTOP, SIG_IGN); - - while (TRUE) - pause (); - - exit (0); - } - } - - rofiles_dir = g_object_ref (self->rofiles_allocated_dir); - argv[4] = (char *)flatpak_file_get_path_cached (rofiles_dir); - - g_debug ("starting: rofiles-fuse %s %s", argv[3], argv[4]); - if (!g_spawn_sync (NULL, (char **)argv, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_CLOEXEC_PIPES, rofiles_child_setup, NULL, NULL, NULL, &exit_status, error)) - { - g_prefix_error (error, "Can't spawn rofiles-fuse"); - return FALSE; - } - else if (exit_status != 0) - { - return flatpak_fail (error, "Failure spawning rofiles-fuse, exit_status: %d", exit_status); - } - - - self->rofiles_dir = g_steal_pointer (&rofiles_dir); - - return TRUE; -} - -gboolean -builder_context_disable_rofiles (BuilderContext *self, - GError **error) -{ - char *argv[] = { "fusermount", "-u", NULL, - NULL }; - - if (!self->use_rofiles) - return TRUE; - - if (!self->have_rofiles) - return TRUE; - - g_assert (self->rofiles_dir != NULL); - - argv[2] = (char *)flatpak_file_get_path_cached (self->rofiles_dir); - - g_debug ("unmounting rofiles-fuse %s", rofiles_unmount_path); - g_spawn_sync (NULL, (char **)argv, NULL, - G_SPAWN_SEARCH_PATH | G_SPAWN_CLOEXEC_PIPES, - NULL, NULL, NULL, NULL, NULL, NULL); - - g_clear_object (&self->rofiles_dir); - - return TRUE; -} - -gboolean -builder_context_get_rofiles_active (BuilderContext *self) -{ - return self->rofiles_dir != NULL; -} - -gboolean -builder_context_get_use_rofiles (BuilderContext *self) -{ - return self->use_rofiles; -} - -void -builder_context_set_use_rofiles (BuilderContext *self, - gboolean use_rofiles) -{ - self->use_rofiles = use_rofiles; -} - -gboolean -builder_context_get_rebuild_on_sdk_change (BuilderContext *self) -{ - return self->rebuild_on_sdk_change; -} - -void -builder_context_set_rebuild_on_sdk_change (BuilderContext *self, - gboolean rebuild_on_sdk_change) -{ - self->rebuild_on_sdk_change = !!rebuild_on_sdk_change; -} - -gboolean -builder_context_enable_ccache (BuilderContext *self, - GError **error) -{ - g_autofree char *ccache_path = g_file_get_path (self->ccache_dir); - g_autofree char *ccache_bin_path = g_build_filename (ccache_path, "bin", NULL); - int i; - static const char *compilers[] = { - "cc", - "c++", - "gcc", - "g++" - }; - - if (g_mkdir_with_parents (ccache_bin_path, 0755) != 0) - { - glnx_set_error_from_errno (error); - return FALSE; - } - - for (i = 0; i < G_N_ELEMENTS (compilers); i++) - { - const char *symlink_path = g_build_filename (ccache_bin_path, compilers[i], NULL); - if (symlink ("/usr/bin/ccache", symlink_path) && errno != EEXIST) - { - glnx_set_error_from_errno (error); - return FALSE; - } - } - - self->use_ccache = TRUE; - - return TRUE; -} - -char ** -builder_context_extend_env (BuilderContext *self, - char **envp) -{ - if (self->use_ccache) - { - const char *old_path = g_environ_getenv (envp, "PATH"); - g_autofree char *new_path = NULL; - if (old_path == NULL) - old_path = "/app/bin:/usr/bin"; /* This is the flatpak default PATH */ - - new_path = g_strdup_printf ("/run/ccache/bin:%s", old_path); - envp = g_environ_setenv (envp, "PATH", new_path, TRUE); - envp = g_environ_setenv (envp, "CCACHE_DIR", "/run/ccache", TRUE); - } - - return envp; -} - -BuilderContext * -builder_context_new (GFile *run_dir, - GFile *app_dir) -{ - return g_object_new (BUILDER_TYPE_CONTEXT, - "run-dir", run_dir, - "app-dir", app_dir, - NULL); -} diff --git a/builder/builder-context.h b/builder/builder-context.h deleted file mode 100644 index 52a910e8..00000000 --- a/builder/builder-context.h +++ /dev/null @@ -1,135 +0,0 @@ -/* - * 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.1 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_CONTEXT_H__ -#define __BUILDER_CONTEXT_H__ - -#include -#include -#include "builder-options.h" - -G_BEGIN_DECLS - -/* BuilderContext defined in builder-cache.h to fix include loop */ - -#define BUILDER_TYPE_CONTEXT (builder_context_get_type ()) -#define BUILDER_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUILDER_TYPE_CONTEXT, BuilderContext)) -#define BUILDER_IS_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUILDER_TYPE_CONTEXT)) - -GType builder_context_get_type (void); - -GFile * builder_context_get_app_dir (BuilderContext *self); -GFile * builder_context_get_app_dir_raw (BuilderContext *self); -GFile * builder_context_get_run_dir (BuilderContext *self); -GFile * builder_context_get_base_dir (BuilderContext *self); -void builder_context_set_base_dir (BuilderContext *self, - GFile *base_dir); -GFile * builder_context_get_state_dir (BuilderContext *self); -GFile * builder_context_get_cache_dir (BuilderContext *self); -GFile * builder_context_get_build_dir (BuilderContext *self); -GFile * builder_context_allocate_build_subdir (BuilderContext *self, - const char *name, - GError **error); -GFile * builder_context_get_ccache_dir (BuilderContext *self); -GFile * builder_context_get_download_dir (BuilderContext *self); -GPtrArray * builder_context_get_sources_dirs (BuilderContext *self); -void builder_context_set_sources_dirs (BuilderContext *self, - GPtrArray *sources_dirs); -GFile * builder_context_find_in_sources_dirs (BuilderContext *self, - ...) G_GNUC_NULL_TERMINATED; -GFile * builder_context_find_in_sources_dirs_va (BuilderContext *self, - va_list args); -GPtrArray * builder_context_get_sources_urls (BuilderContext *self); -void builder_context_set_sources_urls (BuilderContext *self, - GPtrArray *sources_urls); -gboolean builder_context_download_uri (BuilderContext *self, - const char *url, - GFile *dest, - char *sha256, - GError **error); -SoupSession * builder_context_get_soup_session (BuilderContext *self); -const char * builder_context_get_arch (BuilderContext *self); -void builder_context_set_arch (BuilderContext *self, - const char *arch); -const char * builder_context_get_stop_at (BuilderContext *self); -void builder_context_set_stop_at (BuilderContext *self, - const char *module); -int builder_context_get_jobs (BuilderContext *self); -void builder_context_set_jobs (BuilderContext *self, - int n_jobs); -void builder_context_set_keep_build_dirs (BuilderContext *self, - gboolean keep_build_dirs); -gboolean builder_context_get_delete_build_dirs (BuilderContext *self); -void builder_context_set_delete_build_dirs (BuilderContext *self, - gboolean delete_build_dirs); -gboolean builder_context_get_keep_build_dirs (BuilderContext *self); -void builder_context_set_sandboxed (BuilderContext *self, - gboolean sandboxed); -gboolean builder_context_get_sandboxed (BuilderContext *self); -void builder_context_set_global_cleanup (BuilderContext *self, - const char **cleanup); -const char ** builder_context_get_global_cleanup (BuilderContext *self); -void builder_context_set_global_cleanup_platform (BuilderContext *self, - const char **cleanup); -const char ** builder_context_get_global_cleanup_platform (BuilderContext *self); -BuilderOptions *builder_context_get_options (BuilderContext *self); -void builder_context_set_options (BuilderContext *self, - BuilderOptions *option); -gboolean builder_context_get_build_runtime (BuilderContext *self); -void builder_context_set_build_runtime (BuilderContext *self, - gboolean build_runtime); -gboolean builder_context_get_build_extension (BuilderContext *self); -void builder_context_set_build_extension (BuilderContext *self, - gboolean build_extension); -gboolean builder_context_get_separate_locales (BuilderContext *self); -void builder_context_set_separate_locales (BuilderContext *self, - gboolean separate_locales); -void builder_context_set_bundle_sources (BuilderContext *self, - gboolean bundle_sources); -gboolean builder_context_get_bundle_sources (BuilderContext *self); -gboolean builder_context_get_rebuild_on_sdk_change (BuilderContext *self); -void builder_context_set_rebuild_on_sdk_change (BuilderContext *self, - gboolean rebuild_on_sdk_change); -char * builder_context_get_checksum_for (BuilderContext *self, - const char *name); -void builder_context_set_checksum_for (BuilderContext *self, - const char *name, - const char *checksum); - -BuilderContext *builder_context_new (GFile *run_dir, - GFile *app_dir); -gboolean builder_context_enable_ccache (BuilderContext *self, - GError **error); -gboolean builder_context_enable_rofiles (BuilderContext *self, - GError **error); -gboolean builder_context_disable_rofiles (BuilderContext *self, - GError **error); -gboolean builder_context_get_rofiles_active (BuilderContext *self); -gboolean builder_context_get_use_rofiles (BuilderContext *self); -void builder_context_set_use_rofiles (BuilderContext *self, - gboolean use_rofiles); -char ** builder_context_extend_env (BuilderContext *self, - char **envp); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (BuilderContext, g_object_unref) - -G_END_DECLS - -#endif /* __BUILDER_CONTEXT_H__ */ diff --git a/builder/builder-extension.c b/builder/builder-extension.c deleted file mode 100644 index 208f3f5f..00000000 --- a/builder/builder-extension.c +++ /dev/null @@ -1,425 +0,0 @@ -/* builder-extension.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 -#include -#include "libglnx/libglnx.h" - -#include "flatpak-utils.h" -#include "flatpak-run.h" -#include "builder-utils.h" -#include "builder-extension.h" - -struct BuilderExtension -{ - GObject parent; - - char *name; - char *directory; - gboolean bundle; - gboolean autodelete; - gboolean no_autodownload; - gboolean subdirectories; - char *add_ld_path; - char *download_if; - char *enable_if; - char *merge_dirs; - char *subdirectory_suffix; - char *version; - char *versions; -}; - -typedef struct -{ - GObjectClass parent_class; -} BuilderExtensionClass; - -G_DEFINE_TYPE (BuilderExtension, builder_extension, G_TYPE_OBJECT); - -enum { - PROP_0, - PROP_DIRECTORY, - PROP_BUNDLE, - PROP_AUTODELETE, - PROP_ADD_LD_PATH, - PROP_DOWNLOAD_IF, - PROP_ENABLE_IF, - PROP_MERGE_DIRS, - PROP_NO_AUTODOWNLOAD, - PROP_SUBDIRECTORIES, - PROP_SUBDIRECTORY_SUFFIX, - PROP_VERSION, - PROP_VERSIONS, - LAST_PROP -}; - -static void -builder_extension_finalize (GObject *object) -{ - BuilderExtension *self = (BuilderExtension *) object; - - g_free (self->name); - g_free (self->directory); - g_free (self->add_ld_path); - g_free (self->download_if); - g_free (self->enable_if); - g_free (self->merge_dirs); - g_free (self->subdirectory_suffix); - g_free (self->version); - g_free (self->versions); - - G_OBJECT_CLASS (builder_extension_parent_class)->finalize (object); -} - -static void -builder_extension_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - BuilderExtension *self = BUILDER_EXTENSION (object); - - switch (prop_id) - { - case PROP_DIRECTORY: - g_value_set_string (value, self->directory); - break; - - case PROP_BUNDLE: - g_value_set_boolean (value, self->bundle); - break; - - case PROP_AUTODELETE: - g_value_set_boolean (value, self->autodelete); - break; - - case PROP_NO_AUTODOWNLOAD: - g_value_set_boolean (value, self->autodelete); - break; - - case PROP_SUBDIRECTORIES: - g_value_set_boolean (value, self->autodelete); - break; - - case PROP_ADD_LD_PATH: - g_value_set_string (value, self->add_ld_path); - break; - - case PROP_DOWNLOAD_IF: - g_value_set_string (value, self->download_if); - break; - - case PROP_ENABLE_IF: - g_value_set_string (value, self->enable_if); - break; - - case PROP_MERGE_DIRS: - g_value_set_string (value, self->merge_dirs); - break; - - case PROP_SUBDIRECTORY_SUFFIX: - g_value_set_string (value, self->subdirectory_suffix); - break; - - case PROP_VERSION: - g_value_set_string (value, self->version); - break; - - case PROP_VERSIONS: - g_value_set_string (value, self->versions); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -builder_extension_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - BuilderExtension *self = BUILDER_EXTENSION (object); - - switch (prop_id) - { - case PROP_DIRECTORY: - g_clear_pointer (&self->directory, g_free); - self->directory = g_value_dup_string (value); - break; - - case PROP_BUNDLE: - self->bundle = g_value_get_boolean (value); - break; - - case PROP_AUTODELETE: - self->autodelete = g_value_get_boolean (value); - break; - - case PROP_NO_AUTODOWNLOAD: - self->no_autodownload = g_value_get_boolean (value); - break; - - case PROP_SUBDIRECTORIES: - self->subdirectories = g_value_get_boolean (value); - break; - - case PROP_ADD_LD_PATH: - g_clear_pointer (&self->add_ld_path, g_free); - self->add_ld_path = g_value_dup_string (value); - break; - - case PROP_DOWNLOAD_IF: - g_clear_pointer (&self->download_if, g_free); - self->download_if = g_value_dup_string (value); - break; - - case PROP_ENABLE_IF: - g_clear_pointer (&self->enable_if, g_free); - self->enable_if = g_value_dup_string (value); - break; - - case PROP_MERGE_DIRS: - g_clear_pointer (&self->merge_dirs, g_free); - self->merge_dirs = g_value_dup_string (value); - break; - - case PROP_SUBDIRECTORY_SUFFIX: - g_clear_pointer (&self->subdirectory_suffix, g_free); - self->subdirectory_suffix = g_value_dup_string (value); - break; - - case PROP_VERSION: - g_clear_pointer (&self->version, g_free); - self->version = g_value_dup_string (value); - break; - - case PROP_VERSIONS: - g_clear_pointer (&self->versions, g_free); - self->versions = g_value_dup_string (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -builder_extension_class_init (BuilderExtensionClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = builder_extension_finalize; - object_class->get_property = builder_extension_get_property; - object_class->set_property = builder_extension_set_property; - - g_object_class_install_property (object_class, - PROP_DIRECTORY, - g_param_spec_string ("directory", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_BUNDLE, - g_param_spec_boolean ("bundle", - "", - "", - FALSE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_AUTODELETE, - g_param_spec_boolean ("autodelete", - "", - "", - FALSE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_NO_AUTODOWNLOAD, - g_param_spec_boolean ("no-autodownload", - "", - "", - FALSE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_SUBDIRECTORIES, - g_param_spec_boolean ("subdirectories", - "", - "", - FALSE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_ADD_LD_PATH, - g_param_spec_string ("add-ld-path", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_DOWNLOAD_IF, - g_param_spec_string ("download-if", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_ENABLE_IF, - g_param_spec_string ("enable-if", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_MERGE_DIRS, - g_param_spec_string ("merge-dirs", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_SUBDIRECTORY_SUFFIX, - g_param_spec_string ("subdirectory-suffix", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_VERSION, - g_param_spec_string ("version", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_VERSIONS, - g_param_spec_string ("versions", - "", - "", - NULL, - G_PARAM_READWRITE)); -} - -static void -builder_extension_init (BuilderExtension *self) -{ -} - -void -builder_extension_set_name (BuilderExtension *self, - const char *name) -{ - g_free (self->name); - self->name = g_strdup (name); -} - -const char * -builder_extension_get_name (BuilderExtension *self) -{ - return self->name; -} - - -gboolean -builder_extension_is_bundled (BuilderExtension *self) -{ - return self->bundle; -} - -const char * -builder_extension_get_directory (BuilderExtension *self) -{ - return self->directory; -} - -static void -add_arg (BuilderExtension *self, - GPtrArray *args, - const char *key, - const char *value) -{ - if (value == NULL) - return; - g_ptr_array_add (args, - g_strdup_printf ("--extension=%s=%s=%s", self->name, key, value)); -} - -static void -add_argb (BuilderExtension *self, - GPtrArray *args, - const char *key, - gboolean val) -{ - if (val) - add_arg (self, args, key, "true"); -} - -void -builder_extension_add_finish_args (BuilderExtension *self, - GPtrArray *args) -{ - if (self->directory == NULL) - { - g_warning ("No directory specified for extension '%s'", self->name); - return; - } - - add_arg (self, args, FLATPAK_METADATA_KEY_DIRECTORY, self->directory); - add_argb (self, args, FLATPAK_METADATA_KEY_AUTODELETE, self->autodelete); - add_argb (self, args, FLATPAK_METADATA_KEY_NO_AUTODOWNLOAD, self->no_autodownload); - add_argb (self, args, FLATPAK_METADATA_KEY_SUBDIRECTORIES, self->subdirectories); - add_arg (self, args, FLATPAK_METADATA_KEY_ADD_LD_PATH, self->add_ld_path); - add_arg (self, args, FLATPAK_METADATA_KEY_DOWNLOAD_IF, self->download_if); - add_arg (self, args, FLATPAK_METADATA_KEY_ENABLE_IF, self->enable_if); - add_arg (self, args, FLATPAK_METADATA_KEY_MERGE_DIRS, self->merge_dirs); - add_arg (self, args, FLATPAK_METADATA_KEY_SUBDIRECTORY_SUFFIX, self->subdirectory_suffix); - add_arg (self, args, FLATPAK_METADATA_KEY_VERSION, self->version); - add_arg (self, args, FLATPAK_METADATA_KEY_VERSIONS, self->versions); -} - -void -builder_extension_checksum (BuilderExtension *self, - BuilderCache *cache, - BuilderContext *context) -{ - builder_cache_checksum_str (cache, BUILDER_EXTENSION_CHECKSUM_VERSION); - builder_cache_checksum_str (cache, self->name); - builder_cache_checksum_str (cache, self->directory); - builder_cache_checksum_boolean (cache, self->bundle); - builder_cache_checksum_boolean (cache, self->autodelete); - builder_cache_checksum_boolean (cache, self->no_autodownload); - builder_cache_checksum_boolean (cache, self->subdirectories); - builder_cache_checksum_str (cache, self->add_ld_path); - builder_cache_checksum_str (cache, self->download_if); - builder_cache_checksum_str (cache, self->enable_if); - builder_cache_checksum_str (cache, self->merge_dirs); - builder_cache_checksum_str (cache, self->subdirectory_suffix); - builder_cache_checksum_str (cache, self->version); - builder_cache_checksum_str (cache, self->versions); -} diff --git a/builder/builder-extension.h b/builder/builder-extension.h deleted file mode 100644 index 9c318ed3..00000000 --- a/builder/builder-extension.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright © 2017 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.1 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_EXTENSION_H__ -#define __BUILDER_EXTENSION_H__ - -#include - -#include "builder-context.h" -#include "builder-cache.h" - -G_BEGIN_DECLS - -typedef struct BuilderExtension BuilderExtension; - -#define BUILDER_TYPE_EXTENSION (builder_extension_get_type ()) -#define BUILDER_EXTENSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUILDER_TYPE_EXTENSION, BuilderExtension)) -#define BUILDER_IS_EXTENSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUILDER_TYPE_EXTENSION)) - -/* Bump this if format changes in incompatible ways to force rebuild */ -#define BUILDER_EXTENSION_CHECKSUM_VERSION "1" - -GType builder_extension_get_type (void); - -void builder_extension_set_name (BuilderExtension *self, - const char *name); -const char * builder_extension_get_name (BuilderExtension *self); - -gboolean builder_extension_is_bundled (BuilderExtension *self); -const char * builder_extension_get_directory (BuilderExtension *self); - -void builder_extension_add_finish_args (BuilderExtension *self, - GPtrArray *args); -void builder_extension_checksum (BuilderExtension *self, - BuilderCache *cache, - BuilderContext *context); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (BuilderExtension, g_object_unref) - -G_END_DECLS - -#endif /* __BUILDER_EXTENSION_H__ */ diff --git a/builder/builder-git.c b/builder/builder-git.c deleted file mode 100644 index 049d5cc6..00000000 --- a/builder/builder-git.c +++ /dev/null @@ -1,517 +0,0 @@ -/* builder-git.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-git.h" -#include "builder-utils.h" -#include "flatpak-utils.h" - -static gboolean -git (GFile *dir, - char **output, - GError **error, - ...) -{ - gboolean res; - va_list ap; - - va_start (ap, error); - res = flatpak_spawn (dir, output, error, "git", ap); - va_end (ap); - - return res; -} - -static GFile * -git_get_mirror_dir (const char *url_or_path, - BuilderContext *context) -{ - g_autoptr(GFile) git_dir = NULL; - g_autofree char *filename = NULL; - g_autofree char *git_dir_path = NULL; - - git_dir = g_file_get_child (builder_context_get_state_dir (context), - "git"); - - git_dir_path = g_file_get_path (git_dir); - g_mkdir_with_parents (git_dir_path, 0755); - - /* Technically a path isn't a uri but if it's absolute it should still be unique. */ - filename = builder_uri_to_filename (url_or_path); - return g_file_get_child (git_dir, filename); -} - -static char * -git_get_current_commit (GFile *repo_dir, - const char *branch, - gboolean ensure_commit, - BuilderContext *context, - GError **error) -{ - char *output = NULL; - g_autofree char *arg = NULL; - - if (ensure_commit) - arg = g_strconcat (branch, "^{commit}", NULL); - else - arg = g_strdup (branch); - - if (!git (repo_dir, &output, error, - "rev-parse", arg, NULL)) - return NULL; - - /* Trim trailing whitespace */ - g_strchomp (output); - - return output; -} - -char * -builder_git_get_current_commit (const char *repo_location, - const char *branch, - gboolean ensure_commit, - BuilderContext *context, - GError **error) -{ - g_autoptr(GFile) mirror_dir = NULL; - - mirror_dir = git_get_mirror_dir (repo_location, context); - return git_get_current_commit (mirror_dir, branch, ensure_commit, context, error); -} - -static char * -make_absolute (const char *orig_parent, const char *orig_relpath, GError **error) -{ - g_autofree char *parent = g_strdup (orig_parent); - const char *relpath = orig_relpath; - char *start; - char *parent_path; - - if (!g_str_has_prefix (relpath, "../")) - return g_strdup (orig_relpath); - - if (parent[strlen (parent) - 1] == '/') - parent[strlen (parent) - 1] = 0; - - if ((start = strstr (parent, "://"))) - start = start + 3; - else - start = parent; - - parent_path = strchr (start, '/'); - if (parent_path == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Invalid uri or path %s", orig_parent); - return NULL; - } - - while (g_str_has_prefix (relpath, "../")) - { - char *last_slash = strrchr (parent_path, '/'); - if (last_slash == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Invalid relative path %s for uri or path %s", orig_relpath, orig_parent); - return NULL; - } - relpath += 3; - *last_slash = 0; - } - - return g_strconcat (parent, "/", relpath, NULL); -} - -static gboolean -git_mirror_submodules (const char *repo_location, - const char *destination_path, - gboolean update, - GFile *mirror_dir, - gboolean disable_fsck, - const char *revision, - BuilderContext *context, - GError **error) -{ - g_autoptr(GKeyFile) key_file = g_key_file_new (); - g_autofree gchar *rev_parse_output = NULL; - g_autofree gchar *submodule_data = NULL; - g_autofree gchar **submodules = NULL; - g_autofree gchar *gitmodules = g_strconcat (revision, ":.gitmodules", NULL); - gsize num_submodules; - - if (!git (mirror_dir, &rev_parse_output, NULL, "rev-parse", "--verify", "--quiet", gitmodules, NULL)) - return TRUE; - - if (git (mirror_dir, &submodule_data, NULL, "show", gitmodules, NULL)) - { - if (!g_key_file_load_from_data (key_file, submodule_data, -1, - G_KEY_FILE_NONE, error)) - return FALSE; - - submodules = g_key_file_get_groups (key_file, &num_submodules); - - int i; - for (i = 0; i < num_submodules; i++) - { - g_autofree gchar *submodule = NULL; - g_autofree gchar *path = NULL; - g_autofree gchar *relative_url = NULL; - g_autofree gchar *absolute_url = NULL; - g_autofree gchar *ls_tree = NULL; - g_auto(GStrv) lines = NULL; - g_auto(GStrv) words = NULL; - - submodule = submodules[i]; - - if (!g_str_has_prefix (submodule, "submodule \"")) - continue; - - path = g_key_file_get_string (key_file, submodule, "path", error); - if (path == NULL) - return FALSE; - - relative_url = g_key_file_get_string (key_file, submodule, "url", error); - /* Remove any trailing whitespace */ - g_strchomp (relative_url); - absolute_url = make_absolute (repo_location, relative_url, error); - if (absolute_url == NULL) - return FALSE; - - if (!git (mirror_dir, &ls_tree, error, "ls-tree", revision, path, NULL)) - return FALSE; - - lines = g_strsplit (g_strstrip (ls_tree), "\n", 0); - if (g_strv_length (lines) != 1) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Not a gitlink tree: %s", path); - return FALSE; - } - - words = g_strsplit_set (lines[0], " \t", 4); - - if (g_strcmp0 (words[0], "160000") != 0) - continue; - - if (!builder_git_mirror_repo (absolute_url, destination_path, update, TRUE, disable_fsck, words[2], context, error)) - return FALSE; - } - } - - return TRUE; -} - -gboolean -builder_git_mirror_repo (const char *repo_location, - const char *destination_path, - gboolean update, - gboolean mirror_submodules, - gboolean disable_fsck, - const char *ref, - BuilderContext *context, - GError **error) -{ - g_autoptr(GFile) cache_mirror_dir = NULL; - g_autoptr(GFile) mirror_dir = NULL; - g_autofree char *current_commit = NULL; - - cache_mirror_dir = git_get_mirror_dir (repo_location, context); - - if (destination_path != NULL) - { - g_autofree char *file_name = g_file_get_basename (cache_mirror_dir); - g_autofree char *destination_file_path = g_build_filename (destination_path, - file_name, - NULL); - mirror_dir = g_file_new_for_path (destination_file_path); - } - else - mirror_dir = g_object_ref (cache_mirror_dir); - - if (!g_file_query_exists (mirror_dir, NULL)) - { - g_autofree char *filename = g_file_get_basename (mirror_dir); - g_autoptr(GFile) parent = g_file_get_parent (mirror_dir); - g_autofree char *mirror_path = g_file_get_path (mirror_dir); - g_autofree char *path_tmp = g_strconcat (mirror_path, ".clone_XXXXXX", NULL); - g_autofree char *filename_tmp = NULL; - g_autoptr(GFile) mirror_dir_tmp = NULL; - g_autoptr(GFile) cached_git_dir = NULL; - gboolean res; - g_autoptr(GPtrArray) args = g_ptr_array_new (); - - if (g_mkdtemp_full (path_tmp, 0755) == NULL) - return flatpak_fail (error, "Can't create temporary directory"); - - mirror_dir_tmp = g_file_new_for_path (path_tmp); - filename_tmp = g_file_get_basename (mirror_dir_tmp); - - g_ptr_array_add (args, "git"); - g_ptr_array_add (args, "clone"); - - if (!disable_fsck) - { - g_ptr_array_add (args, "-c"); - g_ptr_array_add (args, "transfer.fsckObjects=1"); - } - - g_ptr_array_add (args, "--mirror"); - - /* If we're doing a regular download, look for cache sources */ - if (destination_path == NULL) - cached_git_dir = builder_context_find_in_sources_dirs (context, "git", filename, NULL); - else - cached_git_dir = g_object_ref (cache_mirror_dir); - - g_print ("Cloning git repo %s\n", repo_location); - - if (cached_git_dir && update) - { - g_ptr_array_add (args, "--reference"); - g_ptr_array_add (args, (char *)flatpak_file_get_path_cached (cached_git_dir)); - } - - /* Non-updating use of caches we just pull from the cache to avoid network i/o */ - if (cached_git_dir && !update) - g_ptr_array_add (args, (char *)flatpak_file_get_path_cached (cached_git_dir)); - else - g_ptr_array_add (args, (char *)repo_location); - - g_ptr_array_add (args, filename_tmp); - g_ptr_array_add (args, NULL); - - res = flatpak_spawnv (parent, NULL, 0, error, - (const gchar * const *) args->pdata); - - if (cached_git_dir && !update && - !git (mirror_dir_tmp, NULL, error, - "config", "--local", "remote.origin.url", - repo_location, NULL)) - return FALSE; - - /* Ensure we copy the files from the cache, to be safe if the extra source changes */ - if (cached_git_dir && update) - { - g_autoptr(GFile) alternates = g_file_resolve_relative_path (mirror_dir_tmp, "objects/info/alternates"); - - if (!git (mirror_dir_tmp, NULL, error, - "repack", "-a", "-d", NULL)) - return FALSE; - - g_file_delete (alternates, NULL, NULL); - } - - if (!res || !g_file_move (mirror_dir_tmp, mirror_dir, 0, NULL, NULL, NULL, error)) - return FALSE; - } - else if (update) - { - g_print ("Fetching git repo %s\n", repo_location); - if (!git (mirror_dir, NULL, error, - "fetch", "-p", NULL)) - return FALSE; - } - - if (mirror_submodules) - { - current_commit = git_get_current_commit (mirror_dir, ref, FALSE, context, error); - if (current_commit == NULL) - return FALSE; - - if (!git_mirror_submodules (repo_location, destination_path, update, - mirror_dir, disable_fsck, current_commit, context, error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -git_extract_submodule (const char *repo_location, - GFile *checkout_dir, - const char *revision, - BuilderContext *context, - GError **error) -{ - g_autoptr(GKeyFile) key_file = g_key_file_new (); - g_autofree gchar *rev_parse_output = NULL; - g_autofree gchar *submodule_data = NULL; - g_autofree gchar **submodules = NULL; - g_autofree gchar *gitmodules = g_strconcat (revision, ":.gitmodules", NULL); - gsize num_submodules; - - if (!git (checkout_dir, &rev_parse_output, NULL, "rev-parse", "--verify", "--quiet", gitmodules, NULL)) - return TRUE; - - if (git (checkout_dir, &submodule_data, NULL, "show", gitmodules, NULL)) - { - if (!g_key_file_load_from_data (key_file, submodule_data, -1, - G_KEY_FILE_NONE, error)) - return FALSE; - - submodules = g_key_file_get_groups (key_file, &num_submodules); - - int i; - for (i = 0; i < num_submodules; i++) - { - g_autofree gchar *submodule = NULL; - g_autofree gchar *name = NULL; - g_autofree gchar *update_method = NULL; - g_autofree gchar *path = NULL; - g_autofree gchar *relative_url = NULL; - g_autofree gchar *absolute_url = NULL; - g_autofree gchar *ls_tree = NULL; - g_auto(GStrv) lines = NULL; - g_auto(GStrv) words = NULL; - g_autoptr(GFile) mirror_dir = NULL; - g_autoptr(GFile) child_dir = NULL; - g_autofree gchar *mirror_dir_as_url = NULL; - g_autofree gchar *option = NULL; - gsize len; - - submodule = submodules[i]; - len = strlen (submodule); - - if (!g_str_has_prefix (submodule, "submodule \"")) - continue; - - name = g_strndup (submodule + 11, len - 12); - - /* Skip any submodules that are disabled (have the update method set to "none") - Only check if the command succeeds. If it fails, the update method is not set. */ - update_method = g_key_file_get_string (key_file, submodule, "update", NULL); - if (g_strcmp0 (update_method, "none") == 0) - continue; - - path = g_key_file_get_string (key_file, submodule, "path", error); - if (path == NULL) - return FALSE; - - relative_url = g_key_file_get_string (key_file, submodule, "url", error); - absolute_url = make_absolute (repo_location, relative_url, error); - if (absolute_url == NULL) - return FALSE; - - if (!git (checkout_dir, &ls_tree, error, "ls-tree", revision, path, NULL)) - return FALSE; - - lines = g_strsplit (g_strstrip (ls_tree), "\n", 0); - if (g_strv_length (lines) != 1) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Not a gitlink tree: %s", path); - return FALSE; - } - - words = g_strsplit_set (lines[0], " \t", 4); - - if (g_strcmp0 (words[0], "160000") != 0) - continue; - - mirror_dir = git_get_mirror_dir (absolute_url, context); - mirror_dir_as_url = g_file_get_uri (mirror_dir); - option = g_strdup_printf ("submodule.%s.url", name); - - if (!git (checkout_dir, NULL, error, - "config", option, mirror_dir_as_url, NULL)) - return FALSE; - - if (!git (checkout_dir, NULL, error, - "submodule", "update", "--init", path, NULL)) - return FALSE; - - child_dir = g_file_resolve_relative_path (checkout_dir, path); - - if (!git_extract_submodule (absolute_url, child_dir, words[2], context, error)) - return FALSE; - } - } - - return TRUE; -} - -gboolean -builder_git_checkout_dir (const char *repo_location, - const char *branch, - const char *dir, - GFile *dest, - BuilderContext *context, - GError **error) -{ - g_autoptr(GFile) mirror_dir = NULL; - g_autofree char *mirror_dir_path = NULL; - g_autofree char *dest_path = NULL; - - mirror_dir = git_get_mirror_dir (repo_location, context); - - mirror_dir_path = g_file_get_path (mirror_dir); - dest_path = g_file_get_path (dest); - - if (!git (NULL, NULL, error, - "clone", "-n", mirror_dir_path, dest_path, NULL)) - return FALSE; - - if (!git (dest, NULL, error, - "checkout", branch, "--", dir ? dir : ".", NULL)) - return FALSE; - - return TRUE; -} - -gboolean -builder_git_checkout (const char *repo_location, - const char *branch, - GFile *dest, - BuilderContext *context, - GError **error) -{ - g_autoptr(GFile) mirror_dir = NULL; - g_autofree char *mirror_dir_path = NULL; - g_autofree char *dest_path = NULL; - - mirror_dir = git_get_mirror_dir (repo_location, context); - - mirror_dir_path = g_file_get_path (mirror_dir); - dest_path = g_file_get_path (dest); - - if (!git (NULL, NULL, error, - "clone", mirror_dir_path, dest_path, NULL)) - return FALSE; - - if (!git (dest, NULL, error, - "checkout", branch, NULL)) - return FALSE; - - if (!git_extract_submodule (repo_location, dest, branch, context, error)) - return FALSE; - - if (!git (dest, NULL, error, - "config", "--local", "remote.origin.url", - repo_location, NULL)) - return FALSE; - - return TRUE; -} diff --git a/builder/builder-git.h b/builder/builder-git.h deleted file mode 100644 index 7f16d042..00000000 --- a/builder/builder-git.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.1 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_GIT_H__ -#define __BUILDER_GIT_H__ - -#include "builder-context.h" - -G_BEGIN_DECLS - -gboolean builder_git_mirror_repo (const char *repo_location, - const char *destination_path, - gboolean update, - gboolean mirror_submodules, - gboolean disable_fsck, - const char *ref, - BuilderContext *context, - GError **error); -char * builder_git_get_current_commit (const char *repo_location, - const char *branch, - gboolean ensure_commit, - BuilderContext *context, - GError **error); -gboolean builder_git_checkout (const char *repo_location, - const char *branch, - GFile *dest, - BuilderContext *context, - GError **error); -gboolean builder_git_checkout_dir (const char *repo_location, - const char *branch, - const char *dir, - GFile *dest, - BuilderContext *context, - GError **error); - -G_END_DECLS - -#endif /* __BUILDER_GIT_H__ */ diff --git a/builder/builder-main.c b/builder/builder-main.c deleted file mode 100644 index 2377c737..00000000 --- a/builder/builder-main.c +++ /dev/null @@ -1,928 +0,0 @@ -/* - * 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.1 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 - */ - -#include "config.h" - -#include -#include -#include -#include - -#include -#include "libglnx/libglnx.h" - -#include "builder-manifest.h" -#include "builder-utils.h" -#include "builder-git.h" - -static gboolean opt_verbose; -static gboolean opt_version; -static gboolean opt_run; -static gboolean opt_disable_cache; -static gboolean opt_disable_rofiles; -static gboolean opt_download_only; -static gboolean opt_bundle_sources; -static gboolean opt_build_only; -static gboolean opt_finish_only; -static gboolean opt_export_only; -static gboolean opt_show_deps; -static gboolean opt_disable_download; -static gboolean opt_disable_updates; -static gboolean opt_ccache; -static gboolean opt_require_changes; -static gboolean opt_keep_build_dirs; -static gboolean opt_delete_build_dirs; -static gboolean opt_force_clean; -static gboolean opt_allow_missing_runtimes; -static gboolean opt_sandboxed; -static gboolean opt_rebuild_on_sdk_change; -static gboolean opt_skip_if_unchanged; -static char *opt_from_git; -static char *opt_from_git_branch; -static char *opt_stop_at; -static char *opt_build_shell; -static char *opt_arch; -static char *opt_default_branch; -static char *opt_repo; -static char *opt_subject; -static char *opt_body; -static char *opt_collection_id = NULL; -static char *opt_gpg_homedir; -static char **opt_key_ids; -static char **opt_sources_dirs; -static char **opt_sources_urls; -static int opt_jobs; -static char *opt_mirror_screenshots_url; -static char *opt_install_deps_from; -static gboolean opt_install_deps_only; -static gboolean opt_user; -static char *opt_installation; - -static GOptionEntry entries[] = { - { "verbose", 'v', 0, G_OPTION_ARG_NONE, &opt_verbose, "Print debug information during command processing", NULL }, - { "version", 0, 0, G_OPTION_ARG_NONE, &opt_version, "Print version information and exit", NULL }, - { "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, "Architecture to build for (must be host compatible)", "ARCH" }, - { "default-branch", 0, 0, G_OPTION_ARG_STRING, &opt_default_branch, "Change the default branch", "BRANCH" }, - { "run", 0, 0, G_OPTION_ARG_NONE, &opt_run, "Run a command in the build directory (see --run --help)", NULL }, - { "ccache", 0, 0, G_OPTION_ARG_NONE, &opt_ccache, "Use ccache", NULL }, - { "disable-cache", 0, 0, G_OPTION_ARG_NONE, &opt_disable_cache, "Disable cache lookups", NULL }, - { "disable-rofiles-fuse", 0, 0, G_OPTION_ARG_NONE, &opt_disable_rofiles, "Disable rofiles-fuse use", NULL }, - { "disable-download", 0, 0, G_OPTION_ARG_NONE, &opt_disable_download, "Don't download any new sources", NULL }, - { "disable-updates", 0, 0, G_OPTION_ARG_NONE, &opt_disable_updates, "Only download missing sources, never update to latest vcs version", NULL }, - { "download-only", 0, 0, G_OPTION_ARG_NONE, &opt_download_only, "Only download sources, don't build", NULL }, - { "bundle-sources", 0, 0, G_OPTION_ARG_NONE, &opt_bundle_sources, "Bundle module sources as runtime", NULL }, - { "extra-sources", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_sources_dirs, "Add a directory of sources specified by SOURCE-DIR, multiple uses of this option possible", "SOURCE-DIR"}, - { "extra-sources-url", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_sources_urls, "Add a url of sources specified by SOURCE-URL multiple uses of this option possible", "SOURCE-URL"}, - { "build-only", 0, 0, G_OPTION_ARG_NONE, &opt_build_only, "Stop after build, don't run clean and finish phases", NULL }, - { "finish-only", 0, 0, G_OPTION_ARG_NONE, &opt_finish_only, "Only run clean and finish and export phases", NULL }, - { "export-only", 0, 0, G_OPTION_ARG_NONE, &opt_export_only, "Only run export phase", NULL }, - { "allow-missing-runtimes", 0, 0, G_OPTION_ARG_NONE, &opt_allow_missing_runtimes, "Don't fail if runtime and sdk missing", NULL }, - { "show-deps", 0, 0, G_OPTION_ARG_NONE, &opt_show_deps, "List the dependencies of the json file (see --show-deps --help)", NULL }, - { "require-changes", 0, 0, G_OPTION_ARG_NONE, &opt_require_changes, "Don't create app dir or export if no changes", NULL }, - { "keep-build-dirs", 0, 0, G_OPTION_ARG_NONE, &opt_keep_build_dirs, "Don't remove build directories after install", NULL }, - { "delete-build-dirs", 0, 0, G_OPTION_ARG_NONE, &opt_delete_build_dirs, "Always remove build directories, even after build failure", NULL }, - { "repo", 0, 0, G_OPTION_ARG_STRING, &opt_repo, "Repo to export into", "DIR"}, - { "subject", 's', 0, G_OPTION_ARG_STRING, &opt_subject, "One line subject (passed to build-export)", "SUBJECT" }, - { "body", 'b', 0, G_OPTION_ARG_STRING, &opt_body, "Full description (passed to build-export)", "BODY" }, -#ifdef FLATPAK_ENABLE_P2P - { "collection-id", 0, 0, G_OPTION_ARG_STRING, &opt_collection_id, "Collection ID (passed to build-export)", "COLLECTION-ID" }, -#endif /* FLATPAK_ENABLE_P2P */ - { "gpg-sign", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_key_ids, "GPG Key ID to sign the commit with", "KEY-ID"}, - { "gpg-homedir", 0, 0, G_OPTION_ARG_STRING, &opt_gpg_homedir, "GPG Homedir to use when looking for keyrings", "HOMEDIR"}, - { "force-clean", 0, 0, G_OPTION_ARG_NONE, &opt_force_clean, "Erase previous contents of DIRECTORY", NULL }, - { "sandbox", 0, 0, G_OPTION_ARG_NONE, &opt_sandboxed, "Enforce sandboxing, disabling build-args", NULL }, - { "stop-at", 0, 0, G_OPTION_ARG_STRING, &opt_stop_at, "Stop building at this module (implies --build-only)", "MODULENAME"}, - { "jobs", 0, 0, G_OPTION_ARG_INT, &opt_jobs, "Number of parallel jobs to build (default=NCPU)", "JOBS"}, - { "rebuild-on-sdk-change", 0, 0, G_OPTION_ARG_NONE, &opt_rebuild_on_sdk_change, "Rebuild if sdk changes", NULL }, - { "skip-if-unchanged", 0, 0, G_OPTION_ARG_NONE, &opt_skip_if_unchanged, "Don't do anything if the json didn't change", NULL }, - { "build-shell", 0, 0, G_OPTION_ARG_STRING, &opt_build_shell, "Extract and prepare sources for module, then start build shell", "MODULENAME"}, - { "from-git", 0, 0, G_OPTION_ARG_STRING, &opt_from_git, "Get input files from git repo", "URL"}, - { "from-git-branch", 0, 0, G_OPTION_ARG_STRING, &opt_from_git_branch, "Branch to use in --from-git", "BRANCH"}, - { "mirror-screenshots-url", 0, 0, G_OPTION_ARG_STRING, &opt_mirror_screenshots_url, "Download and rewrite screenshots to match this url", "URL"}, - { "install-deps-from", 0, 0, G_OPTION_ARG_STRING, &opt_install_deps_from, "Install build dependencies from this remote", "REMOTE"}, - { "install-deps-only", 0, 0, G_OPTION_ARG_NONE, &opt_install_deps_only, "Stop after installing dependencies"}, - { "user", 0, 0, G_OPTION_ARG_NONE, &opt_user, "Install dependencies in user installations", NULL }, - { "system", 0, G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &opt_user, "Install dependencies in system-wide installations (default)", NULL }, - { "installation", 0, 0, G_OPTION_ARG_STRING, &opt_installation, "Install dependencies in a specific system-wide installation", "NAME" }, - { NULL } -}; - -static GOptionEntry run_entries[] = { - { "verbose", 'v', 0, G_OPTION_ARG_NONE, &opt_verbose, "Print debug information during command processing", NULL }, - { "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, "Architecture to build for (must be host compatible)", "ARCH" }, - { "run", 0, 0, G_OPTION_ARG_NONE, &opt_run, "Run a command in the build directory", NULL }, - { "ccache", 0, 0, G_OPTION_ARG_NONE, &opt_ccache, "Use ccache", NULL }, - { NULL } -}; - -static GOptionEntry show_deps_entries[] = { - { "verbose", 'v', 0, G_OPTION_ARG_NONE, &opt_verbose, "Print debug information during command processing", NULL }, - { "show-deps", 0, 0, G_OPTION_ARG_NONE, &opt_show_deps, "List the dependencies of the json file (see --show-deps --help)", NULL }, - { NULL } -}; - - -static void -message_handler (const gchar *log_domain, - GLogLevelFlags log_level, - const gchar *message, - gpointer user_data) -{ - /* Make this look like normal console output */ - if (log_level & G_LOG_LEVEL_DEBUG) - g_printerr ("XAB: %s\n", message); - else - g_printerr ("%s: %s\n", g_get_prgname (), message); -} - -static int -usage (GOptionContext *context, const char *message) -{ - g_autofree gchar *help = g_option_context_get_help (context, TRUE, NULL); - - g_printerr ("%s\n", message); - g_printerr ("%s", help); - return 1; -} - -static const char skip_arg[] = "skip"; - -static gboolean -do_export (BuilderContext *build_context, - GError **error, - gboolean runtime, - const gchar *location, - const gchar *directory, - char **exclude_dirs, - const gchar *branch, - const gchar *collection_id, - ...) -{ - va_list ap; - const char *arg; - int i; - - g_autoptr(GPtrArray) args = NULL; - g_autoptr(GSubprocess) subp = NULL; - - args = g_ptr_array_new_with_free_func (g_free); - g_ptr_array_add (args, g_strdup ("flatpak")); - g_ptr_array_add (args, g_strdup ("build-export")); - - g_ptr_array_add (args, g_strdup_printf ("--arch=%s", builder_context_get_arch (build_context))); - - if (runtime) - g_ptr_array_add (args, g_strdup ("--runtime")); - - if (opt_subject) - g_ptr_array_add (args, g_strdup_printf ("--subject=%s", opt_subject)); - - if (opt_body) - g_ptr_array_add (args, g_strdup_printf ("--body=%s", opt_body)); - - if (opt_gpg_homedir) - g_ptr_array_add (args, g_strdup_printf ("--gpg-homedir=%s", opt_gpg_homedir)); - - for (i = 0; opt_key_ids != NULL && opt_key_ids[i] != NULL; i++) - g_ptr_array_add (args, g_strdup_printf ("--gpg-sign=%s", opt_key_ids[i])); - - if (collection_id) - g_ptr_array_add (args, g_strdup_printf ("--collection-id=%s", collection_id)); - - /* Additional flags. */ - va_start (ap, collection_id); - while ((arg = va_arg (ap, const gchar *))) - if (arg != skip_arg) - g_ptr_array_add (args, g_strdup ((gchar *) arg)); - va_end (ap); - - if (exclude_dirs) - { - for (i = 0; exclude_dirs[i] != NULL; i++) - g_ptr_array_add (args, g_strdup_printf ("--exclude=/%s/*", exclude_dirs[i])); - } - - /* Mandatory positional arguments. */ - g_ptr_array_add (args, g_strdup (location)); - g_ptr_array_add (args, g_strdup (directory)); - g_ptr_array_add (args, g_strdup (branch)); - - g_ptr_array_add (args, NULL); - - subp = - g_subprocess_newv ((const gchar * const *) args->pdata, - G_SUBPROCESS_FLAGS_NONE, - error); - - if (subp == NULL || - !g_subprocess_wait_check (subp, NULL, error)) - return FALSE; - - return TRUE; -} - - -int -main (int argc, - char **argv) -{ - g_autofree const char *old_env = NULL; - - g_autoptr(GError) error = NULL; - g_autoptr(BuilderManifest) manifest = NULL; - g_autoptr(GOptionContext) context = NULL; - const char *app_dir_path = NULL, *manifest_rel_path; - g_autofree gchar *json = NULL; - g_autofree gchar *json_sha256 = NULL; - g_autofree gchar *old_json_sha256 = NULL; - g_autoptr(BuilderContext) build_context = NULL; - g_autoptr(GFile) base_dir = NULL; - g_autoptr(GFile) manifest_file = NULL; - g_autoptr(GFile) app_dir = NULL; - g_autoptr(BuilderCache) cache = NULL; - g_autofree char *cache_branch = NULL; - g_autoptr(GFileEnumerator) dir_enum = NULL; - g_autoptr(GFileEnumerator) dir_enum2 = NULL; - g_autofree char *cwd = NULL; - g_autoptr(GFile) cwd_dir = NULL; - GFileInfo *next = NULL; - const char *platform_id = NULL; - g_autofree char **orig_argv = NULL; - gboolean is_run = FALSE; - gboolean is_show_deps = FALSE; - gboolean app_dir_is_empty = FALSE; - g_autoptr(FlatpakContext) arg_context = NULL; - g_autoptr(FlatpakTempDir) cleanup_manifest_dir = NULL; - g_autofree char *manifest_basename = NULL; - int i, first_non_arg, orig_argc; - int argnr; - - setlocale (LC_ALL, ""); - - g_log_set_handler (NULL, G_LOG_LEVEL_MESSAGE, message_handler, NULL); - - g_set_prgname (argv[0]); - - /* avoid gvfs (http://bugzilla.gnome.org/show_bug.cgi?id=526454) */ - old_env = g_strdup (g_getenv ("GIO_USE_VFS")); - g_setenv ("GIO_USE_VFS", "local", TRUE); - g_vfs_get_default (); - if (old_env) - g_setenv ("GIO_USE_VFS", old_env, TRUE); - else - g_unsetenv ("GIO_USE_VFS"); - - orig_argv = g_memdup (argv, sizeof (char *) * argc); - orig_argc = argc; - - first_non_arg = 1; - for (i = 1; i < argc; i++) - { - if (argv[i][0] != '-') - break; - first_non_arg = i + 1; - if (strcmp (argv[i], "--run") == 0) - is_run = TRUE; - if (strcmp (argv[i], "--show-deps") == 0) - is_show_deps = TRUE; - } - - if (is_run) - { - context = g_option_context_new ("DIRECTORY MANIFEST COMMAND [args] - Run command in build sandbox"); - g_option_context_add_main_entries (context, run_entries, NULL); - arg_context = flatpak_context_new (); - g_option_context_add_group (context, flatpak_context_get_options (arg_context)); - - /* We drop the post-command part from the args, these go with the command in the sandbox */ - argc = MIN (first_non_arg + 3, argc); - } - else if (is_show_deps) - { - context = g_option_context_new ("MANIFEST - Show manifest dependencies"); - g_option_context_add_main_entries (context, show_deps_entries, NULL); - } - else - { - context = g_option_context_new ("DIRECTORY MANIFEST - Build manifest"); - g_option_context_add_main_entries (context, entries, NULL); - } - - if (!g_option_context_parse (context, &argc, &argv, &error)) - { - g_printerr ("Option parsing failed: %s\n", error->message); - return 1; - } - - if (opt_version) - { - g_print ("%s\n", PACKAGE_STRING); - exit (EXIT_SUCCESS); - } - - if (opt_verbose) - g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, message_handler, NULL); - - argnr = 1; - - if (!is_show_deps) - { - if (argc == argnr) - return usage (context, "DIRECTORY must be specified"); - app_dir_path = argv[argnr++]; - } - - if (argc == argnr) - return usage (context, "MANIFEST must be specified"); - manifest_rel_path = argv[argnr++]; - manifest_basename = g_path_get_basename (manifest_rel_path); - -#ifdef FLATPAK_ENABLE_P2P - if (opt_collection_id != NULL && - !ostree_validate_collection_id (opt_collection_id, &error)) - { - g_printerr ("‘%s’ is not a valid collection ID: %s", opt_collection_id, error->message); - return 1; - } -#endif /* FLATPAK_ENABLE_P2P */ - - if (app_dir_path) - app_dir = g_file_new_for_path (app_dir_path); - cwd = g_get_current_dir (); - cwd_dir = g_file_new_for_path (cwd); - - build_context = builder_context_new (cwd_dir, app_dir); - - builder_context_set_use_rofiles (build_context, !opt_disable_rofiles); - builder_context_set_keep_build_dirs (build_context, opt_keep_build_dirs); - builder_context_set_delete_build_dirs (build_context, opt_delete_build_dirs); - builder_context_set_sandboxed (build_context, opt_sandboxed); - builder_context_set_jobs (build_context, opt_jobs); - builder_context_set_rebuild_on_sdk_change (build_context, opt_rebuild_on_sdk_change); - builder_context_set_bundle_sources (build_context, opt_bundle_sources); - - if (opt_sources_dirs) - { - g_autoptr(GPtrArray) sources_dirs = NULL; - sources_dirs = g_ptr_array_new_with_free_func (g_object_unref); - for (i = 0; opt_sources_dirs != NULL && opt_sources_dirs[i] != NULL; i++) - { - GFile *file = g_file_new_for_commandline_arg (opt_sources_dirs[i]); - g_ptr_array_add (sources_dirs, file); - } - builder_context_set_sources_dirs (build_context, sources_dirs); - } - - if (opt_sources_urls) - { - g_autoptr(GPtrArray) sources_urls = NULL; - sources_urls = g_ptr_array_new_with_free_func ((GDestroyNotify)soup_uri_free); - for (i = 0; opt_sources_urls[i] != NULL; i++) - { - SoupURI *uri = soup_uri_new (opt_sources_urls[i]); - if (uri == NULL) - { - g_printerr ("Invalid URL '%s'", opt_sources_urls[i]); - return 1; - } - g_ptr_array_add (sources_urls, uri); - } - builder_context_set_sources_urls (build_context, sources_urls); - } - - if (opt_arch) - builder_context_set_arch (build_context, opt_arch); - - if (opt_stop_at) - { - opt_build_only = TRUE; - builder_context_set_stop_at (build_context, opt_stop_at); - } - - if (opt_ccache && - !builder_context_enable_ccache (build_context, &error)) - { - g_printerr ("Can't initialize ccache use: %s\n", error->message); - return 1; - } - - if (opt_from_git) - { - g_autofree char *manifest_dirname = g_path_get_dirname (manifest_rel_path); - const char *git_branch = opt_from_git_branch ? opt_from_git_branch : "master"; - g_autofree char *git_origin_branch = g_strconcat ("origin/", git_branch, NULL); - g_autoptr(GFile) build_subdir = NULL; - - if (!builder_git_mirror_repo (opt_from_git, - NULL, - !opt_disable_updates, FALSE, FALSE, - git_branch, build_context, &error)) - { - g_printerr ("Can't clone manifest repo: %s\n", error->message); - return 1; - } - - build_subdir = builder_context_allocate_build_subdir (build_context, manifest_basename, &error); - if (build_subdir == NULL) - { - g_printerr ("Can't check out manifest repo: %s\n", error->message); - return 1; - } - - cleanup_manifest_dir = g_object_ref (build_subdir); - - if (!builder_git_checkout_dir (opt_from_git, - git_origin_branch, - manifest_dirname, - build_subdir, - build_context, - &error)) - { - g_printerr ("Can't check out manifest repo: %s\n", error->message); - return 1; - } - - manifest_file = g_file_get_child (build_subdir, manifest_rel_path); - base_dir = g_file_resolve_relative_path (build_subdir, manifest_dirname); - } - else - { - manifest_file = g_file_new_for_path (manifest_rel_path); - base_dir = g_file_get_parent (manifest_file); - } - - builder_context_set_base_dir (build_context, base_dir); - - if (!g_file_get_contents (flatpak_file_get_path_cached (manifest_file), &json, NULL, &error)) - { - g_printerr ("Can't load '%s': %s\n", manifest_rel_path, error->message); - return 1; - } - - json_sha256 = g_compute_checksum_for_string (G_CHECKSUM_SHA256, json, -1); - - if (opt_skip_if_unchanged) - { - old_json_sha256 = builder_context_get_checksum_for (build_context, manifest_basename); - if (old_json_sha256 != NULL && strcmp (json_sha256, old_json_sha256) == 0) - { - g_print ("No changes to manifest, skipping\n"); - return 42; - } - } - - /* Can't push this as user data to the demarshalling :/ */ - builder_manifest_set_demarshal_base_dir (builder_context_get_base_dir (build_context)); - - manifest = (BuilderManifest *) json_gobject_from_data (BUILDER_TYPE_MANIFEST, - json, -1, &error); - - builder_manifest_set_demarshal_base_dir (NULL); - - if (manifest == NULL) - { - g_printerr ("Can't parse '%s': %s\n", manifest_rel_path, error->message); - return 1; - } - - if (opt_default_branch) - builder_manifest_set_default_branch (manifest, opt_default_branch); - - if (opt_collection_id) - builder_manifest_set_default_collection_id (manifest, opt_collection_id); - - if (is_run && argc == 3) - return usage (context, "Program to run must be specified"); - - if (opt_show_deps && !is_show_deps) - return usage (context, "Can't use --show-deps after a non-option"); - - if (opt_run && !is_run) - return usage (context, "Can't use --run after a non-option"); - - if (is_show_deps) - { - if (!builder_manifest_show_deps (manifest, build_context, &error)) - { - g_printerr ("Error running %s: %s\n", argv[3], error->message); - return 1; - } - - return 0; - } - - if (opt_install_deps_from != NULL) - { - if (!builder_manifest_install_deps (manifest, build_context, opt_install_deps_from, opt_user, opt_installation, &error)) - { - g_printerr ("Error running %s: %s\n", argv[3], error->message); - return 1; - } - if (opt_install_deps_only) - return 0; - } - - app_dir_is_empty = !g_file_query_exists (app_dir, NULL) || - directory_is_empty (app_dir_path); - - if (is_run) - { - g_assert (opt_run); - - if (app_dir_is_empty) - { - g_printerr ("App dir '%s' is empty or doesn't exist.\n", app_dir_path); - return 1; - } - - if (!builder_manifest_run (manifest, build_context, arg_context, - orig_argv + first_non_arg + 2, - orig_argc - first_non_arg - 2, &error)) - { - g_printerr ("Error running %s: %s\n", argv[3], error->message); - return 1; - } - - return 0; - } - - g_assert (!opt_run); - g_assert (!opt_show_deps); - - if (opt_export_only || opt_finish_only || opt_build_shell) - { - if (app_dir_is_empty) - { - g_printerr ("App dir '%s' is empty or doesn't exist.\n", app_dir_path); - return 1; - } - } - else - { - if (!app_dir_is_empty) - { - if (opt_force_clean) - { - g_print ("Emptying app dir '%s'\n", app_dir_path); - if (!flatpak_rm_rf (app_dir, NULL, &error)) - { - g_printerr ("Couldn't empty app dir '%s': %s", - app_dir_path, error->message); - return 1; - } - } - else - { - g_printerr ("App dir '%s' is not empty. Please delete " - "the existing contents or use --force-clean.\n", app_dir_path); - return 1; - } - } - } - - builder_context_set_checksum_for (build_context, manifest_basename, json_sha256); - - if (!builder_manifest_start (manifest, opt_allow_missing_runtimes, build_context, &error)) - { - g_printerr ("Failed to init: %s\n", error->message); - return 1; - } - - if (!opt_finish_only && - !opt_export_only && - !opt_disable_download && - !builder_manifest_download (manifest, !opt_disable_updates, opt_build_shell, build_context, &error)) - { - g_printerr ("Failed to download sources: %s\n", error->message); - return 1; - } - - if (opt_download_only) - return 0; - - if (opt_build_shell) - { - if (!builder_manifest_build_shell (manifest, build_context, opt_build_shell, &error)) - { - g_printerr ("Failed to setup module: %s\n", error->message); - return 1; - } - - return 0; - } - - cache_branch = g_strconcat (builder_context_get_arch (build_context), "-", manifest_basename, NULL); - - cache = builder_cache_new (build_context, app_dir, cache_branch); - if (!builder_cache_open (cache, &error)) - { - g_printerr ("Error opening cache: %s\n", error->message); - return 1; - } - - if (opt_disable_cache) /* This disables *lookups*, but we still build the cache */ - builder_cache_disable_lookups (cache); - - builder_manifest_checksum (manifest, cache, build_context); - - if (!opt_finish_only && !opt_export_only) - { - if (!builder_cache_lookup (cache, "init")) - { - g_autofree char *body = - g_strdup_printf ("Initialized %s\n", - builder_manifest_get_id (manifest)); - if (!builder_manifest_init_app_dir (manifest, cache, build_context, &error)) - { - g_printerr ("Error: %s\n", error->message); - return 1; - } - - if (!builder_cache_commit (cache, body, &error)) - { - g_printerr ("Error: %s\n", error->message); - return 1; - } - } - - if (!builder_manifest_build (manifest, cache, build_context, &error)) - { - g_printerr ("Error: %s\n", error->message); - return 1; - } - } - - if (!opt_build_only && !opt_export_only) - { - if (!builder_manifest_cleanup (manifest, cache, build_context, &error)) - { - g_printerr ("Error: %s\n", error->message); - return 1; - } - - if (!builder_manifest_finish (manifest, cache, build_context, &error)) - { - g_printerr ("Error: %s\n", error->message); - return 1; - } - - if (!builder_manifest_create_platform (manifest, cache, build_context, &error)) - { - g_printerr ("Error: %s\n", error->message); - return 1; - } - - if (builder_context_get_bundle_sources (build_context) && - !builder_manifest_bundle_sources (manifest, json, cache, build_context, &error)) - { - g_printerr ("Error: %s\n", error->message); - return 1; - } - } - - if (!opt_require_changes && !opt_export_only) - builder_cache_ensure_checkout (cache); - - if (opt_mirror_screenshots_url && !opt_export_only) - { - g_autofree char *screenshot_subdir = g_strdup_printf ("%s-%s", builder_manifest_get_id (manifest), - builder_manifest_get_branch (manifest)); - g_autofree char *url = g_build_filename (opt_mirror_screenshots_url, screenshot_subdir, NULL); - g_autofree char *xml_relpath = g_strdup_printf ("files/share/app-info/xmls/%s.xml.gz", builder_manifest_get_id (manifest)); - g_autoptr(GFile) xml = g_file_resolve_relative_path (app_dir, xml_relpath); - g_autoptr(GFile) cache = flatpak_build_file (builder_context_get_state_dir (build_context), "screenshots-cache", NULL); - g_autoptr(GFile) screenshots = flatpak_build_file (app_dir, "screenshots", NULL); - g_autoptr(GFile) screenshots_sub = flatpak_build_file (screenshots, screenshot_subdir, NULL); - const char *argv[] = { - "appstream-util", - "mirror-screenshots", - flatpak_file_get_path_cached (xml), - url, - flatpak_file_get_path_cached (cache), - flatpak_file_get_path_cached (screenshots_sub), - NULL - }; - - g_print ("Mirroring screenshots from appdata\n"); - - if (!flatpak_mkdir_p (screenshots, NULL, &error)) - { - g_printerr ("Error creating screenshot dir: %s\n", error->message); - return 1; - } - - if (g_file_query_exists (xml, NULL)) - { - if (!builder_maybe_host_spawnv (NULL, - NULL, - &error, - argv)) - { - g_printerr ("Error mirroring screenshots: %s\n", error->message); - return 1; - } - } - - g_print ("Saved screenshots in %s\n", flatpak_file_get_path_cached (screenshots)); - } - - if (!opt_build_only && opt_repo && (opt_export_only || builder_cache_has_checkout (cache))) - { - g_autoptr(GFile) debuginfo_metadata = NULL; - g_autoptr(GFile) sourcesinfo_metadata = NULL; - g_auto(GStrv) exclude_dirs = builder_manifest_get_exclude_dirs (manifest); - GList *l; - - g_print ("Exporting %s to repo\n", builder_manifest_get_id (manifest)); - - if (!do_export (build_context, &error, - FALSE, - opt_repo, app_dir_path, exclude_dirs, builder_manifest_get_branch (manifest), - builder_manifest_get_collection_id (manifest), - "--exclude=/lib/debug/*", - "--include=/lib/debug/app", - builder_context_get_separate_locales (build_context) ? "--exclude=/share/runtime/locale/*/*" : skip_arg, - NULL)) - { - g_printerr ("Export failed: %s\n", error->message); - return 1; - } - - /* Export regular locale extensions */ - dir_enum = g_file_enumerate_children (app_dir, "standard::name,standard::type", - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - NULL, NULL); - while (dir_enum != NULL && - (next = g_file_enumerator_next_file (dir_enum, NULL, NULL))) - { - g_autoptr(GFileInfo) child_info = next; - const char *name = g_file_info_get_name (child_info); - g_autofree char *metadata_arg = NULL; - g_autofree char *files_arg = NULL; - g_autofree char *locale_id = builder_manifest_get_locale_id (manifest); - - if (strcmp (name, "metadata.locale") == 0) - g_print ("Exporting %s to repo\n", locale_id); - else - continue; - - metadata_arg = g_strdup_printf ("--metadata=%s", name); - files_arg = g_strconcat (builder_context_get_build_runtime (build_context) ? "--files=usr" : "--files=files", - "/share/runtime/locale/", NULL); - if (!do_export (build_context, &error, TRUE, - opt_repo, app_dir_path, NULL, builder_manifest_get_branch (manifest), - builder_manifest_get_collection_id (manifest), - metadata_arg, - files_arg, - NULL)) - { - g_printerr ("Export failed: %s\n", error->message); - return 1; - } - } - - /* Export debug extensions */ - debuginfo_metadata = g_file_get_child (app_dir, "metadata.debuginfo"); - if (g_file_query_exists (debuginfo_metadata, NULL)) - { - g_autofree char *debug_id = builder_manifest_get_debug_id (manifest); - g_print ("Exporting %s to repo\n", debug_id); - - if (!do_export (build_context, &error, TRUE, - opt_repo, app_dir_path, NULL, builder_manifest_get_branch (manifest), - builder_manifest_get_collection_id (manifest), - "--metadata=metadata.debuginfo", - builder_context_get_build_runtime (build_context) ? "--files=usr/lib/debug" : "--files=files/lib/debug", - NULL)) - { - g_printerr ("Export failed: %s\n", error->message); - return 1; - } - } - - for (l = builder_manifest_get_add_extensions (manifest); l != NULL; l = l->next) - { - BuilderExtension *e = l->data; - const char *extension_id = NULL; - g_autofree char *metadata_arg = NULL; - g_autofree char *files_arg = NULL; - - if (!builder_extension_is_bundled (e)) - continue; - - extension_id = builder_extension_get_name (e); - g_print ("Exporting %s to repo\n", extension_id); - - metadata_arg = g_strdup_printf ("--metadata=metadata.%s", extension_id); - files_arg = g_strdup_printf ("--files=%s/%s", - builder_context_get_build_runtime (build_context) ? "usr" : "files", - builder_extension_get_directory (e)); - - if (!do_export (build_context, &error, TRUE, - opt_repo, app_dir_path, NULL, builder_manifest_get_branch (manifest), - builder_manifest_get_collection_id (manifest), - metadata_arg, files_arg, - NULL)) - { - g_printerr ("Export failed: %s\n", error->message); - return 1; - } - } - - /* Export sources extensions */ - sourcesinfo_metadata = g_file_get_child (app_dir, "metadata.sources"); - if (g_file_query_exists (sourcesinfo_metadata, NULL)) - { - g_autofree char *sources_id = builder_manifest_get_sources_id (manifest); - g_print ("Exporting %s to repo\n", sources_id); - - if (!do_export (build_context, &error, TRUE, - opt_repo, app_dir_path, NULL, builder_manifest_get_branch (manifest), - builder_manifest_get_collection_id (manifest), - "--metadata=metadata.sources", - "--files=sources", - NULL)) - { - g_printerr ("Export failed: %s\n", error->message); - return 1; - } - } - - /* Export platform */ - platform_id = builder_manifest_get_id_platform (manifest); - if (builder_context_get_build_runtime (build_context) && - platform_id != NULL) - { - g_print ("Exporting %s to repo\n", platform_id); - - if (!do_export (build_context, &error, TRUE, - opt_repo, app_dir_path, NULL, builder_manifest_get_branch (manifest), - builder_manifest_get_collection_id (manifest), - "--metadata=metadata.platform", - "--files=platform", - builder_context_get_separate_locales (build_context) ? "--exclude=/share/runtime/locale/*/*" : skip_arg, - NULL)) - { - g_printerr ("Export failed: %s\n", error->message); - return 1; - } - } - - /* Export platform locales */ - dir_enum2 = g_file_enumerate_children (app_dir, "standard::name,standard::type", - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - NULL, NULL); - while (dir_enum2 != NULL && - (next = g_file_enumerator_next_file (dir_enum2, NULL, NULL))) - { - g_autoptr(GFileInfo) child_info = next; - const char *name = g_file_info_get_name (child_info); - g_autofree char *metadata_arg = NULL; - g_autofree char *files_arg = NULL; - g_autofree char *locale_id = builder_manifest_get_locale_id_platform (manifest); - - if (strcmp (name, "metadata.platform.locale") == 0) - g_print ("Exporting %s to repo\n", locale_id); - else - continue; - - metadata_arg = g_strdup_printf ("--metadata=%s", name); - files_arg = g_strconcat ("--files=platform/share/runtime/locale/", NULL); - if (!do_export (build_context, &error, TRUE, - opt_repo, app_dir_path, NULL, builder_manifest_get_branch (manifest), - builder_manifest_get_collection_id (manifest), - metadata_arg, - files_arg, - NULL)) - { - g_printerr ("Export failed: %s\n", error->message); - return 1; - } - } - } - - if (!builder_gc (cache, &error)) - { - g_warning ("Failed to GC build cache: %s", error->message); - g_clear_error (&error); - } - - return 0; -} diff --git a/builder/builder-manifest.c b/builder/builder-manifest.c deleted file mode 100644 index 7997a865..00000000 --- a/builder/builder-manifest.c +++ /dev/null @@ -1,3335 +0,0 @@ -/* builder-manifest.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-manifest.h" -#include "builder-utils.h" -#include "flatpak-utils.h" -#include "builder-post-process.h" -#include "builder-extension.h" - -#include "libglnx/libglnx.h" - -#define LOCALES_SEPARATE_DIR "share/runtime/locale" - -static GFile *demarshal_base_dir = NULL; - -void -builder_manifest_set_demarshal_base_dir (GFile *dir) -{ - g_set_object (&demarshal_base_dir, dir); -} - -GFile * -builder_manifest_get_demarshal_base_dir (void) -{ - return g_object_ref (demarshal_base_dir); -} - -struct BuilderManifest -{ - GObject parent; - - char *id; - char *id_platform; - char *branch; - char *collection_id; - char *type; - char *runtime; - char *runtime_commit; - char *runtime_version; - char *sdk; - char *sdk_commit; - char *var; - char *base; - char *base_commit; - char *base_version; - char **base_extensions; - char *metadata; - char *metadata_platform; - gboolean separate_locales; - char **cleanup; - char **cleanup_commands; - char **cleanup_platform; - char **cleanup_platform_commands; - char **finish_args; - char **inherit_extensions; - char **tags; - char *rename_desktop_file; - char *rename_appdata_file; - char *rename_icon; - gboolean copy_icon; - char *desktop_file_name_prefix; - char *desktop_file_name_suffix; - gboolean build_runtime; - gboolean build_extension; - gboolean writable_sdk; - gboolean appstream_compose; - char **sdk_extensions; - char **platform_extensions; - char *command; - BuilderOptions *build_options; - GList *modules; - GList *expanded_modules; - GList *add_extensions; -}; - -typedef struct -{ - GObjectClass parent_class; -} BuilderManifestClass; - -static void serializable_iface_init (JsonSerializableIface *serializable_iface); - -G_DEFINE_TYPE_WITH_CODE (BuilderManifest, builder_manifest, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (JSON_TYPE_SERIALIZABLE, serializable_iface_init)); - -enum { - PROP_0, - PROP_APP_ID, /* Backwards compat with early version, use id */ - PROP_ID, - PROP_ID_PLATFORM, - PROP_BRANCH, - PROP_RUNTIME, - PROP_RUNTIME_VERSION, - PROP_RUNTIME_COMMIT, - PROP_SDK, - PROP_SDK_COMMIT, - PROP_BASE, - PROP_BASE_VERSION, - PROP_BASE_COMMIT, - PROP_BASE_EXTENSIONS, - PROP_VAR, - PROP_METADATA, - PROP_METADATA_PLATFORM, - PROP_BUILD_OPTIONS, - PROP_COMMAND, - PROP_MODULES, - PROP_CLEANUP, - PROP_CLEANUP_COMMANDS, - PROP_CLEANUP_PLATFORM_COMMANDS, - PROP_CLEANUP_PLATFORM, - PROP_BUILD_RUNTIME, - PROP_BUILD_EXTENSION, - PROP_SEPARATE_LOCALES, - PROP_WRITABLE_SDK, - PROP_APPSTREAM_COMPOSE, - PROP_SDK_EXTENSIONS, - PROP_PLATFORM_EXTENSIONS, - PROP_FINISH_ARGS, - PROP_INHERIT_EXTENSIONS, - PROP_TAGS, - PROP_RENAME_DESKTOP_FILE, - PROP_RENAME_APPDATA_FILE, - PROP_RENAME_ICON, - PROP_COPY_ICON, - PROP_DESKTOP_FILE_NAME_PREFIX, - PROP_DESKTOP_FILE_NAME_SUFFIX, - PROP_COLLECTION_ID, - PROP_ADD_EXTENSIONS, - LAST_PROP -}; - -static void -builder_manifest_finalize (GObject *object) -{ - BuilderManifest *self = (BuilderManifest *) object; - - g_free (self->id); - g_free (self->branch); - g_free (self->collection_id); - g_free (self->runtime); - g_free (self->runtime_commit); - g_free (self->runtime_version); - g_free (self->sdk); - g_free (self->sdk_commit); - g_free (self->base); - g_free (self->base_commit); - g_free (self->base_version); - g_free (self->var); - g_free (self->metadata); - g_free (self->metadata_platform); - g_free (self->command); - g_clear_object (&self->build_options); - g_list_free_full (self->modules, g_object_unref); - g_list_free_full (self->add_extensions, g_object_unref); - g_list_free (self->expanded_modules); - g_strfreev (self->cleanup); - g_strfreev (self->cleanup_commands); - g_strfreev (self->cleanup_platform); - g_strfreev (self->cleanup_platform_commands); - g_strfreev (self->finish_args); - g_strfreev (self->inherit_extensions); - g_strfreev (self->tags); - g_free (self->rename_desktop_file); - g_free (self->rename_appdata_file); - g_free (self->rename_icon); - g_free (self->desktop_file_name_prefix); - g_free (self->desktop_file_name_suffix); - - G_OBJECT_CLASS (builder_manifest_parent_class)->finalize (object); -} - -static gboolean -expand_modules (BuilderContext *context, GList *modules, - GList **expanded, GHashTable *names, GError **error) -{ - GList *l; - - for (l = modules; l; l = l->next) - { - BuilderModule *m = l->data; - GList *submodules = NULL; - const char *name; - - if (!builder_module_is_enabled (m, context)) - continue; - - if (!expand_modules (context, builder_module_get_modules (m), &submodules, names, error)) - return FALSE; - - *expanded = g_list_concat (*expanded, submodules); - - name = builder_module_get_name (m); - - if (name == NULL) - { - /* FIXME: We'd like to report *something* for the user - to locate the errornous module definition. - */ - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Module has no 'name' attribute set"); - return FALSE; - } - - if (g_hash_table_lookup (names, name) != NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Duplicate modules named '%s'", name); - return FALSE; - } - g_hash_table_insert (names, (char *)name, (char *)name); - *expanded = g_list_append (*expanded, m); - } - - return TRUE; -} - -static void -builder_manifest_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - BuilderManifest *self = BUILDER_MANIFEST (object); - - switch (prop_id) - { - case PROP_APP_ID: - g_value_set_string (value, NULL); - break; - - case PROP_ID: - g_value_set_string (value, self->id); - break; - - case PROP_ID_PLATFORM: - g_value_set_string (value, self->id_platform); - break; - - case PROP_BRANCH: - g_value_set_string (value, self->branch); - break; - - case PROP_RUNTIME: - g_value_set_string (value, self->runtime); - break; - - case PROP_RUNTIME_COMMIT: - g_value_set_string (value, self->runtime_commit); - break; - - case PROP_RUNTIME_VERSION: - g_value_set_string (value, self->runtime_version); - break; - - case PROP_SDK: - g_value_set_string (value, self->sdk); - break; - - case PROP_SDK_COMMIT: - g_value_set_string (value, self->sdk_commit); - break; - - case PROP_BASE: - g_value_set_string (value, self->base); - break; - - case PROP_BASE_COMMIT: - g_value_set_string (value, self->base_commit); - break; - - case PROP_BASE_VERSION: - g_value_set_string (value, self->base_version); - break; - - case PROP_BASE_EXTENSIONS: - g_value_set_boxed (value, self->base_extensions); - break; - - case PROP_VAR: - g_value_set_string (value, self->var); - break; - - case PROP_METADATA: - g_value_set_string (value, self->metadata); - break; - - case PROP_METADATA_PLATFORM: - g_value_set_string (value, self->metadata_platform); - break; - - case PROP_COMMAND: - g_value_set_string (value, self->command); - break; - - case PROP_BUILD_OPTIONS: - g_value_set_object (value, self->build_options); - break; - - case PROP_MODULES: - g_value_set_pointer (value, self->modules); - break; - - case PROP_ADD_EXTENSIONS: - g_value_set_pointer (value, self->add_extensions); - break; - - case PROP_CLEANUP: - g_value_set_boxed (value, self->cleanup); - break; - - case PROP_CLEANUP_COMMANDS: - g_value_set_boxed (value, self->cleanup_commands); - break; - - case PROP_CLEANUP_PLATFORM: - g_value_set_boxed (value, self->cleanup_platform); - break; - - case PROP_CLEANUP_PLATFORM_COMMANDS: - g_value_set_boxed (value, self->cleanup_platform_commands); - break; - - case PROP_FINISH_ARGS: - g_value_set_boxed (value, self->finish_args); - break; - - case PROP_INHERIT_EXTENSIONS: - g_value_set_boxed (value, self->inherit_extensions); - break; - - case PROP_TAGS: - g_value_set_boxed (value, self->tags); - break; - - case PROP_BUILD_RUNTIME: - g_value_set_boolean (value, self->build_runtime); - break; - - case PROP_BUILD_EXTENSION: - g_value_set_boolean (value, self->build_extension); - break; - - case PROP_SEPARATE_LOCALES: - g_value_set_boolean (value, self->separate_locales); - break; - - case PROP_WRITABLE_SDK: - g_value_set_boolean (value, self->writable_sdk); - break; - - case PROP_APPSTREAM_COMPOSE: - g_value_set_boolean (value, self->appstream_compose); - break; - - case PROP_SDK_EXTENSIONS: - g_value_set_boxed (value, self->sdk_extensions); - break; - - case PROP_PLATFORM_EXTENSIONS: - g_value_set_boxed (value, self->platform_extensions); - break; - - case PROP_COPY_ICON: - g_value_set_boolean (value, self->copy_icon); - break; - - case PROP_RENAME_DESKTOP_FILE: - g_value_set_string (value, self->rename_desktop_file); - break; - - case PROP_RENAME_APPDATA_FILE: - g_value_set_string (value, self->rename_appdata_file); - break; - - case PROP_RENAME_ICON: - g_value_set_string (value, self->rename_icon); - break; - - case PROP_DESKTOP_FILE_NAME_PREFIX: - g_value_set_string (value, self->desktop_file_name_prefix); - break; - - case PROP_DESKTOP_FILE_NAME_SUFFIX: - g_value_set_string (value, self->desktop_file_name_suffix); - break; - - case PROP_COLLECTION_ID: - g_value_set_string (value, self->collection_id); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -builder_manifest_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - BuilderManifest *self = BUILDER_MANIFEST (object); - gchar **tmp; - - switch (prop_id) - { - case PROP_APP_ID: - g_free (self->id); - self->id = g_value_dup_string (value); - break; - - case PROP_ID: - g_free (self->id); - self->id = g_value_dup_string (value); - break; - - case PROP_ID_PLATFORM: - g_free (self->id_platform); - self->id_platform = g_value_dup_string (value); - break; - - case PROP_BRANCH: - g_free (self->branch); - self->branch = g_value_dup_string (value); - break; - - case PROP_RUNTIME: - g_free (self->runtime); - self->runtime = g_value_dup_string (value); - break; - - case PROP_RUNTIME_COMMIT: - g_free (self->runtime_commit); - self->runtime_commit = g_value_dup_string (value); - break; - - case PROP_RUNTIME_VERSION: - g_free (self->runtime_version); - self->runtime_version = g_value_dup_string (value); - break; - - case PROP_SDK: - g_free (self->sdk); - self->sdk = g_value_dup_string (value); - break; - - case PROP_SDK_COMMIT: - g_free (self->sdk_commit); - self->sdk_commit = g_value_dup_string (value); - break; - - case PROP_BASE: - g_free (self->base); - self->base = g_value_dup_string (value); - break; - - case PROP_BASE_COMMIT: - g_free (self->base_commit); - self->base_commit = g_value_dup_string (value); - break; - - case PROP_BASE_VERSION: - g_free (self->base_version); - self->base_version = g_value_dup_string (value); - break; - - case PROP_BASE_EXTENSIONS: - tmp = self->base_extensions; - self->base_extensions = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - case PROP_VAR: - g_free (self->var); - self->var = g_value_dup_string (value); - break; - - case PROP_METADATA: - g_free (self->metadata); - self->metadata = g_value_dup_string (value); - break; - - case PROP_METADATA_PLATFORM: - g_free (self->metadata_platform); - self->metadata_platform = g_value_dup_string (value); - break; - - case PROP_COMMAND: - g_free (self->command); - self->command = g_value_dup_string (value); - break; - - case PROP_BUILD_OPTIONS: - g_set_object (&self->build_options, g_value_get_object (value)); - break; - - case PROP_MODULES: - g_list_free_full (self->modules, g_object_unref); - /* NOTE: This takes ownership of the list! */ - self->modules = g_value_get_pointer (value); - break; - - case PROP_ADD_EXTENSIONS: - g_list_free_full (self->add_extensions, g_object_unref); - /* NOTE: This takes ownership of the list! */ - self->add_extensions = g_value_get_pointer (value); - break; - - case PROP_CLEANUP: - tmp = self->cleanup; - self->cleanup = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - case PROP_CLEANUP_COMMANDS: - tmp = self->cleanup_commands; - self->cleanup_commands = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - case PROP_CLEANUP_PLATFORM: - tmp = self->cleanup_platform; - self->cleanup_platform = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - case PROP_CLEANUP_PLATFORM_COMMANDS: - tmp = self->cleanup_platform_commands; - self->cleanup_platform_commands = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - case PROP_FINISH_ARGS: - tmp = self->finish_args; - self->finish_args = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - case PROP_INHERIT_EXTENSIONS: - tmp = self->inherit_extensions; - self->inherit_extensions = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - case PROP_TAGS: - tmp = self->tags; - self->tags = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - case PROP_BUILD_RUNTIME: - self->build_runtime = g_value_get_boolean (value); - break; - - case PROP_BUILD_EXTENSION: - self->build_extension = g_value_get_boolean (value); - break; - - case PROP_SEPARATE_LOCALES: - self->separate_locales = g_value_get_boolean (value); - break; - - case PROP_WRITABLE_SDK: - self->writable_sdk = g_value_get_boolean (value); - break; - - case PROP_APPSTREAM_COMPOSE: - self->appstream_compose = g_value_get_boolean (value); - break; - - case PROP_SDK_EXTENSIONS: - tmp = self->sdk_extensions; - self->sdk_extensions = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - case PROP_PLATFORM_EXTENSIONS: - tmp = self->platform_extensions; - self->platform_extensions = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - case PROP_COPY_ICON: - self->copy_icon = g_value_get_boolean (value); - break; - - case PROP_RENAME_DESKTOP_FILE: - g_free (self->rename_desktop_file); - self->rename_desktop_file = g_value_dup_string (value); - break; - - case PROP_RENAME_APPDATA_FILE: - g_free (self->rename_appdata_file); - self->rename_appdata_file = g_value_dup_string (value); - break; - - case PROP_RENAME_ICON: - g_free (self->rename_icon); - self->rename_icon = g_value_dup_string (value); - break; - - case PROP_DESKTOP_FILE_NAME_PREFIX: - g_free (self->desktop_file_name_prefix); - self->desktop_file_name_prefix = g_value_dup_string (value); - break; - - case PROP_DESKTOP_FILE_NAME_SUFFIX: - g_free (self->desktop_file_name_suffix); - self->desktop_file_name_suffix = g_value_dup_string (value); - break; - - case PROP_COLLECTION_ID: - g_free (self->collection_id); - self->collection_id = g_value_dup_string (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -builder_manifest_class_init (BuilderManifestClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = builder_manifest_finalize; - object_class->get_property = builder_manifest_get_property; - object_class->set_property = builder_manifest_set_property; - - g_object_class_install_property (object_class, - PROP_APP_ID, - g_param_spec_string ("app-id", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_ID, - g_param_spec_string ("id", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_ID_PLATFORM, - g_param_spec_string ("id-platform", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_BRANCH, - g_param_spec_string ("branch", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_RUNTIME, - g_param_spec_string ("runtime", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_RUNTIME_COMMIT, - g_param_spec_string ("runtime-commit", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_RUNTIME_VERSION, - g_param_spec_string ("runtime-version", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_SDK, - g_param_spec_string ("sdk", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_SDK_COMMIT, - g_param_spec_string ("sdk-commit", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_BASE, - g_param_spec_string ("base", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_BASE_COMMIT, - g_param_spec_string ("base-commit", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_BASE_VERSION, - g_param_spec_string ("base-version", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_BASE_EXTENSIONS, - g_param_spec_boxed ("base-extensions", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_VAR, - g_param_spec_string ("var", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_METADATA, - g_param_spec_string ("metadata", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_METADATA_PLATFORM, - g_param_spec_string ("metadata-platform", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_COMMAND, - g_param_spec_string ("command", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_BUILD_OPTIONS, - g_param_spec_object ("build-options", - "", - "", - BUILDER_TYPE_OPTIONS, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_MODULES, - g_param_spec_pointer ("modules", - "", - "", - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_ADD_EXTENSIONS, - g_param_spec_pointer ("add-extensions", - "", - "", - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_CLEANUP, - g_param_spec_boxed ("cleanup", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_CLEANUP_COMMANDS, - g_param_spec_boxed ("cleanup-commands", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_CLEANUP_PLATFORM, - g_param_spec_boxed ("cleanup-platform", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_CLEANUP_PLATFORM_COMMANDS, - g_param_spec_boxed ("cleanup-platform-commands", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_FINISH_ARGS, - g_param_spec_boxed ("finish-args", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_INHERIT_EXTENSIONS, - g_param_spec_boxed ("inherit-extensions", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_BUILD_RUNTIME, - g_param_spec_boolean ("build-runtime", - "", - "", - FALSE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_BUILD_EXTENSION, - g_param_spec_boolean ("build-extension", - "", - "", - FALSE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_SEPARATE_LOCALES, - g_param_spec_boolean ("separate-locales", - "", - "", - TRUE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_WRITABLE_SDK, - g_param_spec_boolean ("writable-sdk", - "", - "", - FALSE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_APPSTREAM_COMPOSE, - g_param_spec_boolean ("appstream-compose", - "", - "", - TRUE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_SDK_EXTENSIONS, - g_param_spec_boxed ("sdk-extensions", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_PLATFORM_EXTENSIONS, - g_param_spec_boxed ("platform-extensions", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_TAGS, - g_param_spec_boxed ("tags", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_RENAME_DESKTOP_FILE, - g_param_spec_string ("rename-desktop-file", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_RENAME_APPDATA_FILE, - g_param_spec_string ("rename-appdata-file", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_RENAME_ICON, - g_param_spec_string ("rename-icon", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_COPY_ICON, - g_param_spec_boolean ("copy-icon", - "", - "", - FALSE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_DESKTOP_FILE_NAME_PREFIX, - g_param_spec_string ("desktop-file-name-prefix", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_DESKTOP_FILE_NAME_SUFFIX, - g_param_spec_string ("desktop-file-name-suffix", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_COLLECTION_ID, - g_param_spec_string ("collection-id", - "", - "", - NULL, - G_PARAM_READWRITE)); -} - -static void -builder_manifest_init (BuilderManifest *self) -{ - self->appstream_compose = TRUE; - self->separate_locales = TRUE; -} - -static JsonNode * -builder_manifest_serialize_property (JsonSerializable *serializable, - const gchar *property_name, - const GValue *value, - GParamSpec *pspec) -{ - if (strcmp (property_name, "modules") == 0) - { - BuilderManifest *self = BUILDER_MANIFEST (serializable); - JsonNode *retval = NULL; - GList *l; - - if (self->modules) - { - JsonArray *array; - - array = json_array_sized_new (g_list_length (self->modules)); - - for (l = self->modules; l != NULL; l = l->next) - { - JsonNode *child = json_gobject_serialize (l->data); - json_array_add_element (array, child); - } - - retval = json_node_init_array (json_node_alloc (), array); - json_array_unref (array); - } - - return retval; - } - else if (strcmp (property_name, "add-extensions") == 0) - { - BuilderManifest *self = BUILDER_MANIFEST (serializable); - JsonNode *retval = NULL; - - if (self->add_extensions) - { - JsonObject *object; - GList *l; - - object = json_object_new (); - - for (l = self->add_extensions; l != NULL; l = l->next) - { - BuilderExtension *e = l->data; - JsonNode *child = json_gobject_serialize (G_OBJECT (e)); - json_object_set_member (object, (char *) builder_extension_get_name (e), child); - } - - retval = json_node_init_object (json_node_alloc (), object); - json_object_unref (object); - } - - return retval; - } - else - { - return json_serializable_default_serialize_property (serializable, - property_name, - value, - pspec); - } -} - -static gint -sort_extension (gconstpointer a, - gconstpointer b) -{ - return strcmp (builder_extension_get_name (BUILDER_EXTENSION (a)), - builder_extension_get_name (BUILDER_EXTENSION (b))); -} - -static gboolean -builder_manifest_deserialize_property (JsonSerializable *serializable, - const gchar *property_name, - GValue *value, - GParamSpec *pspec, - JsonNode *property_node) -{ - if (strcmp (property_name, "modules") == 0) - { - if (JSON_NODE_TYPE (property_node) == JSON_NODE_NULL) - { - g_value_set_pointer (value, NULL); - return TRUE; - } - else if (JSON_NODE_TYPE (property_node) == JSON_NODE_ARRAY) - { - JsonArray *array = json_node_get_array (property_node); - guint i, array_len = json_array_get_length (array); - g_autoptr(GFile) saved_demarshal_base_dir = builder_manifest_get_demarshal_base_dir (); - GList *modules = NULL; - GObject *module; - - for (i = 0; i < array_len; i++) - { - JsonNode *element_node = json_array_get_element (array, i); - - module = NULL; - - if (JSON_NODE_HOLDS_VALUE (element_node) && - json_node_get_value_type (element_node) == G_TYPE_STRING) - { - const char *module_relpath = json_node_get_string (element_node); - g_autoptr(GFile) module_file = - g_file_resolve_relative_path (demarshal_base_dir, module_relpath); - const char *module_path = flatpak_file_get_path_cached (module_file); - g_autofree char *json = NULL; - g_autoptr(GError) error = NULL; - - if (g_file_get_contents (module_path, &json, NULL, &error)) - { - g_autoptr(GFile) module_file_dir = g_file_get_parent (module_file); - builder_manifest_set_demarshal_base_dir (module_file_dir); - module = json_gobject_from_data (BUILDER_TYPE_MODULE, - json, -1, &error); - builder_manifest_set_demarshal_base_dir (saved_demarshal_base_dir); - if (module) - { - builder_module_set_json_path (BUILDER_MODULE (module), module_path); - builder_module_set_base_dir (BUILDER_MODULE (module), module_file_dir); - } - } - if (error != NULL) - { - g_error ("Failed to load included manifest (%s): %s", module_path, error->message); - } - } - else if (JSON_NODE_HOLDS_OBJECT (element_node)) - { - module = json_gobject_deserialize (BUILDER_TYPE_MODULE, element_node); - if (module != NULL) - builder_module_set_base_dir (BUILDER_MODULE (module), saved_demarshal_base_dir); - } - - if (module == NULL) - { - g_list_free_full (modules, g_object_unref); - return FALSE; - } - - modules = g_list_prepend (modules, module); - } - - g_value_set_pointer (value, g_list_reverse (modules)); - - return TRUE; - } - - return FALSE; - } - else if (strcmp (property_name, "add-extensions") == 0) - { - if (JSON_NODE_TYPE (property_node) == JSON_NODE_NULL) - { - g_value_set_pointer (value, NULL); - return TRUE; - } - else if (JSON_NODE_TYPE (property_node) == JSON_NODE_OBJECT) - { - JsonObject *object = json_node_get_object (property_node); - g_autoptr(GHashTable) hash = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref); - g_autoptr(GList) members = NULL; - GList *extensions; - GList *l; - - members = json_object_get_members (object); - for (l = members; l != NULL; l = l->next) - { - const char *member_name = l->data; - JsonNode *val; - GObject *extension; - - val = json_object_get_member (object, member_name); - extension = json_gobject_deserialize (BUILDER_TYPE_EXTENSION, val); - if (extension == NULL) - return FALSE; - - builder_extension_set_name (BUILDER_EXTENSION (extension), member_name); - g_hash_table_insert (hash, (char *)builder_extension_get_name (BUILDER_EXTENSION (extension)), extension); - } - - extensions = g_hash_table_get_values (hash); - g_hash_table_steal_all (hash); - - extensions = g_list_sort (extensions, sort_extension); - g_value_set_pointer (value, extensions); - - return TRUE; - } - - return FALSE; - } - else - { - return json_serializable_default_deserialize_property (serializable, - property_name, - value, - pspec, property_node); - } -} - -static void -serializable_iface_init (JsonSerializableIface *serializable_iface) -{ - serializable_iface->serialize_property = builder_manifest_serialize_property; - serializable_iface->deserialize_property = builder_manifest_deserialize_property; - serializable_iface->find_property = builder_serializable_find_property_with_error; -} - -const char * -builder_manifest_get_id (BuilderManifest *self) -{ - return self->id; -} - -char * -builder_manifest_get_locale_id (BuilderManifest *self) -{ - g_autofree char *id = flatpak_make_valid_id_prefix (self->id); - return g_strdup_printf ("%s.Locale", id); -} - -char * -builder_manifest_get_debug_id (BuilderManifest *self) -{ - g_autofree char *id = flatpak_make_valid_id_prefix (self->id); - return g_strdup_printf ("%s.Debug", id); -} - -char * -builder_manifest_get_sources_id (BuilderManifest *self) -{ - g_autofree char *id = flatpak_make_valid_id_prefix (self->id); - return g_strdup_printf ("%s.Sources", id); -} - -const char * -builder_manifest_get_id_platform (BuilderManifest *self) -{ - return self->id_platform; -} - -char * -builder_manifest_get_locale_id_platform (BuilderManifest *self) -{ - char *res = NULL; - - if (self->id_platform != NULL) - { - g_autofree char *id = flatpak_make_valid_id_prefix (self->id_platform); - res = g_strdup_printf ("%s.Locale", id); - } - - return res; -} - -BuilderOptions * -builder_manifest_get_build_options (BuilderManifest *self) -{ - return self->build_options; -} - -GList * -builder_manifest_get_modules (BuilderManifest *self) -{ - return self->modules; -} - -GList * -builder_manifest_get_add_extensions (BuilderManifest *self) -{ - return self->add_extensions; -} - -static const char * -builder_manifest_get_runtime_version (BuilderManifest *self) -{ - return self->runtime_version ? self->runtime_version : "master"; -} - -const char * -builder_manifest_get_branch (BuilderManifest *self) -{ - if (self->branch) - return self->branch; - - return "master"; -} - -void -builder_manifest_set_default_branch (BuilderManifest *self, - const char *default_branch) -{ - if (self->branch == NULL) - self->branch = g_strdup (default_branch); -} - -const char * -builder_manifest_get_collection_id (BuilderManifest *self) -{ - return self->collection_id; -} - -void -builder_manifest_set_default_collection_id (BuilderManifest *self, - const char *default_collection_id) -{ - if (self->collection_id == NULL) - self->collection_id = g_strdup (default_collection_id); -} - -static const char * -builder_manifest_get_base_version (BuilderManifest *self) -{ - return self->base_version ? self->base_version : builder_manifest_get_branch (self); -} - -static char * -flatpak (GError **error, - ...) -{ - gboolean res; - g_autofree char *output = NULL; - va_list ap; - - va_start (ap, error); - res = flatpak_spawn (NULL, &output, error, "flatpak", ap); - va_end (ap); - - if (res) - { - g_strchomp (output); - return g_steal_pointer (&output); - } - return NULL; -} - -static void -add_installation_args (GPtrArray *args, - gboolean opt_user, - const char *opt_installation) -{ - if (opt_user) - g_ptr_array_add (args, g_strdup ("--user")); - else if (opt_installation) - g_ptr_array_add (args, g_strdup_printf ("--installation=%s", opt_installation)); - else - g_ptr_array_add (args, g_strdup ("--system")); -} - -static char * -flatpak_info (gboolean opt_user, - const char *opt_installation, - const char *ref, - const char *extra_arg, - GError **error) -{ - gboolean res; - g_autofree char *output = NULL; - g_autoptr(GPtrArray) args = NULL; - - args = g_ptr_array_new_with_free_func (g_free); - g_ptr_array_add (args, g_strdup ("flatpak")); - add_installation_args (args, opt_user, opt_installation); - g_ptr_array_add (args, g_strdup ("info")); - if (extra_arg) - g_ptr_array_add (args, g_strdup (extra_arg)); - g_ptr_array_add (args, g_strdup (ref)); - g_ptr_array_add (args, NULL); - - res = flatpak_spawnv (NULL, &output, G_SUBPROCESS_FLAGS_STDERR_SILENCE, error, (const char * const *)args->pdata); - - if (res) - { - g_strchomp (output); - return g_steal_pointer (&output); - } - return NULL; -} - -gboolean -builder_manifest_start (BuilderManifest *self, - gboolean allow_missing_runtimes, - BuilderContext *context, - GError **error) -{ - g_autofree char *arch_option = NULL; - g_autoptr(GHashTable) names = g_hash_table_new (g_str_hash, g_str_equal); - const char *stop_at; - - if (self->sdk == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "sdk not specified"); - return FALSE; - } - - arch_option = g_strdup_printf ("--arch=%s", builder_context_get_arch (context)); - - self->sdk_commit = flatpak (NULL, "info", arch_option, "--show-commit", self->sdk, - builder_manifest_get_runtime_version (self), NULL); - if (!allow_missing_runtimes && self->sdk_commit == NULL) - return flatpak_fail (error, "Unable to find sdk %s version %s", - self->sdk, - builder_manifest_get_runtime_version (self)); - - self->runtime_commit = flatpak (NULL, "info", arch_option, "--show-commit", self->runtime, - builder_manifest_get_runtime_version (self), NULL); - if (!allow_missing_runtimes && self->runtime_commit == NULL) - return flatpak_fail (error, "Unable to find runtime %s version %s", - self->runtime, - builder_manifest_get_runtime_version (self)); - - if (self->base != NULL && *self->base != 0) - { - self->base_commit = flatpak (NULL, "info", arch_option, "--show-commit", self->base, - builder_manifest_get_base_version (self), NULL); - if (self->base_commit == NULL) - return flatpak_fail (error, "Unable to find app %s version %s", - self->base, builder_manifest_get_base_version (self)); - } - - if (!expand_modules (context, self->modules, &self->expanded_modules, names, error)) - return FALSE; - - stop_at = builder_context_get_stop_at (context); - if (stop_at != NULL && g_hash_table_lookup (names, stop_at) == NULL) - return flatpak_fail (error, "No module named %s (specified with --stop-at)", stop_at); - - return TRUE; -} - -gboolean -builder_manifest_init_app_dir (BuilderManifest *self, - BuilderCache *cache, - BuilderContext *context, - GError **error) -{ - GFile *app_dir = builder_context_get_app_dir (context); - - g_autoptr(GSubprocess) subp = NULL; - g_autoptr(GPtrArray) args = NULL; - g_autofree char *commandline = NULL; - int i; - - g_print ("Initializing build dir\n"); - - if (self->id == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "id not specified"); - return FALSE; - } - - if (self->runtime == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "runtime not specified"); - return FALSE; - } - - if (self->sdk == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "sdk not specified"); - return FALSE; - } - - args = g_ptr_array_new_with_free_func (g_free); - - g_ptr_array_add (args, g_strdup ("flatpak")); - g_ptr_array_add (args, g_strdup ("build-init")); - if (self->writable_sdk || self->build_runtime) - { - if (self->build_runtime) - g_ptr_array_add (args, g_strdup ("--type=runtime")); - else - g_ptr_array_add (args, g_strdup ("--writable-sdk")); - } - - for (i = 0; self->sdk_extensions != NULL && self->sdk_extensions[i] != NULL; i++) - { - const char *ext = self->sdk_extensions[i]; - g_ptr_array_add (args, g_strdup_printf ("--sdk-extension=%s", ext)); - } - - if (self->build_extension) - { - g_ptr_array_add (args, g_strdup ("--type=extension")); - } - if (self->tags) - { - for (i = 0; self->tags[i] != NULL; i++) - g_ptr_array_add (args, g_strdup_printf ("--tag=%s", self->tags[i])); - } - if (self->var) - g_ptr_array_add (args, g_strdup_printf ("--var=%s", self->var)); - - if (self->base) - { - g_ptr_array_add (args, g_strdup_printf ("--base=%s", self->base)); - g_ptr_array_add (args, g_strdup_printf ("--base-version=%s", builder_manifest_get_base_version (self))); - - for (i = 0; self->base_extensions != NULL && self->base_extensions[i] != NULL; i++) - { - const char *ext = self->base_extensions[i]; - g_ptr_array_add (args, g_strdup_printf ("--base-extension=%s", ext)); - } - } - - g_ptr_array_add (args, g_strdup_printf ("--arch=%s", builder_context_get_arch (context))); - g_ptr_array_add (args, g_file_get_path (app_dir)); - g_ptr_array_add (args, g_strdup (self->id)); - g_ptr_array_add (args, g_strdup (self->sdk)); - g_ptr_array_add (args, g_strdup (self->runtime)); - g_ptr_array_add (args, g_strdup (builder_manifest_get_runtime_version (self))); - g_ptr_array_add (args, NULL); - - commandline = flatpak_quote_argv ((const char **) args->pdata); - g_debug ("Running '%s'", commandline); - - subp = - g_subprocess_newv ((const gchar * const *) args->pdata, - G_SUBPROCESS_FLAGS_NONE, - error); - - if (subp == NULL || - !g_subprocess_wait_check (subp, NULL, error)) - return FALSE; - - if (self->build_runtime && self->separate_locales) - { - g_autoptr(GFile) root_dir = NULL; - - root_dir = g_file_get_child (app_dir, "usr"); - - if (!builder_migrate_locale_dirs (root_dir, error)) - return FALSE; - } - - /* Fix up any python timestamps from base */ - if (!builder_post_process (BUILDER_POST_PROCESS_FLAGS_PYTHON_TIMESTAMPS, app_dir, - cache, context, error)) - return FALSE; - - return TRUE; -} - -/* This gets the checksum of everything that globally affects the build */ -void -builder_manifest_checksum (BuilderManifest *self, - BuilderCache *cache, - BuilderContext *context) -{ - builder_cache_checksum_str (cache, BUILDER_MANIFEST_CHECKSUM_VERSION); - builder_cache_checksum_str (cache, self->id); - /* No need to include version here, it doesn't affect the build */ - builder_cache_checksum_str (cache, self->runtime); - builder_cache_checksum_str (cache, builder_manifest_get_runtime_version (self)); - builder_cache_checksum_str (cache, self->sdk); - /* Always rebuild on sdk change if we're actually including the sdk in the cache */ - if (self->writable_sdk || self->build_runtime || - builder_context_get_rebuild_on_sdk_change (context)) - builder_cache_checksum_str (cache, self->sdk_commit); - builder_cache_checksum_str (cache, self->var); - builder_cache_checksum_str (cache, self->metadata); - builder_cache_checksum_strv (cache, self->tags); - builder_cache_checksum_boolean (cache, self->writable_sdk); - builder_cache_checksum_strv (cache, self->sdk_extensions); - builder_cache_checksum_boolean (cache, self->build_runtime); - builder_cache_checksum_boolean (cache, self->build_extension); - builder_cache_checksum_boolean (cache, self->separate_locales); - builder_cache_checksum_str (cache, self->base); - builder_cache_checksum_str (cache, self->base_version); - builder_cache_checksum_str (cache, self->base_commit); - builder_cache_checksum_strv (cache, self->base_extensions); - - if (self->build_options) - builder_options_checksum (self->build_options, cache, context); -} - -static void -builder_manifest_checksum_for_cleanup (BuilderManifest *self, - BuilderCache *cache, - BuilderContext *context) -{ - GList *l; - - builder_cache_checksum_str (cache, BUILDER_MANIFEST_CHECKSUM_CLEANUP_VERSION); - builder_cache_checksum_strv (cache, self->cleanup); - builder_cache_checksum_strv (cache, self->cleanup_commands); - builder_cache_checksum_str (cache, self->rename_desktop_file); - builder_cache_checksum_str (cache, self->rename_appdata_file); - builder_cache_checksum_str (cache, self->rename_icon); - builder_cache_checksum_boolean (cache, self->copy_icon); - builder_cache_checksum_str (cache, self->desktop_file_name_prefix); - builder_cache_checksum_str (cache, self->desktop_file_name_suffix); - builder_cache_checksum_boolean (cache, self->appstream_compose); - - for (l = self->expanded_modules; l != NULL; l = l->next) - { - BuilderModule *m = l->data; - builder_module_checksum_for_cleanup (m, cache, context); - } -} - -static void -builder_manifest_checksum_for_finish (BuilderManifest *self, - BuilderCache *cache, - BuilderContext *context) -{ - GList *l; - - builder_cache_checksum_str (cache, BUILDER_MANIFEST_CHECKSUM_FINISH_VERSION); - builder_cache_checksum_strv (cache, self->finish_args); - builder_cache_checksum_str (cache, self->command); - builder_cache_checksum_compat_strv (cache, self->inherit_extensions); - - for (l = self->add_extensions; l != NULL; l = l->next) - { - BuilderExtension *e = l->data; - builder_extension_checksum (e, cache, context); - } - - if (self->metadata) - { - GFile *base_dir = builder_context_get_base_dir (context); - g_autoptr(GFile) metadata = g_file_resolve_relative_path (base_dir, self->metadata); - g_autofree char *data = NULL; - g_autoptr(GError) my_error = NULL; - gsize len; - - if (g_file_load_contents (metadata, NULL, &data, &len, NULL, &my_error)) - builder_cache_checksum_data (cache, (guchar *) data, len); - else - g_warning ("Can't load metadata file %s: %s", self->metadata, my_error->message); - } -} - -static void -builder_manifest_checksum_for_bundle_sources (BuilderManifest *self, - BuilderCache *cache, - BuilderContext *context) -{ - builder_cache_checksum_str (cache, BUILDER_MANIFEST_CHECKSUM_BUNDLE_SOURCES_VERSION); - builder_cache_checksum_boolean (cache, builder_context_get_bundle_sources (context)); -} - -static void -builder_manifest_checksum_for_platform (BuilderManifest *self, - BuilderCache *cache, - BuilderContext *context) -{ - GList *l; - - builder_cache_checksum_str (cache, BUILDER_MANIFEST_CHECKSUM_PLATFORM_VERSION); - builder_cache_checksum_str (cache, self->id_platform); - builder_cache_checksum_str (cache, self->runtime_commit); - builder_cache_checksum_str (cache, self->metadata_platform); - builder_cache_checksum_strv (cache, self->cleanup_platform); - builder_cache_checksum_strv (cache, self->cleanup_platform_commands); - builder_cache_checksum_strv (cache, self->platform_extensions); - - if (self->metadata_platform) - { - GFile *base_dir = builder_context_get_base_dir (context); - g_autoptr(GFile) metadata = g_file_resolve_relative_path (base_dir, self->metadata_platform); - g_autofree char *data = NULL; - g_autoptr(GError) my_error = NULL; - gsize len; - - if (g_file_load_contents (metadata, NULL, &data, &len, NULL, &my_error)) - builder_cache_checksum_data (cache, (guchar *) data, len); - else - g_warning ("Can't load metadata-platform file %s: %s", self->metadata_platform, my_error->message); - } - - for (l = self->expanded_modules; l != NULL; l = l->next) - { - BuilderModule *m = l->data; - builder_module_checksum_for_platform (m, cache, context); - } -} - -gboolean -builder_manifest_download (BuilderManifest *self, - gboolean update_vcs, - const char *only_module, - BuilderContext *context, - GError **error) -{ - const char *stop_at = builder_context_get_stop_at (context); - GList *l; - - g_print ("Downloading sources\n"); - for (l = self->expanded_modules; l != NULL; l = l->next) - { - BuilderModule *m = l->data; - const char *name = builder_module_get_name (m); - - if (only_module && strcmp (name, only_module) != 0) - continue; - - if (stop_at != NULL && strcmp (name, stop_at) == 0) - { - g_print ("Stopping at module %s\n", stop_at); - return TRUE; - } - - if (!builder_module_download_sources (m, update_vcs, context, error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -setup_context (BuilderManifest *self, - BuilderContext *context, - GError **error) -{ - builder_context_set_options (context, self->build_options); - builder_context_set_global_cleanup (context, (const char **) self->cleanup); - builder_context_set_global_cleanup_platform (context, (const char **) self->cleanup_platform); - if (self->build_runtime && self->build_extension) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Can't build both a runtime and an extension"); - return FALSE; - } - builder_context_set_build_runtime (context, self->build_runtime); - builder_context_set_build_extension (context, self->build_extension); - builder_context_set_separate_locales (context, self->separate_locales); - return TRUE; -} - -gboolean -builder_manifest_build_shell (BuilderManifest *self, - BuilderContext *context, - const char *modulename, - GError **error) -{ - GList *l; - BuilderModule *found = NULL; - - if (!builder_context_enable_rofiles (context, error)) - return FALSE; - - if (!setup_context (self, context, error)) - return FALSE; - - for (l = self->expanded_modules; l != NULL; l = l->next) - { - BuilderModule *m = l->data; - const char *name = builder_module_get_name (m); - - if (strcmp (name, modulename) == 0) - { - found = m; - break; - } - } - - if (found == NULL) - return flatpak_fail (error, "Can't find module %s", modulename); - - if (!builder_module_build (found, NULL, context, TRUE, error)) - return FALSE; - - return TRUE; -} - -gboolean -builder_manifest_build (BuilderManifest *self, - BuilderCache *cache, - BuilderContext *context, - GError **error) -{ - const char *stop_at = builder_context_get_stop_at (context); - GList *l; - - if (!setup_context (self, context, error)) - return FALSE; - - g_print ("Starting build of %s\n", self->id ? self->id : "app"); - for (l = self->expanded_modules; l != NULL; l = l->next) - { - BuilderModule *m = l->data; - g_autoptr(GPtrArray) changes = NULL; - const char *name = builder_module_get_name (m); - - g_autofree char *stage = g_strdup_printf ("build-%s", name); - - if (stop_at != NULL && strcmp (name, stop_at) == 0) - { - g_print ("Stopping at module %s\n", stop_at); - return TRUE; - } - - if (!builder_module_should_build (m)) - { - g_print ("Skipping module %s (no sources)\n", name); - continue; - } - - builder_module_checksum (m, cache, context); - - if (!builder_cache_lookup (cache, stage)) - { - g_autofree char *body = - g_strdup_printf ("Built %s\n", name); - if (!builder_module_ensure_writable (m, cache, context, error)) - return FALSE; - if (!builder_context_enable_rofiles (context, error)) - return FALSE; - if (!builder_module_build (m, cache, context, FALSE, error)) - return FALSE; - if (!builder_context_disable_rofiles (context, error)) - return FALSE; - if (!builder_cache_commit (cache, body, error)) - return FALSE; - } - else - { - g_print ("Cache hit for %s, skipping build\n", name); - } - - changes = builder_cache_get_changes (cache, error); - if (changes == NULL) - return FALSE; - - builder_module_set_changes (m, changes); - - builder_module_update (m, context, error); - } - - return TRUE; -} - -static gboolean -command (GFile *app_dir, - char **env_vars, - char **extra_args, - const char *commandline, - GError **error) -{ - g_autoptr(GPtrArray) args = NULL; - int i; - - args = g_ptr_array_new_with_free_func (g_free); - g_ptr_array_add (args, g_strdup ("flatpak")); - g_ptr_array_add (args, g_strdup ("build")); - - g_ptr_array_add (args, g_strdup ("--nofilesystem=host")); - if (extra_args) - { - for (i = 0; extra_args[i] != NULL; i++) - g_ptr_array_add (args, g_strdup (extra_args[i])); - } - - if (env_vars) - { - for (i = 0; env_vars[i] != NULL; i++) - g_ptr_array_add (args, g_strdup_printf ("--env=%s", env_vars[i])); - } - - 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 (commandline)); - g_ptr_array_add (args, NULL); - - return builder_maybe_host_spawnv (NULL, NULL, error, (const char * const *)args->pdata); -} - -typedef gboolean (*ForeachFileFunc) (BuilderManifest *self, - int source_parent_fd, - const char *source_name, - const char *full_dir, - const char *rel_dir, - struct stat *stbuf, - gboolean *found, - int depth, - GError **error); - -static gboolean -foreach_file_helper (BuilderManifest *self, - ForeachFileFunc func, - int source_parent_fd, - const char *source_name, - const char *full_dir, - const char *rel_dir, - gboolean *found, - int depth, - GError **error) -{ - g_auto(GLnxDirFdIterator) source_iter = {0}; - struct dirent *dent; - g_autoptr(GError) my_error = NULL; - - if (!glnx_dirfd_iterator_init_at (source_parent_fd, source_name, FALSE, &source_iter, &my_error)) - { - if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) - return TRUE; - - g_propagate_error (error, g_steal_pointer (&my_error)); - return FALSE; - } - - while (TRUE) - { - struct stat stbuf; - - if (!glnx_dirfd_iterator_next_dent (&source_iter, &dent, NULL, error)) - return FALSE; - - if (dent == NULL) - break; - - if (fstatat (source_iter.fd, dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW) == -1) - { - if (errno == ENOENT) - { - continue; - } - else - { - glnx_set_error_from_errno (error); - return FALSE; - } - } - - if (S_ISDIR (stbuf.st_mode)) - { - g_autofree char *child_dir = g_build_filename (full_dir, dent->d_name, NULL); - g_autofree char *child_rel_dir = g_build_filename (rel_dir, dent->d_name, NULL); - if (!foreach_file_helper (self, func, source_iter.fd, dent->d_name, child_dir, child_rel_dir, found, depth + 1, error)) - return FALSE; - } - - if (!func (self, source_iter.fd, dent->d_name, full_dir, rel_dir, &stbuf, found, depth, error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -foreach_file (BuilderManifest *self, - ForeachFileFunc func, - gboolean *found, - GFile *root, - GError **error) -{ - return foreach_file_helper (self, func, AT_FDCWD, - flatpak_file_get_path_cached (root), - flatpak_file_get_path_cached (root), - "", - found, 0, - error); -} - -static gboolean -rename_icon_cb (BuilderManifest *self, - int source_parent_fd, - const char *source_name, - const char *full_dir, - const char *rel_dir, - struct stat *stbuf, - gboolean *found, - int depth, - GError **error) -{ - if (g_str_has_prefix (source_name, self->rename_icon)) - { - if (S_ISREG (stbuf->st_mode) && - depth == 3 && - (g_str_has_prefix (source_name + strlen (self->rename_icon), ".") || - g_str_has_prefix (source_name + strlen (self->rename_icon), "-symbolic."))) - { - const char *extension = source_name + strlen (self->rename_icon); - g_autofree char *new_name = g_strconcat (self->id, extension, NULL); - int res; - - *found = TRUE; - - g_print ("%s icon %s/%s to %s/%s\n", self->copy_icon ? "Copying" : "Renaming", rel_dir, source_name, rel_dir, new_name); - - if (self->copy_icon) - res = linkat (source_parent_fd, source_name, source_parent_fd, new_name, AT_SYMLINK_FOLLOW); - else - res = renameat (source_parent_fd, source_name, source_parent_fd, new_name); - - if (res != 0) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "Can't rename icon %s/%s", rel_dir, source_name); - return FALSE; - } - } - else - { - if (!S_ISREG (stbuf->st_mode)) - g_debug ("%s/%s matches 'rename-icon', but not a regular file", full_dir, source_name); - else if (depth != 3) - g_debug ("%s/%s matches 'rename-icon', but not at depth 3", full_dir, source_name); - else - g_debug ("%s/%s matches 'rename-icon', but name does not continue with '.' or '-symbolic.'", full_dir, source_name); - } - } - - return TRUE; -} - -static int -cmpstringp (const void *p1, const void *p2) -{ - return strcmp (*(char * const *) p1, *(char * const *) p2); -} - -static gboolean -appstream_compose (GFile *app_dir, - GError **error, - ...) -{ - g_autoptr(GPtrArray) args = NULL; - const gchar *arg; - va_list ap; - - args = g_ptr_array_new_with_free_func (g_free); - g_ptr_array_add (args, g_strdup ("flatpak")); - g_ptr_array_add (args, g_strdup ("build")); - g_ptr_array_add (args, g_strdup ("--nofilesystem=host")); - g_ptr_array_add (args, g_file_get_path (app_dir)); - g_ptr_array_add (args, g_strdup ("appstream-compose")); - - va_start (ap, error); - while ((arg = va_arg (ap, const gchar *))) - g_ptr_array_add (args, g_strdup (arg)); - g_ptr_array_add (args, NULL); - va_end (ap); - - if (!builder_maybe_host_spawnv (NULL, NULL, error, (const char * const *)args->pdata)) - { - g_prefix_error (error, "ERROR: appstream-compose failed: "); - return FALSE; - } - - return TRUE; -} - -static char ** -strcatv (char **strv1, - char **strv2) -{ - if (strv1 == NULL && strv2 == NULL) - return NULL; - if (strv1 == NULL) - return g_strdupv (strv2); - if (strv2 == NULL) - return g_strdupv (strv1); - - unsigned len1 = g_strv_length (strv1); - unsigned len2 = g_strv_length (strv2); - char **retval = g_new (char *, len1 + len2 + 1); - unsigned ix; - - for (ix = 0; ix < len1; ix++) - retval[ix] = g_strdup (strv1[ix]); - for (ix = 0; ix < len2; ix++) - retval[len1 + ix] = g_strdup (strv2[ix]); - retval[len1 + len2] = NULL; - - return retval; -} - -gboolean -builder_manifest_cleanup (BuilderManifest *self, - BuilderCache *cache, - BuilderContext *context, - GError **error) -{ - g_autoptr(GFile) app_root = NULL; - GList *l; - g_auto(GStrv) env = NULL; - g_autoptr(GFile) appdata_dir = NULL; - g_autofree char *appdata_basename = NULL; - g_autoptr(GFile) appdata_file = NULL; - g_autoptr(GFile) appdata_source = NULL; - int i; - - builder_manifest_checksum_for_cleanup (self, cache, context); - if (!builder_cache_lookup (cache, "cleanup")) - { - g_autoptr(GHashTable) to_remove_ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - g_autofree char **keys = NULL; - GFile *app_dir = NULL; - guint n_keys; - - g_print ("Cleaning up\n"); - - if (!builder_context_enable_rofiles (context, error)) - return FALSE; - - /* Call after enabling rofiles */ - app_dir = builder_context_get_app_dir (context); - - if (self->cleanup_commands) - { - g_auto(GStrv) build_args = builder_options_get_build_args (self->build_options, context, error); - if (!build_args) - return FALSE; - env = builder_options_get_env (self->build_options, context); - for (i = 0; self->cleanup_commands[i] != NULL; i++) - { - if (!command (app_dir, env, build_args, self->cleanup_commands[i], error)) - return FALSE; - } - } - - for (l = self->expanded_modules; l != NULL; l = l->next) - { - BuilderModule *m = l->data; - - builder_module_cleanup_collect (m, FALSE, context, to_remove_ht); - } - - keys = (char **) g_hash_table_get_keys_as_array (to_remove_ht, &n_keys); - - qsort (keys, n_keys, sizeof (char *), cmpstringp); - /* Iterate in reverse to remove leafs first */ - for (i = n_keys - 1; i >= 0; i--) - { - g_autoptr(GError) my_error = NULL; - g_autoptr(GFile) f = g_file_resolve_relative_path (app_dir, keys[i]); - g_print ("Removing %s\n", keys[i]); - if (!g_file_delete (f, NULL, &my_error)) - { - if (!g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) && - !g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_EMPTY)) - { - g_propagate_error (error, g_steal_pointer (&my_error)); - return FALSE; - } - } - } - - app_root = g_file_get_child (app_dir, "files"); - - appdata_basename = g_strdup_printf ("%s.appdata.xml", self->id); - appdata_dir = g_file_resolve_relative_path (app_root, "share/appdata"); - appdata_source = g_file_get_child (appdata_dir, self->rename_appdata_file ? self->rename_appdata_file : appdata_basename); - if (!g_file_query_exists (appdata_source, NULL)) - { - g_object_unref (appdata_dir); - appdata_dir = g_file_resolve_relative_path (app_root, "share/metainfo"); - } - appdata_file = g_file_get_child (appdata_dir, appdata_basename); - - if (self->rename_appdata_file != NULL) - { - g_autoptr(GFile) src = g_file_get_child (appdata_dir, self->rename_appdata_file); - - g_print ("Renaming %s to %s\n", self->rename_appdata_file, appdata_basename); - if (!g_file_move (src, appdata_file, 0, NULL, NULL, NULL, error)) - return FALSE; - } - - if (self->rename_desktop_file != NULL) - { - g_autoptr(GFile) applications_dir = g_file_resolve_relative_path (app_root, "share/applications"); - g_autoptr(GFile) src = g_file_get_child (applications_dir, self->rename_desktop_file); - g_autofree char *desktop_basename = g_strdup_printf ("%s.desktop", self->id); - g_autoptr(GFile) dest = g_file_get_child (applications_dir, desktop_basename); - - g_print ("Renaming %s to %s\n", self->rename_desktop_file, desktop_basename); - if (!g_file_move (src, dest, 0, NULL, NULL, NULL, error)) - return FALSE; - - if (g_file_query_exists (appdata_file, NULL)) - { - g_autofree char *contents; - const char *to_replace; - const char *match; - g_autoptr(GString) new_contents = NULL; - - if (!g_file_load_contents (appdata_file, NULL, &contents, NULL, NULL, error)) - return FALSE; - - new_contents = g_string_sized_new (strlen (contents)); - - to_replace = contents; - - while ((match = strstr (to_replace, self->rename_desktop_file)) != NULL) - { - g_string_append_len (new_contents, to_replace, match - to_replace); - g_string_append (new_contents, desktop_basename); - to_replace = match + strlen (self->rename_desktop_file); - } - - g_string_append (new_contents, to_replace); - - if (!g_file_set_contents (flatpak_file_get_path_cached (appdata_file), - new_contents->str, - new_contents->len, - error)) - return FALSE; - } - } - - if (self->rename_icon) - { - gboolean found_icon = FALSE; - g_autoptr(GFile) icons_dir = g_file_resolve_relative_path (app_root, "share/icons"); - - if (!foreach_file (self, rename_icon_cb, &found_icon, icons_dir, error)) - return FALSE; - - if (!found_icon) - { - g_autofree char *icon_path = g_file_get_path (icons_dir); - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "icon %s not found below %s", - self->rename_icon, icon_path); - return FALSE; - } - } - - if (self->rename_icon || - self->desktop_file_name_prefix || - self->desktop_file_name_suffix) - { - g_autoptr(GFile) applications_dir = g_file_resolve_relative_path (app_root, "share/applications"); - g_autofree char *desktop_basename = g_strdup_printf ("%s.desktop", self->id); - g_autoptr(GFile) desktop = g_file_get_child (applications_dir, desktop_basename); - g_autoptr(GKeyFile) keyfile = g_key_file_new (); - g_autofree char *desktop_contents = NULL; - gsize desktop_size; - g_auto(GStrv) desktop_keys = NULL; - - g_print ("Rewriting contents of %s\n", desktop_basename); - if (!g_file_load_contents (desktop, NULL, - &desktop_contents, &desktop_size, NULL, error)) - { - g_autofree char *desktop_path = g_file_get_path (desktop); - g_prefix_error (error, "Can't load desktop file %s: ", desktop_path); - return FALSE; - } - - if (!g_key_file_load_from_data (keyfile, - desktop_contents, desktop_size, - G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, - error)) - return FALSE; - - desktop_keys = g_key_file_get_keys (keyfile, - G_KEY_FILE_DESKTOP_GROUP, - NULL, NULL); - - if (self->rename_icon) - { - g_autofree char *original_icon_name = g_key_file_get_string (keyfile, - G_KEY_FILE_DESKTOP_GROUP, - G_KEY_FILE_DESKTOP_KEY_ICON, - NULL); - - g_key_file_set_string (keyfile, - G_KEY_FILE_DESKTOP_GROUP, - G_KEY_FILE_DESKTOP_KEY_ICON, - self->id); - - /* Also rename localized version of the Icon= field */ - for (i = 0; desktop_keys[i]; i++) - { - /* Only rename untranslated icon names */ - if (g_str_has_prefix (desktop_keys[i], "Icon[")) - { - g_autofree char *icon_name = g_key_file_get_string (keyfile, - G_KEY_FILE_DESKTOP_GROUP, - desktop_keys[i], NULL); - - if (strcmp (icon_name, original_icon_name) == 0) - g_key_file_set_string (keyfile, - G_KEY_FILE_DESKTOP_GROUP, - desktop_keys[i], - self->id); - } - } - } - - if (self->desktop_file_name_suffix || - self->desktop_file_name_prefix) - { - for (i = 0; desktop_keys[i]; i++) - { - if (strcmp (desktop_keys[i], "Name") == 0 || - g_str_has_prefix (desktop_keys[i], "Name[")) - { - g_autofree char *name = g_key_file_get_string (keyfile, G_KEY_FILE_DESKTOP_GROUP, desktop_keys[i], NULL); - if (name) - { - g_autofree char *new_name = - g_strdup_printf ("%s%s%s", - self->desktop_file_name_prefix ? self->desktop_file_name_prefix : "", - name, - self->desktop_file_name_suffix ? self->desktop_file_name_suffix : ""); - g_key_file_set_string (keyfile, - G_KEY_FILE_DESKTOP_GROUP, - desktop_keys[i], - new_name); - } - } - } - } - - g_free (desktop_contents); - desktop_contents = g_key_file_to_data (keyfile, &desktop_size, error); - if (desktop_contents == NULL) - return FALSE; - - if (!g_file_set_contents (flatpak_file_get_path_cached (desktop), - desktop_contents, desktop_size, error)) - return FALSE; - } - - if (self->appstream_compose && - g_file_query_exists (appdata_file, NULL)) - { - g_autofree char *basename_arg = g_strdup_printf ("--basename=%s", self->id); - g_print ("Running appstream-compose\n"); - if (!appstream_compose (app_dir, error, - self->build_runtime ? "--prefix=/usr" : "--prefix=/app", - "--origin=flatpak", - basename_arg, - self->id, - NULL)) - return FALSE; - } - - if (!builder_context_disable_rofiles (context, error)) - return FALSE; - - if (!builder_cache_commit (cache, "Cleanup", error)) - return FALSE; - } - else - { - g_print ("Cache hit for cleanup, skipping\n"); - } - - return TRUE; -} - - -gboolean -builder_manifest_finish (BuilderManifest *self, - BuilderCache *cache, - BuilderContext *context, - GError **error) -{ - g_autoptr(GFile) manifest_file = NULL; - g_autoptr(GFile) debuginfo_dir = NULL; - g_autoptr(GFile) sources_dir = NULL; - g_autoptr(GFile) locale_parent_dir = NULL; - g_autofree char *json = NULL; - g_autofree char *commandline = NULL; - g_autoptr(GPtrArray) args = NULL; - g_autoptr(GSubprocess) subp = NULL; - int i; - GList *l; - JsonNode *node; - JsonGenerator *generator; - - builder_manifest_checksum_for_finish (self, cache, context); - if (!builder_cache_lookup (cache, "finish")) - { - GFile *app_dir = NULL; - g_autofree char *ref = NULL; - g_print ("Finishing app\n"); - - if (!builder_context_enable_rofiles (context, error)) - return FALSE; - - /* Call after enabling rofiles */ - app_dir = builder_context_get_app_dir (context); - - ref = flatpak_compose_ref (!self->build_runtime && !self->build_extension, - builder_manifest_get_id (self), - builder_manifest_get_branch (self), - builder_context_get_arch (context), error); - if (ref == NULL) - return FALSE; - - if (self->metadata) - { - GFile *base_dir = builder_context_get_base_dir (context); - g_autoptr(GFile) dest_metadata = g_file_get_child (app_dir, "metadata"); - g_autoptr(GFile) src_metadata = g_file_resolve_relative_path (base_dir, self->metadata); - g_autofree char *contents = NULL; - gsize length; - - if (!g_file_get_contents (flatpak_file_get_path_cached (src_metadata), - &contents, &length, error)) - return FALSE; - - if (!g_file_set_contents (flatpak_file_get_path_cached (dest_metadata), - contents, length, error)) - return FALSE; - } - - if (self->inherit_extensions && self->inherit_extensions[0] != NULL) - { - g_autoptr(GFile) metadata = g_file_get_child (app_dir, "metadata"); - g_autoptr(GKeyFile) keyfile = g_key_file_new (); - g_autoptr(GKeyFile) base_keyfile = g_key_file_new (); - g_autofree char *arch_option = NULL; - const char *parent_id = NULL; - const char *parent_version = NULL; - g_autofree char *base_metadata = NULL; - - arch_option = g_strdup_printf ("--arch=%s", builder_context_get_arch (context)); - - if (self->base != NULL && *self->base != 0) - { - parent_id = self->base; - parent_version = builder_manifest_get_base_version (self); - } - else - { - parent_id = self->sdk; - parent_version = builder_manifest_get_runtime_version (self); - } - - base_metadata = flatpak (NULL, "info", arch_option, "--show-metadata", parent_id, parent_version, NULL); - if (base_metadata == NULL) - return flatpak_fail (error, "Inherit extensions specified, but could not get metadata for parent %s version %s", parent_id, parent_version); - - if (!g_key_file_load_from_data (base_keyfile, - base_metadata, -1, - G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, - error)) - { - g_prefix_error (error, "Can't load metadata file: "); - return FALSE; - } - - if (!g_key_file_load_from_file (keyfile, - flatpak_file_get_path_cached (metadata), - G_KEY_FILE_KEEP_COMMENTS|G_KEY_FILE_KEEP_TRANSLATIONS, - error)) - { - g_prefix_error (error, "Can't load metadata file: "); - return FALSE; - } - - for (i = 0; self->inherit_extensions[i] != NULL; i++) - { - g_autofree char *group = g_strconcat (FLATPAK_METADATA_GROUP_PREFIX_EXTENSION, - self->inherit_extensions[i], - NULL); - g_auto(GStrv) keys = NULL; - int j; - - if (!g_key_file_has_group (base_keyfile, group)) - return flatpak_fail (error, "Can't find inherited extension point %s", self->inherit_extensions[i]); - - keys = g_key_file_get_keys (base_keyfile, group, NULL, error); - if (keys == NULL) - return FALSE; - - for (j = 0; keys[j] != NULL; j++) - { - g_autofree char *value = g_key_file_get_value (base_keyfile, group, keys[j], error); - if (value == NULL) - return FALSE; - g_key_file_set_value (keyfile, group, keys[j], value); - } - - if (!g_key_file_has_key (keyfile, group, - FLATPAK_METADATA_KEY_VERSION, NULL) && - !g_key_file_has_key (keyfile, group, - FLATPAK_METADATA_KEY_VERSIONS, NULL)) - g_key_file_set_value (keyfile, group, - FLATPAK_METADATA_KEY_VERSION, - parent_version); - } - - if (!g_key_file_save_to_file (keyfile, - flatpak_file_get_path_cached (metadata), - error)) - { - g_prefix_error (error, "Can't save metadata.platform: "); - return FALSE; - } - } - - if (self->command) - { - g_autoptr(GFile) files_dir = g_file_resolve_relative_path (app_dir, "files"); - g_autoptr(GFile) command_file = NULL; - - if (!g_path_is_absolute (self->command)) - { - g_autoptr(GFile) bin_dir = g_file_resolve_relative_path (files_dir, "bin"); - command_file = g_file_get_child (bin_dir, self->command); - } - else if (g_str_has_prefix (self->command, "/app/")) - command_file = g_file_resolve_relative_path (files_dir, self->command + strlen ("/app/")); - - if (command_file != NULL && - !g_file_query_exists (command_file, NULL)) - { - const char *help = ""; - - if (strchr (self->command, ' ')) - help = ". Use a shell wrapper for passing arguments"; - - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Command '%s' not found%s", self->command, help); - - return FALSE; - } - } - - args = g_ptr_array_new_with_free_func (g_free); - g_ptr_array_add (args, g_strdup ("flatpak")); - g_ptr_array_add (args, g_strdup ("build-finish")); - if (self->command) - g_ptr_array_add (args, g_strdup_printf ("--command=%s", self->command)); - - if (self->finish_args) - { - for (i = 0; self->finish_args[i] != NULL; i++) - g_ptr_array_add (args, g_strdup (self->finish_args[i])); - } - - for (l = self->add_extensions; l != NULL; l = l->next) - builder_extension_add_finish_args (l->data, args); - - g_ptr_array_add (args, g_file_get_path (app_dir)); - g_ptr_array_add (args, NULL); - - commandline = flatpak_quote_argv ((const char **) args->pdata); - g_debug ("Running '%s'", commandline); - - subp = - g_subprocess_newv ((const gchar * const *) args->pdata, - G_SUBPROCESS_FLAGS_NONE, - error); - - if (subp == NULL || - !g_subprocess_wait_check (subp, NULL, error)) - return FALSE; - - node = json_gobject_serialize (G_OBJECT (self)); - generator = json_generator_new (); - json_generator_set_pretty (generator, TRUE); - json_generator_set_root (generator, node); - json = json_generator_to_data (generator, NULL); - g_object_unref (generator); - json_node_free (node); - - if (self->build_runtime) - manifest_file = g_file_resolve_relative_path (app_dir, "usr/manifest.json"); - else - manifest_file = g_file_resolve_relative_path (app_dir, "files/manifest.json"); - - if (g_file_query_exists (manifest_file, NULL)) - { - /* Move existing base manifest aside */ - g_autoptr(GFile) manifest_dir = g_file_get_parent (manifest_file); - g_autoptr(GFile) old_manifest = NULL; - int ver = 0; - - do - { - g_autofree char *basename = g_strdup_printf ("manifest-base-%d.json", ++ver); - g_clear_object (&old_manifest); - old_manifest = g_file_get_child (manifest_dir, basename); - } - while (g_file_query_exists (old_manifest, NULL)); - - if (!g_file_move (manifest_file, old_manifest, 0, - NULL, NULL, NULL, error)) - return FALSE; - } - - if (!g_file_set_contents (flatpak_file_get_path_cached (manifest_file), - json, strlen (json), error)) - return FALSE; - - if (self->build_runtime) - { - debuginfo_dir = g_file_resolve_relative_path (app_dir, "usr/lib/debug"); - locale_parent_dir = g_file_resolve_relative_path (app_dir, "usr/" LOCALES_SEPARATE_DIR); - } - else - { - debuginfo_dir = g_file_resolve_relative_path (app_dir, "files/lib/debug"); - locale_parent_dir = g_file_resolve_relative_path (app_dir, "files/" LOCALES_SEPARATE_DIR); - } - sources_dir = g_file_resolve_relative_path (app_dir, "sources"); - - if (self->separate_locales && g_file_query_exists (locale_parent_dir, NULL)) - { - g_autoptr(GFile) metadata_file = NULL; - g_autofree char *extension_contents = NULL; - g_autoptr(GFileOutputStream) output = NULL; - g_autoptr(GFile) metadata_locale_file = NULL; - g_autofree char *metadata_contents = NULL; - g_autofree char *locale_id = builder_manifest_get_locale_id (self); - - metadata_file = g_file_get_child (app_dir, "metadata"); - - extension_contents = g_strdup_printf ("\n" - "[Extension %s]\n" - "directory=%s\n" - "autodelete=true\n", - locale_id, - LOCALES_SEPARATE_DIR); - - output = g_file_append_to (metadata_file, G_FILE_CREATE_NONE, NULL, error); - if (output == NULL) - return FALSE; - - if (!g_output_stream_write_all (G_OUTPUT_STREAM (output), - extension_contents, strlen (extension_contents), - NULL, NULL, error)) - return FALSE; - - - metadata_locale_file = g_file_get_child (app_dir, "metadata.locale"); - metadata_contents = g_strdup_printf ("[Runtime]\n" - "name=%s\n" - "\n" - "[ExtensionOf]\n" - "ref=%s\n", - locale_id, ref); - if (!g_file_set_contents (flatpak_file_get_path_cached (metadata_locale_file), - metadata_contents, strlen (metadata_contents), - error)) - return FALSE; - } - - - if (g_file_query_exists (debuginfo_dir, NULL)) - { - g_autoptr(GFile) metadata_file = NULL; - g_autoptr(GFile) metadata_debuginfo_file = NULL; - g_autofree char *metadata_contents = NULL; - g_autofree char *extension_contents = NULL; - g_autoptr(GFileOutputStream) output = NULL; - g_autofree char *debug_id = builder_manifest_get_debug_id (self); - - metadata_file = g_file_get_child (app_dir, "metadata"); - metadata_debuginfo_file = g_file_get_child (app_dir, "metadata.debuginfo"); - - extension_contents = g_strdup_printf ("\n" - "[Extension %s]\n" - "directory=lib/debug\n" - "autodelete=true\n" - "no-autodownload=true\n", - debug_id); - - output = g_file_append_to (metadata_file, G_FILE_CREATE_NONE, NULL, error); - if (output == NULL) - return FALSE; - - if (!g_output_stream_write_all (G_OUTPUT_STREAM (output), extension_contents, strlen (extension_contents), - NULL, NULL, error)) - return FALSE; - - metadata_contents = g_strdup_printf ("[Runtime]\n" - "name=%s\n" - "\n" - "[ExtensionOf]\n" - "ref=%s\n", - debug_id, ref); - if (!g_file_set_contents (flatpak_file_get_path_cached (metadata_debuginfo_file), - metadata_contents, strlen (metadata_contents), error)) - return FALSE; - } - - - for (l = self->add_extensions; l != NULL; l = l->next) - { - BuilderExtension *e = l->data; - g_autofree char *extension_metadata_name = NULL; - g_autoptr(GFile) metadata_extension_file = NULL; - g_autofree char *metadata_contents = NULL; - - if (!builder_extension_is_bundled (e)) - continue; - - extension_metadata_name = g_strdup_printf ("metadata.%s", builder_extension_get_name (e)); - metadata_extension_file = g_file_get_child (app_dir, extension_metadata_name); - metadata_contents = g_strdup_printf ("[Runtime]\n" - "name=%s\n" - "\n" - "[ExtensionOf]\n" - "ref=%s\n", - builder_extension_get_name (e), ref); - if (!g_file_set_contents (flatpak_file_get_path_cached (metadata_extension_file), - metadata_contents, strlen (metadata_contents), error)) - return FALSE; - } - - if (!builder_context_disable_rofiles (context, error)) - return FALSE; - - if (!builder_cache_commit (cache, "Finish", error)) - return FALSE; - } - else - { - g_print ("Cache hit for finish, skipping\n"); - } - - return TRUE; -} - -gboolean -builder_manifest_create_platform (BuilderManifest *self, - BuilderCache *cache, - BuilderContext *context, - GError **error) -{ - g_autofree char *commandline = NULL; - - g_autoptr(GFile) locale_dir = NULL; - int i; - - if (!self->build_runtime || - self->id_platform == NULL) - return TRUE; - - builder_manifest_checksum_for_platform (self, cache, context); - if (!builder_cache_lookup (cache, "platform")) - { - g_autoptr(GHashTable) to_remove_ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - g_autoptr(GPtrArray) changes = NULL; - GList *l; - g_autoptr(GFile) platform_dir = NULL; - g_autoptr(GSubprocess) subp = NULL; - g_autoptr(GPtrArray) args = NULL; - GFile *app_dir = NULL; - g_autofree char *ref = NULL; - - g_print ("Creating platform based on %s\n", self->runtime); - - if (!builder_context_enable_rofiles (context, error)) - return FALSE; - - /* Call after enabling rofiles */ - app_dir = builder_context_get_app_dir (context); - - ref = flatpak_compose_ref (!self->build_runtime && !self->build_extension, - builder_manifest_get_id_platform (self), - builder_manifest_get_branch (self), - builder_context_get_arch (context), error); - if (ref == NULL) - return FALSE; - - platform_dir = g_file_get_child (app_dir, "platform"); - - args = g_ptr_array_new_with_free_func (g_free); - - g_ptr_array_add (args, g_strdup ("flatpak")); - g_ptr_array_add (args, g_strdup ("build-init")); - g_ptr_array_add (args, g_strdup ("--update")); - g_ptr_array_add (args, g_strdup ("--writable-sdk")); - g_ptr_array_add (args, g_strdup ("--sdk-dir=platform")); - g_ptr_array_add (args, g_strdup_printf ("--arch=%s", builder_context_get_arch (context))); - - for (i = 0; self->platform_extensions != NULL && self->platform_extensions[i] != NULL; i++) - { - const char *ext = self->platform_extensions[i]; - g_ptr_array_add (args, g_strdup_printf ("--sdk-extension=%s", ext)); - } - - g_ptr_array_add (args, g_file_get_path (app_dir)); - g_ptr_array_add (args, g_strdup (self->id)); - g_ptr_array_add (args, g_strdup (self->runtime)); - g_ptr_array_add (args, g_strdup (self->runtime)); - g_ptr_array_add (args, g_strdup (builder_manifest_get_runtime_version (self))); - - g_ptr_array_add (args, NULL); - - commandline = flatpak_quote_argv ((const char **) args->pdata); - g_debug ("Running '%s'", commandline); - - subp = - g_subprocess_newv ((const gchar * const *) args->pdata, - G_SUBPROCESS_FLAGS_NONE, - error); - - if (subp == NULL || - !g_subprocess_wait_check (subp, NULL, error)) - return FALSE; - - if (self->separate_locales) - { - g_autoptr(GFile) root_dir = NULL; - - root_dir = g_file_get_child (app_dir, "platform"); - - if (!builder_migrate_locale_dirs (root_dir, error)) - return FALSE; - - locale_dir = g_file_resolve_relative_path (root_dir, LOCALES_SEPARATE_DIR); - } - - if (self->metadata_platform) - { - GFile *base_dir = builder_context_get_base_dir (context); - g_autoptr(GFile) dest_metadata = g_file_get_child (app_dir, "metadata.platform"); - g_autoptr(GFile) src_metadata = g_file_resolve_relative_path (base_dir, self->metadata_platform); - g_autofree char *contents = NULL; - gsize length; - - if (!g_file_get_contents (flatpak_file_get_path_cached (src_metadata), - &contents, &length, error)) - return FALSE; - - if (!g_file_set_contents (flatpak_file_get_path_cached (dest_metadata), - contents, length, error)) - return FALSE; - } - else - { - g_autoptr(GFile) metadata = g_file_get_child (app_dir, "metadata"); - g_autoptr(GFile) dest_metadata = g_file_get_child (app_dir, "metadata.platform"); - g_autoptr(GKeyFile) keyfile = g_key_file_new (); - g_auto(GStrv) groups = NULL; - g_autofree char *sdk_group_prefix = g_strconcat (FLATPAK_METADATA_GROUP_PREFIX_EXTENSION, self->id, NULL); - int j; - - if (!g_key_file_load_from_file (keyfile, - flatpak_file_get_path_cached (metadata), - G_KEY_FILE_KEEP_COMMENTS|G_KEY_FILE_KEEP_TRANSLATIONS, - error)) - { - g_prefix_error (error, "Can't load metadata file: "); - return FALSE; - } - - g_key_file_set_string (keyfile, FLATPAK_METADATA_GROUP_RUNTIME, - FLATPAK_METADATA_KEY_NAME, self->id_platform); - - groups = g_key_file_get_groups (keyfile, NULL); - for (j = 0; groups[j] != NULL; j++) - { - if (g_str_has_prefix (groups[j], sdk_group_prefix)) - g_key_file_remove_group (keyfile, groups[j], NULL); - } - - if (!g_key_file_save_to_file (keyfile, - flatpak_file_get_path_cached (dest_metadata), - error)) - { - g_prefix_error (error, "Can't save metadata.platform: "); - return FALSE; - } - } - - for (l = self->expanded_modules; l != NULL; l = l->next) - { - BuilderModule *m = l->data; - - builder_module_cleanup_collect (m, TRUE, context, to_remove_ht); - } - - changes = builder_cache_get_all_changes (cache, error); - if (changes == NULL) - return FALSE; - - g_ptr_array_sort (changes, cmpstringp); - - for (i = 0; i < changes->len; i++) - { - const char *changed = g_ptr_array_index (changes, i); - g_autoptr(GFile) src = NULL; - g_autoptr(GFile) dest = NULL; - g_autoptr(GFileInfo) info = NULL; - g_autoptr(GError) my_error = NULL; - - if (!g_str_has_prefix (changed, "usr/")) - continue; - - if (g_str_has_prefix (changed, "usr/lib/debug/") && - !g_str_equal (changed, "usr/lib/debug/app")) - continue; - - if (g_hash_table_contains (to_remove_ht, changed)) - { - g_print ("Ignoring %s\n", changed); - continue; - } - - src = g_file_resolve_relative_path (app_dir, changed); - dest = g_file_resolve_relative_path (platform_dir, changed + strlen ("usr/")); - - info = g_file_query_info (src, "standard::type,standard::symlink-target", - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - NULL, &my_error); - if (info == NULL) - { - if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) - continue; - - g_propagate_error (error, g_steal_pointer (&my_error)); - return FALSE; - } - g_clear_error (&my_error); - - if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) - { - if (!flatpak_mkdir_p (dest, NULL, error)) - return FALSE; - } - else - { - g_autoptr(GFile) dest_parent = g_file_get_parent (dest); - - if (!flatpak_mkdir_p (dest_parent, NULL, error)) - return FALSE; - - if (!g_file_delete (dest, NULL, &my_error) && - !g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) - { - g_propagate_error (error, g_steal_pointer (&my_error)); - return FALSE; - } - g_clear_error (&my_error); - - if (g_file_info_get_file_type (info) == G_FILE_TYPE_SYMBOLIC_LINK) - { - if (!g_file_make_symbolic_link (dest, - g_file_info_get_symlink_target (info), - NULL, error)) - return FALSE; - } - else - { - g_autofree char *src_path = g_file_get_path (src); - g_autofree char *dest_path = g_file_get_path (dest); - - if (link (src_path, dest_path)) - { - glnx_set_error_from_errno (error); - return FALSE; - } - } - } - } - - if (self->cleanup_platform_commands) - { - g_auto(GStrv) env = builder_options_get_env (self->build_options, context); - g_auto(GStrv) build_args = builder_options_get_build_args (self->build_options, context, error); - if (!build_args) - return FALSE; - char *platform_args[] = { "--sdk-dir=platform", "--metadata=metadata.platform", NULL }; - g_auto(GStrv) extra_args = strcatv (build_args, platform_args); - - for (i = 0; self->cleanup_platform_commands[i] != NULL; i++) - { - if (!command (app_dir, env, extra_args, self->cleanup_platform_commands[i], error)) - return FALSE; - } - } - - if (self->separate_locales && locale_dir && g_file_query_exists (locale_dir, NULL)) - { - g_autoptr(GFile) metadata_file = NULL; - g_autofree char *extension_contents = NULL; - g_autoptr(GFileOutputStream) output = NULL; - g_autoptr(GFile) metadata_locale_file = NULL; - g_autofree char *metadata_contents = NULL; - g_autofree char *locale_id = builder_manifest_get_locale_id_platform (self); - - metadata_file = g_file_get_child (app_dir, "metadata.platform"); - - extension_contents = g_strdup_printf ("\n" - "[Extension %s]\n" - "directory=%s\n" - "autodelete=true\n", - locale_id, - LOCALES_SEPARATE_DIR); - - output = g_file_append_to (metadata_file, G_FILE_CREATE_NONE, NULL, error); - if (output == NULL) - return FALSE; - - if (!g_output_stream_write_all (G_OUTPUT_STREAM (output), - extension_contents, strlen (extension_contents), - NULL, NULL, error)) - return FALSE; - - - metadata_locale_file = g_file_get_child (app_dir, "metadata.platform.locale"); - metadata_contents = g_strdup_printf ("[Runtime]\n" - "name=%s\n" - "\n" - "[ExtensionOf]\n" - "ref=%s\n", locale_id, ref); - if (!g_file_set_contents (flatpak_file_get_path_cached (metadata_locale_file), - metadata_contents, strlen (metadata_contents), - error)) - return FALSE; - } - - if (!builder_context_disable_rofiles (context, error)) - return FALSE; - - if (!builder_cache_commit (cache, "Created platform", error)) - return FALSE; - } - else - { - g_print ("Cache hit for create platform, skipping\n"); - } - - return TRUE; -} - -gboolean -builder_manifest_bundle_sources (BuilderManifest *self, - const char *json, - BuilderCache *cache, - BuilderContext *context, - GError **error) -{ - - builder_manifest_checksum_for_bundle_sources (self, cache, context); - if (!builder_cache_lookup (cache, "bundle-sources")) - { - g_autofree char *sources_id = builder_manifest_get_sources_id (self); - GFile *app_dir; - g_autoptr(GFile) metadata_sources_file = NULL; - g_autoptr(GFile) json_dir = NULL; - g_autofree char *manifest_filename = NULL; - g_autoptr(GFile) manifest_file = NULL; - g_autofree char *metadata_contents = NULL; - GList *l; - - g_print ("Bundling sources\n"); - - if (!builder_context_enable_rofiles (context, error)) - return FALSE; - - app_dir = builder_context_get_app_dir (context); - metadata_sources_file = g_file_get_child (app_dir, "metadata.sources"); - metadata_contents = g_strdup_printf ("[Runtime]\n" - "name=%s\n", sources_id); - if (!g_file_set_contents (flatpak_file_get_path_cached (metadata_sources_file), - metadata_contents, strlen (metadata_contents), error)) - return FALSE; - - json_dir = g_file_resolve_relative_path (app_dir, "sources/manifest"); - if (!flatpak_mkdir_p (json_dir, NULL, error)) - return FALSE; - - manifest_filename = g_strconcat (self->id, ".json", NULL); - manifest_file = g_file_get_child (json_dir, manifest_filename); - if (!g_file_set_contents (flatpak_file_get_path_cached (manifest_file), - json, strlen (json), error)) - return FALSE; - - - for (l = self->expanded_modules; l != NULL; l = l->next) - { - BuilderModule *m = l->data; - - if (!builder_module_bundle_sources (m, context, error)) - return FALSE; - } - - if (!builder_context_disable_rofiles (context, error)) - return FALSE; - - if (!builder_cache_commit (cache, "Bundled sources", error)) - return FALSE; - } - else - { - g_print ("Cache hit for bundle-sources, skipping\n"); - } - - return TRUE; -} - -gboolean -builder_manifest_show_deps (BuilderManifest *self, - BuilderContext *context, - GError **error) -{ - g_autoptr(GHashTable) names = g_hash_table_new (g_str_hash, g_str_equal); - GList *l; - - if (!expand_modules (context, self->modules, &self->expanded_modules, names, error)) - return FALSE; - - for (l = self->expanded_modules; l != NULL; l = l->next) - { - BuilderModule *module = l->data; - - if (!builder_module_show_deps (module, context, error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -builder_manifest_install_dep (BuilderManifest *self, - BuilderContext *context, - const char *remote, - gboolean opt_user, - const char *opt_installation, - const char *runtime, - const char *version, - GError **error) -{ - g_autofree char *ref = NULL; - g_autofree char *commit = NULL; - g_autoptr(GPtrArray) args = NULL; - gboolean installed; - - if (version == NULL) - version = builder_manifest_get_runtime_version (self); - - ref = flatpak_build_untyped_ref (runtime, - version, - builder_context_get_arch (context)); - - commit = flatpak_info (opt_user, opt_installation, "--show-commit", ref, NULL); - installed = (commit != NULL); - - args = g_ptr_array_new_with_free_func (g_free); - g_ptr_array_add (args, g_strdup ("flatpak")); - add_installation_args (args, opt_user, opt_installation); - if (installed) - { - g_ptr_array_add (args, g_strdup ("update")); - g_ptr_array_add (args, g_strdup ("--subpath=")); - } - else - { - g_ptr_array_add (args, g_strdup ("install")); - g_ptr_array_add (args, g_strdup (remote)); - } - - g_ptr_array_add (args, g_strdup (ref)); - g_ptr_array_add (args, NULL); - - if (!flatpak_spawnv (NULL, NULL, 0, error, (const char * const *)args->pdata)) - return FALSE; - - return TRUE; -} - -static gboolean -builder_manifest_install_extension_deps (BuilderManifest *self, - BuilderContext *context, - const char *runtime, - char **runtime_extensions, - const char *remote, - gboolean opt_user, - const char *opt_installation, - GError **error) -{ - g_autofree char *runtime_ref = flatpak_build_runtime_ref (runtime, builder_manifest_get_runtime_version (self), - builder_context_get_arch (context)); - g_autofree char *metadata = NULL; - g_autoptr(GKeyFile) keyfile = g_key_file_new (); - int i; - - if (runtime_extensions == NULL) - return TRUE; - - metadata = flatpak_info (opt_user, opt_installation, "--show-metadata", runtime_ref, NULL); - if (metadata == NULL) - return FALSE; - - if (!g_key_file_load_from_data (keyfile, - metadata, -1, - 0, - error)) - return FALSE; - - for (i = 0; runtime_extensions != NULL && runtime_extensions[i] != NULL; i++) - { - g_autofree char *extension_group = g_strdup_printf ("Extension %s", runtime_extensions[i]); - g_autofree char *extension_version = NULL; - - if (!g_key_file_has_group (keyfile, extension_group)) - { - g_autofree char *base = g_strdup (runtime_extensions[i]); - char *dot = strrchr (base, '.'); - if (dot != NULL) - *dot = 0; - - g_free (extension_group); - extension_group = g_strdup_printf ("Extension %s", base); - if (!g_key_file_has_group (keyfile, extension_group)) - return flatpak_fail (error, "Unknown extension '%s' in runtime\n", runtime_extensions[i]); - } - - extension_version = g_key_file_get_string (keyfile, extension_group, "version", NULL); - if (extension_version == NULL) - extension_version = g_strdup (builder_manifest_get_runtime_version (self)); - - g_print ("Dependency Extension: %s %s\n", runtime_extensions[i], extension_version); - if (!builder_manifest_install_dep (self, context, remote, opt_user, opt_installation, - runtime_extensions[i], extension_version, - error)) - return FALSE; - } - - return TRUE; -} - -gboolean -builder_manifest_install_deps (BuilderManifest *self, - BuilderContext *context, - const char *remote, - gboolean opt_user, - const char *opt_installation, - GError **error) -{ - /* Sdk */ - g_print ("Dependency Sdk: %s %s\n", self->sdk, builder_manifest_get_runtime_version (self)); - if (!builder_manifest_install_dep (self, context, remote, opt_user, opt_installation, - self->sdk, builder_manifest_get_runtime_version (self), - error)) - return FALSE; - - /* Runtime */ - g_print ("Dependency Runtime: %s %s\n", self->runtime, builder_manifest_get_runtime_version (self)); - if (!builder_manifest_install_dep (self, context, remote, opt_user, opt_installation, - self->runtime, builder_manifest_get_runtime_version (self), - error)) - return FALSE; - - if (self->base) - { - g_print ("Dependency Base: %s %s\n", self->base, builder_manifest_get_base_version (self)); - if (!builder_manifest_install_dep (self, context, remote, opt_user, opt_installation, - self->base, builder_manifest_get_base_version (self), - error)) - return FALSE; - } - - if (!builder_manifest_install_extension_deps (self, context, - self->sdk, self->sdk_extensions, - remote,opt_user, opt_installation, - error)) - return FALSE; - - if (!builder_manifest_install_extension_deps (self, context, - self->runtime, self->platform_extensions, - remote, opt_user, opt_installation, - error)) - return FALSE; - - return TRUE; -} - -gboolean -builder_manifest_run (BuilderManifest *self, - BuilderContext *context, - FlatpakContext *arg_context, - char **argv, - int argc, - GError **error) -{ - g_autoptr(GPtrArray) args = NULL; - g_autofree char *commandline = NULL; - g_autofree char *build_dir_path = NULL; - g_autofree char *ccache_dir_path = NULL; - g_auto(GStrv) env = NULL; - g_auto(GStrv) build_args = NULL; - int i; - - if (!builder_context_enable_rofiles (context, error)) - return FALSE; - - if (!flatpak_mkdir_p (builder_context_get_build_dir (context), - NULL, error)) - return FALSE; - - args = g_ptr_array_new_with_free_func (g_free); - g_ptr_array_add (args, g_strdup ("flatpak")); - g_ptr_array_add (args, g_strdup ("build")); - - build_dir_path = g_file_get_path (builder_context_get_build_dir (context)); - g_ptr_array_add (args, g_strdup_printf ("--bind-mount=/run/%s=%s", - builder_context_get_build_runtime (context) ? "build-runtime" : "build", - build_dir_path)); - - if (g_file_query_exists (builder_context_get_ccache_dir (context), NULL)) - { - ccache_dir_path = g_file_get_path (builder_context_get_ccache_dir (context)); - g_ptr_array_add (args, g_strdup_printf ("--bind-mount=/run/ccache=%s", ccache_dir_path)); - } - - build_args = builder_options_get_build_args (self->build_options, context, error); - if (build_args == NULL) - return FALSE; - - for (i = 0; build_args[i] != NULL; i++) - g_ptr_array_add (args, g_strdup (build_args[i])); - - env = builder_options_get_env (self->build_options, context); - if (env) - { - for (i = 0; env[i] != NULL; i++) - g_ptr_array_add (args, g_strdup_printf ("--env=%s", env[i])); - } - - /* Just add something so that we get the default rules (own our own id) */ - g_ptr_array_add (args, g_strdup ("--talk-name=org.freedesktop.DBus")); - - /* Inherit all finish args except --filesystem and some that - * build doesn't understand so the command gets the same access - * as the final app - */ - if (self->finish_args) - { - for (i = 0; self->finish_args[i] != NULL; i++) - { - const char *arg = self->finish_args[i]; - if (!g_str_has_prefix (arg, "--filesystem") && - !g_str_has_prefix (arg, "--extension") && - !g_str_has_prefix (arg, "--sdk") && - !g_str_has_prefix (arg, "--runtime") && - !g_str_has_prefix (arg, "--command") && - !g_str_has_prefix (arg, "--extra-data") && - !g_str_has_prefix (arg, "--require-version")) - g_ptr_array_add (args, g_strdup (arg)); - } - } - - flatpak_context_to_args (arg_context, args); - - g_ptr_array_add (args, g_file_get_path (builder_context_get_app_dir (context))); - - for (i = 0; i < argc; i++) - g_ptr_array_add (args, g_strdup (argv[i])); - g_ptr_array_add (args, NULL); - - commandline = flatpak_quote_argv ((const char **) args->pdata); - g_debug ("Running '%s'", commandline); - - if (execvp ((char *) args->pdata[0], (char **) args->pdata) == -1) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "Unable to start flatpak build"); - return FALSE; - } - - /* Not reached */ - return TRUE; -} - -char ** -builder_manifest_get_exclude_dirs (BuilderManifest *self) -{ - g_autoptr(GPtrArray) dirs = NULL; - GList *l; - - dirs = g_ptr_array_new (); - - for (l = self->add_extensions; l != NULL; l = l->next) - { - BuilderExtension *e = l->data; - - if (builder_extension_is_bundled (e)) - g_ptr_array_add (dirs, g_strdup (builder_extension_get_directory (e))); - } - g_ptr_array_add (dirs, NULL); - - return (char **)g_ptr_array_free (g_steal_pointer (&dirs), FALSE); -} diff --git a/builder/builder-manifest.h b/builder/builder-manifest.h deleted file mode 100644 index 04acad85..00000000 --- a/builder/builder-manifest.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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.1 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_MANIFEST_H__ -#define __BUILDER_MANIFEST_H__ - -#include - -#include "flatpak-run.h" -#include "builder-options.h" -#include "builder-module.h" -#include "builder-cache.h" -#include "builder-extension.h" - -G_BEGIN_DECLS - -typedef struct BuilderManifest BuilderManifest; - -#define BUILDER_TYPE_MANIFEST (builder_manifest_get_type ()) -#define BUILDER_MANIFEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUILDER_TYPE_MANIFEST, BuilderManifest)) -#define BUILDER_IS_MANIFEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUILDER_TYPE_MANIFEST)) - -/* Bump this if format changes in incompatible ways to force rebuild */ -#define BUILDER_MANIFEST_CHECKSUM_VERSION "4" -#define BUILDER_MANIFEST_CHECKSUM_CLEANUP_VERSION "1" -#define BUILDER_MANIFEST_CHECKSUM_FINISH_VERSION "2" -#define BUILDER_MANIFEST_CHECKSUM_BUNDLE_SOURCES_VERSION "1" -#define BUILDER_MANIFEST_CHECKSUM_PLATFORM_VERSION "1" - -GType builder_manifest_get_type (void); - -void builder_manifest_set_demarshal_base_dir (GFile *dir); -GFile *builder_manifest_get_demarshal_base_dir (void); - -const char * builder_manifest_get_id (BuilderManifest *self); -char * builder_manifest_get_locale_id (BuilderManifest *self); -char * builder_manifest_get_debug_id (BuilderManifest *self); -char * builder_manifest_get_sources_id (BuilderManifest *self); -const char * builder_manifest_get_id_platform (BuilderManifest *self); -char * builder_manifest_get_locale_id_platform (BuilderManifest *self); -BuilderOptions *builder_manifest_get_build_options (BuilderManifest *self); -GList * builder_manifest_get_modules (BuilderManifest *self); -GList * builder_manifest_get_add_extensions (BuilderManifest *self); -const char * builder_manifest_get_branch (BuilderManifest *self); -void builder_manifest_set_default_branch (BuilderManifest *self, - const char *default_branch); -const char * builder_manifest_get_collection_id (BuilderManifest *self); -void builder_manifest_set_default_collection_id (BuilderManifest *self, - const char *default_collection_id); - - -char ** builder_manifest_get_exclude_dirs (BuilderManifest *self); - -gboolean builder_manifest_start (BuilderManifest *self, - gboolean allow_missing_runtimes, - BuilderContext *context, - GError **error); -gboolean builder_manifest_init_app_dir (BuilderManifest *self, - BuilderCache *cache, - BuilderContext *context, - GError **error); -gboolean builder_manifest_download (BuilderManifest *self, - gboolean update_vcs, - const char *only_module, - BuilderContext *context, - GError **error); -gboolean builder_manifest_build_shell (BuilderManifest *self, - BuilderContext *context, - const char *modulename, - GError **error); -gboolean builder_manifest_build (BuilderManifest *self, - BuilderCache *cache, - BuilderContext *context, - GError **error); -gboolean builder_manifest_install_deps (BuilderManifest *self, - BuilderContext *context, - const char *remote, - gboolean opt_user, - const char *opt_installation, - GError **error); -gboolean builder_manifest_run (BuilderManifest *self, - BuilderContext *context, - FlatpakContext *arg_context, - char **argv, - int argc, - GError **error); -gboolean builder_manifest_show_deps (BuilderManifest *self, - BuilderContext *context, - GError **error); -void builder_manifest_checksum (BuilderManifest *self, - BuilderCache *cache, - BuilderContext *context); -gboolean builder_manifest_cleanup (BuilderManifest *self, - BuilderCache *cache, - BuilderContext *context, - GError **error); -gboolean builder_manifest_finish (BuilderManifest *self, - BuilderCache *cache, - BuilderContext *context, - GError **error); -gboolean builder_manifest_bundle_sources (BuilderManifest *self, - const char *json, - BuilderCache *cache, - BuilderContext *context, - GError **error); -gboolean builder_manifest_create_platform (BuilderManifest *self, - BuilderCache *cache, - BuilderContext *context, - GError **error); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (BuilderManifest, g_object_unref) - -G_END_DECLS - -#endif /* __BUILDER_MANIFEST_H__ */ diff --git a/builder/builder-module.c b/builder/builder-module.c deleted file mode 100644 index e7175a9d..00000000 --- a/builder/builder-module.c +++ /dev/null @@ -1,1880 +0,0 @@ -/* builder-module.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 -#include -#include "libglnx/libglnx.h" - -#include "flatpak-utils.h" -#include "builder-utils.h" -#include "builder-module.h" -#include "builder-post-process.h" -#include "builder-manifest.h" - -struct BuilderModule -{ - GObject parent; - - char *json_path; - char *name; - char *subdir; - char **post_install; - char **config_opts; - char **make_args; - char **make_install_args; - char *install_rule; - char *buildsystem; - char **ensure_writable; - char **only_arches; - char **skip_arches; - gboolean disabled; - gboolean rm_configure; - gboolean no_autogen; - gboolean no_parallel_make; - gboolean no_make_install; - gboolean no_python_timestamp_fix; - gboolean cmake; - gboolean builddir; - BuilderOptions *build_options; - GPtrArray *changes; - char **cleanup; - char **cleanup_platform; - GList *sources; - GList *modules; - char **build_commands; -}; - -typedef struct -{ - GObjectClass parent_class; -} BuilderModuleClass; - -static void serializable_iface_init (JsonSerializableIface *serializable_iface); - -G_DEFINE_TYPE_WITH_CODE (BuilderModule, builder_module, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (JSON_TYPE_SERIALIZABLE, serializable_iface_init)); - -enum { - PROP_0, - PROP_NAME, - PROP_SUBDIR, - PROP_RM_CONFIGURE, - PROP_DISABLED, - PROP_NO_AUTOGEN, - PROP_NO_PARALLEL_MAKE, - PROP_NO_MAKE_INSTALL, - PROP_NO_PYTHON_TIMESTAMP_FIX, - PROP_CMAKE, - PROP_INSTALL_RULE, - PROP_BUILDSYSTEM, - PROP_BUILDDIR, - PROP_CONFIG_OPTS, - PROP_MAKE_ARGS, - PROP_MAKE_INSTALL_ARGS, - PROP_ENSURE_WRITABLE, - PROP_ONLY_ARCHES, - PROP_SKIP_ARCHES, - PROP_SOURCES, - PROP_BUILD_OPTIONS, - PROP_CLEANUP, - PROP_CLEANUP_PLATFORM, - PROP_POST_INSTALL, - PROP_MODULES, - PROP_BUILD_COMMANDS, - LAST_PROP -}; - -static void -collect_cleanup_for_path (const char **patterns, - const char *path, - const char *add_prefix, - GHashTable *to_remove_ht) -{ - int i; - - if (patterns == NULL) - return; - - for (i = 0; patterns[i] != NULL; i++) - flatpak_collect_matches_for_path_pattern (path, patterns[i], add_prefix, to_remove_ht); -} - -static void -builder_module_finalize (GObject *object) -{ - BuilderModule *self = (BuilderModule *) object; - - g_free (self->json_path); - g_free (self->name); - g_free (self->subdir); - g_free (self->install_rule); - g_free (self->buildsystem); - g_strfreev (self->post_install); - g_strfreev (self->config_opts); - g_strfreev (self->make_args); - g_strfreev (self->make_install_args); - g_strfreev (self->ensure_writable); - g_strfreev (self->only_arches); - g_strfreev (self->skip_arches); - g_clear_object (&self->build_options); - g_list_free_full (self->sources, g_object_unref); - g_strfreev (self->cleanup); - g_strfreev (self->cleanup_platform); - g_list_free_full (self->modules, g_object_unref); - g_strfreev (self->build_commands); - - if (self->changes) - g_ptr_array_unref (self->changes); - - G_OBJECT_CLASS (builder_module_parent_class)->finalize (object); -} - -static void -builder_module_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - BuilderModule *self = BUILDER_MODULE (object); - - switch (prop_id) - { - case PROP_NAME: - g_value_set_string (value, self->name); - break; - - case PROP_SUBDIR: - g_value_set_string (value, self->subdir); - break; - - case PROP_RM_CONFIGURE: - g_value_set_boolean (value, self->rm_configure); - break; - - case PROP_DISABLED: - g_value_set_boolean (value, self->disabled); - break; - - case PROP_NO_AUTOGEN: - g_value_set_boolean (value, self->no_autogen); - break; - - case PROP_NO_PARALLEL_MAKE: - g_value_set_boolean (value, self->no_parallel_make); - break; - - case PROP_NO_MAKE_INSTALL: - g_value_set_boolean (value, self->no_make_install); - break; - - case PROP_NO_PYTHON_TIMESTAMP_FIX: - g_value_set_boolean (value, self->no_python_timestamp_fix); - break; - - case PROP_CMAKE: - g_value_set_boolean (value, self->cmake); - break; - - case PROP_BUILDSYSTEM: - g_value_set_string (value, self->buildsystem); - break; - - case PROP_INSTALL_RULE: - g_value_set_string (value, self->install_rule); - break; - - case PROP_BUILDDIR: - g_value_set_boolean (value, self->builddir); - break; - - case PROP_CONFIG_OPTS: - g_value_set_boxed (value, self->config_opts); - break; - - case PROP_MAKE_ARGS: - g_value_set_boxed (value, self->make_args); - break; - - case PROP_MAKE_INSTALL_ARGS: - g_value_set_boxed (value, self->make_install_args); - break; - - case PROP_ENSURE_WRITABLE: - g_value_set_boxed (value, self->ensure_writable); - break; - - case PROP_ONLY_ARCHES: - g_value_set_boxed (value, self->only_arches); - break; - - case PROP_SKIP_ARCHES: - g_value_set_boxed (value, self->skip_arches); - break; - - case PROP_POST_INSTALL: - g_value_set_boxed (value, self->post_install); - break; - - case PROP_BUILD_OPTIONS: - g_value_set_object (value, self->build_options); - break; - - case PROP_SOURCES: - g_value_set_pointer (value, self->sources); - break; - - case PROP_CLEANUP: - g_value_set_boxed (value, self->cleanup); - break; - - case PROP_CLEANUP_PLATFORM: - g_value_set_boxed (value, self->cleanup_platform); - break; - - case PROP_MODULES: - g_value_set_pointer (value, self->modules); - break; - - case PROP_BUILD_COMMANDS: - g_value_set_boxed (value, self->build_commands); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -builder_module_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - BuilderModule *self = BUILDER_MODULE (object); - gchar **tmp; - char *p; - - switch (prop_id) - { - case PROP_NAME: - g_clear_pointer (&self->name, g_free); - self->name = g_value_dup_string (value); - if ((p = strchr (self->name, ' ')) || - (p = strchr (self->name, '/'))) - g_printerr ("Module names like '%s' containing '%c' are problematic. Expect errors.\n", self->name, *p); - break; - - case PROP_SUBDIR: - g_clear_pointer (&self->subdir, g_free); - self->subdir = g_value_dup_string (value); - break; - - case PROP_RM_CONFIGURE: - self->rm_configure = g_value_get_boolean (value); - break; - - case PROP_DISABLED: - self->disabled = g_value_get_boolean (value); - break; - - case PROP_NO_AUTOGEN: - self->no_autogen = g_value_get_boolean (value); - break; - - case PROP_NO_PARALLEL_MAKE: - self->no_parallel_make = g_value_get_boolean (value); - break; - - case PROP_NO_MAKE_INSTALL: - self->no_make_install = g_value_get_boolean (value); - break; - - case PROP_NO_PYTHON_TIMESTAMP_FIX: - self->no_python_timestamp_fix = g_value_get_boolean (value); - break; - - case PROP_CMAKE: - self->cmake = g_value_get_boolean (value); - break; - - case PROP_BUILDSYSTEM: - g_free (self->buildsystem); - self->buildsystem = g_value_dup_string (value); - break; - - case PROP_INSTALL_RULE: - g_free (self->install_rule); - self->install_rule = g_value_dup_string (value); - break; - - case PROP_BUILDDIR: - self->builddir = g_value_get_boolean (value); - break; - - case PROP_CONFIG_OPTS: - tmp = self->config_opts; - self->config_opts = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - case PROP_MAKE_ARGS: - tmp = self->make_args; - self->make_args = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - case PROP_MAKE_INSTALL_ARGS: - tmp = self->make_install_args; - self->make_install_args = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - case PROP_ENSURE_WRITABLE: - tmp = self->ensure_writable; - self->ensure_writable = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - case PROP_ONLY_ARCHES: - tmp = self->only_arches; - self->only_arches = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - case PROP_SKIP_ARCHES: - tmp = self->skip_arches; - self->skip_arches = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - case PROP_POST_INSTALL: - tmp = self->post_install; - self->post_install = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - case PROP_BUILD_OPTIONS: - g_set_object (&self->build_options, g_value_get_object (value)); - break; - - case PROP_SOURCES: - g_list_free_full (self->sources, g_object_unref); - /* NOTE: This takes ownership of the list! */ - self->sources = g_value_get_pointer (value); - break; - - case PROP_CLEANUP: - tmp = self->cleanup; - self->cleanup = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - case PROP_CLEANUP_PLATFORM: - tmp = self->cleanup_platform; - self->cleanup_platform = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - case PROP_MODULES: - g_list_free_full (self->modules, g_object_unref); - /* NOTE: This takes ownership of the list! */ - self->modules = g_value_get_pointer (value); - break; - - case PROP_BUILD_COMMANDS: - tmp = self->build_commands; - self->build_commands = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -builder_module_class_init (BuilderModuleClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = builder_module_finalize; - object_class->get_property = builder_module_get_property; - object_class->set_property = builder_module_set_property; - - g_object_class_install_property (object_class, - PROP_NAME, - g_param_spec_string ("name", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_SUBDIR, - g_param_spec_string ("subdir", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_RM_CONFIGURE, - g_param_spec_boolean ("rm-configure", - "", - "", - FALSE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_DISABLED, - g_param_spec_boolean ("disabled", - "", - "", - FALSE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_NO_AUTOGEN, - g_param_spec_boolean ("no-autogen", - "", - "", - FALSE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_NO_PARALLEL_MAKE, - g_param_spec_boolean ("no-parallel-make", - "", - "", - FALSE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_NO_MAKE_INSTALL, - g_param_spec_boolean ("no-make-install", - "", - "", - FALSE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_NO_PYTHON_TIMESTAMP_FIX, - g_param_spec_boolean ("no-python-timestamp-fix", - "", - "", - FALSE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_CMAKE, - g_param_spec_boolean ("cmake", - "", - "", - FALSE, - G_PARAM_READWRITE|G_PARAM_DEPRECATED)); - g_object_class_install_property (object_class, - PROP_BUILDSYSTEM, - g_param_spec_string ("buildsystem", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_INSTALL_RULE, - g_param_spec_string ("install-rule", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_BUILDDIR, - g_param_spec_boolean ("builddir", - "", - "", - FALSE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_SOURCES, - g_param_spec_pointer ("sources", - "", - "", - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_CONFIG_OPTS, - g_param_spec_boxed ("config-opts", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_MAKE_ARGS, - g_param_spec_boxed ("make-args", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_MAKE_INSTALL_ARGS, - g_param_spec_boxed ("make-install-args", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_ENSURE_WRITABLE, - g_param_spec_boxed ("ensure-writable", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_ONLY_ARCHES, - g_param_spec_boxed ("only-arches", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_SKIP_ARCHES, - g_param_spec_boxed ("skip-arches", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_POST_INSTALL, - g_param_spec_boxed ("post-install", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_BUILD_OPTIONS, - g_param_spec_object ("build-options", - "", - "", - BUILDER_TYPE_OPTIONS, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_CLEANUP, - g_param_spec_boxed ("cleanup", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_CLEANUP_PLATFORM, - g_param_spec_boxed ("cleanup-platform", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_MODULES, - g_param_spec_pointer ("modules", - "", - "", - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_BUILD_COMMANDS, - g_param_spec_boxed ("build-commands", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); -} - -static void -builder_module_init (BuilderModule *self) -{ -} - -static JsonNode * -builder_module_serialize_property (JsonSerializable *serializable, - const gchar *property_name, - const GValue *value, - GParamSpec *pspec) -{ - if (strcmp (property_name, "modules") == 0) - { - BuilderModule *self = BUILDER_MODULE (serializable); - JsonNode *retval = NULL; - GList *l; - - if (self->modules) - { - JsonArray *array; - - array = json_array_sized_new (g_list_length (self->modules)); - - for (l = self->modules; l != NULL; l = l->next) - { - JsonNode *child = json_gobject_serialize (l->data); - json_array_add_element (array, child); - } - - retval = json_node_init_array (json_node_alloc (), array); - json_array_unref (array); - } - - return retval; - } - else if (strcmp (property_name, "sources") == 0) - { - BuilderModule *self = BUILDER_MODULE (serializable); - JsonNode *retval = NULL; - GList *l; - - if (self->sources) - { - JsonArray *array; - - array = json_array_sized_new (g_list_length (self->sources)); - - for (l = self->sources; l != NULL; l = l->next) - { - JsonNode *child = builder_source_to_json (BUILDER_SOURCE (l->data)); - json_array_add_element (array, child); - } - - retval = json_node_init_array (json_node_alloc (), array); - json_array_unref (array); - } - - return retval; - } - else - { - return json_serializable_default_serialize_property (serializable, - property_name, - value, - pspec); - } -} - -static gboolean -builder_module_deserialize_property (JsonSerializable *serializable, - const gchar *property_name, - GValue *value, - GParamSpec *pspec, - JsonNode *property_node) -{ - if (strcmp (property_name, "modules") == 0) - { - if (JSON_NODE_TYPE (property_node) == JSON_NODE_NULL) - { - g_value_set_pointer (value, NULL); - return TRUE; - } - else if (JSON_NODE_TYPE (property_node) == JSON_NODE_ARRAY) - { - JsonArray *array = json_node_get_array (property_node); - guint i, array_len = json_array_get_length (array); - g_autoptr(GFile) saved_demarshal_base_dir = builder_manifest_get_demarshal_base_dir (); - GList *modules = NULL; - GObject *module; - - for (i = 0; i < array_len; i++) - { - JsonNode *element_node = json_array_get_element (array, i); - - module = NULL; - - if (JSON_NODE_HOLDS_VALUE (element_node) && - json_node_get_value_type (element_node) == G_TYPE_STRING) - { - const char *module_relpath = json_node_get_string (element_node); - g_autoptr(GFile) module_file = - g_file_resolve_relative_path (saved_demarshal_base_dir, module_relpath); - const char *module_path = flatpak_file_get_path_cached (module_file); - g_autofree char *json = NULL; - - if (g_file_get_contents (module_path, &json, NULL, NULL)) - { - g_autoptr(GFile) module_file_dir = g_file_get_parent (module_file); - builder_manifest_set_demarshal_base_dir (module_file_dir); - module = json_gobject_from_data (BUILDER_TYPE_MODULE, - json, -1, NULL); - builder_manifest_set_demarshal_base_dir (saved_demarshal_base_dir); - if (module) - { - builder_module_set_json_path (BUILDER_MODULE (module), module_path); - builder_module_set_base_dir (BUILDER_MODULE (module), module_file_dir); - } - } - } - else if (JSON_NODE_HOLDS_OBJECT (element_node)) - { - module = json_gobject_deserialize (BUILDER_TYPE_MODULE, element_node); - if (module != NULL) - builder_module_set_base_dir (BUILDER_MODULE (module), saved_demarshal_base_dir); - } - - if (module == NULL) - { - g_list_free_full (modules, g_object_unref); - return FALSE; - } - - modules = g_list_prepend (modules, module); - } - - g_value_set_pointer (value, g_list_reverse (modules)); - - return TRUE; - } - - return FALSE; - } - else if (strcmp (property_name, "sources") == 0) - { - if (JSON_NODE_TYPE (property_node) == JSON_NODE_NULL) - { - g_value_set_pointer (value, NULL); - return TRUE; - } - else if (JSON_NODE_TYPE (property_node) == JSON_NODE_ARRAY) - { - JsonArray *array = json_node_get_array (property_node); - guint i, array_len = json_array_get_length (array); - GList *sources = NULL; - BuilderSource *source; - - for (i = 0; i < array_len; i++) - { - JsonNode *element_node = json_array_get_element (array, i); - - if (JSON_NODE_TYPE (element_node) != JSON_NODE_OBJECT) - { - g_list_free_full (sources, g_object_unref); - return FALSE; - } - - source = builder_source_from_json (element_node); - if (source == NULL) - { - g_list_free_full (sources, g_object_unref); - return FALSE; - } - - sources = g_list_prepend (sources, source); - } - - g_value_set_pointer (value, g_list_reverse (sources)); - - return TRUE; - } - - return FALSE; - } - else - { - return json_serializable_default_deserialize_property (serializable, - property_name, - value, - pspec, property_node); - } -} - -static void -serializable_iface_init (JsonSerializableIface *serializable_iface) -{ - serializable_iface->serialize_property = builder_module_serialize_property; - serializable_iface->deserialize_property = builder_module_deserialize_property; - serializable_iface->find_property = builder_serializable_find_property_with_error; -} - -const char * -builder_module_get_name (BuilderModule *self) -{ - return self->name; -} - -gboolean -builder_module_is_enabled (BuilderModule *self, - BuilderContext *context) -{ - if (self->disabled) - return FALSE; - - if (self->only_arches != NULL && - self->only_arches[0] != NULL && - !g_strv_contains ((const char * const *) self->only_arches, builder_context_get_arch (context))) - return FALSE; - - if (self->skip_arches != NULL && - g_strv_contains ((const char * const *)self->skip_arches, builder_context_get_arch (context))) - return FALSE; - - return TRUE; -} - -gboolean -builder_module_should_build (BuilderModule *self) -{ - if (self->sources != NULL) - return TRUE; - - /* We allow building simple types even without sources, that is often useful */ - if (!g_strcmp0 (self->buildsystem, "simple")) - return TRUE; - - return FALSE; -} - -gboolean -builder_module_get_disabled (BuilderModule *self) -{ - return self->disabled; -} - -GList * -builder_module_get_sources (BuilderModule *self) -{ - return self->sources; -} - -GList * -builder_module_get_modules (BuilderModule *self) -{ - return self->modules; -} - -gboolean -builder_module_show_deps (BuilderModule *self, - BuilderContext *context, - GError **error) -{ - GList *l; - if (self->json_path) - g_print ("%s\n", self->json_path); - - for (l = self->sources; l != NULL; l = l->next) - { - BuilderSource *source = l->data; - - if (!builder_source_is_enabled (source, context)) - continue; - - if (!builder_source_show_deps (source, error)) - return FALSE; - } - - return TRUE; -} - -gboolean -builder_module_download_sources (BuilderModule *self, - gboolean update_vcs, - BuilderContext *context, - GError **error) -{ - GList *l; - - for (l = self->sources; l != NULL; l = l->next) - { - BuilderSource *source = l->data; - - if (!builder_source_is_enabled (source, context)) - continue; - - builder_set_term_title (_("Downloading %s"), self->name); - - if (!builder_source_download (source, update_vcs, context, error)) - { - g_prefix_error (error, "module %s: ", self->name); - return FALSE; - } - } - - return TRUE; -} - -gboolean -builder_module_extract_sources (BuilderModule *self, - GFile *dest, - BuilderContext *context, - GError **error) -{ - GList *l; - - if (!g_file_query_exists (dest, NULL) && - !g_file_make_directory_with_parents (dest, NULL, error)) - return FALSE; - - for (l = self->sources; l != NULL; l = l->next) - { - BuilderSource *source = l->data; - - if (!builder_source_is_enabled (source, context)) - continue; - - if (!builder_source_extract (source, dest, self->build_options, context, error)) - { - g_prefix_error (error, "module %s: ", self->name); - return FALSE; - } - } - - return TRUE; -} - -gboolean -builder_module_bundle_sources (BuilderModule *self, - BuilderContext *context, - GError **error) -{ - GList *l; - - if (self->json_path) - { - g_autoptr(GFile) json_file = g_file_new_for_path (self->json_path); - g_autoptr(GFile) destination_file = NULL; - g_autoptr(GFile) destination_dir = NULL; - GFile *manifest_base_dir = builder_context_get_base_dir (context); - g_autofree char *rel_path = g_file_get_relative_path (manifest_base_dir, json_file); - - if (rel_path == NULL) - { - g_warning ("Included manifest %s is outside manifest tree, not bundling", self->json_path); - return TRUE; - } - - destination_file = flatpak_build_file (builder_context_get_app_dir (context), - "sources/manifest", rel_path, NULL); - - destination_dir = g_file_get_parent (destination_file); - if (!flatpak_mkdir_p (destination_dir, NULL, error)) - return FALSE; - - if (!g_file_copy (json_file, destination_file, - G_FILE_COPY_OVERWRITE, - NULL, - NULL, NULL, - error)) - return FALSE; - } - - for (l = self->sources; l != NULL; l = l->next) - { - BuilderSource *source = l->data; - - if (!builder_source_is_enabled (source, context)) - continue; - - if (!builder_source_bundle (source, context, error)) - { - g_prefix_error (error, "module %s: ", self->name); - return FALSE; - } - } - - return TRUE; -} - -static GPtrArray * -setup_build_args (GFile *app_dir, - const char *module_name, - BuilderContext *context, - GFile *source_dir, - const char *cwd_subdir, - char **flatpak_opts, - char **env_vars, - GFile **cwd_file) -{ - g_autoptr(GPtrArray) args = NULL; - g_autofree char *source_dir_path = g_file_get_path (source_dir); - g_autofree char *source_dir_path_canonical = NULL; - g_autofree char *ccache_dir_path = NULL; - const char *builddir; - int i; - - args = g_ptr_array_new_with_free_func (g_free); - g_ptr_array_add (args, g_strdup ("flatpak")); - g_ptr_array_add (args, g_strdup ("build")); - - source_dir_path_canonical = realpath (source_dir_path, NULL); - if (source_dir_path_canonical == NULL) - source_dir_path_canonical = g_strdup (source_dir_path); - - if (builder_context_get_build_runtime (context)) - builddir = "/run/build-runtime/"; - else - builddir = "/run/build/"; - - g_ptr_array_add (args, g_strdup ("--nofilesystem=host")); - - /* We mount the canonical location, because bind-mounts of symlinks don't really work */ - g_ptr_array_add (args, g_strdup_printf ("--filesystem=%s", source_dir_path_canonical)); - - /* Also make sure the original path is available (if it was not canonical, in case something references that. */ - if (strcmp (source_dir_path_canonical, source_dir_path) != 0) - g_ptr_array_add (args, g_strdup_printf ("--bind-mount=%s=%s", source_dir_path, source_dir_path_canonical)); - - g_ptr_array_add (args, g_strdup_printf ("--bind-mount=%s%s=%s", builddir, module_name, source_dir_path_canonical)); - if (cwd_subdir) - g_ptr_array_add (args, g_strdup_printf ("--build-dir=%s%s/%s", builddir, module_name, cwd_subdir)); - else - g_ptr_array_add (args, g_strdup_printf ("--build-dir=%s%s", builddir, module_name)); - - if (g_file_query_exists (builder_context_get_ccache_dir (context), NULL)) - { - ccache_dir_path = g_file_get_path (builder_context_get_ccache_dir (context)); - g_ptr_array_add (args, g_strdup_printf ("--bind-mount=/run/ccache=%s", ccache_dir_path)); - } - - if (flatpak_opts) - { - for (i = 0; flatpak_opts[i] != NULL; i++) - g_ptr_array_add (args, g_strdup (flatpak_opts[i])); - } - - if (env_vars) - { - for (i = 0; env_vars[i] != NULL; i++) - g_ptr_array_add (args, g_strdup_printf ("--env=%s", env_vars[i])); - } - - g_ptr_array_add (args, g_file_get_path (app_dir)); - - *cwd_file = g_file_new_for_path (source_dir_path_canonical); - - return g_steal_pointer (&args); -} - -static gboolean -shell (GFile *app_dir, - const char *module_name, - BuilderContext *context, - GFile *source_dir, - const char *cwd_subdir, - char **flatpak_opts, - char **env_vars, - GError **error) -{ - g_autoptr(GFile) cwd_file = NULL; - g_autoptr(GPtrArray) args = - setup_build_args (app_dir, module_name, context, source_dir, cwd_subdir, flatpak_opts, env_vars, &cwd_file); - - g_ptr_array_add (args, "sh"); - g_ptr_array_add (args, NULL); - - if (chdir (flatpak_file_get_path_cached (cwd_file))) - { - glnx_set_error_from_errno (error); - return FALSE; - } - - if (execvp ((char *) args->pdata[0], (char **) args->pdata) == -1) - { - g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "Unable to start flatpak build"); - return FALSE; - } - - return TRUE; -} - -static const char skip_arg[] = "skip"; -static const char strv_arg[] = "strv"; - -static gboolean -build (GFile *app_dir, - const char *module_name, - BuilderContext *context, - GFile *source_dir, - const char *cwd_subdir, - char **flatpak_opts, - char **env_vars, - GError **error, - const gchar *argv1, - ...) -{ - g_autoptr(GFile) cwd_file = NULL; - g_autoptr(GPtrArray) args = - setup_build_args (app_dir, module_name, context, source_dir, cwd_subdir, flatpak_opts, env_vars, &cwd_file); - const gchar *arg; - const gchar **argv; - va_list ap; - int i; - - va_start (ap, argv1); - g_ptr_array_add (args, g_strdup (argv1)); - while ((arg = va_arg (ap, const gchar *))) - { - if (arg == strv_arg) - { - argv = va_arg (ap, const gchar **); - if (argv != NULL) - { - for (i = 0; argv[i] != NULL; i++) - g_ptr_array_add (args, g_strdup (argv[i])); - } - } - else if (arg != skip_arg) - { - g_ptr_array_add (args, g_strdup (arg)); - } - } - va_end (ap); - - g_ptr_array_add (args, NULL); - - if (!builder_maybe_host_spawnv (cwd_file, NULL, error, (const char * const *)args->pdata)) - { - g_prefix_error (error, "module %s: ", module_name); - return FALSE; - } - - return TRUE; -} - -gboolean -builder_module_ensure_writable (BuilderModule *self, - BuilderCache *cache, - BuilderContext *context, - GError **error) -{ - g_autoptr(GPtrArray) changes = NULL; - g_autoptr(GHashTable) matches = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - GFile *app_dir = builder_context_get_app_dir (context); - GHashTableIter iter; - gpointer key, value; - int i; - - if (cache == NULL) - return TRUE; - - if (self->ensure_writable == NULL || - self->ensure_writable[0] == NULL) - return TRUE; - - changes = builder_cache_get_files (cache, error); - if (changes == NULL) - return FALSE; - - for (i = 0; i < changes->len; i++) - { - const char *path = g_ptr_array_index (changes, i); - const char *unprefixed_path; - const char *prefix; - - if (g_str_has_prefix (path, "files/")) - prefix = "files/"; - else if (g_str_has_prefix (path, "usr/")) - prefix = "usr/"; - else - continue; - - unprefixed_path = path + strlen (prefix); - - collect_cleanup_for_path ((const char **)self->ensure_writable, unprefixed_path, prefix, matches); - } - - g_hash_table_iter_init (&iter, matches); - while (g_hash_table_iter_next (&iter, &key, &value)) - { - const char *path = key; - g_autoptr(GFile) dest = g_file_resolve_relative_path (app_dir, path); - - g_debug ("Breaking hardlink %s", path); - if (!flatpak_break_hardlink (dest, error)) - return FALSE; - } - - - return TRUE; -} - -static gboolean -builder_module_build_helper (BuilderModule *self, - BuilderCache *cache, - BuilderContext *context, - GFile *source_dir, - gboolean run_shell, - GError **error) -{ - GFile *app_dir = builder_context_get_app_dir (context); - g_autofree char *make_j = NULL; - g_autofree char *make_l = NULL; - const char *make_cmd = NULL; - - gboolean autotools = FALSE, cmake = FALSE, cmake_ninja = FALSE, meson = FALSE, simple = FALSE; - g_autoptr(GFile) configure_file = NULL; - g_autoptr(GFile) build_dir = NULL; - g_autofree char *build_dir_relative = NULL; - gboolean has_configure; - gboolean var_require_builddir; - gboolean use_builddir; - int i; - g_auto(GStrv) env = NULL; - g_auto(GStrv) build_args = NULL; - g_auto(GStrv) config_opts = NULL; - g_autoptr(GFile) source_subdir = NULL; - const char *source_subdir_relative = NULL; - g_autofree char *source_dir_path = NULL; - g_autoptr(GError) my_error = NULL; - BuilderPostProcessFlags post_process_flags = 0; - - source_dir_path = g_file_get_path (source_dir); - - g_print ("========================================================================\n"); - g_print ("Building module %s in %s\n", self->name, source_dir_path); - g_print ("========================================================================\n"); - - builder_set_term_title (_("Building %s"), self->name); - - if (!builder_module_extract_sources (self, source_dir, context, error)) - return FALSE; - - if (self->subdir != NULL && self->subdir[0] != 0) - { - source_subdir = g_file_resolve_relative_path (source_dir, self->subdir); - source_subdir_relative = self->subdir; - } - else - { - source_subdir = g_object_ref (source_dir); - } - - build_args = builder_options_get_build_args (self->build_options, context, error); - if (build_args == NULL) - return FALSE; - - env = builder_options_get_env (self->build_options, context); - config_opts = builder_options_get_config_opts (self->build_options, context, self->config_opts); - - if (!self->buildsystem) - { - if (self->cmake) - cmake = TRUE; - else - autotools = TRUE; - } - else if (!strcmp (self->buildsystem, "cmake")) - cmake = TRUE; - else if (!strcmp (self->buildsystem, "meson")) - meson = TRUE; - else if (!strcmp (self->buildsystem, "autotools")) - autotools = TRUE; - else if (!strcmp (self->buildsystem, "cmake-ninja")) - cmake_ninja = TRUE; - else if (!strcmp (self->buildsystem, "simple")) - simple = TRUE; - else - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "module %s: Invalid buildsystem: \"%s\"", - self->name, self->buildsystem); - return FALSE; - } - - if (simple) - { - if (!self->build_commands) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "module %s: Buildsystem simple requires specifying \"build-commands\"", - self->name); - return FALSE; - } - } - else if (cmake || cmake_ninja) - { - g_autoptr(GFile) cmake_file = NULL; - - cmake_file = g_file_get_child (source_subdir, "CMakeLists.txt"); - if (!g_file_query_exists (cmake_file, NULL)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "module: %s: Can't find CMakeLists.txt", self->name); - return FALSE; - } - configure_file = g_object_ref (cmake_file); - } - else if (meson) - { - g_autoptr(GFile) meson_file = NULL; - - meson_file = g_file_get_child (source_subdir, "meson.build"); - if (!g_file_query_exists (meson_file, NULL)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "module: %s: Can't find meson.build", self->name); - return FALSE; - } - configure_file = g_object_ref (meson_file); - } - else if (autotools) - { - configure_file = g_file_get_child (source_subdir, "configure"); - - if (self->rm_configure) - { - if (!g_file_delete (configure_file, NULL, error)) - { - g_prefix_error (error, "module %s: ", self->name); - return FALSE; - } - } - } - - if (configure_file) - has_configure = g_file_query_exists (configure_file, NULL); - - if (configure_file && !has_configure && !self->no_autogen) - { - const char *autogen_names[] = {"autogen", "autogen.sh", "bootstrap", "bootstrap.sh", NULL}; - g_autofree char *autogen_cmd = NULL; - g_auto(GStrv) env_with_noconfigure = NULL; - - for (i = 0; autogen_names[i] != NULL; i++) - { - g_autoptr(GFile) autogen_file = g_file_get_child (source_subdir, autogen_names[i]); - if (g_file_query_exists (autogen_file, NULL)) - { - autogen_cmd = g_strdup_printf ("./%s", autogen_names[i]); - break; - } - } - - if (autogen_cmd == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "module %s: Can't find autogen, autogen.sh or bootstrap", self->name); - return FALSE; - } - - env_with_noconfigure = g_environ_setenv (g_strdupv (env), "NOCONFIGURE", "1", TRUE); - if (!build (app_dir, self->name, context, source_dir, source_subdir_relative, build_args, env_with_noconfigure, error, - autogen_cmd, NULL)) - { - g_prefix_error (error, "module %s: ", self->name); - return FALSE; - } - - if (!g_file_query_exists (configure_file, NULL)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "module %s: autogen did not create configure", self->name); - return FALSE; - } - - has_configure = TRUE; - } - - if (configure_file && has_configure) - { - const char *configure_cmd; - const char *cmake_generator = NULL; - gchar *configure_final_arg = NULL; - g_autofree char *configure_content = NULL; - g_auto(GStrv) configure_args = NULL; - g_autoptr(GPtrArray) configure_args_arr = g_ptr_array_new (); - - if (!g_file_load_contents (configure_file, NULL, &configure_content, NULL, NULL, error)) - { - g_prefix_error (error, "module %s: ", self->name); - return FALSE; - } - - var_require_builddir = strstr (configure_content, "buildapi-variable-require-builddir") != NULL; - use_builddir = var_require_builddir || self->builddir || meson; - - if (use_builddir) - { - if (source_subdir_relative) - build_dir_relative = g_build_filename (source_subdir_relative, "_flatpak_build", NULL); - else - build_dir_relative = g_strdup ("_flatpak_build"); - build_dir = g_file_get_child (source_subdir, "_flatpak_build"); - - if (!g_file_make_directory (build_dir, NULL, error)) - { - g_prefix_error (error, "module %s: ", self->name); - return FALSE; - } - - if (cmake || cmake_ninja) - { - configure_cmd = "cmake"; - configure_final_arg = g_strdup(".."); - } - else if (meson) - { - configure_cmd = "meson"; - configure_final_arg = g_strdup (".."); - } - else - { - configure_cmd = "../configure"; - } - } - else - { - build_dir_relative = g_strdup (source_subdir_relative); - build_dir = g_object_ref (source_subdir); - if (cmake || cmake_ninja) - { - configure_cmd = "cmake"; - configure_final_arg = g_strdup ("."); - } - else - { - g_assert (!meson); - configure_cmd = "./configure"; - } - } - - if (cmake) - cmake_generator = "Unix Makefiles"; - else if (cmake_ninja) - cmake_generator = "Ninja"; - - if (cmake || cmake_ninja) - { - g_ptr_array_add (configure_args_arr, g_strdup_printf ("-DCMAKE_INSTALL_PREFIX:PATH='%s'", - builder_options_get_prefix (self->build_options, context))); - g_ptr_array_add (configure_args_arr, g_strdup ("-G")); - g_ptr_array_add (configure_args_arr, g_strdup_printf ("%s", cmake_generator)); - } - else /* autotools and meson */ - { - g_ptr_array_add (configure_args_arr, g_strdup_printf ("--prefix=%s", - builder_options_get_prefix (self->build_options, context))); - } - - g_ptr_array_add (configure_args_arr, configure_final_arg); - g_ptr_array_add (configure_args_arr, NULL); - - configure_args = (char **) g_ptr_array_free (g_steal_pointer (&configure_args_arr), FALSE); - - if (!build (app_dir, self->name, context, source_dir, build_dir_relative, build_args, env, error, - configure_cmd, strv_arg, configure_args, strv_arg, config_opts, NULL)) - return FALSE; - } - else - { - build_dir_relative = g_strdup (source_subdir_relative); - build_dir = g_object_ref (source_subdir); - } - - if (meson || cmake_ninja) - { - g_autoptr(GFile) ninja_file = g_file_get_child (build_dir, "build.ninja"); - if (!g_file_query_exists (ninja_file, NULL)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "module %s: Can't find ninja file", self->name); - return FALSE; - } - } - else if (autotools || cmake) - { - const char *makefile_names[] = {"Makefile", "makefile", "GNUmakefile", NULL}; - - for (i = 0; makefile_names[i] != NULL; i++) - { - g_autoptr(GFile) makefile_file = g_file_get_child (build_dir, makefile_names[i]); - if (g_file_query_exists (makefile_file, NULL)) - break; - } - - if (makefile_names[i] == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "module %s: Can't find makefile", self->name); - return FALSE; - } - } - - if (!self->no_parallel_make) - { - make_j = g_strdup_printf ("-j%d", builder_context_get_jobs (context)); - make_l = g_strdup_printf ("-l%d", 2 * builder_context_get_jobs (context)); - } - - if (run_shell) - { - if (!shell (app_dir, self->name, context, source_dir, build_dir_relative, build_args, env, error)) - return FALSE; - return TRUE; - } - - /* Build and install */ - - builder_set_term_title (_("Installing %s"), self->name); - - if (meson || cmake_ninja) - make_cmd = "ninja"; - else if (simple) - make_cmd = NULL; - else - make_cmd = "make"; - - if (make_cmd) - { - if (!build (app_dir, self->name, context, source_dir, build_dir_relative, build_args, env, error, - make_cmd, make_j ? make_j : skip_arg, make_l ? make_l : skip_arg, strv_arg, self->make_args, NULL)) - return FALSE; - } - - for (i = 0; self->build_commands != NULL && self->build_commands[i] != NULL; i++) - { - g_print ("Running: %s\n", self->build_commands[i]); - if (!build (app_dir, self->name, context, source_dir, build_dir_relative, build_args, env, error, - "/bin/sh", "-c", self->build_commands[i], NULL)) - return FALSE; - } - - if (!self->no_make_install && make_cmd) - { - if (!build (app_dir, self->name, context, source_dir, build_dir_relative, build_args, env, error, - make_cmd, self->install_rule ? self->install_rule : "install", - strv_arg, self->make_install_args, NULL)) - return FALSE; - } - - /* Post installation scripts */ - - builder_set_term_title (_("Post-Install %s"), self->name); - - if (builder_context_get_separate_locales (context)) - { - g_autoptr(GFile) root_dir = NULL; - - if (builder_context_get_build_runtime (context)) - root_dir = g_file_get_child (app_dir, "usr"); - else - root_dir = g_file_get_child (app_dir, "files"); - - if (!builder_migrate_locale_dirs (root_dir, error)) - { - g_prefix_error (error, "module %s: ", self->name); - return FALSE; - } - } - - if (self->post_install) - { - for (i = 0; self->post_install[i] != NULL; i++) - { - if (!build (app_dir, self->name, context, source_dir, build_dir_relative, build_args, env, error, - "/bin/sh", "-c", self->post_install[i], NULL)) - return FALSE; - } - } - - if (!self->no_python_timestamp_fix) - post_process_flags |= BUILDER_POST_PROCESS_FLAGS_PYTHON_TIMESTAMPS; - - if (builder_options_get_strip (self->build_options, context)) - post_process_flags |= BUILDER_POST_PROCESS_FLAGS_STRIP; - else if (!builder_options_get_no_debuginfo (self->build_options, context) && - /* No support for debuginfo for extensions atm */ - !builder_context_get_build_extension (context)) - post_process_flags |= BUILDER_POST_PROCESS_FLAGS_DEBUGINFO; - - if (!builder_post_process (post_process_flags, app_dir, - cache, context, error)) - { - g_prefix_error (error, "module %s: ", self->name); - return FALSE; - } - - - return TRUE; -} - -gboolean -builder_module_build (BuilderModule *self, - BuilderCache *cache, - BuilderContext *context, - gboolean run_shell, - GError **error) -{ - g_autoptr(GFile) source_dir = NULL; - g_autoptr(GFile) build_parent_dir = NULL; - g_autoptr(GFile) build_link = NULL; - g_autoptr(GError) my_error = NULL; - g_autofree char *buildname = NULL; - gboolean res; - - source_dir = builder_context_allocate_build_subdir (context, self->name, error); - if (source_dir == NULL) - { - g_prefix_error (error, "module %s: ", self->name); - return FALSE; - } - - build_parent_dir = g_file_get_parent (source_dir); - buildname = g_file_get_basename (source_dir); - - /* Make an unversioned symlink */ - build_link = g_file_get_child (build_parent_dir, self->name); - if (!g_file_delete (build_link, NULL, &my_error) && - !g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) - { - g_propagate_error (error, g_steal_pointer (&my_error)); - g_prefix_error (error, "module %s: ", self->name); - return FALSE; - } - g_clear_error (&my_error); - - if (!g_file_make_symbolic_link (build_link, - buildname, - NULL, error)) - { - g_prefix_error (error, "module %s: ", self->name); - return FALSE; - } - - res = builder_module_build_helper (self, cache, context, source_dir, run_shell, error); - - /* Clean up build dir */ - - if (!run_shell && - (!builder_context_get_keep_build_dirs (context) && - (res || builder_context_get_delete_build_dirs (context)))) - { - builder_set_term_title (_("Cleanup %s"), self->name); - - if (!g_file_delete (build_link, NULL, error)) - { - g_prefix_error (error, "module %s: ", self->name); - return FALSE; - } - - if (!flatpak_rm_rf (source_dir, NULL, error)) - { - g_prefix_error (error, "module %s: ", self->name); - return FALSE; - } - } - - return res; -} - -gboolean -builder_module_update (BuilderModule *self, - BuilderContext *context, - GError **error) -{ - GList *l; - - for (l = self->sources; l != NULL; l = l->next) - { - BuilderSource *source = l->data; - - if (!builder_source_is_enabled (source, context)) - continue; - - builder_set_term_title (_("Updating %s"), self->name); - - if (!builder_source_update (source, context, error)) - { - g_prefix_error (error, "module %s: ", self->name); - return FALSE; - } - } - - return TRUE; -} - -void -builder_module_checksum (BuilderModule *self, - BuilderCache *cache, - BuilderContext *context) -{ - GList *l; - - builder_cache_checksum_str (cache, BUILDER_MODULE_CHECKSUM_VERSION); - builder_cache_checksum_str (cache, self->name); - builder_cache_checksum_str (cache, self->subdir); - builder_cache_checksum_strv (cache, self->post_install); - builder_cache_checksum_strv (cache, self->config_opts); - builder_cache_checksum_strv (cache, self->make_args); - builder_cache_checksum_strv (cache, self->make_install_args); - builder_cache_checksum_strv (cache, self->ensure_writable); - builder_cache_checksum_strv (cache, self->only_arches); - builder_cache_checksum_strv (cache, self->skip_arches); - builder_cache_checksum_boolean (cache, self->rm_configure); - builder_cache_checksum_boolean (cache, self->no_autogen); - builder_cache_checksum_boolean (cache, self->disabled); - builder_cache_checksum_boolean (cache, self->no_parallel_make); - builder_cache_checksum_boolean (cache, self->no_make_install); - builder_cache_checksum_boolean (cache, self->no_python_timestamp_fix); - builder_cache_checksum_boolean (cache, self->cmake); - builder_cache_checksum_boolean (cache, self->builddir); - builder_cache_checksum_compat_strv (cache, self->build_commands); - builder_cache_checksum_compat_str (cache, self->buildsystem); - builder_cache_checksum_compat_str (cache, self->install_rule); - - if (self->build_options) - builder_options_checksum (self->build_options, cache, context); - - for (l = self->sources; l != NULL; l = l->next) - { - BuilderSource *source = l->data; - - if (!builder_source_is_enabled (source, context)) - continue; - - builder_source_checksum (source, cache, context); - } -} - -void -builder_module_checksum_for_cleanup (BuilderModule *self, - BuilderCache *cache, - BuilderContext *context) -{ - builder_cache_checksum_str (cache, BUILDER_MODULE_CHECKSUM_VERSION); - builder_cache_checksum_str (cache, self->name); - builder_cache_checksum_strv (cache, self->cleanup); -} - -void -builder_module_checksum_for_platform (BuilderModule *self, - BuilderCache *cache, - BuilderContext *context) -{ - builder_cache_checksum_strv (cache, self->cleanup_platform); -} - -void -builder_module_set_json_path (BuilderModule *self, - const char *json_path) -{ - self->json_path = g_strdup (json_path); -} - -void -builder_module_set_base_dir (BuilderModule *self, - GFile* base_dir) -{ - GList *l; - - for (l = self->sources; l != NULL; l = l->next) - builder_source_set_base_dir (l->data, base_dir); -} - -GPtrArray * -builder_module_get_changes (BuilderModule *self) -{ - return self->changes; -} - -void -builder_module_set_changes (BuilderModule *self, - GPtrArray *changes) -{ - if (self->changes != changes) - { - if (self->changes) - g_ptr_array_unref (self->changes); - self->changes = g_ptr_array_ref (changes); - } -} - -static gboolean -matches_cleanup_for_path (const char **patterns, - const char *path) -{ - int i; - - if (patterns == NULL) - return FALSE; - - for (i = 0; patterns[i] != NULL; i++) - { - if (flatpak_matches_path_pattern (path, patterns[i])) - return TRUE; - } - - return FALSE; -} - -void -builder_module_cleanup_collect (BuilderModule *self, - gboolean platform, - BuilderContext *context, - GHashTable *to_remove_ht) -{ - GPtrArray *changed_files; - int i; - const char **global_patterns; - const char **local_patterns; - - if (!self->changes) - return; - - if (platform) - { - global_patterns = builder_context_get_global_cleanup_platform (context); - local_patterns = (const char **) self->cleanup_platform; - } - else - { - global_patterns = builder_context_get_global_cleanup (context); - local_patterns = (const char **) self->cleanup; - } - - changed_files = self->changes; - for (i = 0; i < changed_files->len; i++) - { - const char *path = g_ptr_array_index (changed_files, i); - const char *unprefixed_path; - const char *prefix; - - if (g_str_has_prefix (path, "files/")) - prefix = "files/"; - else if (g_str_has_prefix (path, "usr/")) - prefix = "usr/"; - else - continue; - - unprefixed_path = path + strlen (prefix); - - collect_cleanup_for_path (global_patterns, unprefixed_path, prefix, to_remove_ht); - collect_cleanup_for_path (local_patterns, unprefixed_path, prefix, to_remove_ht); - - if (g_str_has_prefix (unprefixed_path, "lib/debug/") && - g_str_has_suffix (unprefixed_path, ".debug")) - { - g_autofree char *real_path = g_strdup (unprefixed_path); - g_autofree char *real_parent = NULL; - g_autofree char *parent = NULL; - g_autofree char *debug_path = NULL; - - debug_path = g_strdup (unprefixed_path + strlen ("lib/debug/")); - debug_path[strlen (debug_path) - strlen (".debug")] = 0; - - while (TRUE) - { - if (matches_cleanup_for_path (global_patterns, debug_path) || - matches_cleanup_for_path (local_patterns, debug_path)) - g_hash_table_insert (to_remove_ht, g_strconcat (prefix, real_path, NULL), GINT_TO_POINTER (1)); - - real_parent = g_path_get_dirname (real_path); - if (strcmp (real_parent, ".") == 0) - break; - g_free (real_path); - real_path = g_steal_pointer (&real_parent); - - parent = g_path_get_dirname (debug_path); - g_free (debug_path); - debug_path = g_steal_pointer (&parent); - } - } - } -} diff --git a/builder/builder-module.h b/builder/builder-module.h deleted file mode 100644 index 22933e8a..00000000 --- a/builder/builder-module.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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.1 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_MODULE_H__ -#define __BUILDER_MODULE_H__ - -#include - -#include "builder-source.h" -#include "builder-options.h" - -G_BEGIN_DECLS - -typedef struct BuilderModule BuilderModule; - -#define BUILDER_TYPE_MODULE (builder_module_get_type ()) -#define BUILDER_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUILDER_TYPE_MODULE, BuilderModule)) -#define BUILDER_IS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUILDER_TYPE_MODULE)) - -/* Bump this if format changes in incompatible ways to force rebuild */ -#define BUILDER_MODULE_CHECKSUM_VERSION "1" - -GType builder_module_get_type (void); - -const char * builder_module_get_name (BuilderModule *self); -gboolean builder_module_is_enabled (BuilderModule *self, - BuilderContext *context); -gboolean builder_module_get_disabled (BuilderModule *self); -gboolean builder_module_should_build (BuilderModule *self); -GList * builder_module_get_sources (BuilderModule *self); -GList * builder_module_get_modules (BuilderModule *self); -void builder_module_set_json_path (BuilderModule *self, - const char *json_path); -void builder_module_set_base_dir (BuilderModule *self, - GFile* base_dir); -GPtrArray * builder_module_get_changes (BuilderModule *self); -void builder_module_set_changes (BuilderModule *self, - GPtrArray *changes); - -gboolean builder_module_show_deps (BuilderModule *self, - BuilderContext *context, - GError **error); -gboolean builder_module_download_sources (BuilderModule *self, - gboolean update_vcs, - BuilderContext *context, - GError **error); -gboolean builder_module_extract_sources (BuilderModule *self, - GFile *dest, - BuilderContext *context, - GError **error); -gboolean builder_module_bundle_sources (BuilderModule *self, - BuilderContext *context, - GError **error); -gboolean builder_module_ensure_writable (BuilderModule *self, - BuilderCache *cache, - BuilderContext *context, - GError **error); -gboolean builder_module_build (BuilderModule *self, - BuilderCache *cache, - BuilderContext *context, - gboolean run_shell, - GError **error); -gboolean builder_module_update (BuilderModule *self, - BuilderContext *context, - GError **error); -void builder_module_checksum (BuilderModule *self, - BuilderCache *cache, - BuilderContext *context); -void builder_module_checksum_for_cleanup (BuilderModule *self, - BuilderCache *cache, - BuilderContext *context); -void builder_module_checksum_for_platform (BuilderModule *self, - BuilderCache *cache, - BuilderContext *context); -void builder_module_cleanup_collect (BuilderModule *self, - gboolean platform, - BuilderContext *context, - GHashTable *to_remove_ht); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (BuilderModule, g_object_unref) - -G_END_DECLS - -#endif /* __BUILDER_MODULE_H__ */ diff --git a/builder/builder-options.c b/builder/builder-options.c deleted file mode 100644 index 4113d584..00000000 --- a/builder/builder-options.c +++ /dev/null @@ -1,788 +0,0 @@ -/* builder-options.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 - -#include "builder-options.h" -#include "builder-context.h" -#include "builder-utils.h" - -struct BuilderOptions -{ - GObject parent; - - gboolean strip; - gboolean no_debuginfo; - char *cflags; - char *cppflags; - char *cxxflags; - char *ldflags; - char *prefix; - char **env; - char **build_args; - char **config_opts; - GHashTable *arch; -}; - -typedef struct -{ - GObjectClass parent_class; -} BuilderOptionsClass; - -static void serializable_iface_init (JsonSerializableIface *serializable_iface); - -G_DEFINE_TYPE_WITH_CODE (BuilderOptions, builder_options, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (JSON_TYPE_SERIALIZABLE, serializable_iface_init)); - -enum { - PROP_0, - PROP_CFLAGS, - PROP_CPPFLAGS, - PROP_CXXFLAGS, - PROP_LDFLAGS, - PROP_PREFIX, - PROP_ENV, - PROP_STRIP, - PROP_NO_DEBUGINFO, - PROP_ARCH, - PROP_BUILD_ARGS, - PROP_CONFIG_OPTS, - LAST_PROP -}; - - -static void -builder_options_finalize (GObject *object) -{ - BuilderOptions *self = (BuilderOptions *) object; - - g_free (self->cflags); - g_free (self->cxxflags); - g_free (self->cppflags); - g_free (self->ldflags); - g_free (self->prefix); - g_strfreev (self->env); - g_strfreev (self->build_args); - g_strfreev (self->config_opts); - g_hash_table_destroy (self->arch); - - G_OBJECT_CLASS (builder_options_parent_class)->finalize (object); -} - -static void -builder_options_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - BuilderOptions *self = BUILDER_OPTIONS (object); - - switch (prop_id) - { - case PROP_CFLAGS: - g_value_set_string (value, self->cflags); - break; - - case PROP_CPPFLAGS: - g_value_set_string (value, self->cppflags); - break; - - case PROP_CXXFLAGS: - g_value_set_string (value, self->cxxflags); - break; - - case PROP_LDFLAGS: - g_value_set_string (value, self->ldflags); - break; - - case PROP_PREFIX: - g_value_set_string (value, self->prefix); - break; - - case PROP_ENV: - g_value_set_boxed (value, self->env); - break; - - case PROP_ARCH: - g_value_set_boxed (value, self->arch); - break; - - case PROP_BUILD_ARGS: - g_value_set_boxed (value, self->build_args); - break; - - case PROP_CONFIG_OPTS: - g_value_set_boxed (value, self->config_opts); - break; - - case PROP_STRIP: - g_value_set_boolean (value, self->strip); - break; - - case PROP_NO_DEBUGINFO: - g_value_set_boolean (value, self->no_debuginfo); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -builder_options_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - BuilderOptions *self = BUILDER_OPTIONS (object); - gchar **tmp; - - switch (prop_id) - { - case PROP_CFLAGS: - g_clear_pointer (&self->cflags, g_free); - self->cflags = g_value_dup_string (value); - break; - - case PROP_CXXFLAGS: - g_clear_pointer (&self->cxxflags, g_free); - self->cxxflags = g_value_dup_string (value); - break; - - case PROP_CPPFLAGS: - g_clear_pointer (&self->cppflags, g_free); - self->cppflags = g_value_dup_string (value); - break; - - case PROP_LDFLAGS: - g_clear_pointer (&self->ldflags, g_free); - self->ldflags = g_value_dup_string (value); - break; - - case PROP_PREFIX: - g_clear_pointer (&self->prefix, g_free); - self->prefix = g_value_dup_string (value); - break; - - case PROP_ENV: - tmp = self->env; - self->env = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - case PROP_ARCH: - g_hash_table_destroy (self->arch); - /* NOTE: This takes ownership of the hash table! */ - self->arch = g_value_dup_boxed (value); - break; - - case PROP_BUILD_ARGS: - tmp = self->build_args; - self->build_args = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - case PROP_CONFIG_OPTS: - tmp = self->config_opts; - self->config_opts = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - case PROP_STRIP: - self->strip = g_value_get_boolean (value); - break; - - case PROP_NO_DEBUGINFO: - self->no_debuginfo = g_value_get_boolean (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -builder_options_class_init (BuilderOptionsClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = builder_options_finalize; - object_class->get_property = builder_options_get_property; - object_class->set_property = builder_options_set_property; - - g_object_class_install_property (object_class, - PROP_CFLAGS, - g_param_spec_string ("cflags", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_CXXFLAGS, - g_param_spec_string ("cxxflags", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_CPPFLAGS, - g_param_spec_string ("cppflags", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_LDFLAGS, - g_param_spec_string ("ldflags", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_PREFIX, - g_param_spec_string ("prefix", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_ENV, - g_param_spec_boxed ("env", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_ARCH, - g_param_spec_boxed ("arch", - "", - "", - G_TYPE_HASH_TABLE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_BUILD_ARGS, - g_param_spec_boxed ("build-args", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_CONFIG_OPTS, - g_param_spec_boxed ("config-opts", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_STRIP, - g_param_spec_boolean ("strip", - "", - "", - FALSE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_NO_DEBUGINFO, - g_param_spec_boolean ("no-debuginfo", - "", - "", - FALSE, - G_PARAM_READWRITE)); -} - -static void -builder_options_init (BuilderOptions *self) -{ - self->arch = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); -} - -static JsonNode * -builder_options_serialize_property (JsonSerializable *serializable, - const gchar *property_name, - const GValue *value, - GParamSpec *pspec) -{ - if (strcmp (property_name, "arch") == 0) - { - BuilderOptions *self = BUILDER_OPTIONS (serializable); - JsonNode *retval = NULL; - - if (self->arch && g_hash_table_size (self->arch) > 0) - { - JsonObject *object; - GHashTableIter iter; - gpointer key, value; - - object = json_object_new (); - - g_hash_table_iter_init (&iter, self->arch); - while (g_hash_table_iter_next (&iter, &key, &value)) - { - JsonNode *child = json_gobject_serialize (value); - json_object_set_member (object, (char *) key, child); - } - - retval = json_node_init_object (json_node_alloc (), object); - json_object_unref (object); - } - - return retval; - } - else if (strcmp (property_name, "env") == 0) - { - BuilderOptions *self = BUILDER_OPTIONS (serializable); - JsonNode *retval = NULL; - - if (self->env && g_strv_length (self->env) > 0) - { - JsonObject *object; - int i; - - object = json_object_new (); - - for (i = 0; self->env[i] != NULL; i++) - { - JsonNode *str = json_node_new (JSON_NODE_VALUE); - const char *equal; - g_autofree char *member = NULL; - - equal = strchr (self->env[i], '='); - if (equal) - { - json_node_set_string (str, equal + 1); - member = g_strndup (self->env[i], equal - self->env[i]); - } - else - { - json_node_set_string (str, ""); - member = g_strdup (self->env[i]); - } - - json_object_set_member (object, member, str); - } - - retval = json_node_init_object (json_node_alloc (), object); - json_object_unref (object); - } - - return retval; - } - else - { - return json_serializable_default_serialize_property (serializable, - property_name, - value, - pspec); - } -} - -static gboolean -builder_options_deserialize_property (JsonSerializable *serializable, - const gchar *property_name, - GValue *value, - GParamSpec *pspec, - JsonNode *property_node) -{ - if (strcmp (property_name, "arch") == 0) - { - if (JSON_NODE_TYPE (property_node) == JSON_NODE_NULL) - { - g_value_set_boxed (value, NULL); - return TRUE; - } - else if (JSON_NODE_TYPE (property_node) == JSON_NODE_OBJECT) - { - JsonObject *object = json_node_get_object (property_node); - g_autoptr(GHashTable) hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); - g_autoptr(GList) members = NULL; - GList *l; - - members = json_object_get_members (object); - for (l = members; l != NULL; l = l->next) - { - const char *member_name = l->data; - JsonNode *val; - GObject *option; - - val = json_object_get_member (object, member_name); - option = json_gobject_deserialize (BUILDER_TYPE_OPTIONS, val); - if (option == NULL) - return FALSE; - - g_hash_table_insert (hash, g_strdup (member_name), option); - } - - g_value_set_boxed (value, hash); - return TRUE; - } - - return FALSE; - } - else if (strcmp (property_name, "env") == 0) - { - if (JSON_NODE_TYPE (property_node) == JSON_NODE_NULL) - { - g_value_set_boxed (value, NULL); - return TRUE; - } - else if (JSON_NODE_TYPE (property_node) == JSON_NODE_OBJECT) - { - JsonObject *object = json_node_get_object (property_node); - g_autoptr(GPtrArray) env = g_ptr_array_new_with_free_func (g_free); - g_autoptr(GList) members = NULL; - GList *l; - - members = json_object_get_members (object); - for (l = members; l != NULL; l = l->next) - { - const char *member_name = l->data; - JsonNode *val; - const char *val_str; - - val = json_object_get_member (object, member_name); - val_str = json_node_get_string (val); - if (val_str == NULL) - return FALSE; - - g_ptr_array_add (env, g_strdup_printf ("%s=%s", member_name, val_str)); - } - - g_ptr_array_add (env, NULL); - g_value_take_boxed (value, g_ptr_array_free (g_steal_pointer (&env), FALSE)); - return TRUE; - } - - return FALSE; - } - else - { - return json_serializable_default_deserialize_property (serializable, - property_name, - value, - pspec, property_node); - } -} - -static void -serializable_iface_init (JsonSerializableIface *serializable_iface) -{ - serializable_iface->serialize_property = builder_options_serialize_property; - serializable_iface->deserialize_property = builder_options_deserialize_property; - serializable_iface->find_property = builder_serializable_find_property_with_error; -} - -static GList * -get_arched_options (BuilderOptions *self, BuilderContext *context) -{ - GList *options = NULL; - const char *arch = builder_context_get_arch (context); - BuilderOptions *arch_options; - - options = g_list_prepend (options, self); - - arch_options = g_hash_table_lookup (self->arch, arch); - if (arch_options) - options = g_list_prepend (options, arch_options); - - return options; -} - -static GList * -get_all_options (BuilderOptions *self, BuilderContext *context) -{ - GList *options = NULL; - BuilderOptions *global_options = builder_context_get_options (context); - - if (self) - options = get_arched_options (self, context); - - if (global_options && global_options != self) - options = g_list_concat (options, get_arched_options (global_options, context)); - - return options; -} - -static const char * -builder_options_get_flags (BuilderOptions *self, BuilderContext *context, size_t field_offset) -{ - g_autoptr(GList) options = get_all_options (self, context); - GList *l; - GString *flags = NULL; - - /* Last command flag wins, so reverse order */ - options = g_list_reverse (options); - - for (l = options; l != NULL; l = l->next) - { - BuilderOptions *o = l->data; - const char *flag = G_STRUCT_MEMBER (const char *, o, field_offset); - - if (flag) - { - if (flags == NULL) - flags = g_string_new (""); - - if (flags->len > 0) - g_string_append_c (flags, ' '); - - g_string_append (flags, flag); - } - } - - if (flags) - return g_string_free (flags, FALSE); - - return NULL; -} - -const char * -builder_options_get_cflags (BuilderOptions *self, BuilderContext *context) -{ - return builder_options_get_flags (self, context, G_STRUCT_OFFSET (BuilderOptions, cflags)); -} - -const char * -builder_options_get_cxxflags (BuilderOptions *self, BuilderContext *context) -{ - return builder_options_get_flags (self, context, G_STRUCT_OFFSET (BuilderOptions, cxxflags)); -} - -const char * -builder_options_get_cppflags (BuilderOptions *self, BuilderContext *context) -{ - return builder_options_get_flags (self, context, G_STRUCT_OFFSET (BuilderOptions, cppflags)); -} - -const char * -builder_options_get_ldflags (BuilderOptions *self, BuilderContext *context) -{ - return builder_options_get_flags (self, context, G_STRUCT_OFFSET (BuilderOptions, ldflags)); -} - -const char * -builder_options_get_prefix (BuilderOptions *self, BuilderContext *context) -{ - g_autoptr(GList) options = get_all_options (self, context); - GList *l; - - for (l = options; l != NULL; l = l->next) - { - BuilderOptions *o = l->data; - if (o->prefix) - return o->prefix; - } - - if (builder_context_get_build_runtime (context)) - return "/usr"; - - return "/app"; -} - -gboolean -builder_options_get_strip (BuilderOptions *self, BuilderContext *context) -{ - g_autoptr(GList) options = get_all_options (self, context); - GList *l; - - for (l = options; l != NULL; l = l->next) - { - BuilderOptions *o = l->data; - if (o->strip) - return TRUE; - } - - return FALSE; -} - -gboolean -builder_options_get_no_debuginfo (BuilderOptions *self, BuilderContext *context) -{ - g_autoptr(GList) options = get_all_options (self, context); - GList *l; - - for (l = options; l != NULL; l = l->next) - { - BuilderOptions *o = l->data; - if (o->no_debuginfo) - return TRUE; - } - - return FALSE; -} - -char ** -builder_options_get_env (BuilderOptions *self, BuilderContext *context) -{ - g_autoptr(GList) options = get_all_options (self, context); - GList *l; - int i; - char **envp = NULL; - const char *cflags, *cppflags, *cxxflags, *ldflags; - - for (l = options; l != NULL; l = l->next) - { - BuilderOptions *o = l->data; - - if (o->env) - { - for (i = 0; o->env[i] != NULL; i++) - { - const char *line = o->env[i]; - const char *eq = strchr (line, '='); - const char *value = ""; - g_autofree char *key = NULL; - - if (eq) - { - key = g_strndup (line, eq - line); - value = eq + 1; - } - else - { - key = g_strdup (key); - } - - envp = g_environ_setenv (envp, key, value, FALSE); - } - } - } - - envp = builder_context_extend_env (context, envp); - - cflags = builder_options_get_cflags (self, context); - if (cflags) - envp = g_environ_setenv (envp, "CFLAGS", cflags, FALSE); - - cppflags = builder_options_get_cppflags (self, context); - if (cppflags) - envp = g_environ_setenv (envp, "CPPFLAGS", cppflags, FALSE); - - cxxflags = builder_options_get_cxxflags (self, context); - if (cxxflags) - envp = g_environ_setenv (envp, "CXXFLAGS", cxxflags, FALSE); - - ldflags = builder_options_get_ldflags (self, context); - if (ldflags) - envp = g_environ_setenv (envp, "LDFLAGS", ldflags, FALSE); - - return envp; -} - -char ** -builder_options_get_build_args (BuilderOptions *self, - BuilderContext *context, - GError **error) -{ - g_autoptr(GList) options = get_all_options (self, context); - GList *l; - int i; - g_autoptr(GPtrArray) array = g_ptr_array_new_with_free_func (g_free); - - /* Last argument wins, so reverse the list for per-module to win */ - options = g_list_reverse (options); - - for (l = options; l != NULL; l = l->next) - { - BuilderOptions *o = l->data; - - if (o->build_args) - { - for (i = 0; o->build_args[i] != NULL; i++) - g_ptr_array_add (array, g_strdup (o->build_args[i])); - } - } - - if (array->len > 0 && builder_context_get_sandboxed (context)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Can't specify build-args in sandboxed build"); - return NULL; - } - - g_ptr_array_add (array, NULL); - - return (char **) g_ptr_array_free (g_steal_pointer (&array), FALSE); -} - -char ** -builder_options_get_config_opts (BuilderOptions *self, - BuilderContext *context, - char **base_opts) -{ - g_autoptr(GList) options = get_all_options (self, context); - GList *l; - int i; - g_autoptr(GPtrArray) array = g_ptr_array_new_with_free_func (g_free); - - /* Last argument wins, so reverse the list for per-module to win */ - options = g_list_reverse (options); - - /* Start by adding the base options */ - if (base_opts) - { - for (i = 0; base_opts[i] != NULL; i++) - g_ptr_array_add (array, g_strdup (base_opts[i])); - } - - for (l = options; l != NULL; l = l->next) - { - BuilderOptions *o = l->data; - - if (o->config_opts) - { - for (i = 0; o->config_opts[i] != NULL; i++) - g_ptr_array_add (array, g_strdup (o->config_opts[i])); - } - } - - g_ptr_array_add (array, NULL); - - return (char **) g_ptr_array_free (g_steal_pointer (&array), FALSE); -} - -void -builder_options_checksum (BuilderOptions *self, - BuilderCache *cache, - BuilderContext *context) -{ - BuilderOptions *arch_options; - - builder_cache_checksum_str (cache, BUILDER_OPTION_CHECKSUM_VERSION); - builder_cache_checksum_str (cache, self->cflags); - builder_cache_checksum_str (cache, self->cxxflags); - builder_cache_checksum_compat_str (cache, self->cppflags); - builder_cache_checksum_str (cache, self->ldflags); - builder_cache_checksum_str (cache, self->prefix); - builder_cache_checksum_strv (cache, self->env); - builder_cache_checksum_strv (cache, self->build_args); - builder_cache_checksum_strv (cache, self->config_opts); - builder_cache_checksum_boolean (cache, self->strip); - builder_cache_checksum_boolean (cache, self->no_debuginfo); - - arch_options = g_hash_table_lookup (self->arch, builder_context_get_arch (context)); - if (arch_options) - builder_options_checksum (arch_options, cache, context); -} diff --git a/builder/builder-options.h b/builder/builder-options.h deleted file mode 100644 index a1fb10e5..00000000 --- a/builder/builder-options.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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.1 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_OPTIONS_H__ -#define __BUILDER_OPTIONS_H__ - -#include -#include "builder-cache.h" - -G_BEGIN_DECLS - -typedef struct BuilderOptions BuilderOptions; - -#define BUILDER_TYPE_OPTIONS (builder_options_get_type ()) -#define BUILDER_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUILDER_TYPE_OPTIONS, BuilderOptions)) -#define BUILDER_IS_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUILDER_TYPE_OPTIONS)) - -/* Bump this if format changes in incompatible ways to force rebuild */ -#define BUILDER_OPTION_CHECKSUM_VERSION "1" - -GType builder_options_get_type (void); - -const char *builder_options_get_cflags (BuilderOptions *self, - BuilderContext *context); -const char *builder_options_get_cxxflags (BuilderOptions *self, - BuilderContext *context); -const char *builder_options_get_cppflags (BuilderOptions *self, - BuilderContext *context); -const char *builder_options_get_ldflags (BuilderOptions *self, - BuilderContext *context); -const char *builder_options_get_prefix (BuilderOptions *self, - BuilderContext *context); -char ** builder_options_get_env (BuilderOptions *self, - BuilderContext *context); -char ** builder_options_get_build_args (BuilderOptions *self, - BuilderContext *context, - GError **error); -char ** builder_options_get_config_opts (BuilderOptions *self, - BuilderContext *context, - char **base_opts); -void builder_options_checksum (BuilderOptions *self, - BuilderCache *cache, - BuilderContext *context); -gboolean builder_options_get_no_debuginfo (BuilderOptions *self, - BuilderContext *context); -gboolean builder_options_get_strip (BuilderOptions *self, - BuilderContext *context); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (BuilderOptions, g_object_unref) - -G_END_DECLS - -#endif /* __BUILDER_OPTIONS_H__ */ diff --git a/builder/builder-post-process.c b/builder/builder-post-process.c deleted file mode 100644 index fae7fcba..00000000 --- a/builder/builder-post-process.c +++ /dev/null @@ -1,504 +0,0 @@ -/* builder-post-process.c - * - * Copyright (C) 2017 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 -#include "libglnx/libglnx.h" - -#include "flatpak-utils.h" -#include "builder-utils.h" -#include "builder-post-process.h" - -static gboolean -invalidate_old_python_compiled (const char *path, - const char *rel_path, - GError **error) -{ - struct stat stbuf; - g_autofree char *pyc = NULL; - g_autofree char *pyo = NULL; - g_autofree char *dir = NULL; - g_autofree char *py3dir = NULL; - g_autofree char *pyfilename = NULL; - g_auto(GLnxDirFdIterator) dfd_iter = { 0, }; - - - /* This is a python file, not a .py[oc]. If it changed (mtime != 0) then - * this needs to invalidate any old (mtime == 0) .py[oc] files that could refer to it. - */ - - if (lstat (path, &stbuf) != 0) - { - g_warning ("Can't stat %s", rel_path); - return TRUE; - } - - if (stbuf.st_mtime == OSTREE_TIMESTAMP) - return TRUE; /* Previously handled .py */ - - pyc = g_strconcat (path, "c", NULL); - if (lstat (pyc, &stbuf) == 0 && - stbuf.st_mtime == OSTREE_TIMESTAMP) - { - g_print ("Removing stale file %sc", rel_path); - if (unlink (pyc) != 0) - g_warning ("Unable to delete %s", pyc); - } - - pyo = g_strconcat (path, "o", NULL); - if (lstat (pyo, &stbuf) == 0 && - stbuf.st_mtime == OSTREE_TIMESTAMP) - { - g_print ("Removing stale file %so", rel_path); - if (unlink (pyo) != 0) - g_warning ("Unable to delete %s", pyo); - } - - /* Handle python3 which is in a __pycache__ subdir */ - - pyfilename = g_path_get_basename (path); - pyfilename[strlen (pyfilename) - 2] = 0; /* skip "py" */ - dir = g_path_get_dirname (path); - py3dir = g_build_filename (dir, "__pycache__", NULL); - - if (glnx_dirfd_iterator_init_at (AT_FDCWD, py3dir, FALSE, &dfd_iter, NULL)) - { - struct dirent *dent; - while (glnx_dirfd_iterator_next_dent (&dfd_iter, &dent, NULL, NULL) && - dent != NULL) - { - if (!(g_str_has_suffix (dent->d_name, ".pyc") || - g_str_has_suffix (dent->d_name, ".pyo"))) - continue; - - if (!g_str_has_prefix (dent->d_name, pyfilename)) - continue; - - if (fstatat (dfd_iter.fd, dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW) == 0 && - stbuf.st_mtime == OSTREE_TIMESTAMP) - { - g_print ("Removing stale file %s/__pycache__/%s", rel_path, dent->d_name); - if (unlinkat (dfd_iter.fd, dent->d_name, 0)) - g_warning ("Unable to delete %s", dent->d_name); - } - } - } - - return TRUE; -} - -static gboolean -fixup_python_time_stamp (const char *path, - const char *rel_path, - GError **error) -{ - glnx_fd_close int fd = -1; - g_auto(GLnxTmpfile) tmpf = { 0 }; - guint8 buffer[8]; - ssize_t res; - guint32 pyc_mtime; - g_autofree char *py_path = NULL; - struct stat stbuf; - gboolean remove_pyc = FALSE; - g_autofree char *path_basename = g_path_get_basename (path); - g_autofree char *dir = g_path_get_dirname (path); - g_autofree char *dir_basename = g_path_get_basename (dir); - - fd = open (path, O_RDONLY | O_CLOEXEC | O_NOFOLLOW); - if (fd == -1) - { - g_warning ("Can't open %s", rel_path); - return TRUE; - } - - res = pread (fd, buffer, 8, 0); - if (res != 8) - { - g_warning ("Short read for %s", rel_path); - return TRUE; - } - - if (buffer[2] != 0x0d || buffer[3] != 0x0a) - { - g_debug ("Not matching python magic: %s", rel_path); - return TRUE; - } - - pyc_mtime = - (buffer[4] << 8*0) | - (buffer[5] << 8*1) | - (buffer[6] << 8*2) | - (buffer[7] << 8*3); - - if (strcmp (dir_basename, "__pycache__") == 0) - { - /* Python3 */ - g_autofree char *base = g_strdup (path_basename); - g_autofree char *real_dir = g_path_get_dirname (dir); - g_autofree char *py_basename = NULL; - char *dot; - - dot = strrchr (base, '.'); - if (dot == NULL) - return TRUE; - *dot = 0; - - dot = strrchr (base, '.'); - if (dot == NULL) - return TRUE; - *dot = 0; - - py_basename = g_strconcat (base, ".py", NULL); - py_path = g_build_filename (real_dir, py_basename, NULL); - } - else - { - /* Python2 */ - py_path = g_strndup (path, strlen (path) - 1); - } - - /* Here we found a .pyc (or .pyo) file and a possible .py file that apply for it. - * There are several possible cases wrt their mtimes: - * - * py not existing: pyc is stale, remove it - * pyc mtime == 0: (.pyc is from an old commited module) - * py mtime == 0: Do nothing, already correct - * py mtime != 0: The py changed in this module, remove pyc - * pyc mtime != 0: (.pyc changed this module, or was never rewritten in base layer) - * py mtime == 0: Shouldn't happen in flatpak-builder, but could be an un-rewritten ctime lower layer, assume it matches and update timestamp - * py mtime != pyc mtime: new pyc doesn't match last py written in this module, remove it - * py mtime == pyc mtime: These match, but the py will be set to mtime 0 by ostree, so update timestamp in pyc. - */ - - if (lstat (py_path, &stbuf) != 0) - { - /* pyc file without .py file, this happens for binary-only deployments. - * Accept it as-is. */ - return TRUE; - } - else if (pyc_mtime == OSTREE_TIMESTAMP) - { - if (stbuf.st_mtime == OSTREE_TIMESTAMP) - return TRUE; /* Previously handled pyc */ - - remove_pyc = TRUE; - } - else /* pyc_mtime != 0 */ - { - if (pyc_mtime != stbuf.st_mtime && stbuf.st_mtime != OSTREE_TIMESTAMP) - remove_pyc = TRUE; - /* else change mtime */ - } - - if (remove_pyc) - { - g_print ("Removing stale python bytecode file %s\n", rel_path); - if (unlink (path) != 0) - g_warning ("Unable to delete %s", rel_path); - return TRUE; - } - - if (!glnx_open_tmpfile_linkable_at (AT_FDCWD, dir, - O_RDWR | O_CLOEXEC | O_NOFOLLOW, - &tmpf, - error)) - return FALSE; - - if (glnx_regfile_copy_bytes (fd, tmpf.fd, (off_t)-1) < 0) - return glnx_throw_errno_prefix (error, "copyfile"); - - /* Change to mtime 0 which is what ostree uses for checkouts */ - buffer[4] = OSTREE_TIMESTAMP; - buffer[5] = buffer[6] = buffer[7] = 0; - - res = pwrite (tmpf.fd, buffer, 8, 0); - if (res != 8) - { - glnx_set_error_from_errno (error); - return FALSE; - } - - if (!glnx_link_tmpfile_at (&tmpf, - GLNX_LINK_TMPFILE_REPLACE, - AT_FDCWD, - path, - error)) - return FALSE; - - g_print ("Fixed up header mtime for %s\n", rel_path); - - /* The mtime will be zeroed on cache commit. We don't want to do that now, because multiple - files could reference one .py file and we need the mtimes to match for them all */ - - return TRUE; -} - -static gboolean -builder_post_process_python_time_stamp (GFile *app_dir, - GPtrArray *changed, - GError **error) -{ - int i; - - for (i = 0; i < changed->len; i++) - { - const char *rel_path = (char *) g_ptr_array_index (changed, i); - g_autoptr(GFile) file = NULL; - g_autofree char *path = NULL; - struct stat stbuf; - - if (!(g_str_has_suffix (rel_path, ".py") || - g_str_has_suffix (rel_path, ".pyc") || - g_str_has_suffix (rel_path, ".pyo"))) - continue; - - file = g_file_resolve_relative_path (app_dir, rel_path); - path = g_file_get_path (file); - - if (lstat (path, &stbuf) == -1) - continue; - - if (!S_ISREG (stbuf.st_mode)) - continue; - - if (g_str_has_suffix (rel_path, ".py")) - { - if (!invalidate_old_python_compiled (path, rel_path, error)) - return FALSE; - } - else - { - if (!fixup_python_time_stamp (path, rel_path, error)) - return FALSE; - } - } - - return TRUE; -} - - -static gboolean -builder_post_process_strip (GFile *app_dir, - GPtrArray *changed, - GError **error) -{ - int i; - - for (i = 0; i < changed->len; i++) - { - const char *rel_path = (char *) g_ptr_array_index (changed, i); - g_autoptr(GFile) file = g_file_resolve_relative_path (app_dir, rel_path); - g_autofree char *path = g_file_get_path (file); - gboolean is_shared, is_stripped; - - if (!is_elf_file (path, &is_shared, &is_stripped)) - continue; - - if (is_stripped) - continue; - - g_print ("stripping: %s\n", rel_path); - if (is_shared) - { - if (!strip (error, "--remove-section=.comment", "--remove-section=.note", "--strip-unneeded", path, NULL)) - return FALSE; - } - else - { - if (!strip (error, "--remove-section=.comment", "--remove-section=.note", path, NULL)) - return FALSE; - } - } - - return TRUE; -} - -static gboolean -builder_post_process_debuginfo (GFile *app_dir, - GPtrArray *changed, - BuilderContext *context, - GError **error) -{ - g_autofree char *app_dir_path = g_file_get_path (app_dir); - int j; - - for (j = 0; j < changed->len; j++) - { - const char *rel_path = (char *) g_ptr_array_index (changed, j); - g_autoptr(GFile) file = g_file_resolve_relative_path (app_dir, rel_path); - g_autofree char *path = g_file_get_path (file); - g_autofree char *debug_path = NULL; - g_autofree char *real_debug_path = NULL; - g_autofree char *rel_path_dir = g_path_get_dirname (rel_path); - g_autofree char *filename = g_path_get_basename (rel_path); - g_autofree char *filename_debug = g_strconcat (filename, ".debug", NULL); - g_autofree char *debug_dir = NULL; - g_autofree char *source_dir_path = NULL; - g_autoptr(GFile) source_dir = NULL; - g_autofree char *real_debug_dir = NULL; - gboolean is_shared, is_stripped; - - if (!is_elf_file (path, &is_shared, &is_stripped)) - continue; - - if (is_stripped) - continue; - - if (g_str_has_prefix (rel_path_dir, "files/")) - { - debug_dir = g_build_filename (app_dir_path, "files/lib/debug", rel_path_dir + strlen ("files/"), NULL); - real_debug_dir = g_build_filename ("/app/lib/debug", rel_path_dir + strlen ("files/"), NULL); - source_dir_path = g_build_filename (app_dir_path, "files/lib/debug/source", NULL); - } - else if (g_str_has_prefix (rel_path_dir, "usr/")) - { - debug_dir = g_build_filename (app_dir_path, "usr/lib/debug", rel_path_dir, NULL); - real_debug_dir = g_build_filename ("/usr/lib/debug", rel_path_dir, NULL); - source_dir_path = g_build_filename (app_dir_path, "usr/lib/debug/source", NULL); - } - - if (debug_dir) - { - const char *builddir; - g_autoptr(GError) local_error = NULL; - g_auto(GStrv) file_refs = NULL; - - if (g_mkdir_with_parents (debug_dir, 0755) != 0) - { - glnx_set_error_from_errno (error); - return FALSE; - } - - source_dir = g_file_new_for_path (source_dir_path); - if (g_mkdir_with_parents (source_dir_path, 0755) != 0) - { - glnx_set_error_from_errno (error); - return FALSE; - } - - if (builder_context_get_build_runtime (context)) - builddir = "/run/build-runtime/"; - else - builddir = "/run/build/"; - - debug_path = g_build_filename (debug_dir, filename_debug, NULL); - real_debug_path = g_build_filename (real_debug_dir, filename_debug, NULL); - - file_refs = builder_get_debuginfo_file_references (path, &local_error); - - if (file_refs == NULL) - { - g_warning ("%s", local_error->message); - } - else - { - GFile *build_dir = builder_context_get_build_dir (context); - int i; - for (i = 0; file_refs[i] != NULL; i++) - { - if (g_str_has_prefix (file_refs[i], builddir)) - { - const char *relative_path = file_refs[i] + strlen (builddir); - g_autoptr(GFile) src = g_file_resolve_relative_path (build_dir, relative_path); - g_autoptr(GFile) dst = g_file_resolve_relative_path (source_dir, relative_path); - g_autoptr(GFile) dst_parent = g_file_get_parent (dst); - GFileType file_type; - - if (!flatpak_mkdir_p (dst_parent, NULL, error)) - return FALSE; - - file_type = g_file_query_file_type (src, 0, NULL); - if (file_type == G_FILE_TYPE_DIRECTORY) - { - if (!flatpak_mkdir_p (dst, NULL, error)) - return FALSE; - } - else if (file_type == G_FILE_TYPE_REGULAR) - { - /* Make sure the target is gone, because g_file_copy does - truncation on hardlinked destinations */ - (void)g_file_delete (dst, NULL, NULL); - - if (!g_file_copy (src, dst, - G_FILE_COPY_OVERWRITE, - NULL, NULL, NULL, error)) - return FALSE; - } - } - } - } - - g_print ("stripping %s to %s\n", path, debug_path); - - /* Some files are hardlinked and eu-strip modifies in-place, - which breaks rofiles-fuse. Unlink them */ - if (!flatpak_break_hardlink (file, error)) - return FALSE; - - if (!eu_strip (error, "--remove-comment", "--reloc-debug-sections", - "-f", debug_path, - "-F", real_debug_path, - path, NULL)) - return FALSE; - } - } - - return TRUE; -} - -gboolean -builder_post_process (BuilderPostProcessFlags flags, - GFile *app_dir, - BuilderCache *cache, - BuilderContext *context, - GError **error) -{ - g_autoptr(GPtrArray) changed = NULL; - - if (!builder_cache_get_outstanding_changes (cache, &changed, error)) - return FALSE; - - if (flags & BUILDER_POST_PROCESS_FLAGS_PYTHON_TIMESTAMPS) - { - if (!builder_post_process_python_time_stamp (app_dir, changed,error)) - return FALSE; - } - - if (flags & BUILDER_POST_PROCESS_FLAGS_STRIP) - { - if (!builder_post_process_strip (app_dir, changed, error)) - return FALSE; - } - else if (flags & BUILDER_POST_PROCESS_FLAGS_DEBUGINFO) - { - if (!builder_post_process_debuginfo (app_dir, changed, context, error)) - return FALSE; - } - - return TRUE; -} diff --git a/builder/builder-post-process.h b/builder/builder-post-process.h deleted file mode 100644 index ddbf39c0..00000000 --- a/builder/builder-post-process.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright © 2017 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.1 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_POST_PROCESS_H__ -#define __BUILDER_POST_PROCESS_H__ - -#include "builder-cache.h" -#include "builder-context.h" - -G_BEGIN_DECLS - -typedef enum { - BUILDER_POST_PROCESS_FLAGS_NONE = 0, - BUILDER_POST_PROCESS_FLAGS_PYTHON_TIMESTAMPS = 1<<0, - BUILDER_POST_PROCESS_FLAGS_STRIP = 1<<1, - BUILDER_POST_PROCESS_FLAGS_DEBUGINFO = 1<<2, -} BuilderPostProcessFlags; - -gboolean builder_post_process (BuilderPostProcessFlags flags, - GFile *app_dir, - BuilderCache *cache, - BuilderContext *context, - GError **error); - -G_END_DECLS - -#endif /* __BUILDER_POST_PROCESS_H__ */ diff --git a/builder/builder-source-archive.c b/builder/builder-source-archive.c deleted file mode 100644 index c6a8099b..00000000 --- a/builder/builder-source-archive.c +++ /dev/null @@ -1,701 +0,0 @@ -/* builder-source-archive.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 "flatpak-utils.h" - -#include "builder-utils.h" -#include "builder-source-archive.h" - -struct BuilderSourceArchive -{ - BuilderSource parent; - - char *path; - char *url; - char *sha256; - guint strip_components; -}; - -typedef struct -{ - BuilderSourceClass parent_class; -} BuilderSourceArchiveClass; - -G_DEFINE_TYPE (BuilderSourceArchive, builder_source_archive, BUILDER_TYPE_SOURCE); - -enum { - PROP_0, - PROP_PATH, - PROP_URL, - PROP_SHA256, - PROP_STRIP_COMPONENTS, - LAST_PROP -}; - -typedef enum { - UNKNOWN, - RPM, - TAR, - TAR_GZIP, - TAR_COMPRESS, - TAR_BZIP2, - TAR_LZIP, - TAR_LZMA, - TAR_LZOP, - TAR_XZ, - ZIP -} BuilderArchiveType; - -static gboolean -is_tar (BuilderArchiveType type) -{ - return (type >= TAR) && (type <= TAR_XZ); -} - -static const char * -tar_decompress_flag (BuilderArchiveType type) -{ - switch (type) - { - default: - case TAR: - return NULL; - - case TAR_GZIP: - return "-z"; - - case TAR_COMPRESS: - return "-Z"; - - case TAR_BZIP2: - return "-j"; - - case TAR_LZIP: - return "--lzip"; - - case TAR_LZMA: - return "--lzma"; - - case TAR_LZOP: - return "--lzop"; - - case TAR_XZ: - return "-J"; - } -} - -static void -builder_source_archive_finalize (GObject *object) -{ - BuilderSourceArchive *self = (BuilderSourceArchive *) object; - - g_free (self->url); - g_free (self->path); - g_free (self->sha256); - - G_OBJECT_CLASS (builder_source_archive_parent_class)->finalize (object); -} - -static void -builder_source_archive_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - BuilderSourceArchive *self = BUILDER_SOURCE_ARCHIVE (object); - - switch (prop_id) - { - case PROP_PATH: - g_value_set_string (value, self->path); - break; - - case PROP_URL: - g_value_set_string (value, self->url); - break; - - case PROP_SHA256: - g_value_set_string (value, self->sha256); - break; - - case PROP_STRIP_COMPONENTS: - g_value_set_uint (value, self->strip_components); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -builder_source_archive_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - BuilderSourceArchive *self = BUILDER_SOURCE_ARCHIVE (object); - - switch (prop_id) - { - case PROP_PATH: - g_free (self->path); - self->path = g_value_dup_string (value); - break; - - case PROP_URL: - g_free (self->url); - self->url = g_value_dup_string (value); - break; - - case PROP_SHA256: - g_free (self->sha256); - self->sha256 = g_value_dup_string (value); - break; - - case PROP_STRIP_COMPONENTS: - self->strip_components = g_value_get_uint (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static SoupURI * -get_uri (BuilderSourceArchive *self, - GError **error) -{ - SoupURI *uri; - - if (self->url == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "URL not specified"); - return NULL; - } - - uri = soup_uri_new (self->url); - if (uri == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Invalid URL '%s'", self->url); - return NULL; - } - return uri; -} - -static GFile * -get_download_location (BuilderSourceArchive *self, - BuilderContext *context, - gboolean *is_local, - GError **error) -{ - g_autoptr(SoupURI) uri = NULL; - const char *path; - g_autofree char *base_name = NULL; - g_autoptr(GFile) file = NULL; - - uri = get_uri (self, error); - if (uri == NULL) - return FALSE; - - path = soup_uri_get_path (uri); - - base_name = g_path_get_basename (path); - - if (self->sha256 == NULL || *self->sha256 == 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Sha256 not specified"); - return FALSE; - } - - file = builder_context_find_in_sources_dirs (context, - "downloads", - self->sha256, - base_name, - NULL); - if (file) - { - *is_local = TRUE; - return g_steal_pointer (&file); - } - - return flatpak_build_file (builder_context_get_download_dir (context), - self->sha256, - base_name, - NULL); -} - -static GFile * -get_source_file (BuilderSourceArchive *self, - BuilderContext *context, - gboolean *is_local, - GError **error) -{ - GFile *base_dir = BUILDER_SOURCE (self)->base_dir; - - if (self->url != NULL && self->url[0] != 0) - { - *is_local = FALSE; - return get_download_location (self, context, is_local, error); - } - - if (self->path != NULL && self->path[0] != 0) - { - *is_local = TRUE; - return g_file_resolve_relative_path (base_dir, self->path); - } - - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "source file path or url not specified"); - return NULL; -} - -static gboolean -builder_source_archive_show_deps (BuilderSource *source, - GError **error) -{ - BuilderSourceArchive *self = BUILDER_SOURCE_ARCHIVE (source); - - if (self->path && self->path[0] != 0) - g_print ("%s\n", self->path); - - return TRUE; -} - -static gboolean -builder_source_archive_download (BuilderSource *source, - gboolean update_vcs, - BuilderContext *context, - GError **error) -{ - BuilderSourceArchive *self = BUILDER_SOURCE_ARCHIVE (source); - - g_autoptr(GFile) file = NULL; - const char *sha256 = NULL; - g_autofree char *base_name = NULL; - gboolean is_local; - - file = get_source_file (self, context, &is_local, error); - if (file == NULL) - return FALSE; - - base_name = g_file_get_basename (file); - - if (g_file_query_exists (file, NULL)) - { - if (is_local && self->sha256 != NULL && *self->sha256 != 0) - { - g_autofree char *data = NULL; - gsize len; - - if (!g_file_load_contents (file, NULL, &data, &len, NULL, error)) - return FALSE; - - sha256 = g_compute_checksum_for_string (G_CHECKSUM_SHA256, data, len); - if (strcmp (sha256, self->sha256) != 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Wrong sha256 for %s, expected %s, was %s", base_name, self->sha256, sha256); - return FALSE; - } - } - return TRUE; - } - - if (is_local) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Can't find file at %s", self->path); - return FALSE; - } - - if (!builder_context_download_uri (context, - self->url, - file, - self->sha256, - error)) - return FALSE; - - return TRUE; -} - -static gboolean -tar (GFile *dir, - GError **error, - ...) -{ - gboolean res; - va_list ap; - - va_start (ap, error); - res = flatpak_spawn (dir, NULL, error, "tar", ap); - va_end (ap); - - return res; -} - -static gboolean -unzip (GFile *dir, - GError **error, - ...) -{ - gboolean res; - va_list ap; - - va_start (ap, error); - res = flatpak_spawn (dir, NULL, error, "unzip", ap); - va_end (ap); - - return res; -} - -static gboolean -unrpm (GFile *dir, - const char *rpm_path, - GError **error) -{ - gboolean res; - const gchar *argv[] = { "sh", "-c", "rpm2cpio \"$1\" | cpio -i -d", - "sh", /* shell's $0 */ - rpm_path, /* shell's $1 */ - NULL }; - - res = flatpak_spawnv (dir, NULL, 0, error, argv); - - return res; -} - -static BuilderArchiveType -get_type (GFile *archivefile) -{ - g_autofree char *base_name = NULL; - g_autofree gchar *lower = NULL; - - base_name = g_file_get_basename (archivefile); - lower = g_ascii_strdown (base_name, -1); - - if (g_str_has_suffix (lower, ".tar")) - return TAR; - - if (g_str_has_suffix (lower, ".tar.gz") || - g_str_has_suffix (lower, ".tgz") || - g_str_has_suffix (lower, ".taz")) - return TAR_GZIP; - - if (g_str_has_suffix (lower, ".tar.Z") || - g_str_has_suffix (lower, ".taZ")) - return TAR_COMPRESS; - - if (g_str_has_suffix (lower, ".tar.bz2") || - g_str_has_suffix (lower, ".tz2") || - g_str_has_suffix (lower, ".tbz2") || - g_str_has_suffix (lower, ".tbz")) - return TAR_BZIP2; - - if (g_str_has_suffix (lower, ".tar.lz")) - return TAR_LZIP; - - if (g_str_has_suffix (lower, ".tar.lzma") || - g_str_has_suffix (lower, ".tlz")) - return TAR_LZMA; - - if (g_str_has_suffix (lower, ".tar.lzo")) - return TAR_LZOP; - - if (g_str_has_suffix (lower, ".tar.xz")) - return TAR_XZ; - - if (g_str_has_suffix (lower, ".zip")) - return ZIP; - - if (g_str_has_suffix (lower, ".rpm")) - return RPM; - - return UNKNOWN; -} - -static gboolean -strip_components_into (GFile *dest, - GFile *src, - int level, - GError **error) -{ - g_autoptr(GFileEnumerator) dir_enum = NULL; - g_autoptr(GFileInfo) child_info = NULL; - GError *temp_error = NULL; - - dir_enum = g_file_enumerate_children (src, "standard::name,standard::type", - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - NULL, error); - if (!dir_enum) - return FALSE; - - while ((child_info = g_file_enumerator_next_file (dir_enum, NULL, &temp_error))) - { - g_autoptr(GFile) child = NULL; - g_autoptr(GFile) dest_child = NULL; - - child = g_file_get_child (src, g_file_info_get_name (child_info)); - - if (g_file_info_get_file_type (child_info) == G_FILE_TYPE_DIRECTORY && - level > 0) - { - if (!strip_components_into (dest, child, level - 1, error)) - return FALSE; - - g_clear_object (&child_info); - continue; - } - - dest_child = g_file_get_child (dest, g_file_info_get_name (child_info)); - if (!g_file_move (child, dest_child, G_FILE_COPY_NONE, NULL, NULL, NULL, error)) - return FALSE; - - g_clear_object (&child_info); - continue; - } - - if (temp_error != NULL) - { - g_propagate_error (error, temp_error); - return FALSE; - } - - if (!g_file_delete (src, NULL, error)) - return FALSE; - - return TRUE; -} - -static GFile * -create_uncompress_directory (BuilderSourceArchive *self, GFile *dest, GError **error) -{ - GFile *uncompress_dest = NULL; - - if (self->strip_components > 0) - { - g_autoptr(GFile) tmp_dir_template = g_file_get_child (dest, ".uncompressXXXXXX"); - g_autofree char *tmp_dir_path = g_file_get_path (tmp_dir_template); - - if (g_mkdtemp (tmp_dir_path) == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Can't create uncompress directory"); - return NULL; - } - - uncompress_dest = g_file_new_for_path (tmp_dir_path); - } - else - { - uncompress_dest = g_object_ref (dest); - } - - return uncompress_dest; -} - -static gboolean -builder_source_archive_extract (BuilderSource *source, - GFile *dest, - BuilderOptions *build_options, - BuilderContext *context, - GError **error) -{ - BuilderSourceArchive *self = BUILDER_SOURCE_ARCHIVE (source); - - g_autoptr(GFile) archivefile = NULL; - g_autofree char *archive_path = NULL; - BuilderArchiveType type; - gboolean is_local; - - archivefile = get_source_file (self, context, &is_local, error); - if (archivefile == NULL) - return FALSE; - - type = get_type (archivefile); - - archive_path = g_file_get_path (archivefile); - - if (is_tar (type)) - { - g_autofree char *strip_components = g_strdup_printf ("--strip-components=%u", self->strip_components); - /* Note: tar_decompress_flag can return NULL, so put it last */ - if (!tar (dest, error, "xf", archive_path, "--no-same-owner", strip_components, tar_decompress_flag (type), NULL)) - return FALSE; - } - else if (type == ZIP) - { - g_autoptr(GFile) zip_dest = NULL; - - zip_dest = create_uncompress_directory (self, dest, error); - if (zip_dest == NULL) - return FALSE; - - if (!unzip (zip_dest, error, archive_path, NULL)) - return FALSE; - - if (self->strip_components > 0) - { - if (!strip_components_into (dest, zip_dest, self->strip_components, error)) - return FALSE; - } - } - else if (type == RPM) - { - g_autoptr(GFile) rpm_dest = NULL; - - rpm_dest = create_uncompress_directory (self, dest, error); - if (rpm_dest == NULL) - return FALSE; - - if (!unrpm (rpm_dest, archive_path, error)) - return FALSE; - - if (self->strip_components > 0) - { - if (!strip_components_into (dest, rpm_dest, self->strip_components, error)) - return FALSE; - } - } - else - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unknown archive format of '%s'", archive_path); - return FALSE; - } - - return TRUE; -} - -static gboolean -builder_source_archive_bundle (BuilderSource *source, - BuilderContext *context, - GError **error) -{ - BuilderSourceArchive *self = BUILDER_SOURCE_ARCHIVE (source); - - g_autoptr(GFile) file = NULL; - g_autoptr(GFile) download_dir = NULL; - g_autoptr(GFile) destination_file = NULL; - g_autofree char *download_dir_path = NULL; - g_autofree char *file_name = NULL; - g_autofree char *destination_file_path = NULL; - g_autofree char *app_dir_path = NULL; - gboolean is_local; - - file = get_source_file (self, context, &is_local, error); - if (file == NULL) - return FALSE; - - app_dir_path = g_file_get_path (builder_context_get_app_dir (context)); - download_dir_path = g_build_filename (app_dir_path, - "sources", - "downloads", - self->sha256, - NULL); - download_dir = g_file_new_for_path (download_dir_path); - if (!flatpak_mkdir_p (download_dir, NULL, error)) - return FALSE; - - file_name = g_file_get_basename (file); - destination_file_path = g_build_filename (download_dir_path, - file_name, - NULL); - destination_file = g_file_new_for_path (destination_file_path); - - if (!g_file_copy (file, destination_file, - G_FILE_COPY_OVERWRITE, - NULL, - NULL, NULL, - error)) - return FALSE; - - return TRUE; -} - -static void -builder_source_archive_checksum (BuilderSource *source, - BuilderCache *cache, - BuilderContext *context) -{ - BuilderSourceArchive *self = BUILDER_SOURCE_ARCHIVE (source); - - builder_cache_checksum_str (cache, self->url); - builder_cache_checksum_str (cache, self->sha256); - builder_cache_checksum_uint32 (cache, self->strip_components); -} - - -static void -builder_source_archive_class_init (BuilderSourceArchiveClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - BuilderSourceClass *source_class = BUILDER_SOURCE_CLASS (klass); - - object_class->finalize = builder_source_archive_finalize; - object_class->get_property = builder_source_archive_get_property; - object_class->set_property = builder_source_archive_set_property; - - source_class->show_deps = builder_source_archive_show_deps; - source_class->download = builder_source_archive_download; - source_class->extract = builder_source_archive_extract; - source_class->bundle = builder_source_archive_bundle; - source_class->checksum = builder_source_archive_checksum; - - g_object_class_install_property (object_class, - PROP_PATH, - g_param_spec_string ("path", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_URL, - g_param_spec_string ("url", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_SHA256, - g_param_spec_string ("sha256", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_STRIP_COMPONENTS, - g_param_spec_uint ("strip-components", - "", - "", - 0, G_MAXUINT, - 1, - G_PARAM_READWRITE)); -} - -static void -builder_source_archive_init (BuilderSourceArchive *self) -{ - self->strip_components = 1; -} diff --git a/builder/builder-source-archive.h b/builder/builder-source-archive.h deleted file mode 100644 index 48004f11..00000000 --- a/builder/builder-source-archive.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.1 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_ARCHIVE_H__ -#define __BUILDER_SOURCE_ARCHIVE_H__ - -#include "builder-source.h" - -G_BEGIN_DECLS - -typedef struct BuilderSourceArchive BuilderSourceArchive; - -#define BUILDER_TYPE_SOURCE_ARCHIVE (builder_source_archive_get_type ()) -#define BUILDER_SOURCE_ARCHIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUILDER_TYPE_SOURCE_ARCHIVE, BuilderSourceArchive)) -#define BUILDER_IS_SOURCE_ARCHIVE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUILDER_TYPE_SOURCE_ARCHIVE)) - -GType builder_source_archive_get_type (void); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (BuilderSourceArchive, g_object_unref) - -G_END_DECLS - -#endif /* __BUILDER_SOURCE_ARCHIVE_H__ */ diff --git a/builder/builder-source-bzr.c b/builder/builder-source-bzr.c deleted file mode 100644 index 62eb8ed0..00000000 --- a/builder/builder-source-bzr.c +++ /dev/null @@ -1,399 +0,0 @@ -/* builder-source-bzr.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-bzr.h" -#include "builder-utils.h" -#include "flatpak-utils.h" - -struct BuilderSourceBzr -{ - BuilderSource parent; - - char *url; - char *revision; -}; - -typedef struct -{ - BuilderSourceClass parent_class; -} BuilderSourceBzrClass; - -G_DEFINE_TYPE (BuilderSourceBzr, builder_source_bzr, BUILDER_TYPE_SOURCE); - -enum { - PROP_0, - PROP_URL, - PROP_REVISION, - LAST_PROP -}; - -static void -builder_source_bzr_finalize (GObject *object) -{ - BuilderSourceBzr *self = (BuilderSourceBzr *) object; - - g_free (self->url); - g_free (self->revision); - - G_OBJECT_CLASS (builder_source_bzr_parent_class)->finalize (object); -} - -static void -builder_source_bzr_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - BuilderSourceBzr *self = BUILDER_SOURCE_BZR (object); - - switch (prop_id) - { - case PROP_URL: - g_value_set_string (value, self->url); - break; - - case PROP_REVISION: - g_value_set_string (value, self->revision); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -builder_source_bzr_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - BuilderSourceBzr *self = BUILDER_SOURCE_BZR (object); - - switch (prop_id) - { - case PROP_URL: - g_free (self->url); - self->url = g_value_dup_string (value); - break; - - case PROP_REVISION: - g_free (self->revision); - self->revision = g_value_dup_string (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static gboolean -bzr (GFile *dir, - char **output, - GError **error, - ...) -{ - gboolean res; - va_list ap; - - va_start (ap, error); - res = flatpak_spawn (dir, output, error, "bzr", ap); - va_end (ap); - - return res; -} - -static GFile * -get_mirror_dir (BuilderSourceBzr *self, BuilderContext *context) -{ - g_autoptr(GFile) bzr_dir = NULL; - g_autofree char *filename = NULL; - g_autofree char *bzr_dir_path = NULL; - - bzr_dir = g_file_get_child (builder_context_get_state_dir (context), - "bzr"); - - bzr_dir_path = g_file_get_path (bzr_dir); - g_mkdir_with_parents (bzr_dir_path, 0755); - - filename = builder_uri_to_filename (self->url); - return g_file_get_child (bzr_dir, filename); -} - -static char * -get_current_commit (BuilderSourceBzr *self, BuilderContext *context, GError **error) -{ - g_autoptr(GFile) mirror_dir = NULL; - char *output = NULL; - - mirror_dir = get_mirror_dir (self, context); - - if (!bzr (mirror_dir, &output, error, - "revno", NULL)) - return NULL; - - return output; -} - -static gboolean -builder_source_bzr_download (BuilderSource *source, - gboolean update_vcs, - BuilderContext *context, - GError **error) -{ - BuilderSourceBzr *self = BUILDER_SOURCE_BZR (source); - - g_autoptr(GFile) mirror_dir = NULL; - - if (self->url == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "URL not specified"); - return FALSE; - } - - mirror_dir = get_mirror_dir (self, context); - - if (!g_file_query_exists (mirror_dir, NULL)) - { - g_autofree char *filename = g_file_get_basename (mirror_dir); - g_autoptr(GFile) parent = g_file_get_parent (mirror_dir); - g_autofree char *mirror_path = g_file_get_path (mirror_dir); - g_autofree char *path_tmp = g_strconcat (mirror_path, ".clone_XXXXXX", NULL); - g_autofree char *filename_tmp = NULL; - g_autoptr(GFile) mirror_dir_tmp = NULL; - g_autoptr(GFile) cached_bzr_dir = NULL; - const char *branch_source; - - g_print ("Getting bzr repo %s\n", self->url); - - if (g_mkdtemp_full (path_tmp, 0755) == NULL) - return flatpak_fail (error, "Can't create temporary directory"); - - /* bzr can't check out to the empty dir, so remove it */ - rmdir (path_tmp); - - mirror_dir_tmp = g_file_new_for_path (path_tmp); - filename_tmp = g_file_get_basename (mirror_dir_tmp); - - branch_source = self->url; - - cached_bzr_dir = builder_context_find_in_sources_dirs (context, "bzr", filename, NULL); - if (cached_bzr_dir != NULL) - branch_source = flatpak_file_get_path_cached (cached_bzr_dir); - - if (!bzr (parent, NULL, error, - "branch", branch_source, filename_tmp, NULL)) - return FALSE; - - /* Rewrite to real url if we used the cache */ - if (cached_bzr_dir != NULL) - { - g_autofree char *setting = g_strdup_printf ("parent_location=%s", self->url); - if (!bzr (mirror_dir_tmp, NULL, error, - "config", setting, NULL)) - return FALSE; - - if (update_vcs && - !bzr (mirror_dir_tmp, NULL, error, - "pull", NULL)) - return FALSE; - } - - if (!g_file_move (mirror_dir_tmp, mirror_dir, 0, NULL, NULL, NULL, error)) - return FALSE; - } - else if (update_vcs) - { - g_print ("Updating bzr repo %s\n", self->url); - - if (!bzr (mirror_dir, NULL, error, - "pull", NULL)) - return FALSE; - } - - return TRUE; -} - -static gboolean -builder_source_bzr_extract (BuilderSource *source, - GFile *dest, - BuilderOptions *build_options, - BuilderContext *context, - GError **error) -{ - BuilderSourceBzr *self = BUILDER_SOURCE_BZR (source); - - g_autoptr(GFile) mirror_dir = NULL; - g_autofree char *mirror_dir_path = NULL; - g_autofree char *dest_path = NULL; - - mirror_dir = get_mirror_dir (self, context); - - mirror_dir_path = g_file_get_path (mirror_dir); - dest_path = g_file_get_path (dest); - - if (!bzr (NULL, NULL, error, - "branch", "--stacked", mirror_dir_path, dest_path, "--use-existing-dir", NULL)) - return FALSE; - - if (self->revision) - { - g_autofree char *revarg = g_strdup_printf ("-r%s", self->revision); - if (!bzr (dest, NULL, error, - "revert", revarg, NULL)) - return FALSE; - } - - return TRUE; -} - -static gboolean -builder_source_bzr_bundle (BuilderSource *source, - BuilderContext *context, - GError **error) -{ - BuilderSourceBzr *self = BUILDER_SOURCE_BZR (source); - - g_autoptr(GFile) sources_dir = NULL; - g_autoptr(GFile) dest_dir = NULL; - g_autoptr(GFile) dest_dir_tmp = NULL; - g_autoptr(GFile) bzr_sources_dir = NULL; - - g_autofree char *sources_dir_path = NULL; - - g_autofree char *base_name = NULL; - g_autofree char *base_name_tmp = NULL; - - sources_dir = get_mirror_dir (self, context); - - if (sources_dir == NULL) { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Can't locate repo with URL '%s'", self->url); - return FALSE; - } - - base_name = g_file_get_basename (sources_dir); - - bzr_sources_dir = flatpak_build_file (builder_context_get_app_dir (context), - "sources/bzr", - NULL); - if (!flatpak_mkdir_p (bzr_sources_dir, NULL, error)) - return FALSE; - - base_name_tmp = g_strconcat (base_name, ".clone_tmp", NULL); - dest_dir_tmp = flatpak_build_file (bzr_sources_dir, - base_name_tmp, - NULL); - dest_dir = flatpak_build_file (bzr_sources_dir, - base_name, - NULL); - - sources_dir_path = g_file_get_path (sources_dir); - if (!bzr (bzr_sources_dir, NULL, error, - "branch", sources_dir_path, base_name_tmp, NULL) || - !g_file_move (dest_dir_tmp, dest_dir, 0, NULL, NULL, NULL, error)) - return FALSE; - - return TRUE; -} - -static void -builder_source_bzr_checksum (BuilderSource *source, - BuilderCache *cache, - BuilderContext *context) -{ - BuilderSourceBzr *self = BUILDER_SOURCE_BZR (source); - g_autofree char *current_commit = NULL; - - g_autoptr(GError) error = NULL; - - builder_cache_checksum_str (cache, self->url); - builder_cache_checksum_str (cache, self->revision); - - current_commit = get_current_commit (self, context, &error); - if (current_commit) - builder_cache_checksum_str (cache, current_commit); - else if (error) - g_warning ("Failed to get current bzr checksum: %s", error->message); -} - -static gboolean -builder_source_bzr_update (BuilderSource *source, - BuilderContext *context, - GError **error) -{ - BuilderSourceBzr *self = BUILDER_SOURCE_BZR (source); - char *current_commit; - - current_commit = get_current_commit (self, context, NULL); - if (current_commit) - { - g_free (self->revision); - self->revision = current_commit; - } - - return TRUE; -} - -static void -builder_source_bzr_class_init (BuilderSourceBzrClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - BuilderSourceClass *source_class = BUILDER_SOURCE_CLASS (klass); - - object_class->finalize = builder_source_bzr_finalize; - object_class->get_property = builder_source_bzr_get_property; - object_class->set_property = builder_source_bzr_set_property; - - source_class->download = builder_source_bzr_download; - source_class->extract = builder_source_bzr_extract; - source_class->bundle = builder_source_bzr_bundle; - source_class->update = builder_source_bzr_update; - source_class->checksum = builder_source_bzr_checksum; - - g_object_class_install_property (object_class, - PROP_URL, - g_param_spec_string ("url", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_REVISION, - g_param_spec_string ("revision", - "", - "", - NULL, - G_PARAM_READWRITE)); -} - -static void -builder_source_bzr_init (BuilderSourceBzr *self) -{ -} diff --git a/builder/builder-source-bzr.h b/builder/builder-source-bzr.h deleted file mode 100644 index b4c34edf..00000000 --- a/builder/builder-source-bzr.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.1 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_BZR_H__ -#define __BUILDER_SOURCE_BZR_H__ - -#include "builder-source.h" - -G_BEGIN_DECLS - -typedef struct BuilderSourceBzr BuilderSourceBzr; - -#define BUILDER_TYPE_SOURCE_BZR (builder_source_bzr_get_type ()) -#define BUILDER_SOURCE_BZR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUILDER_TYPE_SOURCE_BZR, BuilderSourceBzr)) -#define BUILDER_IS_SOURCE_BZR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUILDER_TYPE_SOURCE_BZR)) - -GType builder_source_bzr_get_type (void); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (BuilderSourceBzr, g_object_unref) - -G_END_DECLS - -#endif /* __BUILDER_SOURCE_BZR_H__ */ diff --git a/builder/builder-source-file.c b/builder/builder-source-file.c deleted file mode 100644 index d6792bd1..00000000 --- a/builder/builder-source-file.c +++ /dev/null @@ -1,556 +0,0 @@ -/* builder-source-file.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 "flatpak-utils.h" - -#include "builder-utils.h" -#include "builder-source-file.h" - -struct BuilderSourceFile -{ - BuilderSource parent; - - char *path; - char *url; - char *sha256; - char *dest_filename; -}; - -typedef struct -{ - BuilderSourceClass parent_class; -} BuilderSourceFileClass; - -G_DEFINE_TYPE (BuilderSourceFile, builder_source_file, BUILDER_TYPE_SOURCE); - -enum { - PROP_0, - PROP_PATH, - PROP_URL, - PROP_SHA256, - PROP_DEST_FILENAME, - LAST_PROP -}; - -static void -builder_source_file_finalize (GObject *object) -{ - BuilderSourceFile *self = (BuilderSourceFile *) object; - - g_free (self->path); - g_free (self->url); - g_free (self->sha256); - g_free (self->dest_filename); - - G_OBJECT_CLASS (builder_source_file_parent_class)->finalize (object); -} - -static void -builder_source_file_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - BuilderSourceFile *self = BUILDER_SOURCE_FILE (object); - - switch (prop_id) - { - case PROP_PATH: - g_value_set_string (value, self->path); - break; - - case PROP_URL: - g_value_set_string (value, self->url); - break; - - case PROP_SHA256: - g_value_set_string (value, self->sha256); - break; - - case PROP_DEST_FILENAME: - g_value_set_string (value, self->dest_filename); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -builder_source_file_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - BuilderSourceFile *self = BUILDER_SOURCE_FILE (object); - - switch (prop_id) - { - case PROP_PATH: - g_free (self->path); - self->path = g_value_dup_string (value); - break; - - case PROP_URL: - g_free (self->url); - self->url = g_value_dup_string (value); - break; - - case PROP_SHA256: - g_free (self->sha256); - self->sha256 = g_value_dup_string (value); - break; - - case PROP_DEST_FILENAME: - g_free (self->dest_filename); - self->dest_filename = g_value_dup_string (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static SoupURI * -get_uri (BuilderSourceFile *self, - GError **error) -{ - SoupURI *uri; - - if (self->url == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "URL not specified"); - return NULL; - } - - uri = soup_uri_new (self->url); - if (uri == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Invalid URL '%s'", self->url); - return NULL; - } - return uri; -} - -static GFile * -get_download_location (BuilderSourceFile *self, - gboolean *is_inline, - BuilderContext *context, - GError **error) -{ - g_autoptr(SoupURI) uri = NULL; - const char *path; - g_autofree char *base_name = NULL; - g_autoptr(GFile) file = NULL; - - uri = get_uri (self, error); - if (uri == NULL) - return FALSE; - - path = soup_uri_get_path (uri); - - if (g_str_has_prefix (self->url, "data:")) - { - *is_inline = TRUE; - return g_file_new_for_path ("inline data"); - } - *is_inline = FALSE; - - base_name = g_path_get_basename (path); - - if (self->sha256 == NULL || *self->sha256 == 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Sha256 not specified"); - return FALSE; - } - - file = builder_context_find_in_sources_dirs (context, - "downloads", - self->sha256, - base_name, - NULL); - if (file != NULL) - return g_steal_pointer (&file); - - file = flatpak_build_file (builder_context_get_download_dir (context), - self->sha256, - base_name, - NULL); - return g_steal_pointer (&file); -} - -static GFile * -get_source_file (BuilderSourceFile *self, - BuilderContext *context, - gboolean *is_local, - gboolean *is_inline, - GError **error) -{ - GFile *base_dir = BUILDER_SOURCE (self)->base_dir; - - if (self->url != NULL && self->url[0] != 0) - { - *is_local = FALSE; - return get_download_location (self, is_inline, context, error); - } - - if (self->path != NULL && self->path[0] != 0) - { - *is_local = TRUE; - *is_inline = FALSE; - return g_file_resolve_relative_path (base_dir, self->path); - } - - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "source file path or url not specified"); - return NULL; -} - -static GBytes * -download_uri (const char *url, - BuilderContext *context, - GError **error) -{ - SoupSession *session; - - g_autoptr(SoupRequest) req = NULL; - g_autoptr(GInputStream) input = NULL; - g_autoptr(GOutputStream) out = NULL; - - session = builder_context_get_soup_session (context); - - req = soup_session_request (session, url, error); - if (req == NULL) - return NULL; - - input = soup_request_send (req, NULL, error); - if (input == NULL) - return NULL; - - out = g_memory_output_stream_new_resizable (); - if (!g_output_stream_splice (out, - input, - G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET | G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE, - NULL, - error)) - return NULL; - - return g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (out)); -} - -static gboolean -builder_source_file_show_deps (BuilderSource *source, - GError **error) -{ - BuilderSourceFile *self = BUILDER_SOURCE_FILE (source); - - if (self->path && self->path[0] != 0) - g_print ("%s\n", self->path); - - return TRUE; -} - -static gboolean -builder_source_file_download (BuilderSource *source, - gboolean update_vcs, - BuilderContext *context, - GError **error) -{ - BuilderSourceFile *self = BUILDER_SOURCE_FILE (source); - - g_autoptr(GFile) file = NULL; - gboolean is_local, is_inline; - g_autofree char *sha256 = NULL; - g_autofree char *base_name = NULL; - - file = get_source_file (self, context, &is_local, &is_inline, error); - if (file == NULL) - return FALSE; - - base_name = g_file_get_basename (file); - - if (g_file_query_exists (file, NULL)) - { - if (is_local && self->sha256 != NULL && *self->sha256 != 0) - { - g_autofree char *data = NULL; - gsize len; - - if (!g_file_load_contents (file, NULL, &data, &len, NULL, error)) - return FALSE; - - sha256 = g_compute_checksum_for_string (G_CHECKSUM_SHA256, data, len); - if (strcmp (sha256, self->sha256) != 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Wrong sha256 for %s, expected %s, was %s", base_name, self->sha256, sha256); - return FALSE; - } - } - return TRUE; - } - - if (is_local) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Can't find file at %s", self->path); - return FALSE; - } - - if ((self->sha256 == NULL || *self->sha256 == 0) && !is_inline) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Sha256 not specified"); - return FALSE; - } - - if (!builder_context_download_uri (context, - self->url, - file, - self->sha256, - error)) - return FALSE; - - return TRUE; -} - -static gboolean -builder_source_file_extract (BuilderSource *source, - GFile *dest, - BuilderOptions *build_options, - BuilderContext *context, - GError **error) -{ - BuilderSourceFile *self = BUILDER_SOURCE_FILE (source); - - g_autoptr(GFile) src = NULL; - g_autoptr(GFile) dest_file = NULL; - g_autofree char *dest_filename = NULL; - gboolean is_local, is_inline; - - src = get_source_file (self, context, &is_local, &is_inline, error); - if (src == NULL) - return FALSE; - - if (self->dest_filename) - { - dest_filename = g_strdup (self->dest_filename); - } - else - { - if (is_inline) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "No dest-filename set for inline file data"); - return FALSE; - } - dest_filename = g_file_get_basename (src); - } - - dest_file = g_file_get_child (dest, dest_filename); - - /* If the destination file exists, just delete it. We can encounter errors when - * trying to overwrite files that are not writable. - */ - if (g_file_query_exists (dest_file, NULL) && !g_file_delete (dest_file, NULL, error)) - return FALSE; - - if (is_inline) - { - g_autoptr(GBytes) content = NULL; - - content = download_uri (self->url, - context, - error); - if (content == NULL) - return FALSE; - - if (!g_file_set_contents (flatpak_file_get_path_cached (dest_file), - g_bytes_get_data (content, NULL), - g_bytes_get_size (content), error)) - return FALSE; - } - else - { - /* Make sure the target is gone, because g_file_copy does - truncation on hardlinked destinations */ - (void)g_file_delete (dest_file, NULL, NULL); - - if (!g_file_copy (src, dest_file, - G_FILE_COPY_OVERWRITE, - NULL, - NULL, NULL, - error)) - return FALSE; - } - - return TRUE; -} - -static gboolean -builder_source_file_bundle (BuilderSource *source, - BuilderContext *context, - GError **error) -{ - BuilderSourceFile *self = BUILDER_SOURCE_FILE (source); - - g_autoptr(GFile) file = NULL; - g_autoptr(GFile) destination_file = NULL; - g_autoptr(GFile) destination_dir = NULL; - g_autofree char *file_name = NULL; - gboolean is_local, is_inline; - - file = get_source_file (self, context, &is_local, &is_inline, error); - if (file == NULL) - return FALSE; - - /* Inline URIs (data://) need not be bundled */ - if (is_inline) - return TRUE; - - if (is_local) - { - GFile *manifest_base_dir = builder_context_get_base_dir (context); - g_autofree char *rel_path = g_file_get_relative_path (manifest_base_dir, file); - - if (rel_path == NULL) - { - g_warning ("Local file %s is outside manifest tree, not bundling", flatpak_file_get_path_cached (file)); - return TRUE; - } - - destination_file = flatpak_build_file (builder_context_get_app_dir (context), - "sources/manifest", rel_path, NULL); - } - else - { - file_name = g_file_get_basename (file); - destination_file = flatpak_build_file (builder_context_get_app_dir (context), - "sources/downloads", - self->sha256, - file_name, - NULL); - } - - destination_dir = g_file_get_parent (destination_file); - if (!flatpak_mkdir_p (destination_dir, NULL, error)) - return FALSE; - - if (!g_file_copy (file, destination_file, - G_FILE_COPY_OVERWRITE, - NULL, - NULL, NULL, - error)) - return FALSE; - - return TRUE; -} - -static gboolean -builder_source_file_update (BuilderSource *source, - BuilderContext *context, - GError **error) -{ - return TRUE; -} - -static void -builder_source_file_checksum (BuilderSource *source, - BuilderCache *cache, - BuilderContext *context) -{ - BuilderSourceFile *self = BUILDER_SOURCE_FILE (source); - - g_autoptr(GFile) src = NULL; - g_autofree char *data = NULL; - gsize len; - gboolean is_local, is_inline; - - src = get_source_file (self, context, &is_local, &is_inline, NULL); - if (src == NULL) - return; - - if (is_local && - g_file_load_contents (src, NULL, &data, &len, NULL, NULL)) - builder_cache_checksum_data (cache, (guchar *) data, len); - - builder_cache_checksum_str (cache, self->path); - builder_cache_checksum_str (cache, self->url); - builder_cache_checksum_str (cache, self->sha256); - builder_cache_checksum_str (cache, self->dest_filename); -} - -static void -builder_source_file_class_init (BuilderSourceFileClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - BuilderSourceClass *source_class = BUILDER_SOURCE_CLASS (klass); - - object_class->finalize = builder_source_file_finalize; - object_class->get_property = builder_source_file_get_property; - object_class->set_property = builder_source_file_set_property; - - source_class->show_deps = builder_source_file_show_deps; - source_class->download = builder_source_file_download; - source_class->extract = builder_source_file_extract; - source_class->bundle = builder_source_file_bundle; - source_class->update = builder_source_file_update; - source_class->checksum = builder_source_file_checksum; - - g_object_class_install_property (object_class, - PROP_PATH, - g_param_spec_string ("path", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_URL, - g_param_spec_string ("url", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_SHA256, - g_param_spec_string ("sha256", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_DEST_FILENAME, - g_param_spec_string ("dest-filename", - "", - "", - NULL, - G_PARAM_READWRITE)); -} - -static void -builder_source_file_init (BuilderSourceFile *self) -{ -} diff --git a/builder/builder-source-file.h b/builder/builder-source-file.h deleted file mode 100644 index 3444f7c5..00000000 --- a/builder/builder-source-file.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.1 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_FILE_H__ -#define __BUILDER_SOURCE_FILE_H__ - -#include "builder-source.h" - -G_BEGIN_DECLS - -typedef struct BuilderSourceFile BuilderSourceFile; - -#define BUILDER_TYPE_SOURCE_FILE (builder_source_file_get_type ()) -#define BUILDER_SOURCE_FILE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUILDER_TYPE_SOURCE_FILE, BuilderSourceFile)) -#define BUILDER_IS_SOURCE_FILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUILDER_TYPE_SOURCE_FILE)) - -GType builder_source_file_get_type (void); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (BuilderSourceFile, g_object_unref) - -G_END_DECLS - -#endif /* __BUILDER_SOURCE_FILE_H__ */ diff --git a/builder/builder-source-git.c b/builder/builder-source-git.c deleted file mode 100644 index 87f28682..00000000 --- a/builder/builder-source-git.c +++ /dev/null @@ -1,395 +0,0 @@ -/* builder-source-git.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-git.h" -#include "builder-git.h" -#include "builder-utils.h" -#include "flatpak-utils.h" - -struct BuilderSourceGit -{ - BuilderSource parent; - - char *url; - char *path; - char *branch; - char *commit; - gboolean disable_fsckobjects; -}; - -typedef struct -{ - BuilderSourceClass parent_class; -} BuilderSourceGitClass; - -G_DEFINE_TYPE (BuilderSourceGit, builder_source_git, BUILDER_TYPE_SOURCE); - -enum { - PROP_0, - PROP_URL, - PROP_PATH, - PROP_BRANCH, - PROP_COMMIT, - PROP_DISABLE_FSCKOBJECTS, - LAST_PROP -}; - -static void -builder_source_git_finalize (GObject *object) -{ - BuilderSourceGit *self = (BuilderSourceGit *) object; - - g_free (self->url); - g_free (self->path); - g_free (self->branch); - g_free (self->commit); - - G_OBJECT_CLASS (builder_source_git_parent_class)->finalize (object); -} - -static void -builder_source_git_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - BuilderSourceGit *self = BUILDER_SOURCE_GIT (object); - - switch (prop_id) - { - case PROP_URL: - g_value_set_string (value, self->url); - break; - - case PROP_PATH: - g_value_set_string (value, self->path); - break; - - case PROP_BRANCH: - g_value_set_string (value, self->branch); - break; - - case PROP_COMMIT: - g_value_set_string (value, self->commit); - break; - - case PROP_DISABLE_FSCKOBJECTS: - g_value_set_boolean (value, self->disable_fsckobjects); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -builder_source_git_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - BuilderSourceGit *self = BUILDER_SOURCE_GIT (object); - - switch (prop_id) - { - case PROP_URL: - g_free (self->url); - self->url = g_value_dup_string (value); - break; - - case PROP_PATH: - g_free (self->path); - self->path = g_value_dup_string (value); - break; - - case PROP_BRANCH: - g_free (self->branch); - self->branch = g_value_dup_string (value); - break; - - case PROP_COMMIT: - g_free (self->commit); - self->commit = g_value_dup_string (value); - break; - - case PROP_DISABLE_FSCKOBJECTS: - self->disable_fsckobjects = g_value_get_boolean (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static const char * -get_branch (BuilderSourceGit *self) -{ - if (self->branch) - return self->branch; - else if (self->commit) - return self->commit; - else - return "master"; -} - -static char * -get_url_or_path (BuilderSourceGit *self, - BuilderContext *context, - GError **error) -{ - g_autoptr(GFile) repo = NULL; - GFile *base_dir = BUILDER_SOURCE (self)->base_dir; - - if (self->url == NULL && self->path == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "No URL or path specified"); - return NULL; - } - - if (self->url) - { - g_autofree char *scheme = NULL; - scheme = g_uri_parse_scheme (self->url); - if (scheme == NULL) - { - repo = g_file_resolve_relative_path (base_dir, self->url); - return g_file_get_uri (repo); - } - - return g_strdup (self->url); - } - - repo = g_file_resolve_relative_path (base_dir, - self->path); - return g_file_get_path (repo); -} - -static gboolean -builder_source_git_download (BuilderSource *source, - gboolean update_vcs, - BuilderContext *context, - GError **error) -{ - BuilderSourceGit *self = BUILDER_SOURCE_GIT (source); - g_autofree char *location = NULL; - - location = get_url_or_path (self, context, error); - if (location == NULL) - return FALSE; - - if (!builder_git_mirror_repo (location, - NULL, - update_vcs, TRUE, self->disable_fsckobjects, - get_branch (self), - context, - error)) - return FALSE; - - if (self->commit != NULL && self->branch != NULL) - { - /* We want to support the commit being both a tag object and the real commit object that it points too */ - g_autofree char *current_commit = builder_git_get_current_commit (location,get_branch (self), FALSE, context, error); - g_autofree char *current_commit2 = builder_git_get_current_commit (location,get_branch (self), TRUE, context, error); - if (current_commit == NULL || current_commit2 == NULL) - return FALSE; - if (strcmp (current_commit, self->commit) != 0 && strcmp (current_commit2, self->commit) != 0) - return flatpak_fail (error, "Git commit for branch %s is %s, but expected %s\n", self->branch, current_commit2, self->commit); - } - - return TRUE; -} - -static gboolean -builder_source_git_extract (BuilderSource *source, - GFile *dest, - BuilderOptions *build_options, - BuilderContext *context, - GError **error) -{ - BuilderSourceGit *self = BUILDER_SOURCE_GIT (source); - g_autofree char *location = NULL; - - location = get_url_or_path (self, context, error); - if (location == NULL) - return FALSE; - - if (!builder_git_checkout (location, get_branch (self), - dest, context, error)) - return FALSE; - - return TRUE; -} - -static gboolean -builder_source_git_bundle (BuilderSource *source, - BuilderContext *context, - GError **error) -{ - BuilderSourceGit *self = BUILDER_SOURCE_GIT (source); - - g_autofree char *location = NULL; - g_autoptr(GFile) mirror_dir = NULL; - - location = get_url_or_path (self, context, error); - - g_print ("builder_source_git_bundle %s\n", location); - - if (location == NULL) - return FALSE; - - mirror_dir = flatpak_build_file (builder_context_get_app_dir (context), - "sources/git", - NULL); - if (!flatpak_mkdir_p (mirror_dir, NULL, error)) - return FALSE; - - if (!builder_git_mirror_repo (location, - flatpak_file_get_path_cached (mirror_dir), - FALSE, TRUE, FALSE, - get_branch (self), - context, - error)) - return FALSE; - - return TRUE; -} - -static void -builder_source_git_checksum (BuilderSource *source, - BuilderCache *cache, - BuilderContext *context) -{ - BuilderSourceGit *self = BUILDER_SOURCE_GIT (source); - g_autofree char *current_commit = NULL; - g_autoptr(GError) error = NULL; - g_autofree char *location = NULL; - - builder_cache_checksum_str (cache, self->url); - builder_cache_checksum_str (cache, self->path); - builder_cache_checksum_str (cache, self->branch); - builder_cache_checksum_compat_str (cache, self->commit); - builder_cache_checksum_compat_boolean (cache, self->disable_fsckobjects); - - location = get_url_or_path (self, context, &error); - if (location != NULL) - { - current_commit = builder_git_get_current_commit (location,get_branch (self), FALSE, context, &error); - if (current_commit) - builder_cache_checksum_str (cache, current_commit); - else if (error) - g_warning ("Failed to get current git checksum: %s", error->message); - } - else - { - g_warning ("No url or path"); - } -} - -static gboolean -builder_source_git_update (BuilderSource *source, - BuilderContext *context, - GError **error) -{ - BuilderSourceGit *self = BUILDER_SOURCE_GIT (source); - char *current_commit; - g_autofree char *location = NULL; - - location = get_url_or_path (self, context, error); - if (location == NULL) - return FALSE; - - current_commit = builder_git_get_current_commit (location, get_branch (self), FALSE, context, NULL); - if (current_commit) - { - g_free (self->branch); - self->branch = current_commit; - } - - return TRUE; -} - -static void -builder_source_git_class_init (BuilderSourceGitClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - BuilderSourceClass *source_class = BUILDER_SOURCE_CLASS (klass); - - object_class->finalize = builder_source_git_finalize; - object_class->get_property = builder_source_git_get_property; - object_class->set_property = builder_source_git_set_property; - - source_class->download = builder_source_git_download; - source_class->extract = builder_source_git_extract; - source_class->bundle = builder_source_git_bundle; - source_class->update = builder_source_git_update; - source_class->checksum = builder_source_git_checksum; - - g_object_class_install_property (object_class, - PROP_URL, - g_param_spec_string ("url", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_PATH, - g_param_spec_string ("path", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_BRANCH, - g_param_spec_string ("branch", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_COMMIT, - g_param_spec_string ("commit", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_DISABLE_FSCKOBJECTS, - g_param_spec_boolean ("disable-fsckobjects", - "", - "", - FALSE, - G_PARAM_READWRITE)); -} - -static void -builder_source_git_init (BuilderSourceGit *self) -{ -} diff --git a/builder/builder-source-git.h b/builder/builder-source-git.h deleted file mode 100644 index 61a03f80..00000000 --- a/builder/builder-source-git.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.1 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_GIT_H__ -#define __BUILDER_SOURCE_GIT_H__ - -#include "builder-source.h" - -G_BEGIN_DECLS - -typedef struct BuilderSourceGit BuilderSourceGit; - -#define BUILDER_TYPE_SOURCE_GIT (builder_source_git_get_type ()) -#define BUILDER_SOURCE_GIT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUILDER_TYPE_SOURCE_GIT, BuilderSourceGit)) -#define BUILDER_IS_SOURCE_GIT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUILDER_TYPE_SOURCE_GIT)) - -GType builder_source_git_get_type (void); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (BuilderSourceGit, g_object_unref) - -G_END_DECLS - -#endif /* __BUILDER_SOURCE_GIT_H__ */ diff --git a/builder/builder-source-patch.c b/builder/builder-source-patch.c deleted file mode 100644 index ff35a2ff..00000000 --- a/builder/builder-source-patch.c +++ /dev/null @@ -1,375 +0,0 @@ -/* builder-source-patch.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 "flatpak-utils.h" - -#include "builder-utils.h" -#include "builder-source-patch.h" - -struct BuilderSourcePatch -{ - BuilderSource parent; - - char *path; - guint strip_components; - gboolean use_git; - char **options; -}; - -typedef struct -{ - BuilderSourceClass parent_class; -} BuilderSourcePatchClass; - -G_DEFINE_TYPE (BuilderSourcePatch, builder_source_patch, BUILDER_TYPE_SOURCE); - -enum { - PROP_0, - PROP_PATH, - PROP_STRIP_COMPONENTS, - PROP_USE_GIT, - PROP_OPTIONS, - LAST_PROP -}; - -static void -builder_source_patch_finalize (GObject *object) -{ - BuilderSourcePatch *self = (BuilderSourcePatch *) object; - - g_free (self->path); - g_strfreev (self->options); - - G_OBJECT_CLASS (builder_source_patch_parent_class)->finalize (object); -} - -static void -builder_source_patch_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - BuilderSourcePatch *self = BUILDER_SOURCE_PATCH (object); - - switch (prop_id) - { - case PROP_PATH: - g_value_set_string (value, self->path); - break; - - case PROP_STRIP_COMPONENTS: - g_value_set_uint (value, self->strip_components); - break; - - case PROP_USE_GIT: - g_value_set_boolean (value, self->use_git); - break; - - case PROP_OPTIONS: - g_value_set_boxed (value, self->options); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -builder_source_patch_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - BuilderSourcePatch *self = BUILDER_SOURCE_PATCH (object); - gchar **tmp; - - switch (prop_id) - { - case PROP_PATH: - g_free (self->path); - self->path = g_value_dup_string (value); - break; - - case PROP_STRIP_COMPONENTS: - self->strip_components = g_value_get_uint (value); - break; - - case PROP_USE_GIT: - self->use_git = g_value_get_boolean (value); - break; - - case PROP_OPTIONS: - tmp = self->options; - self->options = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static GFile * -get_source_file (BuilderSourcePatch *self, - BuilderContext *context, - GError **error) -{ - GFile *base_dir = BUILDER_SOURCE (self)->base_dir; - - if (self->path == NULL || self->path[0] == 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "path not specified"); - return NULL; - } - - return g_file_resolve_relative_path (base_dir, self->path); -} - -static gboolean -builder_source_patch_show_deps (BuilderSource *source, - GError **error) -{ - BuilderSourcePatch *self = BUILDER_SOURCE_PATCH (source); - - if (self->path && self->path[0] != 0) - g_print ("%s\n", self->path); - - return TRUE; -} - -static gboolean -builder_source_patch_download (BuilderSource *source, - gboolean update_vcs, - BuilderContext *context, - GError **error) -{ - BuilderSourcePatch *self = BUILDER_SOURCE_PATCH (source); - - g_autoptr(GFile) src = NULL; - - src = get_source_file (self, context, error); - if (src == NULL) - return FALSE; - - if (!g_file_query_exists (src, NULL)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Can't find file at %s", self->path); - return FALSE; - } - - return TRUE; -} - -static gboolean -patch (GFile *dir, - gboolean use_git, - const char *patch_path, - char **extra_options, - GError **error, - ...) -{ - gboolean res; - GPtrArray *args; - const gchar *arg; - va_list ap; - int i; - - va_start(ap, error); - - args = g_ptr_array_new (); - if (use_git) { - g_ptr_array_add (args, "git"); - g_ptr_array_add (args, "apply"); - g_ptr_array_add (args, "-v"); - } else { - g_ptr_array_add (args, "patch"); - } - for (i = 0; extra_options != NULL && extra_options[i] != NULL; i++) - g_ptr_array_add (args, (gchar *) extra_options[i]); - while ((arg = va_arg (ap, const gchar *))) - g_ptr_array_add (args, (gchar *) arg); - if (use_git) { - g_ptr_array_add (args, (char *) patch_path); - } else { - g_ptr_array_add (args, "-i"); - g_ptr_array_add (args, (char *) patch_path); - } - g_ptr_array_add (args, NULL); - - res = flatpak_spawnv (dir, NULL, 0, error, (const char **) args->pdata); - - g_ptr_array_free (args, TRUE); - - va_end (ap); - - return res; -} - -static gboolean -builder_source_patch_extract (BuilderSource *source, - GFile *dest, - BuilderOptions *build_options, - BuilderContext *context, - GError **error) -{ - BuilderSourcePatch *self = BUILDER_SOURCE_PATCH (source); - - g_autoptr(GFile) patchfile = NULL; - g_autofree char *patch_path = NULL; - g_autofree char *strip_components = NULL; - - patchfile = get_source_file (self, context, error); - if (patchfile == NULL) - return FALSE; - - g_print ("Applying patch %s\n", self->path); - strip_components = g_strdup_printf ("-p%u", self->strip_components); - patch_path = g_file_get_path (patchfile); - if (!patch (dest, self->use_git, patch_path, self->options, error, strip_components, NULL)) - return FALSE; - - return TRUE; -} - -static gboolean -builder_source_patch_bundle (BuilderSource *source, - BuilderContext *context, - GError **error) -{ - BuilderSourcePatch *self = BUILDER_SOURCE_PATCH (source); - GFile *manifest_base_dir = builder_context_get_base_dir (context); - g_autoptr(GFile) src = NULL; - g_autoptr(GFile) destination_file = NULL; - g_autofree char *rel_path = NULL; - g_autoptr(GFile) destination_dir = NULL; - - src = get_source_file (self, context, error); - - if (src == NULL) - return FALSE; - - rel_path = g_file_get_relative_path (manifest_base_dir, src); - if (rel_path == NULL) - { - g_warning ("Patch %s is outside manifest tree, not bundling", flatpak_file_get_path_cached (src)); - return TRUE; - } - - destination_file = flatpak_build_file (builder_context_get_app_dir (context), - "sources/manifest", rel_path, NULL); - - destination_dir = g_file_get_parent (destination_file); - if (!flatpak_mkdir_p (destination_dir, NULL, error)) - return FALSE; - - if (!g_file_copy (src, destination_file, - G_FILE_COPY_OVERWRITE, - NULL, - NULL, NULL, - error)) - return FALSE; - - return TRUE; -} - -static void -builder_source_patch_checksum (BuilderSource *source, - BuilderCache *cache, - BuilderContext *context) -{ - BuilderSourcePatch *self = BUILDER_SOURCE_PATCH (source); - - g_autoptr(GFile) src = NULL; - g_autofree char *data = NULL; - gsize len; - - src = get_source_file (self, context, NULL); - if (src == NULL) - return; - - if (g_file_load_contents (src, NULL, &data, &len, NULL, NULL)) - builder_cache_checksum_data (cache, (guchar *) data, len); - - builder_cache_checksum_str (cache, self->path); - builder_cache_checksum_uint32 (cache, self->strip_components); - builder_cache_checksum_strv (cache, self->options); -} - -static void -builder_source_patch_class_init (BuilderSourcePatchClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - BuilderSourceClass *source_class = BUILDER_SOURCE_CLASS (klass); - - object_class->finalize = builder_source_patch_finalize; - object_class->get_property = builder_source_patch_get_property; - object_class->set_property = builder_source_patch_set_property; - - source_class->show_deps = builder_source_patch_show_deps; - source_class->download = builder_source_patch_download; - source_class->extract = builder_source_patch_extract; - source_class->bundle = builder_source_patch_bundle; - source_class->checksum = builder_source_patch_checksum; - - g_object_class_install_property (object_class, - PROP_PATH, - g_param_spec_string ("path", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_STRIP_COMPONENTS, - g_param_spec_uint ("strip-components", - "", - "", - 0, G_MAXUINT, - 1, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_USE_GIT, - g_param_spec_boolean ("use-git", - "", - "", - FALSE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_OPTIONS, - g_param_spec_boxed ("options", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); -} - -static void -builder_source_patch_init (BuilderSourcePatch *self) -{ - self->strip_components = 1; -} diff --git a/builder/builder-source-patch.h b/builder/builder-source-patch.h deleted file mode 100644 index 8d1c6d22..00000000 --- a/builder/builder-source-patch.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.1 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_PATCH_H__ -#define __BUILDER_SOURCE_PATCH_H__ - -#include "builder-source.h" - -G_BEGIN_DECLS - -typedef struct BuilderSourcePatch BuilderSourcePatch; - -#define BUILDER_TYPE_SOURCE_PATCH (builder_source_patch_get_type ()) -#define BUILDER_SOURCE_PATCH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUILDER_TYPE_SOURCE_PATCH, BuilderSourcePatch)) -#define BUILDER_IS_SOURCE_PATCH(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUILDER_TYPE_SOURCE_PATCH)) - -GType builder_source_patch_get_type (void); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (BuilderSourcePatch, g_object_unref) - -G_END_DECLS - -#endif /* __BUILDER_SOURCE_PATCH_H__ */ diff --git a/builder/builder-source-script.c b/builder/builder-source-script.c deleted file mode 100644 index 2c300da2..00000000 --- a/builder/builder-source-script.c +++ /dev/null @@ -1,232 +0,0 @@ -/* builder-source-script.c - * - * Copyright (C) 2015 Red Hat, Inc - * - * This script 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 script 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 "flatpak-utils.h" -#include "builder-utils.h" -#include "builder-source-script.h" - -struct BuilderSourceScript -{ - BuilderSource parent; - - char **commands; - char *dest_filename; -}; - -typedef struct -{ - BuilderSourceClass parent_class; -} BuilderSourceScriptClass; - -G_DEFINE_TYPE (BuilderSourceScript, builder_source_script, BUILDER_TYPE_SOURCE); - -enum { - PROP_0, - PROP_COMMANDS, - PROP_DEST_FILENAME, - LAST_PROP -}; - -static void -builder_source_script_finalize (GObject *object) -{ - BuilderSourceScript *self = (BuilderSourceScript *) object; - - g_strfreev (self->commands); - g_free (self->dest_filename); - - G_OBJECT_CLASS (builder_source_script_parent_class)->finalize (object); -} - -static void -builder_source_script_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - BuilderSourceScript *self = BUILDER_SOURCE_SCRIPT (object); - - switch (prop_id) - { - case PROP_COMMANDS: - g_value_set_boxed (value, self->commands); - break; - - case PROP_DEST_FILENAME: - g_value_set_string (value, self->dest_filename); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -builder_source_script_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - BuilderSourceScript *self = BUILDER_SOURCE_SCRIPT (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; - - case PROP_DEST_FILENAME: - g_free (self->dest_filename); - self->dest_filename = g_value_dup_string (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static gboolean -builder_source_script_download (BuilderSource *source, - gboolean update_vcs, - BuilderContext *context, - GError **error) -{ - return TRUE; -} - -static gboolean -builder_source_script_extract (BuilderSource *source, - GFile *dest, - BuilderOptions *build_options, - BuilderContext *context, - GError **error) -{ - BuilderSourceScript *self = BUILDER_SOURCE_SCRIPT (source); - - g_autoptr(GFile) dest_script = NULL; - const char *dest_filename; - g_autoptr(GString) script = NULL; - int i; - guint32 perms; - - script = g_string_new ("#!/bin/sh\n"); - - if (self->commands) - { - for (i = 0; self->commands[i] != NULL; i++) - { - g_string_append (script, self->commands[i]); - g_string_append_c (script, '\n'); - } - } - - if (self->dest_filename) - dest_filename = self->dest_filename; - else - dest_filename = "autogen.sh"; - - dest_script = g_file_get_child (dest, dest_filename); - - if (!g_file_set_contents (flatpak_file_get_path_cached (dest_script), - script->str, - script->len, - error)) - return FALSE; - - perms = 0755; - if (!g_file_set_attribute (dest_script, - G_FILE_ATTRIBUTE_UNIX_MODE, - G_FILE_ATTRIBUTE_TYPE_UINT32, - &perms, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - NULL, error)) - return FALSE; - - return TRUE; -} - -static gboolean -builder_source_script_bundle (BuilderSource *source, - BuilderContext *context, - GError **error) -{ - /* no need to bundle anything here as this part - can be reconstructed from the manifest */ - return TRUE; -} - -static void -builder_source_script_checksum (BuilderSource *source, - BuilderCache *cache, - BuilderContext *context) -{ - BuilderSourceScript *self = BUILDER_SOURCE_SCRIPT (source); - - builder_cache_checksum_strv (cache, self->commands); - builder_cache_checksum_str (cache, self->dest_filename); -} - -static void -builder_source_script_class_init (BuilderSourceScriptClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - BuilderSourceClass *source_class = BUILDER_SOURCE_CLASS (klass); - - object_class->finalize = builder_source_script_finalize; - object_class->get_property = builder_source_script_get_property; - object_class->set_property = builder_source_script_set_property; - - source_class->download = builder_source_script_download; - source_class->extract = builder_source_script_extract; - source_class->bundle = builder_source_script_bundle; - source_class->checksum = builder_source_script_checksum; - - g_object_class_install_property (object_class, - PROP_COMMANDS, - g_param_spec_boxed ("commands", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_DEST_FILENAME, - g_param_spec_string ("dest-filename", - "", - "", - NULL, - G_PARAM_READWRITE)); -} - -static void -builder_source_script_init (BuilderSourceScript *self) -{ -} diff --git a/builder/builder-source-script.h b/builder/builder-source-script.h deleted file mode 100644 index bb1e0148..00000000 --- a/builder/builder-source-script.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.1 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_SCRIPT_H__ -#define __BUILDER_SOURCE_SCRIPT_H__ - -#include "builder-source.h" - -G_BEGIN_DECLS - -typedef struct BuilderSourceScript BuilderSourceScript; - -#define BUILDER_TYPE_SOURCE_SCRIPT (builder_source_script_get_type ()) -#define BUILDER_SOURCE_SCRIPT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUILDER_TYPE_SOURCE_SCRIPT, BuilderSourceScript)) -#define BUILDER_IS_SOURCE_SCRIPT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUILDER_TYPE_SOURCE_SCRIPT)) - -GType builder_source_script_get_type (void); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (BuilderSourceScript, g_object_unref) - -G_END_DECLS - -#endif /* __BUILDER_SOURCE_SCRIPT_H__ */ diff --git a/builder/builder-source-shell.c b/builder/builder-source-shell.c deleted file mode 100644 index 3bea7dac..00000000 --- a/builder/builder-source-shell.c +++ /dev/null @@ -1,228 +0,0 @@ -/* 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 "flatpak-utils.h" -#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, - BuilderOptions *build_options, - GFile *source_dir, - const gchar *script, - GError **error) -{ - GFile *app_dir = builder_context_get_app_dir (context); - g_autoptr(GPtrArray) args = NULL; - g_autofree char *source_dir_path = g_file_get_path (source_dir); - g_autofree char *source_dir_path_canonical = NULL; - g_autoptr(GFile) source_dir_path_canonical_file = NULL; - g_auto(GStrv) build_args = NULL; - int i; - - args = g_ptr_array_new_with_free_func (g_free); - g_ptr_array_add (args, g_strdup ("flatpak")); - g_ptr_array_add (args, g_strdup ("build")); - - source_dir_path_canonical = realpath (source_dir_path, NULL); - - g_ptr_array_add (args, g_strdup ("--nofilesystem=host")); - g_ptr_array_add (args, g_strdup_printf ("--filesystem=%s", source_dir_path_canonical)); - - build_args = builder_options_get_build_args (build_options, context, error); - if (build_args == NULL) - return FALSE; - - for (i = 0; build_args[i] != NULL; i++) - g_ptr_array_add (args, g_strdup (build_args[i])); - - 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); - - source_dir_path_canonical_file = g_file_new_for_path (source_dir_path_canonical); - - return builder_maybe_host_spawnv (source_dir_path_canonical_file, NULL, error, (const char * const *)args->pdata); -} - - -static gboolean -builder_source_shell_extract (BuilderSource *source, - GFile *dest, - BuilderOptions *build_options, - 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, build_options, - dest, self->commands[i], error)) - return FALSE; - } - } - - - return TRUE; -} - -static gboolean -builder_source_shell_bundle (BuilderSource *source, - BuilderContext *context, - GError **error) -{ - /* no need to bundle anything here as this part - can be reconstructed from the manifest */ - 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->bundle = builder_source_shell_bundle; - 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 deleted file mode 100644 index 1b89db88..00000000 --- a/builder/builder-source-shell.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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.1 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 deleted file mode 100644 index 836d5cb1..00000000 --- a/builder/builder-source.c +++ /dev/null @@ -1,405 +0,0 @@ -/* builder-source.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.h" -#include "builder-source-archive.h" -#include "builder-source-patch.h" -#include "builder-source-git.h" -#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); - -G_DEFINE_TYPE_WITH_CODE (BuilderSource, builder_source, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (JSON_TYPE_SERIALIZABLE, serializable_iface_init)); - -enum { - PROP_0, - PROP_DEST, - PROP_ONLY_ARCHES, - PROP_SKIP_ARCHES, - LAST_PROP -}; - - -static void -builder_source_finalize (GObject *object) -{ - BuilderSource *self = BUILDER_SOURCE (object); - - g_clear_object (&self->base_dir); - g_free (self->dest); - - G_OBJECT_CLASS (builder_source_parent_class)->finalize (object); -} - -void -builder_source_set_base_dir (BuilderSource *self, - GFile *base_dir) -{ - g_set_object (&self->base_dir, base_dir); -} - -static void -builder_source_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - BuilderSource *self = BUILDER_SOURCE (object); - - switch (prop_id) - { - case PROP_DEST: - g_value_set_string (value, self->dest); - break; - - case PROP_ONLY_ARCHES: - g_value_set_boxed (value, self->only_arches); - break; - - case PROP_SKIP_ARCHES: - g_value_set_boxed (value, self->skip_arches); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } -} - -static void -builder_source_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - BuilderSource *self = BUILDER_SOURCE (object); - gchar **tmp; - - switch (prop_id) - { - case PROP_DEST: - g_free (self->dest); - self->dest = g_value_dup_string (value); - break; - - case PROP_ONLY_ARCHES: - tmp = self->only_arches; - self->only_arches = g_strdupv (g_value_get_boxed (value)); - g_strfreev (tmp); - break; - - case PROP_SKIP_ARCHES: - tmp = self->skip_arches; - self->skip_arches = 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_real_show_deps (BuilderSource *self, - GError **error) -{ - return TRUE; -} - -static gboolean -builder_source_real_download (BuilderSource *self, - gboolean update_vcs, - BuilderContext *context, - GError **error) -{ - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Download not implemented for type %s", g_type_name_from_instance ((GTypeInstance *) self)); - return FALSE; -} - -static gboolean -builder_source_real_extract (BuilderSource *self, - GFile *dest, - BuilderOptions *build_options, - BuilderContext *context, - GError **error) -{ - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Extract not implemented for type %s", g_type_name_from_instance ((GTypeInstance *) self)); - return FALSE; -} - -static gboolean -builder_source_real_bundle (BuilderSource *self, - BuilderContext *context, - GError **error) -{ - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Bundle not implemented for type %s", g_type_name_from_instance ((GTypeInstance *) self)); - return FALSE; -} - -static gboolean -builder_source_real_update (BuilderSource *self, - BuilderContext *context, - GError **error) -{ - return TRUE; -} - -static void -builder_source_class_init (BuilderSourceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = builder_source_finalize; - object_class->get_property = builder_source_get_property; - object_class->set_property = builder_source_set_property; - - klass->show_deps = builder_source_real_show_deps; - klass->download = builder_source_real_download; - klass->extract = builder_source_real_extract; - klass->bundle = builder_source_real_bundle; - klass->update = builder_source_real_update; - - g_object_class_install_property (object_class, - PROP_DEST, - g_param_spec_string ("dest", - "", - "", - NULL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_ONLY_ARCHES, - g_param_spec_boxed ("only-arches", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_SKIP_ARCHES, - g_param_spec_boxed ("skip-arches", - "", - "", - G_TYPE_STRV, - G_PARAM_READWRITE)); -} - -static void -builder_source_init (BuilderSource *self) -{ -} - -static GParamSpec * -builder_source_find_property (JsonSerializable *serializable, - const char *name) -{ - if (strcmp (name, "type") == 0) - return NULL; - return builder_serializable_find_property_with_error (serializable, name); -} - -static void -serializable_iface_init (JsonSerializableIface *serializable_iface) -{ - serializable_iface->find_property = builder_source_find_property; -} - -JsonNode * -builder_source_to_json (BuilderSource *self) -{ - JsonNode *node; - JsonObject *object; - const gchar *type = NULL; - - node = json_gobject_serialize (G_OBJECT (self)); - object = json_node_get_object (node); - - if (BUILDER_IS_SOURCE_ARCHIVE (self)) - type = "archive"; - else if (BUILDER_IS_SOURCE_FILE (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)) - type = "git"; - else if (BUILDER_IS_SOURCE_BZR (self)) - type = "bzr"; - else - g_warning ("Unknown source type"); - - if (type) - json_object_set_string_member (object, "type", type); - - return node; -} - -BuilderSource * -builder_source_from_json (JsonNode *node) -{ - JsonObject *object = json_node_get_object (node); - const gchar *type; - - type = json_object_get_string_member (object, "type"); - - if (type == NULL) - g_warning ("Missing source type"); - else if (strcmp (type, "archive") == 0) - return (BuilderSource *) json_gobject_deserialize (BUILDER_TYPE_SOURCE_ARCHIVE, node); - else if (strcmp (type, "file") == 0) - return (BuilderSource *) json_gobject_deserialize (BUILDER_TYPE_SOURCE_FILE, node); - else if (strcmp (type, "script") == 0) - return (BuilderSource *) json_gobject_deserialize (BUILDER_TYPE_SOURCE_SCRIPT, node); - else if (strcmp (type, "shell") == 0) - return (BuilderSource *) json_gobject_deserialize (BUILDER_TYPE_SOURCE_SHELL, node); - else if (strcmp (type, "patch") == 0) - return (BuilderSource *) json_gobject_deserialize (BUILDER_TYPE_SOURCE_PATCH, node); - else if (strcmp (type, "git") == 0) - return (BuilderSource *) json_gobject_deserialize (BUILDER_TYPE_SOURCE_GIT, node); - else if (strcmp (type, "bzr") == 0) - return (BuilderSource *) json_gobject_deserialize (BUILDER_TYPE_SOURCE_BZR, node); - else - g_warning ("Unknown source type %s", type); - - return NULL; -} - -gboolean -builder_source_show_deps (BuilderSource *self, - GError **error) -{ - BuilderSourceClass *class; - - class = BUILDER_SOURCE_GET_CLASS (self); - - return class->show_deps (self, error); -} - -gboolean -builder_source_download (BuilderSource *self, - gboolean update_vcs, - BuilderContext *context, - GError **error) -{ - BuilderSourceClass *class; - - class = BUILDER_SOURCE_GET_CLASS (self); - - return class->download (self, update_vcs, context, error); -} - -gboolean -builder_source_extract (BuilderSource *self, - GFile *dest, - BuilderOptions *build_options, - BuilderContext *context, - GError **error) -{ - BuilderSourceClass *class; - - g_autoptr(GFile) real_dest = NULL; - - class = BUILDER_SOURCE_GET_CLASS (self); - - if (self->dest != NULL) - { - real_dest = g_file_resolve_relative_path (dest, self->dest); - - if (!g_file_query_exists (real_dest, NULL) && - !g_file_make_directory_with_parents (real_dest, NULL, error)) - return FALSE; - } - else - { - real_dest = g_object_ref (dest); - } - - - return class->extract (self, real_dest, build_options, context, error); -} - -gboolean -builder_source_bundle (BuilderSource *self, - BuilderContext *context, - GError **error) -{ - BuilderSourceClass *class; - class = BUILDER_SOURCE_GET_CLASS (self); - - return class->bundle (self, context, error); -} - -gboolean -builder_source_update (BuilderSource *self, - BuilderContext *context, - GError **error) -{ - BuilderSourceClass *class = BUILDER_SOURCE_GET_CLASS (self); - - return class->update (self, context, error); -} - -void -builder_source_checksum (BuilderSource *self, - BuilderCache *cache, - BuilderContext *context) -{ - BuilderSourceClass *class; - - class = BUILDER_SOURCE_GET_CLASS (self); - - builder_cache_checksum_str (cache, self->dest); - builder_cache_checksum_strv (cache, self->only_arches); - builder_cache_checksum_strv (cache, self->skip_arches); - - class->checksum (self, cache, context); -} - -gboolean -builder_source_is_enabled (BuilderSource *self, - BuilderContext *context) -{ - if (self->only_arches != NULL && - self->only_arches[0] != NULL && - !g_strv_contains ((const char * const *) self->only_arches, builder_context_get_arch (context))) - return FALSE; - - if (self->skip_arches != NULL && - g_strv_contains ((const char * const *)self->skip_arches, builder_context_get_arch (context))) - return FALSE; - - return TRUE; -} diff --git a/builder/builder-source.h b/builder/builder-source.h deleted file mode 100644 index 4fa3c599..00000000 --- a/builder/builder-source.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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.1 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_H__ -#define __BUILDER_SOURCE_H__ - -#include - -#include "builder-context.h" -#include "builder-cache.h" - -G_BEGIN_DECLS - -typedef struct BuilderSource BuilderSource; - -#define BUILDER_TYPE_SOURCE (builder_source_get_type ()) -#define BUILDER_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), BUILDER_TYPE_SOURCE, BuilderSource)) -#define BUILDER_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), BUILDER_TYPE_SOURCE, BuilderSourceClass)) -#define BUILDER_IS_SOURCE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), BUILDER_TYPE_SOURCE)) -#define BUILDER_IS_SOURCE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), BUILDER_TYPE_SOURCE)) -#define BUILDER_SOURCE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), BUILDER_TYPE_SOURCE, BuilderSourceClass)) - -struct BuilderSource -{ - GObject parent; - - GFile *base_dir; - char *dest; - char **only_arches; - char **skip_arches; -}; - -typedef struct -{ - GObjectClass parent_class; - - gboolean (* show_deps)(BuilderSource *self, - GError **error); - gboolean (* download)(BuilderSource *self, - gboolean update_vcs, - BuilderContext *context, - GError **error); - gboolean (* extract)(BuilderSource *self, - GFile *dest, - BuilderOptions *build_options, - BuilderContext *context, - GError **error); - gboolean (* bundle)(BuilderSource *self, - BuilderContext *context, - GError **error); - gboolean (* update)(BuilderSource *self, - BuilderContext *context, - GError **error); - void (* checksum)(BuilderSource *self, - BuilderCache *cache, - BuilderContext *context); -} BuilderSourceClass; - -GType builder_source_get_type (void); - -BuilderSource * builder_source_from_json (JsonNode *node); -JsonNode * builder_source_to_json (BuilderSource *self); - - -void builder_source_set_base_dir (BuilderSource *self, - GFile *base_dir); - -gboolean builder_source_show_deps (BuilderSource *self, - GError **error); -gboolean builder_source_download (BuilderSource *self, - gboolean update_vcs, - BuilderContext *context, - GError **error); -gboolean builder_source_extract (BuilderSource *self, - GFile *dest, - BuilderOptions *build_options, - BuilderContext *context, - GError **error); -gboolean builder_source_bundle (BuilderSource *self, - BuilderContext *context, - GError **error); -gboolean builder_source_update (BuilderSource *self, - BuilderContext *context, - GError **error); - -void builder_source_checksum (BuilderSource *self, - BuilderCache *cache, - BuilderContext *context); - -gboolean builder_source_is_enabled (BuilderSource *self, - BuilderContext *context); - -G_DEFINE_AUTOPTR_CLEANUP_FUNC (BuilderSource, g_object_unref) - -G_END_DECLS - -#endif /* __BUILDER_SOURCE_H__ */ diff --git a/builder/builder-utils.c b/builder/builder-utils.c deleted file mode 100644 index 388de9bc..00000000 --- a/builder/builder-utils.c +++ /dev/null @@ -1,1734 +0,0 @@ -/* builder-utils.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 -#include - -#include - -#include -#include -#include -#include - -#include "flatpak-utils.h" -#include "builder-utils.h" - -char * -builder_uri_to_filename (const char *uri) -{ - GString *s; - const char *p; - - s = g_string_new (""); - - for (p = uri; *p != 0; p++) - { - if (*p == '/' || *p == ':') - { - while (p[1] == '/' || p[1] == ':') - p++; - g_string_append_c (s, '_'); - } - else - { - g_string_append_c (s, *p); - } - } - - return g_string_free (s, FALSE); -} - -static const char * -inplace_basename (const char *path) -{ - const char *last_slash; - - last_slash = strrchr (path, '/'); - if (last_slash) - path = last_slash + 1; - - return path; -} - - -/* Adds all matches of path to prefix. There can be multiple, because - * e.g matching "a/b/c" against "/a" matches both "a/b" and "a/b/c" - * - * If pattern starts with a slash, then match on the entire - * path, otherwise just the basename. - */ -void -flatpak_collect_matches_for_path_pattern (const char *path, - const char *pattern, - const char *add_prefix, - GHashTable *to_remove_ht) -{ - const char *rest; - - if (pattern[0] != '/') - { - rest = flatpak_path_match_prefix (pattern, inplace_basename (path)); - if (rest != NULL) - g_hash_table_insert (to_remove_ht, g_strconcat (add_prefix ? add_prefix : "", path, NULL), GINT_TO_POINTER (1)); - } - else - { - /* Absolute pathname match. This can actually match multiple - * files, as a prefix match should remove all files below that - * (in this module) */ - - rest = flatpak_path_match_prefix (pattern, path); - while (rest != NULL) - { - const char *slash; - g_autofree char *prefix = g_strndup (path, rest - path); - g_hash_table_insert (to_remove_ht, g_strconcat (add_prefix ? add_prefix : "", prefix, NULL), GINT_TO_POINTER (1)); - while (*rest == '/') - rest++; - if (*rest == 0) - break; - slash = strchr (rest, '/'); - rest = slash ? slash : rest + strlen (rest); - } - } - - -} - -gboolean -flatpak_matches_path_pattern (const char *path, - const char *pattern) -{ - if (pattern[0] != '/') - path = inplace_basename (path); - - return flatpak_path_match_prefix (pattern, path) != NULL; -} - -gboolean -strip (GError **error, - ...) -{ - gboolean res; - va_list ap; - - va_start (ap, error); - res = flatpak_spawn (NULL, NULL, error, "strip", ap); - va_end (ap); - - return res; -} - -gboolean -eu_strip (GError **error, - ...) -{ - gboolean res; - va_list ap; - - va_start (ap, error); - res = flatpak_spawn (NULL, NULL, error, "eu-strip", ap); - va_end (ap); - - return res; -} - -static gboolean -elf_has_symtab (Elf *elf) -{ - Elf_Scn *scn; - GElf_Shdr shdr; - - scn = NULL; - while ((scn = elf_nextscn (elf, scn)) != NULL) - { - if (gelf_getshdr (scn, &shdr) == NULL) - continue; - - if (shdr.sh_type != SHT_SYMTAB) - continue; - - return TRUE; - } - - return FALSE; -} - -gboolean -is_elf_file (const char *path, - gboolean *is_shared, - gboolean *is_stripped) -{ - g_autofree char *filename = g_path_get_basename (path); - struct stat stbuf; - - if (lstat (path, &stbuf) == -1) - return FALSE; - - if (!S_ISREG (stbuf.st_mode)) - return FALSE; - - /* Self-extracting .zip files can be ELF-executables, but shouldn't be - treated like them - for example, stripping them breaks their - operation */ - if (g_str_has_suffix (filename, ".zip")) - return FALSE; - - if ((strstr (filename, ".so.") != NULL || - g_str_has_suffix (filename, ".so")) || - (stbuf.st_mode & 0111) != 0) - { - glnx_fd_close int fd = -1; - - fd = open (path, O_RDONLY | O_NOFOLLOW | O_CLOEXEC); - if (fd >= 0) - { - Elf *elf; - GElf_Ehdr ehdr; - gboolean res = FALSE; - - if (elf_version (EV_CURRENT) == EV_NONE ) - return FALSE; - - elf = elf_begin (fd, ELF_C_READ, NULL); - if (elf == NULL) - return FALSE; - - if (elf_kind (elf) == ELF_K_ELF && - gelf_getehdr (elf, &ehdr)) - { - if (is_shared) - *is_shared = ehdr.e_type == ET_DYN; - if (is_stripped) - *is_stripped = !elf_has_symtab (elf); - - res = TRUE; - } - - elf_end (elf); - return res; - } - } - - return FALSE; -} - -gboolean -directory_is_empty (const char *path) -{ - GDir *dir; - gboolean empty; - - dir = g_dir_open (path, 0, NULL); - if (g_dir_read_name (dir) == NULL) - empty = TRUE; - else - empty = FALSE; - - g_dir_close (dir); - - return empty; -} - -static gboolean -migrate_locale_dir (GFile *source_dir, - GFile *separate_dir, - const char *subdir, - GError **error) -{ - g_autoptr(GFileEnumerator) dir_enum = NULL; - GFileInfo *next; - GError *temp_error = NULL; - - dir_enum = g_file_enumerate_children (source_dir, "standard::name,standard::type", - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - NULL, NULL); - if (!dir_enum) - return TRUE; - - while ((next = g_file_enumerator_next_file (dir_enum, NULL, &temp_error))) - { - g_autoptr(GFileInfo) child_info = next; - g_autoptr(GFile) locale_subdir = NULL; - - if (g_file_info_get_file_type (child_info) == G_FILE_TYPE_DIRECTORY) - { - g_autoptr(GFile) child = NULL; - const char *name = g_file_info_get_name (child_info); - g_autofree char *language = g_strdup (name); - g_autofree char *relative = NULL; - g_autofree char *target = NULL; - char *c; - - c = strchr (language, '@'); - if (c != NULL) - *c = 0; - c = strchr (language, '_'); - if (c != NULL) - *c = 0; - c = strchr (language, '.'); - if (c != NULL) - *c = 0; - - /* We ship english and C locales always */ - if (strcmp (language, "C") == 0 || - strcmp (language, "en") == 0) - continue; - - child = g_file_get_child (source_dir, g_file_info_get_name (child_info)); - - relative = g_build_filename (language, subdir, name, NULL); - locale_subdir = g_file_resolve_relative_path (separate_dir, relative); - if (!flatpak_mkdir_p (locale_subdir, NULL, error)) - return FALSE; - - if (!flatpak_cp_a (child, locale_subdir, - FLATPAK_CP_FLAGS_MERGE | FLATPAK_CP_FLAGS_MOVE, - NULL, error)) - return FALSE; - - target = g_build_filename ("../../share/runtime/locale", relative, NULL); - - if (!g_file_make_symbolic_link (child, target, - NULL, error)) - return FALSE; - - } - } - - if (temp_error != NULL) - { - g_propagate_error (error, temp_error); - return FALSE; - } - - return TRUE; -} - -gboolean -builder_migrate_locale_dirs (GFile *root_dir, - GError **error) -{ - g_autoptr(GFile) separate_dir = NULL; - g_autoptr(GFile) lib_locale_dir = NULL; - g_autoptr(GFile) share_locale_dir = NULL; - - lib_locale_dir = g_file_resolve_relative_path (root_dir, "lib/locale"); - share_locale_dir = g_file_resolve_relative_path (root_dir, "share/locale"); - separate_dir = g_file_resolve_relative_path (root_dir, "share/runtime/locale"); - - if (!migrate_locale_dir (lib_locale_dir, separate_dir, "lib", error)) - return FALSE; - - if (!migrate_locale_dir (share_locale_dir, separate_dir, "share", error)) - return FALSE; - - return TRUE; -} - - -/* - * This code is based on debugedit.c from rpm, which has this copyright: - * - * - * Copyright (C) 2001, 2002, 2003, 2005, 2007, 2009, 2010, 2011 Red Hat, Inc. - * Written by Alexander Larsson , 2002 - * Based on code by Jakub Jelinek , 2001. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ - - -#define DW_TAG_partial_unit 0x3c -#define DW_FORM_sec_offset 0x17 -#define DW_FORM_exprloc 0x18 -#define DW_FORM_flag_present 0x19 -#define DW_FORM_ref_sig8 0x20 - -/* keep uptodate with changes to debug_sections */ -#define DEBUG_INFO 0 -#define DEBUG_ABBREV 1 -#define DEBUG_LINE 2 -#define DEBUG_ARANGES 3 -#define DEBUG_PUBNAMES 4 -#define DEBUG_PUBTYPES 5 -#define DEBUG_MACINFO 6 -#define DEBUG_LOC 7 -#define DEBUG_STR 8 -#define DEBUG_FRAME 9 -#define DEBUG_RANGES 10 -#define DEBUG_TYPES 11 -#define DEBUG_MACRO 12 -#define DEBUG_GDB_SCRIPT 13 -#define NUM_DEBUG_SECTIONS 14 - -static const char * debug_section_names[] = { - ".debug_info", - ".debug_abbrev", - ".debug_line", - ".debug_aranges", - ".debug_pubnames", - ".debug_pubtypes", - ".debug_macinfo", - ".debug_loc", - ".debug_str", - ".debug_frame", - ".debug_ranges", - ".debug_types", - ".debug_macro", - ".debug_gdb_scripts", -}; - - -typedef struct -{ - unsigned char *data; - Elf_Data *elf_data; - size_t size; - int sec, relsec; -} debug_section_t; - -typedef struct -{ - Elf *elf; - GElf_Ehdr ehdr; - Elf_Scn **scns; - const char *filename; - int lastscn; - debug_section_t debug_sections[NUM_DEBUG_SECTIONS]; - GElf_Shdr *shdr; -} DebuginfoData; - -typedef struct -{ - unsigned char *ptr; - uint32_t addend; -} REL; - -#define read_uleb128(ptr) ({ \ - unsigned int ret = 0; \ - unsigned int c; \ - int shift = 0; \ - do \ - { \ - c = *ptr++; \ - ret |= (c & 0x7f) << shift; \ - shift += 7; \ - } while (c & 0x80); \ - \ - if (shift >= 35) \ - ret = UINT_MAX; \ - ret; \ - }) - -static uint16_t (*do_read_16)(unsigned char *ptr); -static uint32_t (*do_read_32) (unsigned char *ptr); - -static int ptr_size; -static int cu_version; - -static inline uint16_t -buf_read_ule16 (unsigned char *data) -{ - return data[0] | (data[1] << 8); -} - -static inline uint16_t -buf_read_ube16 (unsigned char *data) -{ - return data[1] | (data[0] << 8); -} - -static inline uint32_t -buf_read_ule32 (unsigned char *data) -{ - return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); -} - -static inline uint32_t -buf_read_ube32 (unsigned char *data) -{ - return data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24); -} - -#define read_1(ptr) *ptr++ - -#define read_16(ptr) ({ \ - uint16_t ret = do_read_16 (ptr); \ - ptr += 2; \ - ret; \ - }) - -#define read_32(ptr) ({ \ - uint32_t ret = do_read_32 (ptr); \ - ptr += 4; \ - ret; \ - }) - -REL *relptr, *relend; -int reltype; - -#define do_read_32_relocated(ptr) ({ \ - uint32_t dret = do_read_32 (ptr); \ - if (relptr) \ - { \ - while (relptr < relend && relptr->ptr < ptr) \ - ++relptr; \ - if (relptr < relend && relptr->ptr == ptr) \ - { \ - if (reltype == SHT_REL) \ - dret += relptr->addend; \ - else \ - dret = relptr->addend; \ - } \ - } \ - dret; \ - }) - -#define read_32_relocated(ptr) ({ \ - uint32_t ret = do_read_32_relocated (ptr); \ - ptr += 4; \ - ret; \ - }) - -struct abbrev_attr -{ - unsigned int attr; - unsigned int form; -}; - -struct abbrev_tag -{ - unsigned int tag; - int nattr; - struct abbrev_attr attr[0]; -}; - -static GHashTable * -read_abbrev (DebuginfoData *data, unsigned char *ptr) -{ - GHashTable *h; - unsigned int attr, entry, form; - struct abbrev_tag *t; - int size; - - h = g_hash_table_new_full (g_direct_hash, g_direct_equal, - NULL, g_free); - - while ((attr = read_uleb128 (ptr)) != 0) - { - size = 10; - entry = attr; - t = g_malloc (sizeof (*t) + size * sizeof (struct abbrev_attr)); - t->tag = read_uleb128 (ptr); - t->nattr = 0; - ++ptr; /* skip children flag. */ - while ((attr = read_uleb128 (ptr)) != 0) - { - if (t->nattr == size) - { - size += 10; - t = g_realloc (t, sizeof (*t) + size * sizeof (struct abbrev_attr)); - } - form = read_uleb128 (ptr); - if (form == 2 || (form > DW_FORM_flag_present && form != DW_FORM_ref_sig8)) - g_warning ("%s: Unknown DWARF DW_FORM_%d", data->filename, form); - - t->attr[t->nattr].attr = attr; - t->attr[t->nattr++].form = form; - } - if (read_uleb128 (ptr) != 0) - g_warning ("%s: DWARF abbreviation does not end with 2 zeros", data->filename); - g_hash_table_insert (h, GINT_TO_POINTER (entry), t); - } - - return h; -} - -#define IS_DIR_SEPARATOR(c) ((c) == '/') - -static char * -canonicalize_path (const char *s, char *d) -{ - char *rv = d; - char *droot; - - if (IS_DIR_SEPARATOR (*s)) - { - *d++ = *s++; - if (IS_DIR_SEPARATOR (*s) && !IS_DIR_SEPARATOR (s[1])) - /* Special case for "//foo" meaning a Posix namespace escape. */ - *d++ = *s++; - while (IS_DIR_SEPARATOR (*s)) - s++; - } - droot = d; - - while (*s) - { - /* At this point, we're always at the beginning of a path segment. */ - - if (s[0] == '.' && (s[1] == 0 || IS_DIR_SEPARATOR (s[1]))) - { - s++; - if (*s) - while (IS_DIR_SEPARATOR (*s)) - ++s; - } - else if (s[0] == '.' && s[1] == '.' && - (s[2] == 0 || IS_DIR_SEPARATOR (s[2]))) - { - char *pre = d - 1; /* includes slash */ - while (droot < pre && IS_DIR_SEPARATOR (*pre)) - pre--; - if (droot <= pre && !IS_DIR_SEPARATOR (*pre)) - { - while (droot < pre && !IS_DIR_SEPARATOR (*pre)) - pre--; - /* pre now points to the slash */ - if (droot < pre) - pre++; - if (pre + 3 == d && pre[0] == '.' && pre[1] == '.') - { - *d++ = *s++; - *d++ = *s++; - } - else - { - d = pre; - s += 2; - if (*s) - while (IS_DIR_SEPARATOR (*s)) - s++; - } - } - else - { - *d++ = *s++; - *d++ = *s++; - } - } - else - { - while (*s && !IS_DIR_SEPARATOR (*s)) - *d++ = *s++; - } - - if (IS_DIR_SEPARATOR (*s)) - { - *d++ = *s++; - while (IS_DIR_SEPARATOR (*s)) - s++; - } - } - while (droot < d && IS_DIR_SEPARATOR (d[-1])) - --d; - if (d == rv) - *d++ = '.'; - *d = 0; - - return rv; -} - -static gboolean -handle_dwarf2_line (DebuginfoData *data, uint32_t off, char *comp_dir, GHashTable *files, GError **error) -{ - unsigned char *ptr = data->debug_sections[DEBUG_LINE].data, *dir; - unsigned char **dirt; - unsigned char *endsec = ptr + data->debug_sections[DEBUG_LINE].size; - unsigned char *endcu, *endprol; - unsigned char opcode_base; - uint32_t value, dirt_cnt; - size_t comp_dir_len = !comp_dir ? 0 : strlen (comp_dir); - - - /* XXX: RhBug:929365, should we error out instead of ignoring? */ - if (ptr == NULL) - return TRUE; - - ptr += off; - - endcu = ptr + 4; - endcu += read_32 (ptr); - if (endcu == ptr + 0xffffffff) - return flatpak_fail (error, "%s: 64-bit DWARF not supported", data->filename); - - if (endcu > endsec) - return flatpak_fail (error, "%s: .debug_line CU does not fit into section", data->filename); - - value = read_16 (ptr); - if (value != 2 && value != 3 && value != 4) - return flatpak_fail (error, "%s: DWARF version %d unhandled", data->filename, value); - - endprol = ptr + 4; - endprol += read_32 (ptr); - if (endprol > endcu) - return flatpak_fail (error, "%s: .debug_line CU prologue does not fit into CU", data->filename); - - opcode_base = ptr[4 + (value >= 4)]; - ptr = dir = ptr + 4 + (value >= 4) + opcode_base; - - /* dir table: */ - value = 1; - while (*ptr != 0) - { - ptr = (unsigned char *) strchr ((char *) ptr, 0) + 1; - ++value; - } - - dirt = (unsigned char **) alloca (value * sizeof (unsigned char *)); - dirt[0] = (unsigned char *) "."; - dirt_cnt = 1; - ptr = dir; - while (*ptr != 0) - { - dirt[dirt_cnt++] = ptr; - ptr = (unsigned char *) strchr ((char *) ptr, 0) + 1; - } - ptr++; - - /* file table: */ - while (*ptr != 0) - { - char *s, *file; - size_t file_len, dir_len; - - file = (char *) ptr; - ptr = (unsigned char *) strchr ((char *) ptr, 0) + 1; - value = read_uleb128 (ptr); - - if (value >= dirt_cnt) - return flatpak_fail (error, "%s: Wrong directory table index %u", data->filename, value); - - file_len = strlen (file); - dir_len = strlen ((char *) dirt[value]); - s = g_malloc (comp_dir_len + 1 + file_len + 1 + dir_len + 1); - if (*file == '/') - { - memcpy (s, file, file_len + 1); - } - else if (*dirt[value] == '/') - { - memcpy (s, dirt[value], dir_len); - s[dir_len] = '/'; - memcpy (s + dir_len + 1, file, file_len + 1); - } - else - { - char *p = s; - if (comp_dir_len != 0) - { - memcpy (s, comp_dir, comp_dir_len); - s[comp_dir_len] = '/'; - p += comp_dir_len + 1; - } - memcpy (p, dirt[value], dir_len); - p[dir_len] = '/'; - memcpy (p + dir_len + 1, file, file_len + 1); - } - canonicalize_path (s, s); - - g_hash_table_insert (files, s, NULL); - - (void) read_uleb128 (ptr); - (void) read_uleb128 (ptr); - } - ++ptr; - - return TRUE; -} - -static unsigned char * -handle_attributes (DebuginfoData *data, unsigned char *ptr, struct abbrev_tag *t, GHashTable *files, GError **error) -{ - int i; - uint32_t list_offs; - int found_list_offs; - g_autofree char *comp_dir = NULL; - - comp_dir = NULL; - list_offs = 0; - found_list_offs = 0; - for (i = 0; i < t->nattr; ++i) - { - uint32_t form = t->attr[i].form; - size_t len = 0; - - while (1) - { - if (t->attr[i].attr == DW_AT_stmt_list) - { - if (form == DW_FORM_data4 || - form == DW_FORM_sec_offset) - { - list_offs = do_read_32_relocated (ptr); - found_list_offs = 1; - } - } - - if (t->attr[i].attr == DW_AT_comp_dir) - { - if (form == DW_FORM_string) - { - g_free (comp_dir); - comp_dir = g_strdup ((char *) ptr); - } - else if (form == DW_FORM_strp && - data->debug_sections[DEBUG_STR].data) - { - char *dir; - - dir = (char *) data->debug_sections[DEBUG_STR].data - + do_read_32_relocated (ptr); - - g_free (comp_dir); - comp_dir = g_strdup (dir); - } - } - else if ((t->tag == DW_TAG_compile_unit || - t->tag == DW_TAG_partial_unit) && - t->attr[i].attr == DW_AT_name && - form == DW_FORM_strp && - data->debug_sections[DEBUG_STR].data) - { - char *name; - - name = (char *) data->debug_sections[DEBUG_STR].data - + do_read_32_relocated (ptr); - if (*name == '/' && comp_dir == NULL) - { - char *enddir = strrchr (name, '/'); - - if (enddir != name) - { - comp_dir = g_malloc (enddir - name + 1); - memcpy (comp_dir, name, enddir - name); - comp_dir[enddir - name] = '\0'; - } - else - { - comp_dir = g_strdup ("/"); - } - } - - } - - switch (form) - { - case DW_FORM_ref_addr: - if (cu_version == 2) - ptr += ptr_size; - else - ptr += 4; - break; - - case DW_FORM_flag_present: - break; - - case DW_FORM_addr: - ptr += ptr_size; - break; - - case DW_FORM_ref1: - case DW_FORM_flag: - case DW_FORM_data1: - ++ptr; - break; - - case DW_FORM_ref2: - case DW_FORM_data2: - ptr += 2; - break; - - case DW_FORM_ref4: - case DW_FORM_data4: - case DW_FORM_sec_offset: - ptr += 4; - break; - - case DW_FORM_ref8: - case DW_FORM_data8: - case DW_FORM_ref_sig8: - ptr += 8; - break; - - case DW_FORM_sdata: - case DW_FORM_ref_udata: - case DW_FORM_udata: - (void) read_uleb128 (ptr); - break; - - case DW_FORM_strp: - ptr += 4; - break; - - case DW_FORM_string: - ptr = (unsigned char *) strchr ((char *) ptr, '\0') + 1; - break; - - case DW_FORM_indirect: - form = read_uleb128 (ptr); - continue; - - case DW_FORM_block1: - len = *ptr++; - break; - - case DW_FORM_block2: - len = read_16 (ptr); - form = DW_FORM_block1; - break; - - case DW_FORM_block4: - len = read_32 (ptr); - form = DW_FORM_block1; - break; - - case DW_FORM_block: - case DW_FORM_exprloc: - len = read_uleb128 (ptr); - form = DW_FORM_block1; - g_assert (len < UINT_MAX); - break; - - default: - g_warning ("%s: Unknown DWARF DW_FORM_%d", data->filename, form); - return NULL; - } - - if (form == DW_FORM_block1) - ptr += len; - - break; - } - } - - /* Ensure the CU current directory will exist even if only empty. Source - filenames possibly located in its parent directories refer relatively to - it and the debugger (GDB) cannot safely optimize out the missing - CU current dir subdirectories. */ - if (comp_dir) - g_hash_table_insert (files, g_strdup (comp_dir), NULL); - - if (found_list_offs && - !handle_dwarf2_line (data, list_offs, comp_dir, files, error)) - return NULL; - - return ptr; -} - -static int -rel_cmp (const void *a, const void *b) -{ - REL *rela = (REL *) a, *relb = (REL *) b; - - if (rela->ptr < relb->ptr) - return -1; - - if (rela->ptr > relb->ptr) - return 1; - - return 0; -} - -static gboolean -handle_dwarf2_section (DebuginfoData *data, GHashTable *files, GError **error) -{ - Elf_Data *e_data; - int i; - debug_section_t *debug_sections; - - ptr_size = 0; - - if (data->ehdr.e_ident[EI_DATA] == ELFDATA2LSB) - { - do_read_16 = buf_read_ule16; - do_read_32 = buf_read_ule32; - } - else if (data->ehdr.e_ident[EI_DATA] == ELFDATA2MSB) - { - do_read_16 = buf_read_ube16; - do_read_32 = buf_read_ube32; - } - else - { - return flatpak_fail (error, "%s: Wrong ELF data encoding", data->filename); - } - - debug_sections = data->debug_sections; - - if (debug_sections[DEBUG_INFO].data != NULL) - { - unsigned char *ptr, *endcu, *endsec; - uint32_t value; - struct abbrev_tag *t; - g_autofree REL *relbuf = NULL; - - if (debug_sections[DEBUG_INFO].relsec) - { - Elf_Scn *scn; - int ndx, maxndx; - GElf_Rel rel; - GElf_Rela rela; - GElf_Sym sym; - GElf_Addr base = data->shdr[debug_sections[DEBUG_INFO].sec].sh_addr; - Elf_Data *symdata = NULL; - int rtype; - - i = debug_sections[DEBUG_INFO].relsec; - scn = data->scns[i]; - e_data = elf_getdata (scn, NULL); - g_assert (e_data != NULL && e_data->d_buf != NULL); - g_assert (elf_getdata (scn, e_data) == NULL); - g_assert (e_data->d_off == 0); - g_assert (e_data->d_size == data->shdr[i].sh_size); - maxndx = data->shdr[i].sh_size / data->shdr[i].sh_entsize; - relbuf = g_malloc (maxndx * sizeof (REL)); - reltype = data->shdr[i].sh_type; - - symdata = elf_getdata (data->scns[data->shdr[i].sh_link], NULL); - g_assert (symdata != NULL && symdata->d_buf != NULL); - g_assert (elf_getdata (data->scns[data->shdr[i].sh_link], symdata) == NULL); - g_assert (symdata->d_off == 0); - g_assert (symdata->d_size == data->shdr[data->shdr[i].sh_link].sh_size); - - for (ndx = 0, relend = relbuf; ndx < maxndx; ++ndx) - { - if (data->shdr[i].sh_type == SHT_REL) - { - gelf_getrel (e_data, ndx, &rel); - rela.r_offset = rel.r_offset; - rela.r_info = rel.r_info; - rela.r_addend = 0; - } - else - { - gelf_getrela (e_data, ndx, &rela); - } - gelf_getsym (symdata, ELF64_R_SYM (rela.r_info), &sym); - /* Relocations against section symbols are uninteresting - in REL. */ - if (data->shdr[i].sh_type == SHT_REL && sym.st_value == 0) - continue; - /* Only consider relocations against .debug_str, .debug_line - and .debug_abbrev. */ - if (sym.st_shndx != debug_sections[DEBUG_STR].sec && - sym.st_shndx != debug_sections[DEBUG_LINE].sec && - sym.st_shndx != debug_sections[DEBUG_ABBREV].sec) - continue; - rela.r_addend += sym.st_value; - rtype = ELF64_R_TYPE (rela.r_info); - switch (data->ehdr.e_machine) - { - case EM_SPARC: - case EM_SPARC32PLUS: - case EM_SPARCV9: - if (rtype != R_SPARC_32 && rtype != R_SPARC_UA32) - goto fail; - break; - - case EM_386: - if (rtype != R_386_32) - goto fail; - break; - - case EM_PPC: - case EM_PPC64: - if (rtype != R_PPC_ADDR32 && rtype != R_PPC_UADDR32) - goto fail; - break; - - case EM_S390: - if (rtype != R_390_32) - goto fail; - break; - - case EM_IA_64: - if (rtype != R_IA64_SECREL32LSB) - goto fail; - break; - - case EM_X86_64: - if (rtype != R_X86_64_32) - goto fail; - break; - - case EM_ALPHA: - if (rtype != R_ALPHA_REFLONG) - goto fail; - break; - -#if defined(EM_AARCH64) && defined(R_AARCH64_ABS32) - case EM_AARCH64: - if (rtype != R_AARCH64_ABS32) - goto fail; - break; - -#endif - case EM_68K: - if (rtype != R_68K_32) - goto fail; - break; - - default: -fail: - return flatpak_fail (error, "%s: Unhandled relocation %d in .debug_info section", - data->filename, rtype); - } - relend->ptr = debug_sections[DEBUG_INFO].data - + (rela.r_offset - base); - relend->addend = rela.r_addend; - ++relend; - } - if (relbuf == relend) - { - g_free (relbuf); - relbuf = NULL; - relend = NULL; - } - else - { - qsort (relbuf, relend - relbuf, sizeof (REL), rel_cmp); - } - } - - ptr = debug_sections[DEBUG_INFO].data; - relptr = relbuf; - endsec = ptr + debug_sections[DEBUG_INFO].size; - while (ptr != NULL && ptr < endsec) - { - g_autoptr(GHashTable) abbrev = NULL; - - if (ptr + 11 > endsec) - return flatpak_fail (error, "%s: .debug_info CU header too small", data->filename); - - endcu = ptr + 4; - endcu += read_32 (ptr); - if (endcu == ptr + 0xffffffff) - return flatpak_fail (error, "%s: 64-bit DWARF not supported", data->filename); - - if (endcu > endsec) - return flatpak_fail (error, "%s: .debug_info too small", data->filename); - - cu_version = read_16 (ptr); - if (cu_version != 2 && cu_version != 3 && cu_version != 4) - return flatpak_fail (error, "%s: DWARF version %d unhandled", data->filename, cu_version); - - value = read_32_relocated (ptr); - if (value >= debug_sections[DEBUG_ABBREV].size) - { - if (debug_sections[DEBUG_ABBREV].data == NULL) - return flatpak_fail (error, "%s: .debug_abbrev not present", data->filename); - else - return flatpak_fail (error, "%s: DWARF CU abbrev offset too large", data->filename); - } - - if (ptr_size == 0) - { - ptr_size = read_1 (ptr); - if (ptr_size != 4 && ptr_size != 8) - return flatpak_fail (error, "%s: Invalid DWARF pointer size %d", data->filename, ptr_size); - } - else if (read_1 (ptr) != ptr_size) - { - return flatpak_fail (error, "%s: DWARF pointer size differs between CUs", data->filename); - } - - abbrev = read_abbrev (data, - debug_sections[DEBUG_ABBREV].data + value); - - while (ptr < endcu) - { - guint entry = read_uleb128 (ptr); - if (entry == 0) - continue; - t = g_hash_table_lookup (abbrev, GINT_TO_POINTER (entry)); - if (t == NULL) - { - g_warning ("%s: Could not find DWARF abbreviation %d", data->filename, entry); - } - else - { - ptr = handle_attributes (data, ptr, t, files, error); - if (ptr == NULL) - return FALSE; - } - } - } - } - - return TRUE; -} - -static const char * -strptr (Elf_Scn **scns, GElf_Shdr *shdr, int sec, off_t offset) -{ - Elf_Scn *scn; - Elf_Data *data; - - scn = scns[sec]; - if (offset >= 0 && (GElf_Addr) offset < shdr[sec].sh_size) - { - data = NULL; - while ((data = elf_rawdata (scn, data)) != NULL) - { - if (data->d_buf && - offset >= data->d_off && - offset < data->d_off + data->d_size) - return (const char *) data->d_buf + (offset - data->d_off); - } - } - - return NULL; -} - -char ** -builder_get_debuginfo_file_references (const char *filename, GError **error) -{ - Elf *elf = NULL; - GElf_Ehdr ehdr; - int i, j; - glnx_fd_close int fd = -1; - DebuginfoData data = { 0 }; - g_autofree GElf_Shdr *shdr = NULL; - g_autofree Elf_Scn **scns = NULL; - debug_section_t *debug_sections; - - g_autoptr(GHashTable) files = NULL; - char **res; - - fd = open (filename, O_RDONLY); - if (fd == -1) - { - glnx_set_error_from_errno (error); - return NULL; - } - - elf = elf_begin (fd, ELF_C_RDWR_MMAP, NULL); - if (elf == NULL) - { - flatpak_fail (error, "cannot open ELF file: %s", elf_errmsg (-1)); - return NULL; - } - - if (elf_kind (elf) != ELF_K_ELF) - { - flatpak_fail (error, "\"%s\" is not an ELF file", filename); - return NULL; - } - - if (gelf_getehdr (elf, &ehdr) == NULL) - { - flatpak_fail (error, "cannot get the ELF header: %s", elf_errmsg (-1)); - return NULL; - } - - if (ehdr.e_type != ET_DYN && ehdr.e_type != ET_EXEC && ehdr.e_type != ET_REL) - { - flatpak_fail (error, "\"%s\" is not a shared library", filename); - return NULL; - } - - elf_flagelf (elf, ELF_C_SET, ELF_F_LAYOUT); - - shdr = g_new0 (GElf_Shdr, ehdr.e_shnum); - scns = g_new0 (Elf_Scn *, ehdr.e_shnum); - - for (i = 0; i < ehdr.e_shnum; ++i) - { - scns[i] = elf_getscn (elf, i); - gelf_getshdr (scns[i], &shdr[i]); - } - - data.elf = elf; - data.ehdr = ehdr; - data.shdr = shdr; - data.scns = scns; - data.filename = filename; - - /* Locate all debug sections */ - debug_sections = data.debug_sections; - for (i = 1; i < ehdr.e_shnum; ++i) - { - if (!(shdr[i].sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR)) && shdr[i].sh_size) - { - const char *name = strptr (scns, shdr, ehdr.e_shstrndx, shdr[i].sh_name); - - if (g_str_has_prefix (name, ".debug_")) - { - for (j = 0; j < NUM_DEBUG_SECTIONS; ++j) - { - if (strcmp (name, debug_section_names[j]) == 0) - { - Elf_Scn *scn = scns[i]; - Elf_Data *e_data; - - if (debug_sections[j].data) - g_warning ("%s: Found two copies of %s section", filename, name); - - e_data = elf_rawdata (scn, NULL); - g_assert (e_data != NULL && e_data->d_buf != NULL); - g_assert (elf_rawdata (scn, e_data) == NULL); - g_assert (e_data->d_off == 0); - g_assert (e_data->d_size == shdr[i].sh_size); - debug_sections[j].data = e_data->d_buf; - debug_sections[j].elf_data = e_data; - debug_sections[j].size = e_data->d_size; - debug_sections[j].sec = i; - break; - } - } - - if (j == NUM_DEBUG_SECTIONS) - g_warning ("%s: Unknown debugging section %s", filename, name); - } - else if (ehdr.e_type == ET_REL && - ((shdr[i].sh_type == SHT_REL && g_str_has_prefix (name, ".rel.debug_")) || - (shdr[i].sh_type == SHT_RELA && g_str_has_prefix (name, ".rela.debug_")))) - { - for (j = 0; j < NUM_DEBUG_SECTIONS; ++j) - if (strcmp (name + sizeof (".rel") - 1 - + (shdr[i].sh_type == SHT_RELA), - debug_section_names[j]) == 0) - { - debug_sections[j].relsec = i; - break; - } - } - } - } - - files = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - if (!handle_dwarf2_section (&data, files, error)) - return NULL; - - if (elf_end (elf) < 0) - g_warning ("elf_end failed: %s", elf_errmsg (elf_errno ())); - - res = (char **) g_hash_table_get_keys_as_array (files, NULL); - g_hash_table_steal_all (files); - return res; -} - -typedef struct { - GDBusConnection *connection; - GMainLoop *loop; - GError *splice_error; - guint32 client_pid; - guint32 exit_status; - int refs; -} HostCommandCallData; - -static void -host_command_call_exit (HostCommandCallData *data) -{ - data->refs--; - if (data->refs == 0) - g_main_loop_quit (data->loop); -} - -static void -output_spliced_cb (GObject *obj, - GAsyncResult *result, - gpointer user_data) -{ - HostCommandCallData *data = user_data; - - g_output_stream_splice_finish (G_OUTPUT_STREAM (obj), result, &data->splice_error); - host_command_call_exit (data); -} - -static void -host_command_exited_cb (GDBusConnection *connection, - const gchar *sender_name, - const gchar *object_path, - const gchar *interface_name, - const gchar *signal_name, - GVariant *parameters, - gpointer user_data) -{ - guint32 client_pid, exit_status; - HostCommandCallData *data = (HostCommandCallData *)user_data; - - if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(uu)"))) - return; - - g_variant_get (parameters, "(uu)", &client_pid, &exit_status); - - if (client_pid == data->client_pid) - { - g_print ("host_command_exited_cb %d %d\n", client_pid, exit_status); - data->exit_status = exit_status; - host_command_call_exit (data); - } -} - -static gboolean -sigterm_handler (gpointer user_data) -{ - HostCommandCallData *data = (HostCommandCallData *)user_data; - - g_dbus_connection_call_sync (data->connection, - "org.freedesktop.Flatpak", - "/org/freedesktop/Flatpak/Development", - "org.freedesktop.Flatpak.Development", - "HostCommandSignal", - g_variant_new ("(uub)", data->client_pid, SIGTERM, TRUE), - NULL, - G_DBUS_CALL_FLAGS_NONE, -1, - NULL, NULL); - - kill (getpid (), SIGTERM); - return TRUE; -} - -static gboolean -sigint_handler (gpointer user_data) -{ - HostCommandCallData *data = (HostCommandCallData *)user_data; - - g_dbus_connection_call_sync (data->connection, - "org.freedesktop.Flatpak", - "/org/freedesktop/Flatpak/Development", - "org.freedesktop.Flatpak.Development", - "HostCommandSignal", - g_variant_new ("(uub)", data->client_pid, SIGINT, TRUE), - NULL, - G_DBUS_CALL_FLAGS_NONE, -1, - NULL, NULL); - - kill (getpid (), SIGTERM); - return TRUE; -} - -gboolean -builder_host_spawnv (GFile *dir, - char **output, - GError **error, - const gchar * const *argv) -{ - guint32 client_pid; - GVariantBuilder *fd_builder = g_variant_builder_new (G_VARIANT_TYPE("a{uh}")); - GVariantBuilder *env_builder = g_variant_builder_new (G_VARIANT_TYPE("a{ss}")); - g_autoptr(GUnixFDList) fd_list = g_unix_fd_list_new (); - gint stdout_handle, stdin_handle, stderr_handle; - g_autoptr(GDBusConnection) connection = NULL; - g_autoptr(GVariant) ret = NULL; - g_autoptr(GMainLoop) loop = NULL; - g_auto(GStrv) env_vars = NULL; - guint subscription; - HostCommandCallData data = { NULL }; - guint sigterm_id = 0, sigint_id = 0; - g_autofree gchar *commandline = NULL; - g_autoptr(GOutputStream) out = NULL; - int pipefd[2]; - int i; - - commandline = flatpak_quote_argv ((const char **) argv); - g_debug ("Running '%s' on host", commandline); - - connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error); - if (connection == NULL) - return FALSE; - - loop = g_main_loop_new (NULL, FALSE); - data.connection = connection; - data.loop = loop; - data.refs = 1; - - subscription = g_dbus_connection_signal_subscribe (connection, - NULL, - "org.freedesktop.Flatpak.Development", - "HostCommandExited", - "/org/freedesktop/Flatpak/Development", - NULL, - G_DBUS_SIGNAL_FLAGS_NONE, - host_command_exited_cb, - &data, NULL); - - stdin_handle = g_unix_fd_list_append (fd_list, 0, error); - if (stdin_handle == -1) - return FALSE; - - if (output) - { - g_autoptr(GInputStream) in = NULL; - - if (pipe2 (pipefd, O_CLOEXEC) != 0) - { - glnx_set_error_from_errno (error); - return FALSE; - } - - data.refs++; - in = g_unix_input_stream_new (pipefd[0], TRUE); - out = g_memory_output_stream_new_resizable (); - g_output_stream_splice_async (out, - in, - G_OUTPUT_STREAM_SPLICE_NONE, - 0, - NULL, - output_spliced_cb, - &data); - stdout_handle = g_unix_fd_list_append (fd_list, pipefd[1], error); - close (pipefd[1]); - if (stdout_handle == -1) - return FALSE; - } - else - { - stdout_handle = g_unix_fd_list_append (fd_list, 1, error); - if (stdout_handle == -1) - return FALSE; - } - - stderr_handle = g_unix_fd_list_append (fd_list, 2, error); - if (stderr_handle == -1) - return FALSE; - - g_variant_builder_add (fd_builder, "{uh}", 0, stdin_handle); - g_variant_builder_add (fd_builder, "{uh}", 1, stdout_handle); - g_variant_builder_add (fd_builder, "{uh}", 2, stderr_handle); - - env_vars = g_listenv (); - for (i = 0; env_vars[i] != NULL; i++) - { - const char *env_var = env_vars[i]; - g_variant_builder_add (env_builder, "{ss}", env_var, g_getenv (env_var)); - } - - sigterm_id = g_unix_signal_add (SIGTERM, sigterm_handler, &data); - sigint_id = g_unix_signal_add (SIGINT, sigint_handler, &data); - - ret = g_dbus_connection_call_with_unix_fd_list_sync (connection, - "org.freedesktop.Flatpak", - "/org/freedesktop/Flatpak/Development", - "org.freedesktop.Flatpak.Development", - "HostCommand", - g_variant_new ("(^ay^aay@a{uh}@a{ss}u)", - dir ? flatpak_file_get_path_cached (dir) : "", - argv, - g_variant_builder_end (fd_builder), - g_variant_builder_end (env_builder), - FLATPAK_HOST_COMMAND_FLAGS_CLEAR_ENV), - G_VARIANT_TYPE ("(u)"), - G_DBUS_CALL_FLAGS_NONE, -1, - fd_list, NULL, - NULL, error); - - if (ret == NULL) - return FALSE; - - - g_variant_get (ret, "(u)", &client_pid); - data.client_pid = client_pid; - - g_main_loop_run (loop); - - g_source_remove (sigterm_id); - g_source_remove (sigint_id); - g_dbus_connection_signal_unsubscribe (connection, subscription); - - if (!g_spawn_check_exit_status (data.exit_status, error)) - return FALSE; - - if (out) - { - if (data.splice_error) - { - g_propagate_error (error, data.splice_error); - return FALSE; - } - - /* Null terminate */ - g_output_stream_write (out, "\0", 1, NULL, NULL); - g_output_stream_close (out, NULL, NULL); - *output = g_memory_output_stream_steal_data (G_MEMORY_OUTPUT_STREAM (out)); - } - - return TRUE; -} - -/* Similar to flatpak_spawnv, except uses the session helper HostCommand operation - if in a sandbox */ -gboolean -builder_maybe_host_spawnv (GFile *dir, - char **output, - GError **error, - const gchar * const *argv) -{ - if (flatpak_is_in_sandbox ()) - return builder_host_spawnv (dir, output, error, argv); - - return flatpak_spawnv (dir, output, 0, error, argv); -} - -typedef struct { - int stage; - gboolean printed_something; -} DownloadPromptData; - -static void -download_progress (guint64 downloaded_bytes, - gpointer user_data) -{ - DownloadPromptData *progress_data = user_data; - char chrs[] = { '|', '/', '-', '\\' }; - - if (progress_data->printed_something) - g_print ("\b"); - progress_data->printed_something = TRUE; - g_print ("%c", chrs[progress_data->stage]); - progress_data->stage = (progress_data->stage + 1) % G_N_ELEMENTS(chrs); -} - -static void -download_progress_cleanup (DownloadPromptData *progress_data) -{ - if (progress_data->printed_something) - g_print ("\b"); -} - -gboolean -builder_download_uri (SoupURI *uri, - GFile *dest, - char *sha256, - SoupSession *session, - GError **error) -{ - g_autoptr(SoupRequest) req = NULL; - g_autoptr(GInputStream) input = NULL; - g_autoptr(GFileOutputStream) out = NULL; - g_autoptr(GFile) tmp = NULL; - g_autoptr(GFile) dir = NULL; - g_autoptr(GChecksum) checksum = g_checksum_new (G_CHECKSUM_SHA256); - DownloadPromptData progress_data = {0}; - g_autofree char *basename = g_file_get_basename (dest); - g_autofree char *template = g_strconcat (".", basename, "XXXXXX", NULL); - - dir = g_file_get_parent (dest); - g_mkdir_with_parents (flatpak_file_get_path_cached (dir), 0755); - - tmp = flatpak_file_new_tmp_in (dir, template, error); - if (tmp == NULL) - return FALSE; - - out = g_file_replace (tmp, NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION, - NULL, error); - if (out == NULL) - return FALSE; - - req = soup_session_request_uri (session, uri, error); - if (req == NULL) - return FALSE; - - input = soup_request_send (req, NULL, error); - if (input == NULL) - return FALSE; - - if (SOUP_IS_REQUEST_HTTP (req)) - { - g_autoptr(SoupMessage) msg = soup_request_http_get_message (SOUP_REQUEST_HTTP(req)); - if (!SOUP_STATUS_IS_SUCCESSFUL(msg->status_code)) - { - g_set_error_literal (error, SOUP_HTTP_ERROR, msg->status_code, msg->reason_phrase); - return FALSE; - } - } - - if (!flatpak_splice_update_checksum (G_OUTPUT_STREAM (out), input, checksum, download_progress, &progress_data, NULL, error)) - { - unlink (flatpak_file_get_path_cached (tmp)); - return FALSE; - } - - /* Manually close to flush and detect write errors */ - if (!g_output_stream_close (G_OUTPUT_STREAM (out), NULL, error)) - { - unlink (flatpak_file_get_path_cached (tmp)); - return FALSE; - } - - download_progress_cleanup (&progress_data); - - if (sha256 != NULL && strcmp (g_checksum_get_string (checksum), sha256) != 0) - { - unlink (flatpak_file_get_path_cached (tmp)); - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Wrong sha256 for %s, expected %s, was %s", basename, sha256, g_checksum_get_string (checksum)); - return FALSE; - } - - if (rename (flatpak_file_get_path_cached (tmp), flatpak_file_get_path_cached (dest)) != 0) - { - glnx_set_error_from_errno (error); - return FALSE; - } - - return TRUE; -} - -GParamSpec * -builder_serializable_find_property_with_error (JsonSerializable *serializable, - const char *name) -{ - GParamSpec *pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (serializable), name); - if (pspec == NULL && - !g_str_has_prefix (name, "x-")) - g_warning ("Unknown property %s for type %s", name, g_type_name_from_instance ((GTypeInstance *)serializable)); - return pspec; -} - -void -builder_set_term_title (const gchar *format, - ...) -{ - g_autofree gchar *message = NULL; - va_list args; - - if (isatty (STDOUT_FILENO) != 1) - return; - - va_start (args, format); - message = g_strdup_vprintf (format, args); - va_end (args); - - g_print ("\033]2;flatpak-builder: %s\007", message); -} diff --git a/builder/builder-utils.h b/builder/builder-utils.h deleted file mode 100644 index 48120f3a..00000000 --- a/builder/builder-utils.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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.1 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_UTILS_H__ -#define __BUILDER_UTILS_H__ - -#include -#include -#include - -G_BEGIN_DECLS - -typedef struct BuilderUtils BuilderUtils; - -char *builder_uri_to_filename (const char *uri); - -gboolean strip (GError **error, - ...); -gboolean eu_strip (GError **error, - ...); - -gboolean is_elf_file (const char *path, - gboolean *is_shared, - gboolean *is_stripped); - -char ** builder_get_debuginfo_file_references (const char *filename, - GError **error); - -gboolean directory_is_empty (const char *path); - -gboolean flatpak_matches_path_pattern (const char *path, - const char *pattern); -void flatpak_collect_matches_for_path_pattern (const char *path, - const char *pattern, - const char *add_prefix, - GHashTable *to_remove_ht); -gboolean builder_migrate_locale_dirs (GFile *root_dir, - GError **error); - -gboolean builder_host_spawnv (GFile *dir, - char **output, - GError **error, - const gchar * const *argv); -gboolean builder_maybe_host_spawnv (GFile *dir, - char **output, - GError **error, - const gchar * const *argv); - -gboolean builder_download_uri (SoupURI *uri, - GFile *dest, - char *sha256, - SoupSession *soup_session, - GError **error); - -GParamSpec * builder_serializable_find_property_with_error (JsonSerializable *serializable, - const char *name); - -void builder_set_term_title (const gchar *format, - ...) G_GNUC_PRINTF (1, 2); - -G_END_DECLS - -#endif /* __BUILDER_UTILS_H__ */ diff --git a/doc/Makefile.am b/doc/Makefile.am index 715b8c2b..f9b7a674 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -47,11 +47,9 @@ man1 = \ flatpak-build-sign.1 \ flatpak-build-commit-from.1 \ flatpak-repo.1 \ - flatpak-builder.1 \ $(NULL) man5 = \ - flatpak-manifest.5 \ flatpak-metadata.5 \ flatpak-flatpakrepo.5 \ flatpak-flatpakref.5 \ diff --git a/doc/flatpak-builder.xml b/doc/flatpak-builder.xml deleted file mode 100644 index d01b9d81..00000000 --- a/doc/flatpak-builder.xml +++ /dev/null @@ -1,632 +0,0 @@ - - - - - - - flatpak builder - flatpak - - - - Developer - Alexander - Larsson - alexl@redhat.com - - - - - - flatpak-builder - 1 - - - - flatpak-builder - Help build application dependencies - - - - - flatpak-builder - OPTION - DIRECTORY - MANIFEST - - - flatpak-builder - --run - OPTION - DIRECTORY - MANIFEST - COMMAND - - - flatpak-builder - --show-deps - OPTION - MANIFEST - - - - - Description - - - flatpak-builder is a wrapper around the flatpak build command - that automates the building of applications and their dependencies. It is one option you can use - to build applications. - - - The goal of flatpak-builder is to push as much knowledge about how to build modules to - the individual upstream projects. It does this by assuming that the modules adhere to the Build API specified - at https://github.com/cgwalters/build-api. This essentially means that it follows the ./configure - && make && make install scheme with an optional autogen script. If the upstream - does not adhere to the API you can make it do so by adding patches and extra files. - - - An invocation of flatpak-builder proceeds in these stages, each being specified - in detail in json format in MANIFEST: - - - Download all sources - - - Initialize the application directory with flatpak build-init - - - Build and install each module with flatpak build - - - Clean up the final build tree by removing unwanted files and e.g. stripping binaries - - - Finish the application directory with flatpak build-finish - - - - After this you will end up with a build of the application in DIRECTORY, which you can - export to a repository with the flatpak build-export command. If you use the - option, flatpak-builder will do the export for you at the end of the build process. When flatpak-builder does the - export, it also stores the manifest that was used for the build in /app/manifest.json. The manifest is 'resolved', - i.e. git branch names are replaced by the actual commit IDs that were used in the build. - - - At each of the above steps flatpak caches the result, and if you build the same file again, it will start - at the first step where something changes. For instance the first version controlled source that had - new commits added, or the first module where some changes to the MANIFEST file caused - the build environment to change. This makes flatpak-builder very efficient for incremental builds. - - - - - - Manifest - - The manifest file is a json file whose format is described in detail in its own manual page. - - - - Options - - The following options are understood: - - - - - - - - Show help options and exit. - - - - - - - - - Print debug information during command processing. - - - - - - - - Print version information and exit. - - - - - - - - Specify the machine architecture to build for. If no architecture is specified, the host architecture will be automatically detected. Only host compatible architectures can be specified. - - - - - - - - Don't look at the existing cache for a previous build, instead always rebuild modules. - - - - - - - - Disable the use of rofiles-fuse to optimize the cache use via hardlink checkouts. - - - - - - - - Don't download any sources. This only works if some version of all sources are downloaded - already. This is useful if you want to guarantee that no network i/o is done. However, the - build will fail if some source is not locally available. - - - - - - - - Download missing sources, but don't update local mirrors of version control repos. This is useful - to rebuild things but without updating git or bzr repositories from the remote repository. - - - - - - - - Run a command in a sandbox based on the build dir. This starts flatpak build, with some extra - arguments to give the same environment as the build, and the same permissions the final app - will have. The command to run must be the last argument passed to - flatpak-builder, after the directory and the manifest. - - - - - - - - Extract and prepare the sources for the named module, and then start - a shell in a sandbox identical to the one flatpak-builder would use for buildng the module. - This is useful to debug a module. - - - - - - - - List all the (local) files that the manifest depends on. - - - - - - - - Exit successfully after downloading the required sources. - - - - - - - - Don't do the cleanup and finish stages, which is useful if you - want to build more things into the app. - - - - - - - - Only do the cleanup, finish and export stages, picking up - where a --build-only command left off. - - - - - - - - Only do the export stages, picking up the build result from a previous build. - This can be used to split the build and export/signature into two calls - by leaving out --repo in the first call. - - - - - - - - Do nothing, leaving a non-existent DIRECTORY if nothing changes since - last cached build. If this is not specified, the latest version from the cache will be put - into DIRECTORY. - - - - - - - - Don't remove the sources and build after having built and installed each module. - This also creates a symlink to the build directory with a stable name ("build-modulename"). - - - - - - - - Always remove the sources and build after having built each module, even if the build - failed. The default is to keep failed build directories but remote successful ones. - This is useful in e.g. automatic build systems. - - - - - - - - Enable use of ccache in the build (needs ccache in the sdk) - - - - - - - - Stop at the specified module, ignoring it and all the following ones - in both the "download" and "build" phases. This is useful for debugging - and development. For instance, you can build all the dependencies, but - stop at the main application so that you can then do a build from a - pre-existing checkout. Implies --build-only. - - - - - - - - When build is done, run export the result to this repository. - - - - - - - - - One line subject for the commit message. - Used when exporting the build results. - - - - - - - - - Full description for the commit message. - Used when exporting the build results. - - - - - - - - - - Sign the commit with this GPG key. - Used when exporting the build results. - This option can be used multiple times. - - - - - - - - GPG Homedir to use when looking for keyrings. - Used when exporting the build results. - - - - - - - - Limit the number of parallel jobs during the build. - The default is the number of CPUs on the machine. - - - - - - - - Erase the previous contents of DIRECTORY if it is - not empty. - - - - - - - - Disable the possibility to specify build-args that - are passed to flatpak build. This means the build - process can't break out of its sandbox, and is - useful when building less trusted software. - - - - - - - - Do not immediately fail if the sdk or platform runtimes - are not installed on this system. Attempting to build any - manifest modules will still fail if the sdk is missing, but - may be useful for apps that install files without a sandbox - build. - - - - - - - - Record the exact version of the sdk in the cache, and rebuild everything - if it changes. This is useful if you're building against an API-unstable - runtime, like a nightly build. - - - - - - - - If the json is unchanged since the last build of this filename, then - do nothing, and return exit code 42. - - - - - - - - Mirror any screenshots in the appstream and rewrite the appstream xml - as if they were on the specified URL. The resulting files will - be stored in the "screenshots" subdirectory in the app directory - and needs to be copied to the specified URL for the appdata to work. - - - - - - - - When downloading sources (archives, files, git, bzr), look in this - directory for pre-existing copies and use them instead of downloading. - - - - - - - - When downloading sources (archives, files, git, bzr), look at this url - for mirrored downloads before downloading from the original url. - - - - - - - - Look for the manifest in the given git repository. If this option is - given, MANIFEST is interpreted as a relative path inside the repository. - - - - - - - - The branch to use with --from-git. - - - - - - - - Install/update build required dependencies from the specified remote. - - - - - - - - Stop after downloading dependencies. - - - - - - - - Install the dependencies in a per-user installation. - - - - - - - - Install the dependenceis in the default system-wide installation. - - - - - - - - Install the dependencies in a system-wide installation - specified by NAME among those defined in - /etc/flatpak/installations.d/. Using - --installation=default is equivalent to using - --system. - - - - - - - - Caching - - - flatpak-builder caches sources and partial build results in - the .flatpak-builder subdirectory of the current directory. If you - use , build directories for each - module are also stored here. - - - - It is safe to remove the contents of the .flatpak-builder - directory. This will force a full build the next time you build. - - - - - - Examples - - - $ flatpak-builder my-app-dir manifest.json - - - - Example manifest file: - - -{ - "id": "org.test.TestApp", - "runtime": "org.freedesktop.Platform", - "runtime-version": "1.2", - "sdk": "org.freedesktop.Sdk", - "command": "test", - "clean": [ "/include", "*.la" ], - "build-options" : { - "cflags": "-O2 -g", - "cxxflags": "-O2 -g", - "env": { - "V": "1" - }, - "arch": { - "x86_64": { - "cflags": "-O3 -g", - } - } - }, - "modules": [ - { - "name": "pygobject", - "config-opts": [ "--disable-introspection" ], - "sources": [ - { - "type": "archive", - "url": "http://ftp.gnome.org/pub/GNOME/sources/pygobject/2.28/pygobject-2.28.6.tar.xz", - "sha256": "fb8a1d4f665130a125011659bd347c7339c944232163dbb9a34fd0686577adb8" - }, - { - "type": "patch", - "path": "required-pygobject-fix.patch" - }, - { - "type": "file", - "path": "pygobject-extra-file", - "dest-filename": "extra-file" - } - ] - }, - { - "name": "babl", - "build-options" : { "cxxflags": "-O2 -g -std=c++11" }, - "cleanup": [ "/bin" ], - "sources": [ - { - "type": "git", - "url": "git://git.gnome.org/babl" - } - ] - }, - { - "name": "testapp", - "sources": [ - { - "type": "bzr", - "url": "lp:testapp" - } - ] - } - ] -} - - - - - - See also - - - flatpak1, - flatpak-manifest5 - flatpak-build-init1, - flatpak-build1, - flatpak-build-finish1, - flatpak-build-export1 - - - - - diff --git a/doc/flatpak-docs.xml.in b/doc/flatpak-docs.xml.in index bffc955f..c01065d5 100644 --- a/doc/flatpak-docs.xml.in +++ b/doc/flatpak-docs.xml.in @@ -16,7 +16,6 @@ Executables - Commands @@ -53,7 +52,6 @@ - diff --git a/doc/flatpak-manifest.xml b/doc/flatpak-manifest.xml deleted file mode 100644 index 8c189fb4..00000000 --- a/doc/flatpak-manifest.xml +++ /dev/null @@ -1,710 +0,0 @@ - - - - - - - flatpak manifest - flatpak - - - - Developer - Alexander - Larsson - alexl@redhat.com - - - - - - flatpak manifest - 5 - - - - flatpak-manifest - Information for building an application - - - - Description - - - Flatpak uses manifest, or recipe, files in a json format to describe how an - application and its bundled dependencies can be built from sources. The manifest - gets used by flatpak-builder. - - - - - File format - - - The top level of the json file describes global attributes of the application, how - it can be built, and the list of modules that need to be built. - - - - Toplevel properties - - These are the properties that are accepted: - - - - or (string) - A string defining the application id. - - - (string) - The branch of the application, defaults to master. - - - - (string) - The name of the runtime that the application uses. - - - (string) - The version of the runtime that the application uses, defaults to master. - - - (string) - The name of the development runtime that the application builds with. - - - (string) - Initialize the (otherwise empty) writable /var in the build with a copy of this runtime. - - - (string) - Use this file as the base metadata file when finishing. - - - (string) - The filename or path to the main binary of the application. Note that this is really just a single file, not a commandline. If you want to pass arguments, install a shell script wrapper and use that as the command. - - - (boolean) - Build a new runtime instead of an application. - - - (boolean) - Build an extension. - - - (boolean) - Separate out locale files and translations to an extension runtime. Defaults to true. - - - (string) - When building a runtime sdk, also create a platform based on it with this id. - - - (string) - The metadata file to use for the platform we create. - - - (boolean) - If true, use a writable copy of the sdk for /usr. - Defaults to true if build-runtime is specified. - - - (boolean) - Run appstream-compose during cleanup phase. Defaults to true. - - - (array of strings) - Install these extra sdk extensions in /usr. - - - (array of strings) - Install these extra sdk extensions when creating the platform. - - - - (string) - Start with the files from the specified application. This can be - used to create applications that extend another application. - - - (string) - Use this specific version of the application specified in base. - If unspecified, this uses the value specified in branch - - - (array of strings) - Install these extra extensions from the base application when initializing - the application directory. - - - (array of strings) - Inherit these extra extensions points from the base application or sdk when - finishing the build. - - - - (array of strings) - Add these tags to the metadata file. - - - (object) - Object specifying the build environment. See below for details. - - - (array of objects or string) - An array of objects specifying the modules to be built in order. - String members in the array are interpreted as the name of a separate json file that contains a module. - See below for details. - - - (objects) - This is a dictionary of extension objects. The key is the name of the extension. See below for details. - - - (array of strings) - An array of file patterns that should be removed at the end. - Patterns starting with / are taken to be full pathnames (without the /app prefix), otherwise they just match - the basename. - - - (array of strings) - An array of commandlines that are run during the cleanup phase. - - - (array of strings) - Extra files to clean up in the platform. - - - (array of strings) - An array of commandlines that are run during the cleanup phase of the platform. - - - (array of strings) - An array of arguments passed to the flatpak build-finish command. - - - (string) - Any desktop file with this name will be renamed to a name based on id during the cleanup phase. - - - (string) - Any appdata file with this name will be renamed to a name based on id during the cleanup phase. - - - (string) - Any icon with this name will be renamed to a name based on id during the cleanup phase. Note that this is the icon name, not the full filenames, so it should not include a filename extension. - - - (boolean) - If rename-icon is set, keep a copy of the old icon file. - - - (string) - This string will be prefixed to the Name key in the main application desktop file. - - - (string) - This string will be suffixed to the Name key in the main application desktop file. - - - - - - Build Options - - Build options specify the build environment of a module, and can be specified globally as - well as per-module. Options can also be specified on a per-architecture basis using the arch property. - - - These are the properties that are accepted: - - - - (string) - This is set in the environment variable CFLAGS during the build. Multiple specifications of this (in e.g. per-arch area) are concatinated with spaces inbetween. - - - (string) - This is set in the environment variable CPPFLAGS during the build. Multiple specifications of this (in e.g. per-arch area) are concatinated with spaces inbetween. - - - (string) - This is set in the environment variable CXXFLAGS during the build. Multiple specifications of this (in e.g. per-arch area) are concatinated with spaces inbetween. - - - (string) - This is set in the environment variable LDFLAGS during the build. Multiple specifications of this (in e.g. per-arch area) are concatinated with spaces inbetween. - - - (string) - The build prefix for the modules (defaults to /app for - applications and /usr for runtimes). - - - (object) - This is a dictionary defining environment variables to be set during the build. Elements in this override the properties that set the environment, like cflags and ldflags. - - - (array of strings) - This is an array containing extra options to pass to flatpak build. - - - (array of strings) - This is an array containing extra options to pass to configure. - - - (boolean) - If this is true (the default is false) then all ELF files will be stripped after install. - - - (boolean) - By default (if strip is not true) flatpak-builder extracts all debug info in ELF files to a separate files - and puts this in an extension. If you want to disable this, set no-debuginfo to true. - - - (object) - This is a dictionary defining for each arch a separate build options object that override the main one. - - - - - Extension - - Extension define extension points in the app/runtime that can be implemented by extensions, supplying extra files - which are available during runtime.. - - - These are the properties that are accepted: - - - - (string) - The directory where the extension is mounted. - - - (boolean) - If this is true, then the data - created in the extension directory is omitted from - the result, and instead packaged in a separate - extension.. - - - - Additionally the standard flatpak extension properies - are supported, and put directly into the metadata file: - autodelete, no-autodownload, subdirectories, - add-ld-path, download-if, enable-if, merge-dirs, - subdirectory-suffix, version, versions. - - - - Module - - Each module specifies a source that has to be separately built and installed. It contains - the build options and a list of sources to download and extract before building. - - - Modules can be nested, in order to turn related modules on and off with a single key. - - - These are the properties that are accepted: - - - - (string) - The name of the module, used in e.g. build logs. The name is also used for constructing filenames and commandline arguments, therefore using spaces or '/' in this string is a bad idea. - - - (boolean) - If true, skip this module - - - (array of objects) - An array of objects defining sources that will be downloaded and extracted in order - - - (array of strings) - An array of options that will be passed to configure - - - (array of strings) - An array of arguments that will be passed to make - - - (array of strings) - An array of arguments that will be passed to make install - - - (boolean) - If true, remove the configure script before starting build - - - (boolean) - Ignore the existence of an autogen script - - - (boolean) - Don't call make with arguments to build in parallel - - - (string) - Name of the rule passed to make for the install phase, default is install - - - (boolean) - Don't run the make install (or equivalent) stage - - - (boolean) - Don't fix up the *.py[oc] header timestamps for ostree use. - - - (boolean) - Use cmake instead of configure (deprecated: use buildsystem instead) - - - (string) - Build system to use: autotools, cmake, cmake-ninja, meson, simple - - - (boolean) - Use a build directory that is separate from the source directory - - - (string) - Build inside this subdirectory of the extracted sources - - - (object) - A build options object that can override global options - - - (array of strings) - An array of commands to run during build (between make and make install if those are used). - This is primarily useful when using the "simple" buildsystem. - - - - (array of strings) - An array of shell commands that are run after the install phase. Can for example - clean up the install dir, or install extra files. - - - - (array of strings) - An array of file patterns that should be removed at the end. - Patterns starting with / are taken to be full pathnames (without the /app prefix), otherwise they just match - the basename. Note that any patterns will only match files installed by this module. - - - - (array of strings) - The way the builder works is that files in the install directory - are hard-links to the cached files, so you're not allowed to modify them in-place. - If you list a file in this then the hardlink will be broken and you can modify it. - This is a workaround, ideally installing files should replace files, not modify - existing ones. - - - (array of strings) - If non-empty, only build the module on the arches listed. - - - (array of strings) - Don't build on any of the arches listed. - - - (array of strings) - Extra files to clean up in the platform. - - - (array of objects or strings) - An array of objects specifying nested modules to be built before this one. - String members in the array are interpreted as names of a separate json file that contains a module. - - - - - Sources - - These contain a pointer to the source that will be extracted into the source directory before - the build starts. They can be of several types, distinguished by the type property. - - - All sources - - - (array of strings) - If non-empty, only build the module on the arches listed. - - - (array of strings) - Don't build on any of the arches listed. - - - (string) - Directory inside the source dir where this source will be extracted. - - - - - Archive sources (tar, zip) - - - - "archive" - - - (string) - The path of the archive - - - (string) - The URL of a remote archive that will be downloaded. This overrides path if both are specified. - - - (string) - The sha256 checksum of the file, verified after download - - - (integer) - The number of initial pathname components to strip during extraction. Defaults to 1. - - - - - Git sources - - - - "git" - - - (string) - The path to a local checkout of the git repository. Due to how git-clone works, this will be much faster than specifying a URL of file:///... - - - (string) - URL of the git repository. This overrides path if both are specified. - - - (string) - The branch/tag to use from the git repository - - - (string) - The commit to use from the git repository. If branch is also specified, then it is verified that the branch/tag is at this specific commit. This is - a readable way to document that you're using a particular tag, but verify that it does not change. - - - (boolean) - Don't use transfer.fsckObjects=1 to mirror git repository. This may be needed for some (broken) repositories. - - - - - Bzr sources - - - - "bzr" - - - (string) - URL of the bzr repository - - - (string) - A specific revision to use in the branch - - - - - File sources - - - - "file" - - - (string) - The path of a local file that will be copied into the source dir - - - (string) - The URL of a remote file that will be downloaded and copied into the source dir. This overrides path if both are specified. - - - (string) - The sha256 checksum of the file, verified after download. This is optional for local files. - - - (string) - Filename to use inside the source dir, default to the basename of path. - - - - - Script sources - - This is a way to create a shell (/bin/sh) script from an inline set of commands. - - - - - "script" - - - (array of strings) - An array of shell commands that will be put in a shellscript file - - - (string) - Filename to use inside the source dir, default to the basename of path. - - - - - Shell sources - - This is a way to create/modify the sources by running shell commands. - - - - - "shell" - - - (array of strings) - An array of shell commands that will be run during source extraction - - - - - Patch sources - - - - "patch" - - - (string) - The path of a patch file that will be applied in the source dir - - - (integer) - The value of the -p argument to patch, defaults to 1. - - - (boolean) - Whether to use "git apply" rather than "patch" to apply the patch, required when the patch file contains binary diffs. - - - (array of strings) - Extra options to pass to the patch command. - - - - - - - - Examples - - - $ flatpak-builder my-app-dir manifest.json - - - - Example manifest file: - - -{ - "id": "org.test.TestApp", - "runtime": "org.freedesktop.Platform", - "runtime-version": "1.2", - "sdk": "org.freedesktop.Sdk", - "command": "test", - "clean": [ "/include", "*.la" ], - "build-options" : { - "cflags": "-O2 -g", - "cxxflags": "-O2 -g", - "env": { - "V": "1" - }, - "arch": { - "x86_64": { - "cflags": "-O3 -g", - } - } - }, - "modules": [ - { - "name": "pygobject", - "config-opts": [ "--disable-introspection" ], - "sources": [ - { - "type": "archive", - "url": "http://ftp.gnome.org/pub/GNOME/sources/pygobject/2.28/pygobject-2.28.6.tar.xz", - "sha256": "fb8a1d4f665130a125011659bd347c7339c944232163dbb9a34fd0686577adb8" - }, - { - "type": "patch", - "path": "required-pygobject-fix.patch" - }, - { - "type": "file", - "path": "pygobject-extra-file", - "dest-filename": "extra-file" - } - ] - }, - { - "name": "babl", - "build-options" : { "cxxflags": "-O2 -g -std=c++11" }, - "cleanup": [ "/bin" ], - "sources": [ - { - "type": "git", - "url": "git://git.gnome.org/babl" - } - ] - }, - { - "name": "testapp", - "sources": [ - { - "type": "bzr", - "url": "lp:testapp" - } - ] - } - ] -} - - - - - - See also - - - flatpak-builder1 - - - - - diff --git a/po/POTFILES.in b/po/POTFILES.in index dbac97c6..0019e7b3 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -29,8 +29,6 @@ app/flatpak-builtins-uninstall.c app/flatpak-builtins-update.c app/flatpak-main.c app/flatpak-transaction.c -builder/builder-context.c -builder/builder-module.c common/flatpak-dir.c common/flatpak-run.c common/flatpak-utils.c diff --git a/tests/Makefile.am.inc b/tests/Makefile.am.inc index dcd8fa17..2aef5d5a 100644 --- a/tests/Makefile.am.inc +++ b/tests/Makefile.am.inc @@ -78,12 +78,9 @@ tests/test-basic.sh: tests/package_version.txt dist_installed_test_extra_scripts += \ buildutil/tap-driver.sh \ - tests/empty-configure \ - tests/test-configure \ tests/make-test-app.sh \ tests/make-test-runtime.sh \ tests/make-test-bundles.sh \ - tests/testpython.py \ tests/test-webserver.sh \ $(NULL) @@ -91,20 +88,7 @@ dist_installed_test_data = \ tests/libtest.sh \ tests/org.test.Hello.png \ tests/package_version.txt \ - tests/test.json \ - tests/test-runtime.json \ - tests/module1.json \ - tests/data1 \ - tests/data1.patch \ - tests/module2.json \ - tests/data2 \ - tests/data2.patch \ tests/session.conf.in \ - tests/0001-Add-test-logo.patch \ - tests/org.test.Python.json \ - tests/org.test.Python2.json \ - tests/importme.py \ - tests/importme2.py \ $(NULL) installed_test_keyringdir = $(installed_testdir)/test-keyring @@ -138,8 +122,6 @@ dist_test_scripts = \ tests/test-extensions.sh \ tests/test-bundle.sh \ tests/test-bundle-system.sh \ - tests/test-builder.sh \ - tests/test-builder-python.sh \ tests/test-oci.sh \ tests/test-unsigned-summaries.sh \ tests/test-update-remote-configuration.sh \ diff --git a/tests/data1 b/tests/data1 deleted file mode 100644 index 18cb9ad0..00000000 --- a/tests/data1 +++ /dev/null @@ -1 +0,0 @@ -Some data1 diff --git a/tests/data1.patch b/tests/data1.patch deleted file mode 100644 index 09ede7e4..00000000 --- a/tests/data1.patch +++ /dev/null @@ -1,5 +0,0 @@ ---- data1 2017-04-24 09:24:02.861719643 +0200 -+++ data1.mod 2017-04-24 09:35:44.589157410 +0200 -@@ -1 +1 @@ --Some data1 -+Some modified data1 diff --git a/tests/data2 b/tests/data2 deleted file mode 100644 index d1eea3cb..00000000 --- a/tests/data2 +++ /dev/null @@ -1 +0,0 @@ -some data2 diff --git a/tests/data2.patch b/tests/data2.patch deleted file mode 100644 index 6f3c4351..00000000 --- a/tests/data2.patch +++ /dev/null @@ -1,5 +0,0 @@ ---- tests/data2 2017-04-24 09:31:18.793726921 +0200 -+++ tests/data2.mod 2017-04-24 09:36:26.485552769 +0200 -@@ -1 +1 @@ --some data2 -+some modified data2 diff --git a/tests/empty-configure b/tests/empty-configure deleted file mode 100755 index b967536e..00000000 --- a/tests/empty-configure +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -cat < Makefile -all: - echo Building - -install: - echo Installing -EOF diff --git a/tests/importme.py b/tests/importme.py deleted file mode 100644 index 27c7815e..00000000 --- a/tests/importme.py +++ /dev/null @@ -1,2 +0,0 @@ -import sys -foo = "first " diff --git a/tests/importme2.py b/tests/importme2.py deleted file mode 100644 index f257cf08..00000000 --- a/tests/importme2.py +++ /dev/null @@ -1,2 +0,0 @@ -import sys -foo = "modified" diff --git a/tests/libtest.sh b/tests/libtest.sh index 77da52c2..900cd302 100644 --- a/tests/libtest.sh +++ b/tests/libtest.sh @@ -103,7 +103,6 @@ if [ x${USE_DELTAS-} == xyes ] ; then fi export FLATPAK="${CMD_PREFIX} flatpak" -export FLATPAK_BUILDER="${CMD_PREFIX} flatpak-builder" assert_streq () { test "$1" = "$2" || (echo 1>&2 "$1 != $2"; exit 1) diff --git a/tests/org.test.Python.json b/tests/org.test.Python.json deleted file mode 100644 index b08879bc..00000000 --- a/tests/org.test.Python.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "app-id": "org.test.Python", - "runtime": "org.test.PythonPlatform", - "sdk": "org.test.PythonSdk", - "command": "testpython.py", - "modules": [ - { - "name": "compiled-python", - "post-install": [ - "mkdir /app/bin", - "cp testpython.py /app/bin", - "cp importme.py /app/bin", - /* Compile importme.py */ - "/app/bin/testpython.py" - ], - "sources": [ - { - "type": "file", - "path": "empty-configure", - "dest-filename": "configure" - }, - { - "type": "file", - "path": "testpython.py" - }, - { - "type": "file", - "path": "importme.py" - } - ] - }, - { - "name": "modify-python", - "post-install": [ - "cp --remove-destination importme2.py /app/bin/importme.py" - ], - "sources": [ - { - "type": "file", - "path": "empty-configure", - "dest-filename": "configure" - }, - { - "type": "file", - "path": "importme2.py" - } - ] - }, - { - "name": "recompile-modified-python", - "post-install": [ - "/app/bin/testpython.py" - ], - "sources": [ - { - "type": "file", - "path": "empty-configure", - "dest-filename": "configure" - } - ] - } - ] -} diff --git a/tests/org.test.Python2.json b/tests/org.test.Python2.json deleted file mode 100644 index bf4e1a0c..00000000 --- a/tests/org.test.Python2.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "app-id": "org.test.Python2", - "runtime": "org.test.PythonPlatform", - "sdk": "org.test.PythonSdk", - "command": "testpython.py", - "modules": [ - { - "name": "compiled-python", - "post-install": [ - "mkdir /app/bin", - "cp testpython.py /app/bin", - "cp importme.py /app/bin", - /* Compile importme.py */ - "/app/bin/testpython.py", - /* Remove .py file, but keep .pyc */ - "rm /app/bin/importme.py", - /* Make sure it still works */ - "/app/bin/testpython.py" - ], - "sources": [ - { - "type": "file", - "path": "empty-configure", - "dest-filename": "configure" - }, - { - "type": "file", - "path": "testpython.py" - }, - { - "type": "file", - "path": "importme.py" - } - ] - } - ] -} diff --git a/tests/test-builder-python.sh b/tests/test-builder-python.sh deleted file mode 100755 index 6d6beedb..00000000 --- a/tests/test-builder-python.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2011 Colin Walters -# -# This library 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, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -set -euo pipefail - -. $(dirname $0)/libtest.sh - -skip_without_bwrap -skip_without_user_xattrs -skip_without_python2 - -echo "1..2" - -setup_repo -install_repo -setup_python2_repo -install_python2_repo - -# Need /var/tmp cwd for xattrs -REPO=`pwd`/repo -cd $TEST_DATA_DIR/ - -cp $(dirname $0)/org.test.Python.json . -cp $(dirname $0)/org.test.Python2.json . -cp -a $(dirname $0)/empty-configure . -cp -a $(dirname $0)/testpython.py . -cp $(dirname $0)/importme.py . -cp $(dirname $0)/importme2.py . -chmod u+w *.py -flatpak-builder --force-clean appdir org.test.Python.json - -assert_has_file appdir/files/bin/importme.pyc - -flatpak-builder --run appdir org.test.Python.json testpython.py > testpython.out - -assert_file_has_content testpython.out ^modified$ - -echo "ok handled pyc rewriting multiple times" - -flatpak-builder --force-clean appdir org.test.Python2.json - -assert_not_has_file appdir/files/bin/importme.py -assert_has_file appdir/files/bin/importme.pyc - -flatpak-builder --run appdir org.test.Python2.json testpython.py > testpython.out - -assert_file_has_content testpython.out "^first $" - -echo "ok handled .pyc without .py" diff --git a/tests/test-builder.sh b/tests/test-builder.sh deleted file mode 100755 index 61f22e75..00000000 --- a/tests/test-builder.sh +++ /dev/null @@ -1,98 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2011 Colin Walters -# -# This library 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, write to the -# Free Software Foundation, Inc., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. - -set -euo pipefail - -. $(dirname $0)/libtest.sh - -skip_without_bwrap -skip_without_user_xattrs - -echo "1..4" - -setup_repo -install_repo -setup_sdk_repo -install_sdk_repo - -# Need /var/tmp cwd for xattrs -REPO=`pwd`/repos/test -cd $TEST_DATA_DIR/ - -cp -a $(dirname $0)/test-configure . -echo "version1" > app-data -cp $(dirname $0)/test.json . -cp $(dirname $0)/test-runtime.json . -cp $(dirname $0)/0001-Add-test-logo.patch . -mkdir include1 -cp $(dirname $0)/module1.json include1/ -cp $(dirname $0)/data1 include1/ -cp $(dirname $0)/data1.patch include1/ -mkdir include1/include2 -cp $(dirname $0)/module2.json include1/include2/ -cp $(dirname $0)/data2 include1/include2/ -cp $(dirname $0)/data2.patch include1/include2/ -${FLATPAK_BUILDER} --repo=$REPO $FL_GPGARGS --force-clean appdir test.json - -assert_file_has_content appdir/files/share/app-data version1 -assert_file_has_content appdir/metadata shared=network; -assert_file_has_content appdir/metadata tags=test; -assert_file_has_content appdir/files/ran_module1 module1 -assert_file_has_content appdir/files/ran_module2 module2 - -assert_not_has_file appdir/files/cleanup/a_filee -assert_not_has_file appdir/files/bin/file.cleanup - -assert_has_file appdir/files/cleaned_up > out -assert_has_file appdir/files/share/icons/org.test.Hello.png - -assert_file_has_content appdir/files/out '^foo$' -assert_file_has_content appdir/files/out2 '^foo2$' - -${FLATPAK} build appdir /app/bin/hello2.sh > hello_out2 -assert_file_has_content hello_out2 '^Hello world2, from a sandbox$' - -echo "ok build" - -${FLATPAK} ${U} install test-repo org.test.Hello2 master -run org.test.Hello2 > hello_out3 -assert_file_has_content hello_out3 '^Hello world2, from a sandbox$' - -run --command=cat org.test.Hello2 /app/share/app-data > app_data_1 -assert_file_has_content app_data_1 version1 - -echo "ok install+run" - -echo "version2" > app-data -${FLATPAK_BUILDER} $FL_GPGARGS --repo=$REPO --force-clean appdir test.json -assert_file_has_content appdir/files/share/app-data version2 - -${FLATPAK} ${U} update org.test.Hello2 master - -run --command=cat org.test.Hello2 /app/share/app-data > app_data_2 -assert_file_has_content app_data_2 version2 - -echo "ok update" - -# The build-args of --help should prevent the faulty cleanup and -# platform-cleanup commands from executing -${FLATPAK_BUILDER} $FL_GPGARGS --repo=$REPO --force-clean runtimedir \ - test-runtime.json - -echo "ok runtime build cleanup with build-args" diff --git a/tests/test.json b/tests/test.json deleted file mode 100644 index c837e725..00000000 --- a/tests/test.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "app-id": "org.test.Hello2", - "runtime": "org.test.Platform", - "sdk": "org.test.Sdk", - "command": "hello2.sh", - "tags": ["test"], - "finish-args": [ - "--share=network" - ], - "build-options" : { - "cflags": "-O2 -g", - "cxxflags": "-O2 -g", - "env": { - "FOO": "bar", - "V": "1" - } - }, - "cleanup": ["/cleanup", "*.cleanup"], - "cleanup-commands": [ "touch /app/cleaned_up" ], - "modules": [ - "include1/module1.json", - { - "name": "root", - "modules": [ - { - "name": "test", - "config-opts": ["--some-arg"], - "post-install": [ "touch /app/bin/file.cleanup", "mkdir -p /app/share/icons/", "cp org.test.Hello.png /app/share/icons/" ], - "make-args": ["BAR=2" ], - "make-install-args": ["BAR=3" ], - "build-commands": [ "echo foo > /app/out" ], - "sources": [ - { - "type": "file", - "path": "test-configure", - "dest-filename": "configure", - "sha256": "675a1ac2feec4d4f54e581b4b01bc3cfd2c1cf31aa5963574d31228c8a11b7e7" - }, - { - "type": "file", - "path": "app-data" - }, - { - "type": "script", - "dest-filename": "hello2.sh", - "commands": [ "echo \"Hello world2, from a sandbox\"" ] - }, - { - "type": "shell", - "commands": [ - "mkdir /app/cleanup/", - "touch /app/cleanup/a_file" - ] - }, - { - "type": "patch", - "path": "0001-Add-test-logo.patch", - "use-git": true - } - ] - }, - { - "name": "test2", - "build-commands": [ "echo foo2 > /app/out2" ], - "buildsystem": "simple", - "sources": [ - { - "type": "file", - "path": "app-data" - } - ] - }, - { - "name": "empty" - } - ] - } - ] -} diff --git a/tests/testpython.py b/tests/testpython.py deleted file mode 100755 index b40d848d..00000000 --- a/tests/testpython.py +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/python2 - -import importme -print importme.foo