mirror of
https://github.com/flatpak/flatpak.git
synced 2026-01-02 12:58:04 -05:00
Remove flatpak-builder from flatpak repo
This is now in a separate flatpak-builder repo
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef __BUILDER_CACHE_H__
|
||||
#define __BUILDER_CACHE_H__
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <libglnx/libglnx.h>
|
||||
|
||||
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__ */
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/statfs.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#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);
|
||||
}
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef __BUILDER_CONTEXT_H__
|
||||
#define __BUILDER_CONTEXT_H__
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <libsoup/soup.h>
|
||||
#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__ */
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/statfs.h>
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gio/gio.h>
|
||||
#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);
|
||||
}
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef __BUILDER_EXTENSION_H__
|
||||
#define __BUILDER_EXTENSION_H__
|
||||
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
#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__ */
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/statfs.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#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__ */
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <locale.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <gio/gio.h>
|
||||
#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;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef __BUILDER_MANIFEST_H__
|
||||
#define __BUILDER_MANIFEST_H__
|
||||
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
#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__ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef __BUILDER_MODULE_H__
|
||||
#define __BUILDER_MODULE_H__
|
||||
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
#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__ */
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/statfs.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef __BUILDER_OPTIONS_H__
|
||||
#define __BUILDER_OPTIONS_H__
|
||||
|
||||
#include <json-glib/json-glib.h>
|
||||
#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__ */
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/statfs.h>
|
||||
|
||||
#include <gio/gio.h>
|
||||
#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;
|
||||
}
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#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__ */
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/statfs.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#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__ */
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/statfs.h>
|
||||
|
||||
#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)
|
||||
{
|
||||
}
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#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__ */
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/statfs.h>
|
||||
|
||||
#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)
|
||||
{
|
||||
}
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#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__ */
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/statfs.h>
|
||||
|
||||
#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)
|
||||
{
|
||||
}
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#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__ */
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/statfs.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#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__ */
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/statfs.h>
|
||||
|
||||
#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)
|
||||
{
|
||||
}
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#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__ */
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/statfs.h>
|
||||
|
||||
#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)
|
||||
{
|
||||
}
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#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__ */
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/statfs.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef __BUILDER_SOURCE_H__
|
||||
#define __BUILDER_SOURCE_H__
|
||||
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
#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__ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Authors:
|
||||
* Alexander Larsson <alexl@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef __BUILDER_UTILS_H__
|
||||
#define __BUILDER_UTILS_H__
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <libsoup/soup.h>
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
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__ */
|
||||
@@ -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 \
|
||||
|
||||
@@ -1,632 +0,0 @@
|
||||
<?xml version='1.0'?> <!--*-nxml-*-->
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
|
||||
<refentry id="flatpak-builder">
|
||||
|
||||
<refentryinfo>
|
||||
<title>flatpak builder</title>
|
||||
<productname>flatpak</productname>
|
||||
|
||||
<authorgroup>
|
||||
<author>
|
||||
<contrib>Developer</contrib>
|
||||
<firstname>Alexander</firstname>
|
||||
<surname>Larsson</surname>
|
||||
<email>alexl@redhat.com</email>
|
||||
</author>
|
||||
</authorgroup>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>flatpak-builder</refentrytitle>
|
||||
<manvolnum>1</manvolnum>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>flatpak-builder</refname>
|
||||
<refpurpose>Help build application dependencies</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
<cmdsynopsis>
|
||||
<command>flatpak-builder</command>
|
||||
<arg choice="opt" rep="repeat">OPTION</arg>
|
||||
<arg choice="plain">DIRECTORY</arg>
|
||||
<arg choice="plain">MANIFEST</arg>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>flatpak-builder</command>
|
||||
<arg choice="plain">--run</arg>
|
||||
<arg choice="opt" rep="repeat">OPTION</arg>
|
||||
<arg choice="plain">DIRECTORY</arg>
|
||||
<arg choice="plain">MANIFEST</arg>
|
||||
<arg choice="plain">COMMAND</arg>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>flatpak-builder</command>
|
||||
<arg choice="plain">--show-deps</arg>
|
||||
<arg choice="opt" rep="repeat">OPTION</arg>
|
||||
<arg choice="plain">MANIFEST</arg>
|
||||
</cmdsynopsis>
|
||||
</refsynopsisdiv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>
|
||||
<command>flatpak-builder</command> is a wrapper around the <command>flatpak build</command> command
|
||||
that automates the building of applications and their dependencies. It is one option you can use
|
||||
to build applications.
|
||||
</para>
|
||||
<para>
|
||||
The goal of <command>flatpak-builder</command> 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 <command>./configure
|
||||
&& make && make install</command> 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.
|
||||
</para>
|
||||
<para>
|
||||
An invocation of <command>flatpak-builder</command> proceeds in these stages, each being specified
|
||||
in detail in json format in <arg choice="plain">MANIFEST</arg>:
|
||||
<itemizedlist mark='bullet'>
|
||||
<listitem>
|
||||
<para>Download all sources</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Initialize the application directory with <command>flatpak build-init</command></para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Build and install each module with <command>flatpak build</command></para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Clean up the final build tree by removing unwanted files and e.g. stripping binaries</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>Finish the application directory with <command>flatpak build-finish</command></para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
After this you will end up with a build of the application in <arg choice="plain">DIRECTORY</arg>, which you can
|
||||
export to a repository with the <command>flatpak build-export</command> command. If you use the <option>--repo</option>
|
||||
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.
|
||||
</para>
|
||||
<para>
|
||||
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 <arg choice="plain">MANIFEST</arg> file caused
|
||||
the build environment to change. This makes flatpak-builder very efficient for incremental builds.
|
||||
</para>
|
||||
<!-- FIXME: Uncomment this when enable-p2p is enabled unconditionally.
|
||||
<para>
|
||||
When building a flatpak to be published to the internet,
|
||||
<option>-FIXME-collection-id=COLLECTION-ID</option> should be specified
|
||||
as a globally unique reverse DNS value to identify the collection of
|
||||
flatpaks this will be added to. Setting a globally unique collection
|
||||
ID allows the apps in the repository to be shared over peer to peer
|
||||
systems without needing further configuration.
|
||||
</para>
|
||||
-->
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Manifest</title>
|
||||
|
||||
<para>The manifest file is a json file whose format is described in detail in its own manual page.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Options</title>
|
||||
|
||||
<para>The following options are understood:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>-h</option></term>
|
||||
<term><option>--help</option></term>
|
||||
|
||||
<listitem><para>
|
||||
Show help options and exit.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-v</option></term>
|
||||
<term><option>--verbose</option></term>
|
||||
|
||||
<listitem><para>
|
||||
Print debug information during command processing.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--version</option></term>
|
||||
|
||||
<listitem><para>
|
||||
Print version information and exit.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--arch=ARCH</option></term>
|
||||
|
||||
<listitem><para>
|
||||
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.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--disable-cache</option></term>
|
||||
|
||||
<listitem><para>
|
||||
Don't look at the existing cache for a previous build, instead always rebuild modules.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--disable-rofiles-fuse</option></term>
|
||||
|
||||
<listitem><para>
|
||||
Disable the use of rofiles-fuse to optimize the cache use via hardlink checkouts.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--disable-download</option></term>
|
||||
|
||||
<listitem><para>
|
||||
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.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--disable-updates</option></term>
|
||||
|
||||
<listitem><para>
|
||||
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.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--run</option></term>
|
||||
|
||||
<listitem><para>
|
||||
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.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--build-shell=MODULENAME</option></term>
|
||||
|
||||
<listitem><para>
|
||||
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.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--show-deps</option></term>
|
||||
|
||||
<listitem><para>
|
||||
List all the (local) files that the manifest depends on.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--download-only</option></term>
|
||||
|
||||
<listitem><para>
|
||||
Exit successfully after downloading the required sources.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--build-only</option></term>
|
||||
|
||||
<listitem><para>
|
||||
Don't do the cleanup and finish stages, which is useful if you
|
||||
want to build more things into the app.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--finish-only</option></term>
|
||||
|
||||
<listitem><para>
|
||||
Only do the cleanup, finish and export stages, picking up
|
||||
where a --build-only command left off.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--export-only</option></term>
|
||||
|
||||
<listitem><para>
|
||||
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.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--require-changes</option></term>
|
||||
|
||||
<listitem><para>
|
||||
Do nothing, leaving a non-existent <arg choice="plain">DIRECTORY</arg> if nothing changes since
|
||||
last cached build. If this is not specified, the latest version from the cache will be put
|
||||
into <arg choice="plain">DIRECTORY</arg>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--keep-build-dirs</option></term>
|
||||
|
||||
<listitem><para>
|
||||
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").
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--delete-build-dirs</option></term>
|
||||
|
||||
<listitem><para>
|
||||
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.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--ccache</option></term>
|
||||
|
||||
<listitem><para>
|
||||
Enable use of ccache in the build (needs ccache in the sdk)
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--stop-at=MODULENAME</option></term>
|
||||
|
||||
<listitem><para>
|
||||
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.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--repo=DIR</option></term>
|
||||
|
||||
<listitem><para>
|
||||
When build is done, run export the result to this repository.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-s</option></term>
|
||||
<term><option>--subject=SUBJECT</option></term>
|
||||
|
||||
<listitem><para>
|
||||
One line subject for the commit message.
|
||||
Used when exporting the build results.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-b</option></term>
|
||||
<term><option>--body=BODY</option></term>
|
||||
|
||||
<listitem><para>
|
||||
Full description for the commit message.
|
||||
Used when exporting the build results.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<!-- FIXME: Uncomment this when enable-p2p is enabled unconditionally.
|
||||
<varlistentry>
|
||||
<term><option>-FIXME-collection-id=COLLECTION-ID</option></term>
|
||||
|
||||
<listitem><para>
|
||||
Set as the collection ID of the repository. Setting a globally
|
||||
unique collection ID allows the apps in the repository to be shared over
|
||||
peer to peer systems without needing further configuration.
|
||||
If building in an existing repository, the collection ID
|
||||
must match the existing configured collection ID for that
|
||||
repository.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
-->
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--gpg-sign=KEYID</option></term>
|
||||
|
||||
<listitem><para>
|
||||
Sign the commit with this GPG key.
|
||||
Used when exporting the build results.
|
||||
This option can be used multiple times.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--gpg-homedir=PATH</option></term>
|
||||
|
||||
<listitem><para>
|
||||
GPG Homedir to use when looking for keyrings.
|
||||
Used when exporting the build results.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--jobs=JOBS</option></term>
|
||||
|
||||
<listitem><para>
|
||||
Limit the number of parallel jobs during the build.
|
||||
The default is the number of CPUs on the machine.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--force-clean</option></term>
|
||||
|
||||
<listitem><para>
|
||||
Erase the previous contents of DIRECTORY if it is
|
||||
not empty.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--sandbox</option></term>
|
||||
|
||||
<listitem><para>
|
||||
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.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--allow-missing-runtimes</option></term>
|
||||
|
||||
<listitem><para>
|
||||
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.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--rebuild-on-sdk-change</option></term>
|
||||
|
||||
<listitem><para>
|
||||
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.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--skip-if-unchanged</option></term>
|
||||
|
||||
<listitem><para>
|
||||
If the json is unchanged since the last build of this filename, then
|
||||
do nothing, and return exit code 42.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--mirror-screenshots-url=URL</option></term>
|
||||
|
||||
<listitem><para>
|
||||
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.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--extra-sources=SOURCE-DIR</option></term>
|
||||
|
||||
<listitem><para>
|
||||
When downloading sources (archives, files, git, bzr), look in this
|
||||
directory for pre-existing copies and use them instead of downloading.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--extra-sources-url=URL</option></term>
|
||||
|
||||
<listitem><para>
|
||||
When downloading sources (archives, files, git, bzr), look at this url
|
||||
for mirrored downloads before downloading from the original url.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--from-git=GIT</option></term>
|
||||
|
||||
<listitem><para>
|
||||
Look for the manifest in the given git repository. If this option is
|
||||
given, MANIFEST is interpreted as a relative path inside the repository.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--from-git-branch=BRANCH</option></term>
|
||||
|
||||
<listitem><para>
|
||||
The branch to use with --from-git.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--install-deps-from=REMOTE</option></term>
|
||||
|
||||
<listitem><para>
|
||||
Install/update build required dependencies from the specified remote.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--install-deps-only</option></term>
|
||||
|
||||
<listitem><para>
|
||||
Stop after downloading dependencies.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--user</option></term>
|
||||
|
||||
<listitem><para>
|
||||
Install the dependencies in a per-user installation.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--system</option></term>
|
||||
|
||||
<listitem><para>
|
||||
Install the dependenceis in the default system-wide installation.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--installation=NAME</option></term>
|
||||
|
||||
<listitem><para>
|
||||
Install the dependencies in a system-wide installation
|
||||
specified by <arg choice="plain">NAME</arg> among those defined in
|
||||
<filename>/etc/flatpak/installations.d/</filename>. Using
|
||||
<arg choice="plain">--installation=default</arg> is equivalent to using
|
||||
<arg choice="plain">--system</arg>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Caching</title>
|
||||
|
||||
<para>
|
||||
flatpak-builder caches sources and partial build results in
|
||||
the .flatpak-builder subdirectory of the current directory. If you
|
||||
use <option>--keep-build-dirs</option>, build directories for each
|
||||
module are also stored here.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
It is safe to remove the contents of the .flatpak-builder
|
||||
directory. This will force a full build the next time you build.
|
||||
</para>
|
||||
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Examples</title>
|
||||
|
||||
<para>
|
||||
<command>$ flatpak-builder my-app-dir manifest.json</command>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Example manifest file:
|
||||
</para>
|
||||
<programlisting>
|
||||
{
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See also</title>
|
||||
|
||||
<para>
|
||||
<citerefentry><refentrytitle>flatpak</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>flatpak-manifest</refentrytitle><manvolnum>5</manvolnum></citerefentry>
|
||||
<citerefentry><refentrytitle>flatpak-build-init</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>flatpak-build</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>flatpak-build-finish</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
|
||||
<citerefentry><refentrytitle>flatpak-build-export</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
</para>
|
||||
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
||||
@@ -16,7 +16,6 @@
|
||||
<chapter>
|
||||
<title>Executables</title>
|
||||
<xi:include href="@srcdir@/flatpak.xml"/>
|
||||
<xi:include href="@srcdir@/flatpak-builder.xml"/>
|
||||
</chapter>
|
||||
<chapter>
|
||||
<title>Commands</title>
|
||||
@@ -53,7 +52,6 @@
|
||||
<xi:include href="@srcdir@/flatpak-metadata.xml"/>
|
||||
<xi:include href="@srcdir@/flatpak-flatpakrepo.xml"/>
|
||||
<xi:include href="@srcdir@/flatpak-flatpakref.xml"/>
|
||||
<xi:include href="@srcdir@/flatpak-manifest.xml"/>
|
||||
<xi:include href="@srcdir@/flatpak-remote.xml"/>
|
||||
<xi:include href="@srcdir@/flatpak-installation.xml"/>
|
||||
</chapter>
|
||||
|
||||
@@ -1,710 +0,0 @@
|
||||
<?xml version='1.0'?> <!--*-nxml-*-->
|
||||
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
|
||||
|
||||
<refentry id="flatpak-manifest">
|
||||
|
||||
<refentryinfo>
|
||||
<title>flatpak manifest</title>
|
||||
<productname>flatpak</productname>
|
||||
|
||||
<authorgroup>
|
||||
<author>
|
||||
<contrib>Developer</contrib>
|
||||
<firstname>Alexander</firstname>
|
||||
<surname>Larsson</surname>
|
||||
<email>alexl@redhat.com</email>
|
||||
</author>
|
||||
</authorgroup>
|
||||
</refentryinfo>
|
||||
|
||||
<refmeta>
|
||||
<refentrytitle>flatpak manifest</refentrytitle>
|
||||
<manvolnum>5</manvolnum>
|
||||
</refmeta>
|
||||
|
||||
<refnamediv>
|
||||
<refname>flatpak-manifest</refname>
|
||||
<refpurpose>Information for building an application</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
<para>
|
||||
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.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>File format</title>
|
||||
|
||||
<para>
|
||||
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.
|
||||
</para>
|
||||
|
||||
<refsect2>
|
||||
<title>Toplevel properties</title>
|
||||
<para>
|
||||
These are the properties that are accepted:
|
||||
</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>id</option> or <option>app-id</option> (string)</term>
|
||||
<listitem><para>A string defining the application id.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>branch</option> (string)</term>
|
||||
<listitem><para>The branch of the application, defaults to master.</para></listitem>
|
||||
</varlistentry>
|
||||
<!-- FIXME: Uncomment this when enable-p2p is enabled unconditionally.
|
||||
<varlistentry>
|
||||
<term><option>collection-id</option> (string)</term>
|
||||
<listitem><para>The collection ID of the repository,
|
||||
defaults to being unset. Setting a globally
|
||||
unique collection ID allows the apps in the repository to be shared over
|
||||
peer to peer systems without needing further configuration.
|
||||
If building in an existing repository, the collection ID
|
||||
must match the existing configured collection ID for that
|
||||
repository.</para></listitem>
|
||||
</varlistentry>
|
||||
-->
|
||||
<varlistentry>
|
||||
<term><option>runtime</option> (string)</term>
|
||||
<listitem><para>The name of the runtime that the application uses.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>runtime-version</option> (string)</term>
|
||||
<listitem><para>The version of the runtime that the application uses, defaults to master.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>sdk</option> (string)</term>
|
||||
<listitem><para>The name of the development runtime that the application builds with.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>var</option> (string)</term>
|
||||
<listitem><para>Initialize the (otherwise empty) writable /var in the build with a copy of this runtime.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>metadata</option> (string)</term>
|
||||
<listitem><para>Use this file as the base metadata file when finishing.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>command</option> (string)</term>
|
||||
<listitem><para>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.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>build-runtime</option> (boolean)</term>
|
||||
<listitem><para>Build a new runtime instead of an application.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>build-extension</option> (boolean)</term>
|
||||
<listitem><para>Build an extension.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>separate-locales</option> (boolean)</term>
|
||||
<listitem><para>Separate out locale files and translations to an extension runtime. Defaults to true.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>id-platform</option> (string)</term>
|
||||
<listitem><para>When building a runtime sdk, also create a platform based on it with this id.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>metadata-platform</option> (string)</term>
|
||||
<listitem><para>The metadata file to use for the platform we create.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>writable-sdk</option> (boolean)</term>
|
||||
<listitem><para>If true, use a writable copy of the sdk for /usr.
|
||||
Defaults to true if build-runtime is specified.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>appstream-compose</option> (boolean)</term>
|
||||
<listitem><para>Run appstream-compose during cleanup phase. Defaults to true.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>sdk-extensions</option> (array of strings)</term>
|
||||
<listitem><para>Install these extra sdk extensions in /usr.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>platform-extensions</option> (array of strings)</term>
|
||||
<listitem><para>Install these extra sdk extensions when creating the platform.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>base</option> (string)</term>
|
||||
<listitem><para>Start with the files from the specified application. This can be
|
||||
used to create applications that extend another application.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>base-version</option> (string)</term>
|
||||
<listitem><para>Use this specific version of the application specified in base.
|
||||
If unspecified, this uses the value specified in branch</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>base-extensions</option> (array of strings)</term>
|
||||
<listitem><para>Install these extra extensions from the base application when initializing
|
||||
the application directory.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>inherit-extensions</option> (array of strings)</term>
|
||||
<listitem><para>Inherit these extra extensions points from the base application or sdk when
|
||||
finishing the build.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>tags</option> (array of strings)</term>
|
||||
<listitem><para>Add these tags to the metadata file.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>build-options</option> (object)</term>
|
||||
<listitem><para>Object specifying the build environment. See below for details.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>modules</option> (array of objects or string)</term>
|
||||
<listitem><para>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.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>add-extensions</option> (objects)</term>
|
||||
<listitem><para>This is a dictionary of extension objects. The key is the name of the extension. See below for details.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>cleanup</option> (array of strings)</term>
|
||||
<listitem><para>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.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>cleanup-commands</option> (array of strings)</term>
|
||||
<listitem><para>An array of commandlines that are run during the cleanup phase.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>cleanup-platform</option> (array of strings)</term>
|
||||
<listitem><para>Extra files to clean up in the platform.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>cleanup-platform-commands</option> (array of strings)</term>
|
||||
<listitem><para>An array of commandlines that are run during the cleanup phase of the platform.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>finish-args</option> (array of strings)</term>
|
||||
<listitem><para>An array of arguments passed to the <command>flatpak build-finish</command> command.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>rename-desktop-file</option> (string)</term>
|
||||
<listitem><para>Any desktop file with this name will be renamed to a name based on id during the cleanup phase.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>rename-appdata-file</option> (string)</term>
|
||||
<listitem><para>Any appdata file with this name will be renamed to a name based on id during the cleanup phase.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>rename-icon</option> (string)</term>
|
||||
<listitem><para>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. </para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>copy-icon</option> (boolean)</term>
|
||||
<listitem><para>If rename-icon is set, keep a copy of the old icon file.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>desktop-file-name-prefix</option> (string)</term>
|
||||
<listitem><para>This string will be prefixed to the Name key in the main application desktop file.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>desktop-file-name-suffix</option> (string)</term>
|
||||
<listitem><para>This string will be suffixed to the Name key in the main application desktop file.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
</refsect2>
|
||||
<refsect2>
|
||||
<title>Build Options</title>
|
||||
<para>
|
||||
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.
|
||||
</para>
|
||||
<para>
|
||||
These are the properties that are accepted:
|
||||
</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>cflags</option> (string)</term>
|
||||
<listitem><para>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.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>cppflags</option> (string)</term>
|
||||
<listitem><para>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.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>cxxflags</option> (string)</term>
|
||||
<listitem><para>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.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>ldflags</option> (string)</term>
|
||||
<listitem><para>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.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>prefix</option> (string)</term>
|
||||
<listitem><para>The build prefix for the modules (defaults to <filename>/app</filename> for
|
||||
applications and <filename>/usr</filename> for runtimes).</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>env</option> (object)</term>
|
||||
<listitem><para>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.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>build-args</option> (array of strings)</term>
|
||||
<listitem><para>This is an array containing extra options to pass to flatpak build.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>config-opts</option> (array of strings)</term>
|
||||
<listitem><para>This is an array containing extra options to pass to configure.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>strip</option> (boolean)</term>
|
||||
<listitem><para>If this is true (the default is false) then all ELF files will be stripped after install.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>no-debuginfo</option> (boolean)</term>
|
||||
<listitem><para>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.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>arch</option> (object)</term>
|
||||
<listitem><para>This is a dictionary defining for each arch a separate build options object that override the main one.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect2>
|
||||
<refsect2>
|
||||
<title>Extension</title>
|
||||
<para>
|
||||
Extension define extension points in the app/runtime that can be implemented by extensions, supplying extra files
|
||||
which are available during runtime..
|
||||
</para>
|
||||
<para>
|
||||
These are the properties that are accepted:
|
||||
</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>directory</option> (string)</term>
|
||||
<listitem><para>The directory where the extension is mounted.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>bundle</option> (boolean)</term>
|
||||
<listitem><para>If this is true, then the data
|
||||
created in the extension directory is omitted from
|
||||
the result, and instead packaged in a separate
|
||||
extension..</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
<para>
|
||||
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.
|
||||
</para>
|
||||
</refsect2>
|
||||
<refsect2>
|
||||
<title>Module</title>
|
||||
<para>
|
||||
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.
|
||||
</para>
|
||||
<para>
|
||||
Modules can be nested, in order to turn related modules on and off with a single key.
|
||||
</para>
|
||||
<para>
|
||||
These are the properties that are accepted:
|
||||
</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>name</option> (string)</term>
|
||||
<listitem><para>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.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>disabled</option> (boolean)</term>
|
||||
<listitem><para>If true, skip this module</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>sources</option> (array of objects)</term>
|
||||
<listitem><para>An array of objects defining sources that will be downloaded and extracted in order</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>config-opts</option> (array of strings)</term>
|
||||
<listitem><para>An array of options that will be passed to configure</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>make-args</option> (array of strings)</term>
|
||||
<listitem><para>An array of arguments that will be passed to make</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>make-install-args</option> (array of strings)</term>
|
||||
<listitem><para>An array of arguments that will be passed to make install</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>rm-configure</option> (boolean)</term>
|
||||
<listitem><para>If true, remove the configure script before starting build</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>no-autogen</option> (boolean)</term>
|
||||
<listitem><para>Ignore the existence of an autogen script</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>no-parallel-make</option> (boolean)</term>
|
||||
<listitem><para>Don't call make with arguments to build in parallel</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>install-rule</option> (string)</term>
|
||||
<listitem><para>Name of the rule passed to make for the install phase, default is install</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>no-make-install</option> (boolean)</term>
|
||||
<listitem><para>Don't run the make install (or equivalent) stage</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>no-python-timestamp-fix</option> (boolean)</term>
|
||||
<listitem><para>Don't fix up the *.py[oc] header timestamps for ostree use.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>cmake</option> (boolean)</term>
|
||||
<listitem><para>Use cmake instead of configure (deprecated: use buildsystem instead)</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>buildsystem</option> (string)</term>
|
||||
<listitem><para>Build system to use: autotools, cmake, cmake-ninja, meson, simple</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>builddir</option> (boolean)</term>
|
||||
<listitem><para>Use a build directory that is separate from the source directory</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>subdir</option> (string)</term>
|
||||
<listitem><para>Build inside this subdirectory of the extracted sources</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>build-options</option> (object)</term>
|
||||
<listitem><para>A build options object that can override global options</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>build-commands</option> (array of strings)</term>
|
||||
<listitem><para>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.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>post-install</option> (array of strings)</term>
|
||||
<listitem><para>An array of shell commands that are run after the install phase. Can for example
|
||||
clean up the install dir, or install extra files.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>cleanup</option> (array of strings)</term>
|
||||
<listitem><para>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.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>ensure-writable</option> (array of strings)</term>
|
||||
<listitem><para>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.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>only-arches</option> (array of strings)</term>
|
||||
<listitem><para>If non-empty, only build the module on the arches listed.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>skip-arches</option> (array of strings)</term>
|
||||
<listitem><para>Don't build on any of the arches listed.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>cleanup-platform</option> (array of strings)</term>
|
||||
<listitem><para>Extra files to clean up in the platform.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>modules</option> (array of objects or strings)</term>
|
||||
<listitem><para>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.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect2>
|
||||
<refsect2>
|
||||
<title>Sources</title>
|
||||
<para>
|
||||
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.
|
||||
</para>
|
||||
<refsect3>
|
||||
<title>All sources</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>only-arches</option> (array of strings)</term>
|
||||
<listitem><para>If non-empty, only build the module on the arches listed.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>skip-arches</option> (array of strings)</term>
|
||||
<listitem><para>Don't build on any of the arches listed.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>dest</option> (string)</term>
|
||||
<listitem><para>Directory inside the source dir where this source will be extracted.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect3>
|
||||
<refsect3>
|
||||
<title>Archive sources (tar, zip)</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>type</option></term>
|
||||
<listitem><para>"archive"</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>path</option> (string)</term>
|
||||
<listitem><para>The path of the archive</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>url</option> (string)</term>
|
||||
<listitem><para>The URL of a remote archive that will be downloaded. This overrides path if both are specified.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>sha256</option> (string)</term>
|
||||
<listitem><para>The sha256 checksum of the file, verified after download</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>strip-components</option> (integer)</term>
|
||||
<listitem><para>The number of initial pathname components to strip during extraction. Defaults to 1.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect3>
|
||||
<refsect3>
|
||||
<title>Git sources</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>type</option></term>
|
||||
<listitem><para>"git"</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>path</option> (string)</term>
|
||||
<listitem><para>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:///...</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>url</option> (string)</term>
|
||||
<listitem><para>URL of the git repository. This overrides path if both are specified.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>branch</option> (string)</term>
|
||||
<listitem><para>The branch/tag to use from the git repository</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>commit</option> (string)</term>
|
||||
<listitem><para>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.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>disable-fsckobjects</option> (boolean)</term>
|
||||
<listitem><para>Don't use transfer.fsckObjects=1 to mirror git repository. This may be needed for some (broken) repositories.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect3>
|
||||
<refsect3>
|
||||
<title>Bzr sources</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>type</option></term>
|
||||
<listitem><para>"bzr"</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>url</option> (string)</term>
|
||||
<listitem><para>URL of the bzr repository</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>revision</option> (string)</term>
|
||||
<listitem><para>A specific revision to use in the branch</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect3>
|
||||
<refsect3>
|
||||
<title>File sources</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>type</option></term>
|
||||
<listitem><para>"file"</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>path</option> (string)</term>
|
||||
<listitem><para>The path of a local file that will be copied into the source dir</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>url</option> (string)</term>
|
||||
<listitem><para>The URL of a remote file that will be downloaded and copied into the source dir. This overrides path if both are specified.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>sha256</option> (string)</term>
|
||||
<listitem><para>The sha256 checksum of the file, verified after download. This is optional for local files.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>dest-filename</option> (string)</term>
|
||||
<listitem><para>Filename to use inside the source dir, default to the basename of path.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect3>
|
||||
<refsect3>
|
||||
<title>Script sources</title>
|
||||
<para>
|
||||
This is a way to create a shell (/bin/sh) script from an inline set of commands.
|
||||
</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>type</option></term>
|
||||
<listitem><para>"script"</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>commands</option> (array of strings)</term>
|
||||
<listitem><para>An array of shell commands that will be put in a shellscript file</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>dest-filename</option> (string)</term>
|
||||
<listitem><para>Filename to use inside the source dir, default to the basename of path.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect3>
|
||||
<refsect3>
|
||||
<title>Shell sources</title>
|
||||
<para>
|
||||
This is a way to create/modify the sources by running shell commands.
|
||||
</para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>type</option></term>
|
||||
<listitem><para>"shell"</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>commands</option> (array of strings)</term>
|
||||
<listitem><para>An array of shell commands that will be run during source extraction</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect3>
|
||||
<refsect3>
|
||||
<title>Patch sources</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>type</option></term>
|
||||
<listitem><para>"patch"</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>path</option> (string)</term>
|
||||
<listitem><para>The path of a patch file that will be applied in the source dir</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>strip-components</option> (integer)</term>
|
||||
<listitem><para>The value of the -p argument to patch, defaults to 1.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>use-git</option> (boolean)</term>
|
||||
<listitem><para>Whether to use "git apply" rather than "patch" to apply the patch, required when the patch file contains binary diffs.</para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>options</option> (array of strings)</term>
|
||||
<listitem><para>Extra options to pass to the patch command.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect3>
|
||||
</refsect2>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Examples</title>
|
||||
|
||||
<para>
|
||||
<command>$ flatpak-builder my-app-dir manifest.json</command>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Example manifest file:
|
||||
</para>
|
||||
<programlisting>
|
||||
{
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
</programlisting>
|
||||
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See also</title>
|
||||
|
||||
<para>
|
||||
<citerefentry><refentrytitle>flatpak-builder</refentrytitle><manvolnum>1</manvolnum></citerefentry>
|
||||
</para>
|
||||
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
||||
@@ -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
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
Some data1
|
||||
@@ -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
|
||||
@@ -1 +0,0 @@
|
||||
some data2
|
||||
@@ -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
|
||||
@@ -1,9 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
cat <<EOF > Makefile
|
||||
all:
|
||||
echo Building
|
||||
|
||||
install:
|
||||
echo Installing
|
||||
EOF
|
||||
@@ -1,2 +0,0 @@
|
||||
import sys
|
||||
foo = "first "
|
||||
@@ -1,2 +0,0 @@
|
||||
import sys
|
||||
foo = "modified"
|
||||
@@ -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)
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (C) 2011 Colin Walters <walters@verbum.org>
|
||||
#
|
||||
# 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"
|
||||
@@ -1,98 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright (C) 2011 Colin Walters <walters@verbum.org>
|
||||
#
|
||||
# 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"
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/usr/bin/python2
|
||||
|
||||
import importme
|
||||
print importme.foo
|
||||
Reference in New Issue
Block a user