builder: Add support for defining extensions in flatpak-builder

This takes a list of properties and generate finish arguments.
Additionally you can specify "bundle": true, which causes f-b to emit
an actual extension implementation, similar to e.g. the locale
and debuginfo extension.
This commit is contained in:
Alexander Larsson
2017-08-21 15:40:21 +02:00
parent 0305628758
commit c6ef29c06b
7 changed files with 726 additions and 6 deletions

View File

@@ -8,6 +8,8 @@ flatpak_builder_SOURCES = \
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 \

425
builder/builder-extension.c Normal file
View File

@@ -0,0 +1,425 @@
/* 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);
}

View File

@@ -0,0 +1,59 @@
/*
* 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__ */

View File

@@ -170,6 +170,7 @@ do_export (BuilderContext *build_context,
gboolean runtime,
const gchar *location,
const gchar *directory,
char **exclude_dirs,
const gchar *branch,
const gchar *collection_id,
...)
@@ -212,6 +213,12 @@ do_export (BuilderContext *build_context,
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));
@@ -740,12 +747,14 @@ main (int argc,
{
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, builder_manifest_get_branch (manifest),
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",
@@ -778,7 +787,7 @@ main (int argc,
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, builder_manifest_get_branch (manifest),
opt_repo, app_dir_path, NULL, builder_manifest_get_branch (manifest),
builder_manifest_get_collection_id (manifest),
metadata_arg,
files_arg,
@@ -797,7 +806,7 @@ main (int argc,
g_print ("Exporting %s to repo\n", debug_id);
if (!do_export (build_context, &error, TRUE,
opt_repo, app_dir_path, builder_manifest_get_branch (manifest),
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",
@@ -808,6 +817,35 @@ main (int argc,
}
}
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))
@@ -816,7 +854,7 @@ main (int argc,
g_print ("Exporting %s to repo\n", sources_id);
if (!do_export (build_context, &error, TRUE,
opt_repo, app_dir_path, builder_manifest_get_branch (manifest),
opt_repo, app_dir_path, NULL, builder_manifest_get_branch (manifest),
builder_manifest_get_collection_id (manifest),
"--metadata=metadata.sources",
"--files=sources",
@@ -835,7 +873,7 @@ main (int argc,
g_print ("Exporting %s to repo\n", platform_id);
if (!do_export (build_context, &error, TRUE,
opt_repo, app_dir_path, builder_manifest_get_branch (manifest),
opt_repo, app_dir_path, NULL, builder_manifest_get_branch (manifest),
builder_manifest_get_collection_id (manifest),
"--metadata=metadata.platform",
"--files=platform",
@@ -868,7 +906,7 @@ main (int argc,
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, builder_manifest_get_branch (manifest),
opt_repo, app_dir_path, NULL, builder_manifest_get_branch (manifest),
builder_manifest_get_collection_id (manifest),
metadata_arg,
files_arg,

View File

@@ -31,6 +31,7 @@
#include "builder-utils.h"
#include "flatpak-utils.h"
#include "builder-post-process.h"
#include "builder-extension.h"
#include "libglnx/libglnx.h"
@@ -95,6 +96,7 @@ struct BuilderManifest
BuilderOptions *build_options;
GList *modules;
GList *expanded_modules;
GList *add_extensions;
};
typedef struct
@@ -149,6 +151,7 @@ enum {
PROP_DESKTOP_FILE_NAME_PREFIX,
PROP_DESKTOP_FILE_NAME_SUFFIX,
PROP_COLLECTION_ID,
PROP_ADD_EXTENSIONS,
LAST_PROP
};
@@ -174,6 +177,7 @@ builder_manifest_finalize (GObject *object)
g_free (self->command);
g_clear_object (&self->build_options);
g_list_free_full (self->modules, g_object_unref);
g_list_free_full (self->add_extensions, g_object_unref);
g_list_free (self->expanded_modules);
g_strfreev (self->cleanup);
g_strfreev (self->cleanup_commands);
@@ -322,6 +326,10 @@ builder_manifest_get_property (GObject *object,
g_value_set_pointer (value, self->modules);
break;
case PROP_ADD_EXTENSIONS:
g_value_set_pointer (value, self->add_extensions);
break;
case PROP_CLEANUP:
g_value_set_boxed (value, self->cleanup);
break;
@@ -518,6 +526,12 @@ builder_manifest_set_property (GObject *object,
self->modules = g_value_get_pointer (value);
break;
case PROP_ADD_EXTENSIONS:
g_list_free_full (self->add_extensions, g_object_unref);
/* NOTE: This takes ownership of the list! */
self->add_extensions = g_value_get_pointer (value);
break;
case PROP_CLEANUP:
tmp = self->cleanup;
self->cleanup = g_strdupv (g_value_get_boxed (value));
@@ -772,6 +786,12 @@ builder_manifest_class_init (BuilderManifestClass *klass)
"",
"",
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_ADD_EXTENSIONS,
g_param_spec_pointer ("add-extensions",
"",
"",
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_CLEANUP,
g_param_spec_boxed ("cleanup",
@@ -956,6 +976,31 @@ builder_manifest_serialize_property (JsonSerializable *serializable,
json_array_unref (array);
}
return retval;
}
else if (strcmp (property_name, "add-extensions") == 0)
{
BuilderManifest *self = BUILDER_MANIFEST (serializable);
JsonNode *retval = NULL;
if (self->add_extensions)
{
JsonObject *object;
GList *l;
object = json_object_new ();
for (l = self->add_extensions; l != NULL; l = l->next)
{
BuilderExtension *e = l->data;
JsonNode *child = json_gobject_serialize (G_OBJECT (e));
json_object_set_member (object, (char *) builder_extension_get_name (e), child);
}
retval = json_node_init_object (json_node_alloc (), object);
json_object_unref (object);
}
return retval;
}
else
@@ -967,6 +1012,14 @@ builder_manifest_serialize_property (JsonSerializable *serializable,
}
}
static gint
sort_extension (gconstpointer a,
gconstpointer b)
{
return strcmp (builder_extension_get_name (BUILDER_EXTENSION (a)),
builder_extension_get_name (BUILDER_EXTENSION (b)));
}
static gboolean
builder_manifest_deserialize_property (JsonSerializable *serializable,
const gchar *property_name,
@@ -1044,6 +1097,48 @@ builder_manifest_deserialize_property (JsonSerializable *serializable,
return TRUE;
}
return FALSE;
}
else if (strcmp (property_name, "add-extensions") == 0)
{
if (JSON_NODE_TYPE (property_node) == JSON_NODE_NULL)
{
g_value_set_pointer (value, NULL);
return TRUE;
}
else if (JSON_NODE_TYPE (property_node) == JSON_NODE_OBJECT)
{
JsonObject *object = json_node_get_object (property_node);
g_autoptr(GHashTable) hash = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref);
g_autoptr(GList) members = NULL;
GList *extensions;
GList *l;
members = json_object_get_members (object);
for (l = members; l != NULL; l = l->next)
{
const char *member_name = l->data;
JsonNode *val;
GObject *extension;
val = json_object_get_member (object, member_name);
extension = json_gobject_deserialize (BUILDER_TYPE_EXTENSION, val);
if (extension == NULL)
return FALSE;
builder_extension_set_name (BUILDER_EXTENSION (extension), member_name);
g_hash_table_insert (hash, (char *)builder_extension_get_name (BUILDER_EXTENSION (extension)), extension);
}
extensions = g_hash_table_get_values (hash);
g_hash_table_steal_all (hash);
extensions = g_list_sort (extensions, sort_extension);
g_value_set_pointer (value, extensions);
return TRUE;
}
return FALSE;
}
else
@@ -1122,6 +1217,12 @@ builder_manifest_get_modules (BuilderManifest *self)
return self->modules;
}
GList *
builder_manifest_get_add_extensions (BuilderManifest *self)
{
return self->add_extensions;
}
static const char *
builder_manifest_get_runtime_version (BuilderManifest *self)
{
@@ -1459,11 +1560,19 @@ builder_manifest_checksum_for_finish (BuilderManifest *self,
BuilderCache *cache,
BuilderContext *context)
{
GList *l;
builder_cache_checksum_str (cache, BUILDER_MANIFEST_CHECKSUM_FINISH_VERSION);
builder_cache_checksum_strv (cache, self->finish_args);
builder_cache_checksum_str (cache, self->command);
builder_cache_checksum_compat_strv (cache, self->inherit_extensions);
for (l = self->add_extensions; l != NULL; l = l->next)
{
BuilderExtension *e = l->data;
builder_extension_checksum (e, cache, context);
}
if (self->metadata)
{
GFile *base_dir = builder_context_get_base_dir (context);
@@ -2209,6 +2318,7 @@ builder_manifest_finish (BuilderManifest *self,
g_autoptr(GPtrArray) args = NULL;
g_autoptr(GSubprocess) subp = NULL;
int i;
GList *l;
JsonNode *node;
JsonGenerator *generator;
@@ -2375,6 +2485,9 @@ builder_manifest_finish (BuilderManifest *self,
g_ptr_array_add (args, g_strdup (self->finish_args[i]));
}
for (l = self->add_extensions; l != NULL; l = l->next)
builder_extension_add_finish_args (l->data, args);
g_ptr_array_add (args, g_file_get_path (app_dir));
g_ptr_array_add (args, NULL);
@@ -2519,6 +2632,30 @@ builder_manifest_finish (BuilderManifest *self,
return FALSE;
}
for (l = self->add_extensions; l != NULL; l = l->next)
{
BuilderExtension *e = l->data;
g_autofree char *extension_metadata_name = NULL;
g_autoptr(GFile) metadata_extension_file = NULL;
g_autofree char *metadata_contents = NULL;
if (!builder_extension_is_bundled (e))
continue;
extension_metadata_name = g_strdup_printf ("metadata.%s", builder_extension_get_name (e));
metadata_extension_file = g_file_get_child (app_dir, extension_metadata_name);
metadata_contents = g_strdup_printf ("[Runtime]\n"
"name=%s\n"
"\n"
"[ExtensionOf]\n"
"ref=%s\n",
builder_extension_get_name (e), ref);
if (!g_file_set_contents (flatpak_file_get_path_cached (metadata_extension_file),
metadata_contents, strlen (metadata_contents), error))
return FALSE;
}
if (!builder_context_disable_rofiles (context, error))
return FALSE;
@@ -3173,3 +3310,23 @@ builder_manifest_run (BuilderManifest *self,
/* Not reached */
return TRUE;
}
char **
builder_manifest_get_exclude_dirs (BuilderManifest *self)
{
g_autoptr(GPtrArray) dirs = NULL;
GList *l;
dirs = g_ptr_array_new ();
for (l = self->add_extensions; l != NULL; l = l->next)
{
BuilderExtension *e = l->data;
if (builder_extension_is_bundled (e))
g_ptr_array_add (dirs, g_strdup (builder_extension_get_directory (e)));
}
g_ptr_array_add (dirs, NULL);
return (char **)g_ptr_array_free (g_steal_pointer (&dirs), FALSE);
}

View File

@@ -27,6 +27,7 @@
#include "builder-options.h"
#include "builder-module.h"
#include "builder-cache.h"
#include "builder-extension.h"
G_BEGIN_DECLS
@@ -56,6 +57,7 @@ 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);
@@ -63,6 +65,9 @@ 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,

View File

@@ -169,6 +169,10 @@
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.
@@ -276,6 +280,36 @@
</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>