Delete non-builder files

tingping/wmclass
Alexander Larsson 2017-08-24 15:48:55 +02:00
parent bbfb53abd6
commit 9d1f1ed59c
223 changed files with 1026 additions and 91986 deletions

4
.gitmodules vendored
View File

@ -1,7 +1,3 @@
[submodule "libglnx"]
path = libglnx
url = https://git.gnome.org/browse/libglnx
[submodule "bubblewrap"]
path = bubblewrap
url = https://github.com/projectatomic/bubblewrap.git
ignore = dirty

View File

@ -20,59 +20,20 @@ if BUILD_DOCUMENTATION
SUBDIRS += . doc
endif
SUBDIRS += po
%.service: %.service.in config.log
$(AM_V_GEN) $(SED) -e "s|\@libexecdir\@|$(libexecdir)|" \
-e "s|\@localstatedir\@|$(localstatedir)|" \
-e "s|\@extraargs\@||" $< > $@
dbus_servicedir = $(DBUS_SERVICE_DIR)
service_in_files = $(NULL)
dbus_service_DATA = $(NULL)
systemduserunit_DATA = $(NULL)
CLEANFILES += $(dbus_service_DATA)
CLEANFILES += $(systemduserunit_DATA)
EXTRA_DIST += $(service_in_files)
FLATPAK_BINDIR=$(bindir)
AM_CPPFLAGS = \
-DFLATPAK_BINDIR=\"$(FLATPAK_BINDIR)\" \
-DFLATPAK_SYSTEMDIR=\"$(SYSTEM_INSTALL_DIR)\" \
-DFLATPAK_CONFIGDIR=\"$(sysconfdir)/flatpak\" \
-DFLATPAK_BASEDIR=\"$(pkgdatadir)\" \
-DFLATPAK_TRIGGERDIR=\"$(pkgdatadir)/triggers\" \
-DSYSTEM_FONTS_DIR=\"$(SYSTEM_FONTS_DIR)\" \
-DDBUSPROXY=\"$(libexecdir)/flatpak-dbus-proxy\" \
-DG_LOG_DOMAIN=\"flatpak\" \
-DG_LOG_DOMAIN=\"flatpak-builder\" \
-I$(srcdir)/libglnx \
-I$(srcdir)/common \
-I$(builddir)/common \
-I$(srcdir)/lib \
-I$(builddir)/lib \
-include "config.h" \
$(NULL)
AM_CFLAGS = $(WARN_CFLAGS)
if WITH_SYSTEM_BWRAP
AM_CPPFLAGS += -DHELPER=\"$(BWRAP)\"
else
AM_CPPFLAGS += -DHELPER=\"$(libexecdir)/flatpak-bwrap\"
endif
triggersdir = $(pkgdatadir)/triggers
dist_triggers_SCRIPTS = \
triggers/gtk-icon-cache.trigger \
triggers/mime-database.trigger \
triggers/desktop-database.trigger \
$(NULL)
# This canonicalizes the PKG_CHECK_MODULES or AM_PATH_GPGME results
INTERNAL_GPGME_CFLAGS = $(DEP_GPGME_CFLAGS) $(GPGME_PTHREAD_CFLAGS)
INTERNAL_GPGME_LIBS = $(DEP_GPGME_LIBS) $(GPGME_PTHREAD_LIBS)
lib_LTLIBRARIES =
noinst_LTLIBRARIES += libglnx.la
libglnx_srcpath := $(srcdir)/libglnx
@ -86,79 +47,9 @@ libglnx_libs := $(BASE_LIBS)
include libglnx/Makefile-libglnx.am.inc
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
include permission-store/Makefile.am.inc
include document-portal/Makefile.am.inc
include tests/Makefile.am.inc
if !WITH_SYSTEM_BWRAP
bwrap_PROGRAMS = flatpak-bwrap
flatpak_bwrap_SOURCES = $(bwrap_SOURCES)
flatpak_bwrap_CFLAGS = $(AM_CFLAGS) $(bwrap_CFLAGS)
flatpak_bwrap_LDADD = $(AM_LDADD) $(bwrap_LDADD)
bwrapdir = $(libexecdir)
include bubblewrap/Makefile-bwrap.am.inc
endif # !WITH_SYSTEM_BWRAP
# NOTE: bwrap is install-bwrapPROGS which is run from install-data, not install-exec, this data-hook is used
install-data-hook:
$(MAKE) $(AM_MAKEFLAGS) install-test-data-hook
if !WITH_SYSTEM_BWRAP
if PRIV_MODE_SETUID
$(SUDO_BIN) chown root $(DESTDIR)$(libexecdir)/flatpak-bwrap
$(SUDO_BIN) chmod u+s $(DESTDIR)$(libexecdir)/flatpak-bwrap
endif # !PRIV_MODE_SETUID
endif # !WITH_SYSTEM_BWRAP
completiondir = $(datadir)/bash-completion/completions
completion_DATA = completion/flatpak
EXTRA_DIST += $(completion_DATA)
profiledir = $(PROFILE_DIR)
profile_DATA = flatpak.sh
EXTRA_DIST += \
profile/flatpak.sh.in \
$(NULL)
DISTCLEANFILES += flatpak.sh
flatpak.sh: profile/flatpak.sh.in
$(AM_V_GEN) $(SED) -e "s|\@localstatedir\@|$(localstatedir)|" \
-e "s|\@sysconfdir\@|$(sysconfdir)|" $< > $@
envdir = $(datadir)/gdm/env.d
env_DATA = flatpak.env
EXTRA_DIST += env.d/flatpak.env.in
DISTCLEANFILES += flatpak.env
flatpak.env: env.d/flatpak.env.in
$(AM_V_GEN) $(SED) -e "s|\@localstatedir\@|$(localstatedir)|" \
-e "s|\@sysconfdir\@|$(sysconfdir)|" $< > $@
dbussnippetdir = $(systemduserunitdir)/dbus.service.d
dbussnippet_DATA = flatpak.conf
EXTRA_DIST += dbus.service.d/flatpak.conf.in
DISTCLEANFILES += flatpak.conf
flatpak.conf: dbus.service.d/flatpak.conf.in
$(AM_V_GEN) $(SED) -e "s|\@localstatedir\@|$(localstatedir)|" \
-e "s|\@sysconfdir\@|$(sysconfdir)|" $< > $@
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = flatpak.pc
EXTRA_DIST += flatpak.pc.in
scriptsdir = $(bindir)
scripts_SCRIPTS = scripts/flatpak-bisect
EXTRA_DIST += scripts/flatpak-bisect
EXTRA_DIST += README.md
AM_DISTCHECK_CONFIGURE_FLAGS = \

View File

@ -1,43 +0,0 @@
bin_PROGRAMS += \
flatpak \
$(NULL)
flatpak_SOURCES = \
app/flatpak-main.c \
app/flatpak-builtins.h \
app/flatpak-builtins-utils.h \
app/flatpak-builtins-utils.c \
app/flatpak-transaction.h \
app/flatpak-transaction.c \
app/flatpak-builtins-add-remote.c \
app/flatpak-builtins-delete-remote.c \
app/flatpak-builtins-list-remotes.c \
app/flatpak-builtins-ls-remote.c \
app/flatpak-builtins-install.c \
app/flatpak-builtins-override.c \
app/flatpak-builtins-make-current.c \
app/flatpak-builtins-update.c \
app/flatpak-builtins-uninstall.c \
app/flatpak-builtins-list.c \
app/flatpak-builtins-info.c \
app/flatpak-builtins-run.c \
app/flatpak-builtins-enter.c \
app/flatpak-builtins-build-init.c \
app/flatpak-builtins-build.c \
app/flatpak-builtins-build-finish.c \
app/flatpak-builtins-build-export.c \
app/flatpak-builtins-build-bundle.c \
app/flatpak-builtins-build-import-bundle.c \
app/flatpak-builtins-build-commit-from.c \
app/flatpak-builtins-build-sign.c \
app/flatpak-builtins-repo-update.c \
app/flatpak-builtins-repo.c \
app/flatpak-builtins-document-export.c \
app/flatpak-builtins-document-unexport.c \
app/flatpak-builtins-document-info.c \
app/flatpak-builtins-document-list.c \
$(NULL)
flatpak_LDADD = $(AM_LDADD) $(BASE_LIBS) $(OSTREE_LIBS) $(SOUP_LIBS) $(JSON_LIBS) libglnx.la libflatpak-common.la
flatpak_CFLAGS = $(AM_CFLAGS) $(BASE_CFLAGS) $(OSTREE_CFLAGS) $(SOUP_CFLAGS) $(JSON_CFLAGS) \
-DLOCALEDIR=\"$(localedir)\"

View File

@ -1,529 +0,0 @@
/*
* Copyright © 2014 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 <unistd.h>
#include <string.h>
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
#include "flatpak-builtins.h"
#include "flatpak-builtins-utils.h"
#include "flatpak-utils.h"
static gboolean opt_no_gpg_verify;
static gboolean opt_do_gpg_verify;
static gboolean opt_do_enumerate;
static gboolean opt_no_enumerate;
static gboolean opt_do_deps;
static gboolean opt_no_deps;
static gboolean opt_if_not_exists;
static gboolean opt_enable;
static gboolean opt_oci;
static gboolean opt_update_metadata;
static gboolean opt_disable;
static int opt_prio = -1;
static char *opt_title;
static char *opt_default_branch;
static char *opt_url;
static char *opt_collection_id = NULL;
static gboolean opt_from;
static char **opt_gpg_import;
static GOptionEntry add_options[] = {
{ "if-not-exists", 0, 0, G_OPTION_ARG_NONE, &opt_if_not_exists, N_("Do nothing if the provided remote exists"), NULL },
{ "from", 0, 0, G_OPTION_ARG_NONE, &opt_from, N_("LOCATION specifies a configuration file, not the repo location"), NULL },
{ NULL }
};
static GOptionEntry modify_options[] = {
{ "gpg-verify", 0, 0, G_OPTION_ARG_NONE, &opt_do_gpg_verify, N_("Enable GPG verification"), NULL },
{ "enumerate", 0, 0, G_OPTION_ARG_NONE, &opt_do_enumerate, N_("Mark the remote as enumerate"), NULL },
{ "use-for-deps", 0, 0, G_OPTION_ARG_NONE, &opt_do_deps, N_("Mark the remote as used for dependencies"), NULL },
{ "url", 0, 0, G_OPTION_ARG_STRING, &opt_url, N_("Set a new url"), N_("URL") },
{ "enable", 0, 0, G_OPTION_ARG_NONE, &opt_enable, N_("Enable the remote"), NULL },
{ "update-metadata", 0, 0, G_OPTION_ARG_NONE, &opt_update_metadata, N_("Update extra metadata from the summary file"), NULL },
{ NULL }
};
static GOptionEntry common_options[] = {
{ "no-gpg-verify", 0, 0, G_OPTION_ARG_NONE, &opt_no_gpg_verify, N_("Disable GPG verification"), NULL },
{ "no-enumerate", 0, 0, G_OPTION_ARG_NONE, &opt_no_enumerate, N_("Mark the remote as don't enumerate"), NULL },
{ "no-use-for-deps", 0, 0, G_OPTION_ARG_NONE, &opt_no_deps, N_("Mark the remote as don't use for deps"), NULL },
{ "prio", 0, 0, G_OPTION_ARG_INT, &opt_prio, N_("Set priority (default 1, higher is more prioritized)"), N_("PRIORITY") },
{ "title", 0, 0, G_OPTION_ARG_STRING, &opt_title, N_("A nice name to use for this remote"), N_("TITLE") },
{ "default-branch", 0, 0, G_OPTION_ARG_STRING, &opt_default_branch, N_("Default branch to use for this remote"), N_("BRANCH") },
#ifdef FLATPAK_ENABLE_P2P
{ "collection-id", 0, 0, G_OPTION_ARG_STRING, &opt_collection_id, N_("Collection ID"), N_("COLLECTION-ID") },
#endif /* FLATPAK_ENABLE_P2P */
{ "gpg-import", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_gpg_import, N_("Import GPG key from FILE (- for stdin)"), N_("FILE") },
{ "disable", 0, 0, G_OPTION_ARG_NONE, &opt_disable, N_("Disable the remote"), NULL },
{ "oci", 0, 0, G_OPTION_ARG_NONE, &opt_oci, N_("Add OCI registry"), NULL },
{ NULL }
};
static GKeyFile *
get_config_from_opts (FlatpakDir *dir, const char *remote_name, gboolean *changed)
{
GKeyFile *config = ostree_repo_copy_config (flatpak_dir_get_repo (dir));
g_autofree char *group = g_strdup_printf ("remote \"%s\"", remote_name);
if (opt_no_gpg_verify)
{
g_key_file_set_boolean (config, group, "gpg-verify", FALSE);
g_key_file_set_boolean (config, group, "gpg-verify-summary", FALSE);
*changed = TRUE;
}
if (opt_do_gpg_verify)
{
g_key_file_set_boolean (config, group, "gpg-verify", TRUE);
g_key_file_set_boolean (config, group, "gpg-verify-summary", TRUE);
*changed = TRUE;
}
if (opt_url)
{
if (g_str_has_prefix (opt_url, "metalink="))
g_key_file_set_string (config, group, "metalink", opt_url + strlen ("metalink="));
else
g_key_file_set_string (config, group, "url", opt_url);
*changed = TRUE;
}
if (opt_collection_id)
{
g_key_file_set_string (config, group, "collection-id", opt_collection_id);
g_key_file_set_boolean (config, group, "gpg-verify-summary", FALSE);
*changed = TRUE;
}
if (opt_title)
{
g_key_file_set_string (config, group, "xa.title", opt_title);
g_key_file_set_boolean (config, group, "xa.title-is-set", TRUE);
*changed = TRUE;
}
if (opt_default_branch)
{
g_key_file_set_string (config, group, "xa.default-branch", opt_default_branch);
g_key_file_set_boolean (config, group, "xa.default-branch-is-set", TRUE);
*changed = TRUE;
}
if (opt_no_enumerate)
{
g_key_file_set_boolean (config, group, "xa.noenumerate", TRUE);
*changed = TRUE;
}
if (opt_do_enumerate)
{
g_key_file_set_boolean (config, group, "xa.noenumerate", FALSE);
*changed = TRUE;
}
if (opt_no_deps)
{
g_key_file_set_boolean (config, group, "xa.nodeps", TRUE);
*changed = TRUE;
}
if (opt_do_deps)
{
g_key_file_set_boolean (config, group, "xa.nodeps", FALSE);
*changed = TRUE;
}
if (opt_disable)
{
g_key_file_set_boolean (config, group, "xa.disable", TRUE);
*changed = TRUE;
}
else if (opt_enable)
{
g_key_file_set_boolean (config, group, "xa.disable", FALSE);
*changed = TRUE;
}
if (opt_oci)
{
g_key_file_set_boolean (config, group, "xa.oci", TRUE);
*changed = TRUE;
}
if (opt_prio != -1)
{
g_autofree char *prio_as_string = g_strdup_printf ("%d", opt_prio);
g_key_file_set_string (config, group, "xa.prio", prio_as_string);
*changed = TRUE;
}
return config;
}
static void
load_options (const char *filename,
GBytes **gpg_data)
{
g_autoptr(GError) error = NULL;
g_autoptr(GKeyFile) keyfile = g_key_file_new ();
char *str;
gboolean nodeps;
g_autoptr(GBytes) bytes = NULL;
g_autofree char *version = NULL;
if (g_str_has_prefix (filename, "http:") ||
g_str_has_prefix (filename, "https:"))
{
const char *options_data;
gsize options_size;
bytes = download_uri (filename, &error);
if (bytes == NULL)
{
g_printerr ("Can't load uri %s: %s\n", filename, error->message);
exit (1);
}
options_data = g_bytes_get_data (bytes, &options_size);
if (!g_key_file_load_from_data (keyfile, options_data, options_size, 0, &error))
{
g_printerr ("Can't load uri %s: %s\n", filename, error->message);
exit (1);
}
}
else
{
if (!g_key_file_load_from_file (keyfile, filename, 0, &error))
{
g_printerr ("Can't load file %s: %s\n", filename, error->message);
exit (1);
}
}
if (!g_key_file_has_group (keyfile, FLATPAK_REPO_GROUP))
{
g_printerr ("Invalid file format");
exit (1);
}
version = g_key_file_get_string (keyfile, FLATPAK_REPO_GROUP,
FLATPAK_REPO_VERSION_KEY, NULL);
if (version != NULL && strcmp (version, "1") != 0)
{
g_printerr ("Invalid version %s, only 1 supported", version);
exit (1);
}
str = g_key_file_get_string (keyfile, FLATPAK_REPO_GROUP,
FLATPAK_REPO_URL_KEY, NULL);
if (str != NULL)
opt_url = str;
#ifdef FLATPAK_ENABLE_P2P
str = g_key_file_get_string (keyfile, FLATPAK_REPO_GROUP, FLATPAK_REPO_COLLECTION_ID_KEY, NULL);
if (str != NULL)
opt_collection_id = str;
#endif /* FLATPAK_ENABLE_P2P */
str = g_key_file_get_locale_string (keyfile, FLATPAK_REPO_GROUP,
FLATPAK_REPO_TITLE_KEY, NULL, NULL);
if (str != NULL)
opt_title = str;
str = g_key_file_get_locale_string (keyfile, FLATPAK_REPO_GROUP,
FLATPAK_REPO_DEFAULT_BRANCH_KEY, NULL, NULL);
if (str != NULL)
opt_default_branch = str;
nodeps = g_key_file_get_boolean (keyfile, FLATPAK_REPO_GROUP,
FLATPAK_REPO_NODEPS_KEY, NULL);
if (nodeps)
{
opt_no_deps = TRUE;
opt_do_deps = FALSE;
}
str = g_key_file_get_string (keyfile, FLATPAK_REPO_GROUP,
FLATPAK_REPO_GPGKEY_KEY, NULL);
if (str != NULL)
{
guchar *decoded;
gsize decoded_len;
str = g_strstrip (str);
decoded = g_base64_decode (str, &decoded_len);
if (decoded_len < 10) /* Check some minimal size so we don't get crap */
{
g_printerr ("Invalid gpg key");
exit (1);
}
*gpg_data = g_bytes_new_take (decoded, decoded_len);
if (!opt_no_gpg_verify)
opt_do_gpg_verify = TRUE;
}
}
gboolean
flatpak_builtin_add_remote (int argc, char **argv,
GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDir) dir = NULL;
g_autoptr(GFile) file = NULL;
g_auto(GStrv) remotes = NULL;
g_autofree char *remote_url = NULL;
const char *remote_name;
const char *location = NULL;
g_autoptr(GKeyFile) config = NULL;
g_autoptr(GBytes) gpg_data = NULL;
gboolean changed = FALSE;
g_autoptr(GError) local_error = NULL;
context = g_option_context_new (_("NAME LOCATION - Add a remote repository"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
g_option_context_add_main_entries (context, common_options, NULL);
if (!flatpak_option_context_parse (context, add_options, &argc, &argv, 0, &dir, cancellable, error))
return FALSE;
if (argc < 2)
return usage_error (context, _("NAME must be specified"), error);
if (argc < 3)
return usage_error (context, _("LOCATION must be specified"), error);
if (argc > 3)
return usage_error (context, _("Too many arguments"), error);
#ifdef FLATPAK_ENABLE_P2P
if (opt_collection_id != NULL &&
!ostree_validate_collection_id (opt_collection_id, &local_error))
return flatpak_fail (error, _("%s is not a valid collection ID: %s"), opt_collection_id, local_error->message);
if (opt_collection_id != NULL &&
(opt_no_gpg_verify || opt_gpg_import == NULL || opt_gpg_import[0] == NULL))
return flatpak_fail (error, _("GPG verification is required if collections are enabled"));
#endif /* FLATPAK_ENABLE_P2P */
remote_name = argv[1];
location = argv[2];
remotes = flatpak_dir_list_remotes (dir, cancellable, error);
if (remotes == NULL)
return FALSE;
if (g_strv_contains ((const char **)remotes, remote_name))
{
if (opt_if_not_exists)
return TRUE; /* Do nothing */
return flatpak_fail (error, _("Remote %s already exists"), remote_name);
}
if (opt_from ||
flatpak_file_arg_has_suffix (location, ".flatpakrepo"))
{
load_options (location, &gpg_data);
if (opt_url == NULL)
return flatpak_fail (error, _("No url specified in flatpakrepo file"));
}
else
{
file = g_file_new_for_commandline_arg (location);
if (g_file_is_native (file))
remote_url = g_file_get_uri (file);
else
remote_url = g_strdup (location);
opt_url = remote_url;
}
/* Default to gpg verify */
if (!opt_no_gpg_verify)
opt_do_gpg_verify = TRUE;
config = get_config_from_opts (dir, remote_name, &changed);
if (opt_gpg_import != NULL)
{
gpg_data = flatpak_load_gpg_keys (opt_gpg_import, cancellable, error);
if (gpg_data == NULL)
return FALSE;
}
if (!flatpak_dir_modify_remote (dir, remote_name, config, gpg_data, cancellable, error))
return FALSE;
/* Reload previously changed configuration */
if (!flatpak_dir_recreate_repo (dir, cancellable, error))
return FALSE;
/* We can't retrieve the extra metadata until the remote has been added locally, since
ostree_repo_remote_fetch_summary() works with the repository's name, not its URL.
Don't propagate IO failed errors here because we might just be offline - the
remote should already be usable. */
if (!flatpak_dir_update_remote_configuration (dir, remote_name, cancellable, &local_error))
{
if (local_error->domain == G_RESOLVER_ERROR ||
g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_FAILED))
{
g_printerr (_("Warning: Could not update extra metadata for '%s': %s\n"), remote_name, local_error->message);
}
else
{
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}
}
return TRUE;
}
gboolean
flatpak_complete_add_remote (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDir) dir = NULL;
context = g_option_context_new ("");
g_option_context_add_main_entries (context, common_options, NULL);
if (!flatpak_option_context_parse (context, add_options, &completion->argc, &completion->argv, 0, &dir, NULL, NULL))
return FALSE;
switch (completion->argc)
{
case 0:
case 1:
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, common_options);
flatpak_complete_options (completion, add_options);
flatpak_complete_options (completion, user_entries);
break;
}
return TRUE;
}
gboolean
flatpak_builtin_modify_remote (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDir) dir = NULL;
g_autoptr(GKeyFile) config = NULL;
g_autoptr(GBytes) gpg_data = NULL;
const char *remote_name;
gboolean changed = FALSE;
context = g_option_context_new (_("NAME - Modify a remote repository"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
g_option_context_add_main_entries (context, common_options, NULL);
if (!flatpak_option_context_parse (context, modify_options, &argc, &argv, 0, &dir, cancellable, error))
return FALSE;
if (argc < 2)
return usage_error (context, _("Remote NAME must be specified"), error);
remote_name = argv[1];
if (!ostree_repo_remote_get_url (flatpak_dir_get_repo (dir), remote_name, NULL, NULL))
return flatpak_fail (error, _("No remote %s"), remote_name);
if (opt_update_metadata)
{
g_autoptr(GError) local_error = NULL;
g_print (_("Updating extra metadata from remote summary for %s\n"), remote_name);
if (!flatpak_dir_update_remote_configuration (dir, remote_name, cancellable, &local_error))
{
g_printerr (_("Error updating extra metadata for '%s': %s\n"), remote_name, local_error->message);
return flatpak_fail (error, _("Could not update extra metadata for %s"), remote_name);
}
/* Reload changed configuration */
if (!flatpak_dir_recreate_repo (dir, cancellable, error))
return FALSE;
}
config = get_config_from_opts (dir, remote_name, &changed);
if (opt_gpg_import != NULL)
{
gpg_data = flatpak_load_gpg_keys (opt_gpg_import, cancellable, error);
if (gpg_data == NULL)
return FALSE;
changed = TRUE;
}
if (!changed)
return TRUE;
return flatpak_dir_modify_remote (dir, remote_name, config, gpg_data, cancellable, error);
}
gboolean
flatpak_complete_modify_remote (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDir) dir = NULL;
int i;
context = g_option_context_new ("");
g_option_context_add_main_entries (context, common_options, NULL);
if (!flatpak_option_context_parse (context, modify_options, &completion->argc, &completion->argv, 0, &dir, NULL, NULL))
return FALSE;
switch (completion->argc)
{
case 0:
case 1: /* REMOTE */
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, common_options);
flatpak_complete_options (completion, modify_options);
flatpak_complete_options (completion, user_entries);
{
g_auto(GStrv) remotes = flatpak_dir_list_remotes (dir, NULL, NULL);
if (remotes == NULL)
return FALSE;
for (i = 0; remotes[i] != NULL; i++)
flatpak_complete_word (completion, "%s ", remotes[i]);
}
break;
}
return TRUE;
}

View File

@ -1,552 +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 <unistd.h>
#include <string.h>
#include <json-glib/json-glib.h>
#include <glib/gi18n.h>
#include <gio/gunixinputstream.h>
#include "libglnx/libglnx.h"
#include "flatpak-builtins.h"
#include "flatpak-utils.h"
#include "flatpak-oci-registry.h"
#include "flatpak-chain-input-stream.h"
#include "flatpak-builtins-utils.h"
#include <archive.h>
#include <archive_entry.h>
static char *opt_arch;
static char *opt_repo_url;
static char *opt_runtime_repo;
static gboolean opt_runtime = FALSE;
static char **opt_gpg_file;
static gboolean opt_oci = FALSE;
static char **opt_gpg_key_ids;
static char *opt_gpg_homedir;
static GOptionEntry options[] = {
{ "runtime", 0, 0, G_OPTION_ARG_NONE, &opt_runtime, N_("Export runtime instead of app"), NULL },
{ "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, N_("Arch to bundle for"), N_("ARCH") },
{ "repo-url", 0, 0, G_OPTION_ARG_STRING, &opt_repo_url, N_("Url for repo"), N_("URL") },
{ "runtime-repo", 0, 0, G_OPTION_ARG_STRING, &opt_runtime_repo, N_("Url for runtime flatpakrepo file"), N_("URL") },
{ "gpg-keys", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_gpg_file, N_("Add GPG key from FILE (- for stdin)"), N_("FILE") },
{ "oci", 0, 0, G_OPTION_ARG_NONE, &opt_oci, N_("Export oci image instead of flatpak bundle"), NULL },
{ "gpg-sign", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_gpg_key_ids, N_("GPG Key ID to sign the OCI image with"), N_("KEY-ID") },
{ "gpg-homedir", 0, 0, G_OPTION_ARG_STRING, &opt_gpg_homedir, N_("GPG Homedir to use when looking for keyrings"), N_("HOMEDIR") },
{ NULL }
};
static GBytes *
read_gpg_data (GCancellable *cancellable,
GError **error)
{
g_autoptr(GInputStream) source_stream = NULL;
guint n_keyrings = 0;
g_autoptr(GPtrArray) streams = NULL;
if (opt_gpg_file != NULL)
n_keyrings = g_strv_length (opt_gpg_file);
guint ii;
streams = g_ptr_array_new_with_free_func (g_object_unref);
for (ii = 0; ii < n_keyrings; ii++)
{
GInputStream *input_stream = NULL;
if (strcmp (opt_gpg_file[ii], "-") == 0)
{
input_stream = g_unix_input_stream_new (STDIN_FILENO, FALSE);
}
else
{
g_autoptr(GFile) file = g_file_new_for_commandline_arg (opt_gpg_file[ii]);
input_stream = G_INPUT_STREAM (g_file_read (file, cancellable, error));
if (input_stream == NULL)
return NULL;
}
/* Takes ownership. */
g_ptr_array_add (streams, input_stream);
}
/* Chain together all the --keyring options as one long stream. */
source_stream = (GInputStream *) flatpak_chain_input_stream_new (streams);
return flatpak_read_stream (source_stream, FALSE, error);
}
static gboolean
build_bundle (OstreeRepo *repo, GFile *file,
const char *name, const char *full_branch,
GCancellable *cancellable, GError **error)
{
GVariantBuilder metadata_builder;
GVariantBuilder param_builder;
g_autoptr(GKeyFile) keyfile = NULL;
g_autoptr(GFile) xmls_dir = NULL;
g_autoptr(GFile) metadata_file = NULL;
g_autoptr(GFile) appstream_file = NULL;
g_autofree char *appstream_basename = NULL;
g_autoptr(GInputStream) in = NULL;
g_autoptr(GInputStream) xml_in = NULL;
g_autoptr(GFile) root = NULL;
g_autofree char *commit_checksum = NULL;
g_autoptr(GBytes) gpg_data = NULL;
g_autoptr(GVariant) params = NULL;
g_autoptr(GVariant) metadata = NULL;
const char *collection_id;
if (!ostree_repo_resolve_rev (repo, full_branch, FALSE, &commit_checksum, error))
return FALSE;
if (!ostree_repo_read_commit (repo, commit_checksum, &root, NULL, NULL, error))
return FALSE;
g_variant_builder_init (&metadata_builder, G_VARIANT_TYPE ("a{sv}"));
/* We add this first in the metadata, so this will become the file
* format header. The first part is readable to make it easy to
* figure out the type. The uint32 is basically a random value, but
* it ensures we have both zero and high bits sets, so we don't get
* sniffed as text. Also, the last 01 can be used as a version
* later. Furthermore, the use of an uint32 lets use detect
* byteorder issues.
*/
g_variant_builder_add (&metadata_builder, "{sv}", "flatpak",
g_variant_new_uint32 (0xe5890001));
g_variant_builder_add (&metadata_builder, "{sv}", "ref", g_variant_new_string (full_branch));
metadata_file = g_file_resolve_relative_path (root, "metadata");
keyfile = g_key_file_new ();
in = (GInputStream *) g_file_read (metadata_file, cancellable, NULL);
if (in != NULL)
{
g_autoptr(GBytes) bytes = flatpak_read_stream (in, TRUE, error);
if (bytes == NULL)
return FALSE;
if (!g_key_file_load_from_data (keyfile,
g_bytes_get_data (bytes, NULL),
g_bytes_get_size (bytes),
G_KEY_FILE_NONE, error))
return FALSE;
g_variant_builder_add (&metadata_builder, "{sv}", "metadata",
g_variant_new_string (g_bytes_get_data (bytes, NULL)));
}
xmls_dir = g_file_resolve_relative_path (root, "files/share/app-info/xmls");
appstream_basename = g_strconcat (name, ".xml.gz", NULL);
appstream_file = g_file_get_child (xmls_dir, appstream_basename);
xml_in = (GInputStream *) g_file_read (appstream_file, cancellable, NULL);
if (xml_in)
{
g_autoptr(FlatpakXml) appstream_root = NULL;
g_autoptr(FlatpakXml) xml_root = flatpak_xml_parse (xml_in, TRUE,
cancellable, error);
if (xml_root == NULL)
return FALSE;
appstream_root = flatpak_appstream_xml_new ();
if (flatpak_appstream_xml_migrate (xml_root, appstream_root,
full_branch, name, keyfile))
{
g_autoptr(GBytes) xml_data = flatpak_appstream_xml_root_to_data (appstream_root, error);
int i;
g_autoptr(GFile) icons_dir =
g_file_resolve_relative_path (root,
"files/share/app-info/icons/flatpak");
const char *icon_sizes[] = { "64x64", "128x128" };
const char *icon_sizes_key[] = { "icon-64", "icon-128" };
g_autofree char *icon_name = g_strconcat (name, ".png", NULL);
if (xml_data == NULL)
return FALSE;
g_variant_builder_add (&metadata_builder, "{sv}", "appdata",
g_variant_new_from_bytes (G_VARIANT_TYPE_BYTESTRING,
xml_data, TRUE));
for (i = 0; i < G_N_ELEMENTS (icon_sizes); i++)
{
g_autoptr(GFile) size_dir = g_file_get_child (icons_dir, icon_sizes[i]);
g_autoptr(GFile) icon_file = g_file_get_child (size_dir, icon_name);
g_autoptr(GInputStream) png_in = NULL;
png_in = (GInputStream *) g_file_read (icon_file, cancellable, NULL);
if (png_in != NULL)
{
g_autoptr(GBytes) png_data = flatpak_read_stream (png_in, FALSE, error);
if (png_data == NULL)
return FALSE;
g_variant_builder_add (&metadata_builder, "{sv}", icon_sizes_key[i],
g_variant_new_from_bytes (G_VARIANT_TYPE_BYTESTRING,
png_data, TRUE));
}
}
}
}
if (opt_repo_url)
g_variant_builder_add (&metadata_builder, "{sv}", "origin", g_variant_new_string (opt_repo_url));
if (opt_runtime_repo)
g_variant_builder_add (&metadata_builder, "{sv}", "runtime-repo", g_variant_new_string (opt_runtime_repo));
#ifdef FLATPAK_ENABLE_P2P
collection_id = ostree_repo_get_collection_id (repo);
#else /* if !FLATPAK_ENABLE_P2P */
collection_id = NULL;
#endif /* !FLATPAK_ENABLE_P2P */
g_variant_builder_add (&metadata_builder, "{sv}", "collection-id",
g_variant_new_string (collection_id ? collection_id : ""));
if (opt_gpg_file != NULL)
{
gpg_data = read_gpg_data (cancellable, error);
if (gpg_data == NULL)
return FALSE;
}
if (gpg_data)
{
g_variant_builder_add (&metadata_builder, "{sv}", "gpg-keys",
g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE,
g_bytes_get_data (gpg_data, NULL),
g_bytes_get_size (gpg_data),
1));
}
g_variant_builder_init (&param_builder, G_VARIANT_TYPE ("a{sv}"));
g_variant_builder_add (&param_builder, "{sv}", "min-fallback-size", g_variant_new_uint32 (0));
g_variant_builder_add (&param_builder, "{sv}", "compression", g_variant_new_byte ('x'));
g_variant_builder_add (&param_builder, "{sv}", "bsdiff-enabled", g_variant_new_boolean (FALSE));
g_variant_builder_add (&param_builder, "{sv}", "inline-parts", g_variant_new_boolean (TRUE));
g_variant_builder_add (&param_builder, "{sv}", "include-detached", g_variant_new_boolean (TRUE));
g_variant_builder_add (&param_builder, "{sv}", "filename", g_variant_new_bytestring (flatpak_file_get_path_cached (file)));
params = g_variant_ref_sink (g_variant_builder_end (&param_builder));
metadata = g_variant_ref_sink (g_variant_builder_end (&metadata_builder));
if (!ostree_repo_static_delta_generate (repo,
OSTREE_STATIC_DELTA_GENERATE_OPT_LOWLATENCY,
/* from */ NULL,
commit_checksum,
metadata,
params,
cancellable,
error))
return FALSE;
return TRUE;
}
static gchar *
timestamp_to_iso8601 (guint64 timestamp)
{
GTimeVal stamp;
stamp.tv_sec = timestamp;
stamp.tv_usec = 0;
return g_time_val_to_iso8601 (&stamp);
}
static gboolean
export_commit_to_archive (OstreeRepo *repo,
GFile *root,
guint64 timestamp,
struct archive *a,
GCancellable *cancellable, GError **error)
{
OstreeRepoExportArchiveOptions opts = { 0, };
opts.timestamp_secs = timestamp;
if (!ostree_repo_export_tree_to_archive (repo, &opts, (OstreeRepoFile *) root, a,
cancellable, error))
return FALSE;
return TRUE;
}
static gboolean
build_oci (OstreeRepo *repo, GFile *dir,
const char *name, const char *ref,
GCancellable *cancellable, GError **error)
{
g_autoptr(GFile) root = NULL;
g_autoptr(GVariant) commit_data = NULL;
g_autoptr(GVariant) commit_metadata = NULL;
g_autofree char *commit_checksum = NULL;
g_autofree char *dir_uri = NULL;
g_autoptr(FlatpakOciRegistry) registry = NULL;
g_autoptr(FlatpakOciLayerWriter) layer_writer = NULL;
struct archive *archive;
g_autofree char *uncompressed_digest = NULL;
g_autofree char *timestamp = NULL;
g_autoptr(FlatpakOciImage) image = NULL;
g_autoptr(FlatpakOciDescriptor) layer_desc = NULL;
g_autoptr(FlatpakOciDescriptor) image_desc = NULL;
g_autoptr(FlatpakOciDescriptor) manifest_desc = NULL;
g_autoptr(FlatpakOciManifest) manifest = NULL;
g_autoptr(FlatpakOciIndex) index = NULL;
g_autoptr(GFile) metadata_file = NULL;
guint64 installed_size = 0;
GHashTable *annotations;
gsize metadata_size;
g_autofree char *metadata_contents = NULL;
if (!ostree_repo_resolve_rev (repo, ref, FALSE, &commit_checksum, error))
return FALSE;
if (!ostree_repo_read_commit (repo, commit_checksum, &root, NULL, NULL, error))
return FALSE;
if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT, commit_checksum, &commit_data, error))
return FALSE;
if (!ostree_repo_read_commit_detached_metadata (repo, commit_checksum, &commit_metadata, cancellable, error))
return FALSE;
dir_uri = g_file_get_uri (dir);
registry = flatpak_oci_registry_new (dir_uri, TRUE, -1, cancellable, error);
if (registry == NULL)
return FALSE;
layer_writer = flatpak_oci_registry_write_layer (registry, cancellable, error);
if (layer_writer == NULL)
return FALSE;
archive = flatpak_oci_layer_writer_get_archive (layer_writer);
if (!export_commit_to_archive (repo, root, ostree_commit_get_timestamp (commit_data),
archive, cancellable, error))
return FALSE;
if (!flatpak_oci_layer_writer_close (layer_writer,
&uncompressed_digest,
&layer_desc,
cancellable,
error))
return FALSE;
image = flatpak_oci_image_new ();
flatpak_oci_image_set_layer (image, uncompressed_digest);
timestamp = timestamp_to_iso8601 (ostree_commit_get_timestamp (commit_data));
flatpak_oci_image_set_created (image, timestamp);
image_desc = flatpak_oci_registry_store_json (registry, FLATPAK_JSON (image), cancellable, error);
if (image_desc == NULL)
return FALSE;
manifest = flatpak_oci_manifest_new ();
flatpak_oci_manifest_set_config (manifest, image_desc);
flatpak_oci_manifest_set_layer (manifest, layer_desc);
annotations = flatpak_oci_manifest_get_annotations (manifest);
flatpak_oci_add_annotations_for_commit (annotations, ref, commit_checksum, commit_data);
metadata_file = g_file_get_child (root, "metadata");
if (g_file_load_contents (metadata_file, cancellable, &metadata_contents, &metadata_size, NULL, NULL) &&
g_utf8_validate (metadata_contents, -1, NULL))
{
g_hash_table_replace (annotations,
g_strdup ("org.flatpak.metadata"),
g_steal_pointer (&metadata_contents));
}
if (!flatpak_repo_collect_sizes (repo, root, &installed_size, NULL, NULL, error))
return FALSE;
g_hash_table_replace (annotations,
g_strdup ("org.flatpak.installed-size"),
g_strdup_printf ("%" G_GUINT64_FORMAT, installed_size));
g_hash_table_replace (annotations,
g_strdup ("org.flatpak.download-size"),
g_strdup_printf ("%" G_GUINT64_FORMAT, layer_desc->size));
manifest_desc = flatpak_oci_registry_store_json (registry, FLATPAK_JSON (manifest), cancellable, error);
if (manifest_desc == NULL)
return FALSE;
flatpak_oci_export_annotations (manifest->annotations, manifest_desc->annotations);
if (opt_gpg_key_ids)
{
g_autoptr(FlatpakOciSignature) sig = flatpak_oci_signature_new (manifest_desc->digest, ref);
g_autoptr(GBytes) sig_bytes = flatpak_json_to_bytes (FLATPAK_JSON (sig));
g_autoptr(GBytes) res = NULL;
g_autofree char *signature_digest = NULL;
res = flatpak_oci_sign_data (sig_bytes, (const char **)opt_gpg_key_ids, opt_gpg_homedir, error);
if (res == NULL)
return FALSE;
signature_digest = flatpak_oci_registry_store_blob (registry, res, cancellable, error);
if (signature_digest == NULL)
return FALSE;
g_hash_table_replace (manifest_desc->annotations,
g_strdup ("org.flatpak.signature-digest"),
g_strdup (signature_digest));
}
index = flatpak_oci_registry_load_index (registry, NULL, NULL, NULL, NULL);
if (index == NULL)
index = flatpak_oci_index_new ();
flatpak_oci_index_add_manifest (index, manifest_desc);
if (!flatpak_oci_registry_save_index (registry, index, cancellable, error))
return FALSE;
return TRUE;
}
gboolean
flatpak_builtin_build_bundle (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(GFile) file = NULL;
g_autoptr(GFile) repofile = NULL;
g_autoptr(OstreeRepo) repo = NULL;
g_autoptr(GError) my_error = NULL;
const char *location;
const char *filename;
const char *name;
const char *branch;
g_autofree char *full_branch = NULL;
context = g_option_context_new (_("LOCATION FILENAME NAME [BRANCH] - Create a single file bundle from a local repository"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
if (!flatpak_option_context_parse (context, options, &argc, &argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error))
return FALSE;
if (argc < 4)
return usage_error (context, _("LOCATION, FILENAME and NAME must be specified"), error);
if (argc > 5)
return usage_error (context, _("Too many arguments"), error);
location = argv[1];
filename = argv[2];
name = argv[3];
if (argc >= 5)
branch = argv[4];
else
branch = "master";
repofile = g_file_new_for_commandline_arg (location);
repo = ostree_repo_new (repofile);
if (!g_file_query_exists (repofile, cancellable))
return flatpak_fail (error, _("'%s' is not a valid repository"), location);
if (!ostree_repo_open (repo, cancellable, error))
return FALSE;
file = g_file_new_for_commandline_arg (filename);
if (ostree_repo_resolve_rev (repo, name, FALSE, NULL, NULL))
full_branch = g_strdup (name);
else
{
if (!flatpak_is_valid_name (name, &my_error))
return flatpak_fail (error, _("'%s' is not a valid name: %s"), name, my_error->message);
if (!flatpak_is_valid_branch (branch, &my_error))
return flatpak_fail (error, _("'%s' is not a valid branch name: %s"), branch, my_error->message);
if (opt_runtime)
full_branch = flatpak_build_runtime_ref (name, branch, opt_arch);
else
full_branch = flatpak_build_app_ref (name, branch, opt_arch);
}
if (opt_oci)
{
if (!build_oci (repo, file, name, full_branch, cancellable, error))
return FALSE;
}
else
{
if (!build_bundle (repo, file, name, full_branch, cancellable, error))
return FALSE;
}
return TRUE;
}
gboolean
flatpak_complete_build_bundle (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
context = g_option_context_new ("");
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv,
FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, NULL, NULL))
return FALSE;
switch (completion->argc)
{
case 0:
case 1: /* LOCATION */
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, options);
flatpak_complete_dir (completion);
break;
case 2: /* FILENAME */
flatpak_complete_file (completion);
break;
}
return TRUE;
}

View File

@ -1,423 +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 <unistd.h>
#include <string.h>
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
#include "flatpak-builtins.h"
#include "flatpak-utils.h"
static char *opt_src_repo;
static char *opt_src_ref;
static char *opt_subject;
static char *opt_body;
static gboolean opt_update_appstream;
static gboolean opt_no_update_summary;
static gboolean opt_untrusted;
static gboolean opt_force;
static char **opt_gpg_key_ids;
static char *opt_gpg_homedir;
static GOptionEntry options[] = {
{ "src-repo", 's', 0, G_OPTION_ARG_STRING, &opt_src_repo, N_("Source repo dir"), N_("SRC-REPO") },
{ "src-ref", 's', 0, G_OPTION_ARG_STRING, &opt_src_ref, N_("Source repo ref"), N_("SRC-REF") },
{ "untrusted", 0, 0, G_OPTION_ARG_NONE, &opt_untrusted, "Do not trust SRC-REPO", NULL },
{ "force", 0, 0, G_OPTION_ARG_NONE, &opt_force, "Always commit, even if same content", NULL },
{ "subject", 's', 0, G_OPTION_ARG_STRING, &opt_subject, N_("One line subject"), N_("SUBJECT") },
{ "body", 'b', 0, G_OPTION_ARG_STRING, &opt_body, N_("Full description"), N_("BODY") },
{ "update-appstream", 0, 0, G_OPTION_ARG_NONE, &opt_update_appstream, N_("Update the appstream branch"), NULL },
{ "no-update-summary", 0, 0, G_OPTION_ARG_NONE, &opt_no_update_summary, N_("Don't update the summary"), NULL },
{ "gpg-sign", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_gpg_key_ids, N_("GPG Key ID to sign the commit with"), N_("KEY-ID") },
{ "gpg-homedir", 0, 0, G_OPTION_ARG_STRING, &opt_gpg_homedir, N_("GPG Homedir to use when looking for keyrings"), N_("HOMEDIR") },
{ NULL }
};
gboolean
flatpak_builtin_build_commit_from (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(GFile) dst_repofile = NULL;
g_autoptr(OstreeRepo) dst_repo = NULL;
g_autoptr(GFile) src_repofile = NULL;
g_autoptr(OstreeRepo) src_repo = NULL;
g_autofree char *src_repo_uri = NULL;
const char *dst_repo_arg;
const char **dst_refs;
int n_dst_refs = 0;
g_autoptr(FlatpakRepoTransaction) transaction = NULL;
g_autoptr(GPtrArray) src_refs = NULL;
g_autoptr(GPtrArray) resolved_src_refs = NULL;
OstreeRepoCommitState src_commit_state;
int i;
context = g_option_context_new (_("DST-REPO [DST-REF]... - Make a new commit based on existing commit(s)"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
if (!flatpak_option_context_parse (context, options, &argc, &argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error))
return FALSE;
if (argc < 2)
return usage_error (context, _("DST-REPO must be specified"), error);
dst_repo_arg = argv[1];
dst_refs = (const char **)argv + 2;
n_dst_refs = argc - 2;
if (opt_src_repo == NULL && n_dst_refs != 1)
return usage_error (context, _("If --src-repo is not specified, exactly one destination ref must be specified"), error);
if (opt_src_ref != NULL && n_dst_refs != 1)
return usage_error (context, _("If --src-ref is specified, exactly one destination ref must be specified"), error);
if (opt_src_repo == NULL && opt_src_ref == NULL)
return flatpak_fail (error, _("Either --src-repo or --src-ref must be specified."));
dst_repofile = g_file_new_for_commandline_arg (dst_repo_arg);
if (!g_file_query_exists (dst_repofile, cancellable))
return flatpak_fail (error, _("'%s' is not a valid repository"), dst_repo_arg);
dst_repo = ostree_repo_new (dst_repofile);
if (!ostree_repo_open (dst_repo, cancellable, error))
return FALSE;
if (opt_src_repo)
{
src_repofile = g_file_new_for_commandline_arg (opt_src_repo);
if (!g_file_query_exists (src_repofile, cancellable))
return flatpak_fail (error, _("'%s' is not a valid repository"), opt_src_repo);
src_repo_uri = g_file_get_uri (src_repofile);
src_repo = ostree_repo_new (src_repofile);
if (!ostree_repo_open (src_repo, cancellable, error))
return FALSE;
}
else
{
src_repo = g_object_ref (dst_repo);
}
src_refs = g_ptr_array_new_with_free_func (g_free);
if (opt_src_ref)
{
g_assert (n_dst_refs == 1);
g_ptr_array_add (src_refs, g_strdup (opt_src_ref));
}
else
{
g_assert (opt_src_repo != NULL);
if (n_dst_refs == 0)
{
g_autofree const char **keys = NULL;
g_autoptr(GHashTable) all_src_refs = NULL;
if (!ostree_repo_list_refs (src_repo, NULL, &all_src_refs,
cancellable, error))
return FALSE;
keys = (const char **)g_hash_table_get_keys_as_array (all_src_refs, NULL);
for (i = 0; keys[i] != NULL; i++)
{
if (g_str_has_prefix (keys[i], "runtime/") ||
g_str_has_prefix (keys[i], "app/"))
g_ptr_array_add (src_refs, g_strdup (keys[i]));
}
n_dst_refs = src_refs->len;
dst_refs = (const char **)src_refs->pdata;
}
else
{
for (i = 0; i < n_dst_refs; i++)
g_ptr_array_add (src_refs, g_strdup (dst_refs[i]));
}
}
resolved_src_refs = g_ptr_array_new_with_free_func (g_free);
for (i = 0; i < src_refs->len; i++)
{
const char *src_ref = g_ptr_array_index (src_refs, i);
char *resolved_ref;
if (!ostree_repo_resolve_rev (src_repo, src_ref, FALSE, &resolved_ref, error))
return FALSE;
g_ptr_array_add (resolved_src_refs, resolved_ref);
}
if (src_repo_uri != NULL)
{
OstreeRepoPullFlags pullflags = 0;
GVariantBuilder builder;
g_autoptr(OstreeAsyncProgress) progress = NULL;
g_auto(GLnxConsoleRef) console = { 0, };
gboolean res;
if (opt_untrusted)
pullflags |= OSTREE_REPO_PULL_FLAGS_UNTRUSTED;
glnx_console_lock (&console);
if (console.is_tty)
progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, &console);
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
g_variant_builder_add (&builder, "{s@v}", "flags",
g_variant_new_variant (g_variant_new_int32 (pullflags)));
g_variant_builder_add (&builder, "{s@v}", "refs",
g_variant_new_variant (g_variant_new_strv ((const char *const*) resolved_src_refs->pdata,
resolved_src_refs->len)));
g_variant_builder_add (&builder, "{s@v}", "depth",
g_variant_new_variant (g_variant_new_int32 (0)));
res = ostree_repo_pull_with_options (dst_repo, src_repo_uri,
g_variant_builder_end (&builder),
progress,
cancellable, error);
if (progress)
ostree_async_progress_finish (progress);
if (!res)
return FALSE;
}
/* By now we have the commit with commit_id==resolved_ref and dependencies in dst_repo. We now create a new
* commit based on the toplevel tree ref from that commit.
* This is equivalent to:
* ostree commit --skip-if-unchanged --repo=${destrepo} --tree=ref=${resolved_ref}
*/
transaction = flatpak_repo_transaction_start (dst_repo, cancellable, error);
if (transaction == NULL)
return FALSE;
for (i = 0; i < resolved_src_refs->len; i ++)
{
const char *dst_ref = dst_refs[i];
const char *resolved_ref = g_ptr_array_index (resolved_src_refs, i);
g_autofree char *dst_parent = NULL;
g_autoptr(GFile) dst_parent_root = NULL;
g_autoptr(GFile) src_ref_root = NULL;
g_autoptr(GVariant) src_commitv = NULL;
g_autoptr(OstreeMutableTree) mtree = NULL;
g_autoptr(GFile) dst_root = NULL;
g_autoptr(GVariant) commitv_metadata = NULL;
const char *subject;
const char *body;
g_autofree char *commit_checksum = NULL;
GVariantBuilder metadata_builder;
gint j;
const char *dst_collection_id = NULL;
if (!ostree_repo_resolve_rev (dst_repo, dst_ref, TRUE, &dst_parent, error))
return FALSE;
if (dst_parent != NULL &&
!ostree_repo_read_commit (dst_repo, dst_parent, &dst_parent_root, NULL, cancellable, error))
return FALSE;
if (!ostree_repo_read_commit (dst_repo, resolved_ref, &src_ref_root, NULL, cancellable, error))
return FALSE;
if (!ostree_repo_load_commit (dst_repo, resolved_ref, &src_commitv, &src_commit_state, error))
return FALSE;
if (src_commit_state & OSTREE_REPO_COMMIT_STATE_PARTIAL)
return flatpak_fail (error, _("Can't commit from partial source commit."));
/* Don't create a new commit if this is the same tree */
if (!opt_force && dst_parent_root != NULL && g_file_equal (dst_parent_root, src_ref_root))
{
g_print ("%s: no change\n", dst_ref);
continue;
}
mtree = ostree_mutable_tree_new ();
if (!ostree_repo_write_directory_to_mtree (dst_repo, src_ref_root, mtree, NULL,
cancellable, error))
return FALSE;
if (!ostree_repo_write_mtree (dst_repo, mtree, &dst_root, cancellable, error))
return FALSE;
commitv_metadata = g_variant_get_child_value (src_commitv, 0);
g_variant_get_child (src_commitv, 3, "s", &subject);
if (opt_subject)
subject = (const char *)opt_subject;
g_variant_get_child (src_commitv, 4, "s", &body);
if (opt_body)
body = (const char *)opt_body;
#ifdef FLATPAK_ENABLE_P2P
dst_collection_id = ostree_repo_get_collection_id (dst_repo);
#endif /* FLATPAK_ENABLE_P2P */
/* Copy old metadata */
g_variant_builder_init (&metadata_builder, G_VARIANT_TYPE ("a{sv}"));
/* Bindings. xa.ref is deprecated but added anyway for backwards compatibility.
* Add the bindings even if we are not built with P2P support, since other
* flatpak builds might be. */
g_variant_builder_add (&metadata_builder, "{sv}", "ostree.collection-binding",
g_variant_new_string (dst_collection_id ? dst_collection_id : ""));
g_variant_builder_add (&metadata_builder, "{sv}", "ostree.ref-binding",
g_variant_new_strv (&dst_ref, 1));
g_variant_builder_add (&metadata_builder, "{sv}", "xa.ref", g_variant_new_string (dst_ref));
/* Record the source commit. This is nice to have, but it also
means the commit-from gets a different commit id, which
avoids problems with e.g. sharing .commitmeta files
(signatures) */
g_variant_builder_add (&metadata_builder, "{sv}", "xa.from_commit", g_variant_new_string (resolved_ref));
for (j = 0; j < g_variant_n_children (commitv_metadata); j++)
{
g_autoptr(GVariant) child = g_variant_get_child_value (commitv_metadata, j);
g_autoptr(GVariant) keyv = g_variant_get_child_value (child, 0);
const char *key = g_variant_get_string (keyv, NULL);
if (strcmp (key, "xa.ref") == 0 ||
strcmp (key, "xa.from_commit") == 0 ||
strcmp (key, "ostree.collection-binding") == 0 ||
strcmp (key, "ostree.ref-binding") == 0)
continue;
g_variant_builder_add_value (&metadata_builder, child);
}
if (!ostree_repo_write_commit_with_time (dst_repo, dst_parent, subject, body, g_variant_builder_end (&metadata_builder),
OSTREE_REPO_FILE (dst_root),
ostree_commit_get_timestamp (src_commitv),
&commit_checksum, cancellable, error))
return FALSE;
g_print ("%s: %s\n", dst_ref, commit_checksum);
/* This doesn't copy the detached metadata. I'm not sure if this is a problem.
* The main thing there is commit signatures, and we can't copy those, as the commit hash changes.
*/
if (opt_gpg_key_ids)
{
char **iter;
for (iter = opt_gpg_key_ids; iter && *iter; iter++)
{
const char *keyid = *iter;
g_autoptr(GError) my_error = NULL;
if (!ostree_repo_sign_commit (dst_repo,
commit_checksum,
keyid,
opt_gpg_homedir,
cancellable,
&my_error) &&
!g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_EXISTS))
{
g_propagate_error (error, g_steal_pointer (&my_error));
return FALSE;
}
}
}
#ifdef FLATPAK_ENABLE_P2P
if (dst_collection_id != NULL)
{
OstreeCollectionRef ref = { (char *) dst_collection_id, (char *) dst_ref };
ostree_repo_transaction_set_collection_ref (dst_repo, &ref, commit_checksum);
}
else
#endif /* FLATPAK_ENABLE_P2P */
{
ostree_repo_transaction_set_ref (dst_repo, NULL, dst_ref, commit_checksum);
}
}
if (!ostree_repo_commit_transaction (dst_repo, NULL, cancellable, error))
return FALSE;
if (opt_update_appstream &&
!flatpak_repo_generate_appstream (dst_repo, (const char **) opt_gpg_key_ids, opt_gpg_homedir, 0, cancellable, error))
return FALSE;
if (!opt_no_update_summary &&
!flatpak_repo_update (dst_repo,
(const char **) opt_gpg_key_ids,
opt_gpg_homedir,
cancellable,
error))
return FALSE;
return TRUE;
}
gboolean
flatpak_complete_build_commit_from (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(GFile) dst_repofile = NULL;
g_autoptr(OstreeRepo) dst_repo = NULL;
g_autoptr(GFile) src_repofile = NULL;
g_autoptr(OstreeRepo) src_repo = NULL;
context = g_option_context_new ("");
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv,
FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, NULL, NULL))
return FALSE;
switch (completion->argc)
{
case 0:
case 1: /* DST-REPO */
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, options);
flatpak_complete_dir (completion);
break;
case 2: /* DST-REF */
dst_repofile = g_file_new_for_commandline_arg (completion->argv[1]);
dst_repo = ostree_repo_new (dst_repofile);
if (ostree_repo_open (dst_repo, NULL, NULL))
flatpak_complete_ref (completion, dst_repo);
if (opt_src_repo)
{
src_repofile = g_file_new_for_commandline_arg (opt_src_repo);
src_repo = ostree_repo_new (src_repofile);
if (ostree_repo_open (src_repo, NULL, NULL))
flatpak_complete_ref (completion, src_repo);
}
break;
}
return TRUE;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,605 +0,0 @@
/*
* Copyright © 2014 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 <unistd.h>
#include <string.h>
#include <ftw.h>
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
#include "flatpak-builtins.h"
#include "flatpak-utils.h"
#include "flatpak-run.h"
static char *opt_command;
static char *opt_require_version;
static char **opt_extra_data;
static char **opt_extensions;
static char **opt_metadata;
static gboolean opt_no_exports;
static char *opt_sdk;
static char *opt_runtime;
static GOptionEntry options[] = {
{ "command", 0, 0, G_OPTION_ARG_STRING, &opt_command, N_("Command to set"), N_("COMMAND") },
{ "require-version", 0, 0, G_OPTION_ARG_STRING, &opt_require_version, N_("Flatpak version to require"), N_("MAJOR.MINOR.MICRO") },
{ "no-exports", 0, 0, G_OPTION_ARG_NONE, &opt_no_exports, N_("Don't process exports"), NULL },
{ "extra-data", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_extra_data, N_("Extra data info") },
{ "extension", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_extensions, N_("Add extension point info"), N_("NAME=VARIABLE[=VALUE]") },
{ "sdk", 0, 0, G_OPTION_ARG_STRING, &opt_sdk, N_("Change the sdk used for the app"), N_("SDK") },
{ "runtime", 0, 0, G_OPTION_ARG_STRING, &opt_runtime, N_("Change the runtime used for the app"), N_("RUNTIME") },
{ "metadata", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_metadata, N_("Set generic metadata option"), N_("GROUP=KEY[=VALUE]") },
{ NULL }
};
static gboolean
export_dir (int source_parent_fd,
const char *source_name,
const char *source_relpath,
int destination_parent_fd,
const char *destination_name,
const char *required_prefix,
GCancellable *cancellable,
GError **error)
{
int res;
g_auto(GLnxDirFdIterator) source_iter = {0};
glnx_fd_close int destination_dfd = -1;
struct dirent *dent;
if (!glnx_dirfd_iterator_init_at (source_parent_fd, source_name, FALSE, &source_iter, error))
return FALSE;
do
res = mkdirat (destination_parent_fd, destination_name, 0755);
while (G_UNLIKELY (res == -1 && errno == EINTR));
if (res == -1)
{
if (errno != EEXIST)
{
glnx_set_error_from_errno (error);
return FALSE;
}
}
if (!glnx_opendirat (destination_parent_fd, destination_name, TRUE,
&destination_dfd, error))
return FALSE;
while (TRUE)
{
struct stat stbuf;
g_autofree char *source_printable = NULL;
if (!glnx_dirfd_iterator_next_dent (&source_iter, &dent, cancellable, error))
return FALSE;
if (dent == NULL)
break;
if (fstatat (source_iter.fd, dent->d_name, &stbuf, AT_SYMLINK_NOFOLLOW) == -1)
{
if (errno == ENOENT)
{
continue;
}
else
{
glnx_set_error_from_errno (error);
return FALSE;
}
}
/* Don't export any hidden files or backups */
if (g_str_has_prefix (dent->d_name, ".") ||
g_str_has_suffix (dent->d_name, "~"))
continue;
if (S_ISDIR (stbuf.st_mode))
{
g_autofree gchar *child_relpath = g_build_filename (source_relpath, dent->d_name, NULL);
if (!export_dir (source_iter.fd, dent->d_name, child_relpath, destination_dfd, dent->d_name,
required_prefix, cancellable, error))
return FALSE;
}
else if (S_ISREG (stbuf.st_mode))
{
source_printable = g_build_filename (source_relpath, dent->d_name, NULL);
if (!flatpak_has_name_prefix (dent->d_name, required_prefix))
{
g_print ("Not exporting %s, wrong prefix\n", source_printable);
continue;
}
g_print ("Exporting %s\n", source_printable);
if (!glnx_file_copy_at (source_iter.fd, dent->d_name, &stbuf,
destination_dfd, dent->d_name,
GLNX_FILE_COPY_NOXATTRS,
cancellable,
error))
return FALSE;
}
else
{
source_printable = g_build_filename (source_relpath, dent->d_name, NULL);
g_debug ("Not exporting non-regular file %s", source_printable);
}
}
/* Try to remove the directory, as we don't want to export empty directories.
* However, don't fail if the unlink fails due to the directory not being empty */
do
res = unlinkat (destination_parent_fd, destination_name, AT_REMOVEDIR);
while (G_UNLIKELY (res == -1 && errno == EINTR));
if (res == -1)
{
if (errno != ENOTEMPTY)
{
glnx_set_error_from_errno (error);
return FALSE;
}
}
return TRUE;
}
static gboolean
copy_exports (GFile *source,
GFile *destination,
const char *source_prefix,
const char *required_prefix,
GCancellable *cancellable,
GError **error)
{
if (!flatpak_mkdir_p (destination, cancellable, error))
return FALSE;
/* The fds are closed by this call */
if (!export_dir (AT_FDCWD, flatpak_file_get_path_cached (source), source_prefix,
AT_FDCWD, flatpak_file_get_path_cached (destination),
required_prefix, cancellable, error))
return FALSE;
return TRUE;
}
static gboolean
collect_exports (GFile *base, const char *app_id, GCancellable *cancellable, GError **error)
{
g_autoptr(GFile) files = NULL;
g_autoptr(GFile) export = NULL;
const char *paths[] = {
"share/applications", /* Copy desktop files */
"share/mime/packages", /* Copy MIME Type files */
"share/icons", /* Icons */
"share/dbus-1/services", /* D-Bus service files */
"share/gnome-shell/search-providers", /* Search providers */
NULL,
};
int i;
files = g_file_get_child (base, "files");
export = g_file_get_child (base, "export");
if (!flatpak_mkdir_p (export, cancellable, error))
return FALSE;
if (opt_no_exports)
return TRUE;
for (i = 0; paths[i]; i++)
{
g_autoptr(GFile) src = NULL;
src = g_file_resolve_relative_path (files, paths[i]);
if (g_file_query_exists (src, cancellable))
{
g_debug ("Exporting from %s", paths[i]);
g_autoptr(GFile) dest = NULL;
g_autoptr(GFile) dest_parent = NULL;
dest = g_file_resolve_relative_path (export, paths[i]);
dest_parent = g_file_get_parent (dest);
g_debug ("Ensuring export/%s parent exists", paths[i]);
if (!flatpak_mkdir_p (dest_parent, cancellable, error))
return FALSE;
g_debug ("Copying from files/%s", paths[i]);
if (!copy_exports (src, dest, paths[i], app_id, cancellable, error))
return FALSE;
}
}
g_assert_no_error (*error);
return TRUE;
}
static gboolean
update_metadata (GFile *base, FlatpakContext *arg_context, gboolean is_runtime, GCancellable *cancellable, GError **error)
{
gboolean ret = FALSE;
g_autoptr(GFile) metadata = NULL;
g_autofree char *path = NULL;
g_autoptr(GKeyFile) keyfile = NULL;
g_autoptr(FlatpakContext) app_context = NULL;
GError *temp_error = NULL;
const char *group;
int i;
metadata = g_file_get_child (base, "metadata");
if (!g_file_query_exists (metadata, cancellable))
goto out;
if (is_runtime)
group = FLATPAK_METADATA_GROUP_RUNTIME;
else
group = FLATPAK_METADATA_GROUP_APPLICATION;
path = g_file_get_path (metadata);
keyfile = g_key_file_new ();
if (!g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, error))
goto out;
if (opt_sdk != NULL || opt_runtime != NULL)
{
g_autofree char *old_runtime = g_key_file_get_string (keyfile,
group,
FLATPAK_METADATA_KEY_RUNTIME, NULL);
g_autofree char *old_sdk = g_key_file_get_string (keyfile,
group,
FLATPAK_METADATA_KEY_SDK,
NULL);
const char *old_sdk_arch = NULL;
const char *old_runtime_arch = NULL;
const char *old_sdk_branch = NULL;
const char *old_runtime_branch = NULL;
g_auto(GStrv) old_sdk_parts = NULL;
g_auto(GStrv) old_runtime_parts = NULL;
if (old_sdk)
old_sdk_parts = g_strsplit (old_sdk, "/", 3);
if (old_runtime)
old_runtime_parts = g_strsplit (old_runtime, "/", 3);
if (old_sdk_parts != NULL)
{
old_sdk_arch = old_sdk_parts[1];
old_sdk_branch = old_sdk_parts[2];
}
if (old_runtime_parts != NULL)
{
old_runtime_arch = old_runtime_parts[1];
old_runtime_branch = old_runtime_parts[2];
/* Use the runtime as fallback if sdk is not specified */
if (old_sdk_parts == NULL)
{
old_sdk_arch = old_runtime_parts[1];
old_sdk_branch = old_runtime_parts[2];
}
}
if (opt_sdk)
{
g_autofree char *id = NULL;
g_autofree char *arch = NULL;
g_autofree char *branch = NULL;
g_autofree char *ref = NULL;
FlatpakKinds kinds;
if (!flatpak_split_partial_ref_arg (opt_sdk, FLATPAK_KINDS_RUNTIME,
old_sdk_arch, old_sdk_branch ? old_sdk_branch : "master",
&kinds, &id, &arch, &branch, error))
return FALSE;
ref = flatpak_build_untyped_ref (id, branch, arch);
g_key_file_set_string (keyfile, group, FLATPAK_METADATA_KEY_SDK, ref);
}
if (opt_runtime)
{
g_autofree char *id = NULL;
g_autofree char *arch = NULL;
g_autofree char *branch = NULL;
g_autofree char *ref = NULL;
FlatpakKinds kinds;
if (!flatpak_split_partial_ref_arg (opt_runtime, FLATPAK_KINDS_RUNTIME,
old_runtime_arch, old_runtime_branch ? old_runtime_branch : "master",
&kinds, &id, &arch, &branch, error))
return FALSE;
ref = flatpak_build_untyped_ref (id, branch, arch);
g_key_file_set_string (keyfile, group, FLATPAK_METADATA_KEY_RUNTIME, ref);
}
}
if (!is_runtime)
{
if (g_key_file_has_key (keyfile, group, FLATPAK_METADATA_KEY_COMMAND, NULL))
{
g_debug ("Command key is present");
if (opt_command)
g_key_file_set_string (keyfile, group, FLATPAK_METADATA_KEY_COMMAND, opt_command);
}
else if (opt_command)
{
g_debug ("Using explicitly provided command %s", opt_command);
g_key_file_set_string (keyfile, group, FLATPAK_METADATA_KEY_COMMAND, opt_command);
}
else
{
g_autofree char *command = NULL;
g_autoptr(GFile) bin_dir = NULL;
g_autoptr(GFileEnumerator) bin_enum = NULL;
g_autoptr(GFileInfo) child_info = NULL;
g_debug ("Looking for executables");
bin_dir = g_file_resolve_relative_path (base, "files/bin");
if (g_file_query_exists (bin_dir, cancellable))
{
bin_enum = g_file_enumerate_children (bin_dir, G_FILE_ATTRIBUTE_STANDARD_NAME,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
cancellable, error);
if (!bin_enum)
goto out;
while ((child_info = g_file_enumerator_next_file (bin_enum, cancellable, &temp_error)))
{
if (command != NULL)
{
g_print ("More than one executable found\n");
break;
}
command = g_strdup (g_file_info_get_name (child_info));
}
if (temp_error != NULL)
goto out;
}
if (command)
{
g_print ("Using %s as command\n", command);
g_key_file_set_string (keyfile, group, FLATPAK_METADATA_KEY_COMMAND, command);
}
else
{
g_print ("No executable found\n");
}
}
}
if (opt_require_version)
g_key_file_set_string (keyfile, group, "required-flatpak", opt_require_version);
app_context = flatpak_context_new ();
if (!flatpak_context_load_metadata (app_context, keyfile, error))
goto out;
flatpak_context_merge (app_context, arg_context);
flatpak_context_save_metadata (app_context, FALSE, keyfile);
for (i = 0; opt_extra_data != NULL && opt_extra_data[i] != NULL; i++)
{
char *extra_data = opt_extra_data[i];
g_auto(GStrv) elements = NULL;
g_autofree char *suffix = NULL;
g_autofree char *uri_key = NULL;
g_autofree char *name_key = NULL;
g_autofree char *size_key = NULL;
g_autofree char *installed_size_key = NULL;
g_autofree char *checksum_key = NULL;
if (i == 0)
suffix = g_strdup ("");
else
suffix = g_strdup_printf ("%d", i);
elements = g_strsplit (extra_data, ":", 5);
if (g_strv_length (elements) != 5)
{
flatpak_fail (error, _("Too few elements in --extra-data argument %s"), extra_data);
goto out;
}
uri_key = g_strconcat (FLATPAK_METADATA_KEY_EXTRA_DATA_URI, suffix, NULL);
name_key = g_strconcat (FLATPAK_METADATA_KEY_EXTRA_DATA_NAME, suffix, NULL);
checksum_key = g_strconcat (FLATPAK_METADATA_KEY_EXTRA_DATA_CHECKSUM,
suffix, NULL);
size_key = g_strconcat (FLATPAK_METADATA_KEY_EXTRA_DATA_SIZE, suffix, NULL);
installed_size_key = g_strconcat (FLATPAK_METADATA_KEY_EXTRA_DATA_INSTALLED_SIZE,
suffix, NULL);
if (strlen (elements[0]) > 0)
g_key_file_set_string (keyfile, FLATPAK_METADATA_GROUP_EXTRA_DATA,
name_key, elements[0]);
g_key_file_set_string (keyfile, FLATPAK_METADATA_GROUP_EXTRA_DATA,
checksum_key, elements[1]);
g_key_file_set_string (keyfile, FLATPAK_METADATA_GROUP_EXTRA_DATA,
size_key, elements[2]);
if (strlen (elements[3]) > 0)
g_key_file_set_string (keyfile, FLATPAK_METADATA_GROUP_EXTRA_DATA,
installed_size_key, elements[3]);
g_key_file_set_string (keyfile, FLATPAK_METADATA_GROUP_EXTRA_DATA,
uri_key, elements[4]);
}
for (i = 0; opt_metadata != NULL && opt_metadata[i] != NULL; i++)
{
g_auto(GStrv) elements = NULL;
elements = g_strsplit (opt_metadata[i], "=", 3);
if (g_strv_length (elements) < 2)
{
flatpak_fail (error, _("Too few elements in --metadata argument %s, format should be GROUP=KEY[=VALUE]]"), opt_metadata[i]);
goto out;
}
g_key_file_set_string (keyfile, elements[0], elements[1], elements[2] ? elements[2] : "true");
}
for (i = 0; opt_extensions != NULL && opt_extensions[i] != NULL; i++)
{
g_auto(GStrv) elements = NULL;
g_autofree char *groupname = NULL;
elements = g_strsplit (opt_extensions[i], "=", 3);
if (g_strv_length (elements) < 2)
{
flatpak_fail (error, _("Too few elements in --extension argument %s, format should be NAME=VAR[=VALUE]"), opt_extensions[i]);
goto out;
}
groupname = g_strconcat (FLATPAK_METADATA_GROUP_PREFIX_EXTENSION,
elements[0], NULL);
g_key_file_set_string (keyfile, groupname, elements[1], elements[2] ? elements[2] : "true");
}
if (!g_key_file_save_to_file (keyfile, path, error))
goto out;
ret = TRUE;
out:
if (temp_error != NULL)
g_propagate_error (error, temp_error);
return ret;
}
gboolean
flatpak_builtin_build_finish (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(GFile) base = NULL;
g_autoptr(GFile) files_dir = NULL;
g_autoptr(GFile) export_dir = NULL;
g_autoptr(GFile) metadata_file = NULL;
g_autofree char *metadata_contents = NULL;
g_autofree char *id = NULL;
gboolean is_runtime = FALSE;
gsize metadata_size;
const char *directory;
g_autoptr(GKeyFile) metakey = NULL;
g_autoptr(FlatpakContext) arg_context = NULL;
context = g_option_context_new (_("DIRECTORY - Finalize a build directory"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
arg_context = flatpak_context_new ();
g_option_context_add_group (context, flatpak_context_get_options (arg_context));
if (!flatpak_option_context_parse (context, options, &argc, &argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error))
return FALSE;
if (argc < 2)
return usage_error (context, _("DIRECTORY must be specified"), error);
directory = argv[1];
base = g_file_new_for_commandline_arg (directory);
files_dir = g_file_get_child (base, "files");
export_dir = g_file_get_child (base, "export");
metadata_file = g_file_get_child (base, "metadata");
if (!g_file_query_exists (files_dir, cancellable) ||
!g_file_query_exists (metadata_file, cancellable))
return flatpak_fail (error, _("Build directory %s not initialized"), directory);
if (!g_file_load_contents (metadata_file, cancellable, &metadata_contents, &metadata_size, NULL, error))
return FALSE;
metakey = g_key_file_new ();
if (!g_key_file_load_from_data (metakey, metadata_contents, metadata_size, 0, error))
return FALSE;
id = g_key_file_get_string (metakey, FLATPAK_METADATA_GROUP_APPLICATION,
FLATPAK_METADATA_KEY_NAME, NULL);
if (id == NULL)
{
id = g_key_file_get_string (metakey, FLATPAK_METADATA_GROUP_RUNTIME,
FLATPAK_METADATA_KEY_NAME, NULL);
if (id == NULL)
return flatpak_fail (error, _("No name specified in the metadata"));
is_runtime = TRUE;
}
if (g_file_query_exists (export_dir, cancellable))
return flatpak_fail (error, _("Build directory %s already finalized"), directory);
if (!is_runtime)
{
g_debug ("Collecting exports");
if (!collect_exports (base, id, cancellable, error))
return FALSE;
}
g_debug ("Updating metadata");
if (!update_metadata (base, arg_context, is_runtime, cancellable, error))
return FALSE;
g_print (_("Please review the exported files and the metadata\n"));
return TRUE;
}
gboolean
flatpak_complete_build_finish (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakContext) arg_context = NULL;
context = g_option_context_new ("");
arg_context = flatpak_context_new ();
g_option_context_add_group (context, flatpak_context_get_options (arg_context));
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv,
FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, NULL, NULL))
return FALSE;
switch (completion->argc)
{
case 0:
case 1: /* DIR */
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, options);
flatpak_context_complete (arg_context, completion);
flatpak_complete_dir (completion);
break;
}
return TRUE;
}

View File

@ -1,272 +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 <unistd.h>
#include <string.h>
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
#include "flatpak-builtins.h"
#include "flatpak-utils.h"
#include "flatpak-oci-registry.h"
static char *opt_ref;
static gboolean opt_oci = FALSE;
static char **opt_gpg_key_ids;
static char *opt_gpg_homedir;
static gboolean opt_update_appstream;
static gboolean opt_no_update_summary;
static GOptionEntry options[] = {
{ "ref", 0, 0, G_OPTION_ARG_STRING, &opt_ref, N_("Override the ref used for the imported bundle"), N_("REF") },
{ "oci", 0, 0, G_OPTION_ARG_NONE, &opt_oci, N_("Import oci image instead of flatpak bundle"), NULL },
{ "gpg-sign", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_gpg_key_ids, N_("GPG Key ID to sign the commit with"), N_("KEY-ID") },
{ "gpg-homedir", 0, 0, G_OPTION_ARG_STRING, &opt_gpg_homedir, N_("GPG Homedir to use when looking for keyrings"), N_("HOMEDIR") },
{ "update-appstream", 0, 0, G_OPTION_ARG_NONE, &opt_update_appstream, N_("Update the appstream branch"), NULL },
{ "no-update-summary", 0, 0, G_OPTION_ARG_NONE, &opt_no_update_summary, N_("Don't update the summary"), NULL },
{ NULL }
};
static char *
import_oci (OstreeRepo *repo, GFile *file,
GCancellable *cancellable, GError **error)
{
g_autofree char *commit_checksum = NULL;
g_autofree char *dir_uri = NULL;
g_autofree char *target_ref = NULL;
const char *oci_digest;
g_autoptr(FlatpakOciRegistry) registry = NULL;
g_autoptr(FlatpakOciVersioned) versioned = NULL;
FlatpakOciManifest *manifest = NULL;
g_autoptr(FlatpakOciIndex) index = NULL;
const FlatpakOciManifestDescriptor *desc;
GHashTable *annotations;
dir_uri = g_file_get_uri (file);
registry = flatpak_oci_registry_new (dir_uri, FALSE, -1, cancellable, error);
if (registry == NULL)
return NULL;
index = flatpak_oci_registry_load_index (registry, NULL, NULL, cancellable, error);
if (index == NULL)
return NULL;
if (opt_ref)
{
desc = flatpak_oci_index_get_manifest (index, opt_ref);
if (desc == NULL)
{
flatpak_fail (error, _("Ref '%s' not found in registry"), opt_ref);
return NULL;
}
}
else
{
desc = flatpak_oci_index_get_only_manifest (index);
if (desc == NULL)
{
flatpak_fail (error, _("Multiple images in registry, specify a ref with --ref"));
return NULL;
}
}
oci_digest = desc->parent.digest;
versioned = flatpak_oci_registry_load_versioned (registry,
oci_digest, NULL,
cancellable, error);
if (versioned == NULL)
return NULL;
manifest = FLATPAK_OCI_MANIFEST (versioned);
annotations = flatpak_oci_manifest_get_annotations (manifest);
if (annotations)
flatpak_oci_parse_commit_annotations (annotations, NULL, NULL, NULL,
&target_ref, NULL, NULL, NULL);
if (target_ref == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
"The OCI image didn't specify a ref, use --ref to specify one");
return NULL;
}
commit_checksum = flatpak_pull_from_oci (repo, registry, oci_digest, manifest,
NULL, target_ref, NULL, NULL, NULL, cancellable, error);
if (commit_checksum == NULL)
return NULL;
g_print ("Importing %s (%s)\n", target_ref, commit_checksum);
return g_strdup (commit_checksum);
}
static char *
import_bundle (OstreeRepo *repo, GFile *file,
GCancellable *cancellable, GError **error)
{
g_autoptr(GVariant) metadata = NULL;
g_autofree char *bundle_ref = NULL;
g_autofree char *to_checksum = NULL;
const char *ref;
/* Dont need to check the collection ID of the bundle here;
* flatpak_pull_from_bundle() does that. */
metadata = flatpak_bundle_load (file, &to_checksum,
&bundle_ref,
NULL, NULL, NULL,
NULL, NULL, NULL, error);
if (metadata == NULL)
return NULL;
if (opt_ref != NULL)
ref = opt_ref;
else
ref = bundle_ref;
g_print ("Importing %s (%s)\n", ref, to_checksum);
if (!flatpak_pull_from_bundle (repo, file,
NULL, ref, FALSE,
cancellable,
error))
return NULL;
return g_strdup (to_checksum);
}
gboolean
flatpak_builtin_build_import (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(GFile) file = NULL;
g_autoptr(GFile) repofile = NULL;
g_autoptr(OstreeRepo) repo = NULL;
const char *location;
const char *filename;
g_autofree char *commit = NULL;
context = g_option_context_new (_("LOCATION FILENAME - Import a file bundle into a local repository"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
if (!flatpak_option_context_parse (context, options, &argc, &argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error))
return FALSE;
if (argc < 3)
return usage_error (context, _("LOCATION and FILENAME must be specified"), error);
if (argc > 3)
return usage_error (context, _("Too many arguments"), error);
location = argv[1];
filename = argv[2];
repofile = g_file_new_for_commandline_arg (location);
repo = ostree_repo_new (repofile);
if (!g_file_query_exists (repofile, cancellable))
return flatpak_fail (error, _("'%s' is not a valid repository"), location);
file = g_file_new_for_commandline_arg (filename);
if (!ostree_repo_open (repo, cancellable, error))
return FALSE;
if (opt_oci)
commit = import_oci (repo, file, cancellable, error);
else
commit = import_bundle (repo, file, cancellable, error);
if (commit == NULL)
return FALSE;
if (opt_gpg_key_ids)
{
char **iter;
for (iter = opt_gpg_key_ids; iter && *iter; iter++)
{
const char *keyid = *iter;
g_autoptr(GError) local_error = NULL;
if (!ostree_repo_sign_commit (repo,
commit,
keyid,
opt_gpg_homedir,
cancellable,
&local_error))
{
if (!g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_EXISTS))
{
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}
}
}
}
if (opt_update_appstream &&
!flatpak_repo_generate_appstream (repo, (const char **) opt_gpg_key_ids, opt_gpg_homedir, 0, cancellable, error))
return FALSE;
if (!opt_no_update_summary &&
!flatpak_repo_update (repo,
(const char **) opt_gpg_key_ids,
opt_gpg_homedir,
cancellable,
error))
return FALSE;
return TRUE;
}
gboolean
flatpak_complete_build_import (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
context = g_option_context_new ("");
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv,
FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, NULL, NULL))
return FALSE;
switch (completion->argc)
{
case 0:
case 1: /* LOCATION */
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, options);
flatpak_complete_dir (completion);
break;
case 2: /* FILENAME */
flatpak_complete_file (completion);
break;
}
return TRUE;
}

View File

@ -1,471 +0,0 @@
/*
* Copyright © 2014 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 <unistd.h>
#include <string.h>
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
#include "flatpak-builtins.h"
#include "flatpak-builtins-utils.h"
#include "flatpak-utils.h"
static char *opt_arch;
static char *opt_var;
static char *opt_type;
static char *opt_sdk_dir;
static char **opt_sdk_extensions;
static char **opt_tags;
static char *opt_base;
static char *opt_base_version;
static char **opt_base_extensions;
static gboolean opt_writable_sdk;
static gboolean opt_update;
static GOptionEntry options[] = {
{ "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, N_("Arch to use"), N_("ARCH") },
{ "var", 'v', 0, G_OPTION_ARG_STRING, &opt_var, N_("Initialize var from named runtime"), N_("RUNTIME") },
{ "base", 0, 0, G_OPTION_ARG_STRING, &opt_base, N_("Initialize apps from named app"), N_("APP") },
{ "base-version", 0, 0, G_OPTION_ARG_STRING, &opt_base_version, N_("Specify version for --base"), N_("VERSION") },
{ "base-extension", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_base_extensions, N_("Include this base extension"), N_("EXTENSION") },
{ "writable-sdk", 'w', 0, G_OPTION_ARG_NONE, &opt_writable_sdk, N_("Initialize /usr with a writable copy of the sdk"), NULL },
{ "type", 0, 0, G_OPTION_ARG_STRING, &opt_type, N_("Specify the build type (app, runtime, extension)"), N_("TYPE") },
{ "tag", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_tags, N_("Add a tag"), N_("TAG") },
{ "sdk-extension", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_sdk_extensions, N_("Include this sdk extension in /usr"), N_("EXTENSION") },
{ "sdk-dir", 0, 0, G_OPTION_ARG_STRING, &opt_sdk_dir, N_("Where to store sdk (defaults to 'usr')"), N_("DIR") },
{ "update", 0, 0, G_OPTION_ARG_NONE, &opt_update, N_("Re-initialize the sdk/var"), NULL },
{ NULL }
};
static gboolean
ensure_extensions (FlatpakDeploy *src_deploy, const char *default_branch,
char *src_extensions[], GFile *top_dir, GCancellable *cancellable, GError **error)
{
g_autoptr(GKeyFile) metakey = flatpak_deploy_get_metadata (src_deploy);
GList *extensions = NULL, *l;
int i;
/* We leak this on failure, as we have no autoptr for deep lists.. */
extensions = flatpak_list_extensions (metakey, opt_arch, default_branch);
for (i = 0; src_extensions[i] != NULL; i++)
{
const char *requested_extension = src_extensions[i];
gboolean found = FALSE;
for (l = extensions; l != NULL; l = l->next)
{
FlatpakExtension *ext = l->data;
if (strcmp (ext->installed_id, requested_extension) == 0 ||
strcmp (ext->id, requested_extension) == 0)
{
if (!ext->is_unmaintained)
{
g_autoptr(FlatpakDir) src_dir = NULL;
g_autoptr(GFile) deploy = NULL;
g_autoptr(GVariant) deploy_data = NULL;
const char **subpaths;
deploy = flatpak_find_deploy_dir_for_ref (ext->ref, &src_dir, cancellable, error);
if (deploy == NULL)
return FALSE;
deploy_data = flatpak_dir_get_deploy_data (src_dir, ext->ref, cancellable, error);
if (deploy_data == NULL)
return FALSE;
subpaths = flatpak_deploy_data_get_subpaths (deploy_data);
if (subpaths[0] != NULL)
return flatpak_fail (error, _("Requested extension %s is only partially installed"), ext->installed_id);
}
if (top_dir)
{
g_autoptr(GFile) target = g_file_resolve_relative_path (top_dir, ext->directory);
g_autoptr(GFile) target_parent = g_file_get_parent (target);
g_autoptr(GFile) ext_deploy_files = g_file_new_for_path (ext->files_path);
if (!flatpak_mkdir_p (target_parent, cancellable, error))
return FALSE;
/* An extension overrides whatever is there before, so we clean up first */
if (!flatpak_rm_rf (target, cancellable, error))
return FALSE;
if (!flatpak_cp_a (ext_deploy_files, target,
FLATPAK_CP_FLAGS_NO_CHOWN,
cancellable, error))
return FALSE;
}
found = TRUE;
}
}
if (!found)
{
g_list_free_full (extensions, (GDestroyNotify) flatpak_extension_free);
return flatpak_fail (error, _("Requested extension %s not installed"), requested_extension);
}
}
g_list_free_full (extensions, (GDestroyNotify) flatpak_extension_free);
return TRUE;
}
gboolean
flatpak_builtin_build_init (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(GFile) var_deploy_files = NULL;
g_autoptr(GFile) base = NULL;
g_autoptr(GFile) files_dir = NULL;
g_autoptr(GFile) usr_dir = NULL;
g_autoptr(GFile) var_dir = NULL;
g_autoptr(GFile) var_tmp_dir = NULL;
g_autoptr(GFile) var_run_dir = NULL;
g_autoptr(GFile) metadata_file = NULL;
g_autoptr(GString) metadata_contents = NULL;
g_autoptr(GError) my_error = NULL;
g_autoptr(FlatpakDeploy) sdk_deploy = NULL;
const char *app_id;
const char *directory;
const char *sdk_pref;
const char *runtime_pref;
const char *default_branch = NULL;
g_autofree char *runtime_ref = NULL;
g_autofree char *var_ref = NULL;
g_autofree char *sdk_ref = NULL;
FlatpakKinds kinds;
int i;
g_autoptr(FlatpakDir) sdk_dir = NULL;
g_autoptr(FlatpakDir) runtime_dir = NULL;
gboolean is_app = FALSE;
gboolean is_extension = FALSE;
gboolean is_runtime = FALSE;
context = g_option_context_new (_("DIRECTORY APPNAME SDK RUNTIME [BRANCH] - Initialize a directory for building"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
if (!flatpak_option_context_parse (context, options, &argc, &argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error))
return FALSE;
if (argc < 5)
return usage_error (context, _("RUNTIME must be specified"), error);
if (argc > 6)
return usage_error (context, _("Too many arguments"), error);
directory = argv[1];
app_id = argv[2];
sdk_pref = argv[3];
runtime_pref = argv[4];
if (argc >= 6)
default_branch = argv[5];
if (opt_type != NULL)
{
if (strcmp (opt_type, "app") == 0)
is_app = TRUE;
else if (strcmp (opt_type, "extension") == 0)
is_extension = TRUE;
else if (strcmp (opt_type, "runtime") == 0)
is_runtime = TRUE;
else
return flatpak_fail (error, _("'%s' is not a valid build type name, use app, runtime or extension"), opt_type);
}
else
is_app = TRUE;
if (!flatpak_is_valid_name (app_id, &my_error))
return flatpak_fail (error, _("'%s' is not a valid application name: %s"), app_id, my_error->message);
kinds = FLATPAK_KINDS_RUNTIME;
sdk_dir = flatpak_find_installed_pref (sdk_pref, kinds, opt_arch, default_branch, TRUE, FALSE, FALSE, NULL,
&sdk_ref, cancellable, error);
if (sdk_dir == NULL)
return FALSE;
kinds = FLATPAK_KINDS_RUNTIME;
if (is_extension)
kinds |= FLATPAK_KINDS_APP;
runtime_dir = flatpak_find_installed_pref (runtime_pref, kinds, opt_arch, default_branch, TRUE, FALSE, FALSE, NULL,
&runtime_ref, cancellable, error);
if (runtime_dir == NULL)
return FALSE;
base = g_file_new_for_commandline_arg (directory);
if (!flatpak_mkdir_p (base, cancellable, error))
return FALSE;
files_dir = g_file_get_child (base, "files");
var_dir = g_file_get_child (base, "var");
var_tmp_dir = g_file_get_child (var_dir, "tmp");
var_run_dir = g_file_get_child (var_dir, "run");
metadata_file = g_file_get_child (base, "metadata");
if (!opt_update &&
g_file_query_exists (files_dir, cancellable))
return flatpak_fail (error, _("Build directory %s already initialized"), directory);
sdk_deploy = flatpak_dir_load_deployed (sdk_dir, sdk_ref, NULL, cancellable, error);
if (sdk_deploy == NULL)
return FALSE;
if (opt_writable_sdk || is_runtime)
{
g_autoptr(GFile) sdk_deploy_files = NULL;
if (opt_sdk_dir)
usr_dir = g_file_get_child (base, opt_sdk_dir);
else
usr_dir = g_file_get_child (base, "usr");
if (!flatpak_rm_rf (usr_dir, NULL, &my_error))
{
if (!g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
g_propagate_error (error, g_steal_pointer (&my_error));
return FALSE;
}
g_clear_error (&my_error);
}
sdk_deploy_files = flatpak_deploy_get_files (sdk_deploy);
if (!flatpak_cp_a (sdk_deploy_files, usr_dir, FLATPAK_CP_FLAGS_NO_CHOWN, cancellable, error))
return FALSE;
}
if (opt_sdk_extensions &&
!ensure_extensions (sdk_deploy, default_branch,
opt_sdk_extensions, usr_dir, cancellable, error))
return FALSE;
if (opt_var)
{
var_ref = flatpak_build_runtime_ref (opt_var, default_branch, opt_arch);
var_deploy_files = flatpak_find_files_dir_for_ref (var_ref, cancellable, error);
if (var_deploy_files == NULL)
return FALSE;
}
if (opt_update)
return TRUE;
if (!g_file_make_directory (files_dir, cancellable, error))
return FALSE;
if (opt_base)
{
const char *base_branch;
g_autofree char *base_ref = NULL;
g_autoptr(GFile) base_deploy_files = NULL;
g_autoptr(FlatpakDeploy) base_deploy = NULL;
base_branch = opt_base_version ? opt_base_version : "master";
base_ref = flatpak_build_app_ref (opt_base, base_branch, opt_arch);
base_deploy = flatpak_find_deploy_for_ref (base_ref, cancellable, error);
if (base_deploy == NULL)
return FALSE;
base_deploy_files = flatpak_deploy_get_files (base_deploy);
if (!flatpak_cp_a (base_deploy_files, files_dir,
FLATPAK_CP_FLAGS_MERGE | FLATPAK_CP_FLAGS_NO_CHOWN,
cancellable, error))
return FALSE;
if (opt_base_extensions &&
!ensure_extensions (base_deploy, base_branch, opt_base_extensions, files_dir, cancellable, error))
return FALSE;
}
if (var_deploy_files)
{
if (!flatpak_cp_a (var_deploy_files, var_dir, FLATPAK_CP_FLAGS_NONE, cancellable, error))
return FALSE;
}
else
{
if (!g_file_make_directory (var_dir, cancellable, error))
return FALSE;
}
if (!flatpak_mkdir_p (var_tmp_dir, cancellable, error))
return FALSE;
if (!g_file_query_exists (var_run_dir, cancellable) &&
!g_file_make_symbolic_link (var_run_dir, "/run", cancellable, error))
return FALSE;
metadata_contents = g_string_new ("");
if (is_app)
g_string_append (metadata_contents, "[Application]\n");
else
g_string_append (metadata_contents, "[Runtime]\n");
g_string_append_printf (metadata_contents,
"name=%s\n",
app_id);
/* The "runtime" can be an app in case we're building an extension */
if (g_str_has_prefix (runtime_ref, "runtime/"))
g_string_append_printf (metadata_contents,
"runtime=%s\n",
runtime_ref + strlen ("runtime/"));
if (g_str_has_prefix (sdk_ref, "runtime/"))
g_string_append_printf (metadata_contents,
"sdk=%s\n",
sdk_ref + strlen ("runtime/"));
if (opt_tags != NULL)
{
g_string_append (metadata_contents, "tags=");
for (i = 0; opt_tags[i] != NULL; i++)
{
g_string_append (metadata_contents, opt_tags[i]);
g_string_append_c (metadata_contents, ';');
}
g_string_append_c (metadata_contents, '\n');
}
if (is_extension)
g_string_append_printf (metadata_contents,
"\n"
"[ExtensionOf]\n"
"ref=%s\n",
runtime_ref);
if (!g_file_replace_contents (metadata_file,
metadata_contents->str, metadata_contents->len, NULL, FALSE,
G_FILE_CREATE_REPLACE_DESTINATION,
NULL, cancellable, error))
return FALSE;
return TRUE;
}
gboolean
flatpak_complete_build_init (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDir) user_dir = NULL;
g_autoptr(FlatpakDir) system_dir = NULL;
g_autoptr(GError) error = NULL;
int i;
context = g_option_context_new ("");
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv,
FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, NULL, NULL))
return FALSE;
switch (completion->argc)
{
case 0:
case 1: /* DIR */
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, options);
flatpak_complete_dir (completion);
break;
case 2: /* APP */
break;
case 3: /* RUNTIME */
case 4: /* SDK */
user_dir = flatpak_dir_get_user ();
{
g_auto(GStrv) refs = flatpak_dir_find_installed_refs (user_dir, NULL, NULL, opt_arch,
FLATPAK_KINDS_RUNTIME, &error);
if (refs == NULL)
flatpak_completion_debug ("find local refs error: %s", error->message);
for (i = 0; refs != NULL && refs[i] != NULL; i++)
{
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
if (parts)
flatpak_complete_word (completion, "%s ", parts[1]);
}
}
system_dir = flatpak_dir_get_system_default ();
{
g_auto(GStrv) refs = flatpak_dir_find_installed_refs (system_dir, NULL, NULL, opt_arch,
FLATPAK_KINDS_RUNTIME, &error);
if (refs == NULL)
flatpak_completion_debug ("find local refs error: %s", error->message);
for (i = 0; refs != NULL && refs[i] != NULL; i++)
{
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
if (parts)
flatpak_complete_word (completion, "%s ", parts[1]);
}
}
break;
case 5: /* BRANCH */
user_dir = flatpak_dir_get_user ();
{
g_auto(GStrv) refs = flatpak_dir_find_installed_refs (user_dir, completion->argv[3], NULL, opt_arch,
FLATPAK_KINDS_RUNTIME, &error);
if (refs == NULL)
flatpak_completion_debug ("find local refs error: %s", error->message);
for (i = 0; refs != NULL && refs[i] != NULL; i++)
{
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
if (parts)
flatpak_complete_word (completion, "%s ", parts[3]);
}
}
system_dir = flatpak_dir_get_system_default ();
{
g_auto(GStrv) refs = flatpak_dir_find_installed_refs (system_dir, completion->argv[3], NULL, opt_arch,
FLATPAK_KINDS_RUNTIME, &error);
if (refs == NULL)
flatpak_completion_debug ("find local refs error: %s", error->message);
for (i = 0; refs != NULL && refs[i] != NULL; i++)
{
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
if (parts)
flatpak_complete_word (completion, "%s ", parts[3]);
}
}
break;
}
return TRUE;
}

View File

@ -1,192 +0,0 @@
/*
* Copyright © 2014 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 <unistd.h>
#include <string.h>
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
#include "flatpak-builtins.h"
#include "flatpak-utils.h"
static char *opt_arch;
static gboolean opt_runtime;
static char **opt_gpg_key_ids;
static char *opt_gpg_homedir;
static GOptionEntry options[] = {
{ "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, N_("Arch to install for"), N_("ARCH") },
{ "runtime", 0, 0, G_OPTION_ARG_NONE, &opt_runtime, N_("Look for runtime with the specified name"), NULL },
{ "gpg-sign", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_gpg_key_ids, N_("GPG Key ID to sign the commit with"), N_("KEY-ID") },
{ "gpg-homedir", 0, 0, G_OPTION_ARG_STRING, &opt_gpg_homedir, N_("GPG Homedir to use when looking for keyrings"), N_("HOMEDIR") },
{ NULL }
};
gboolean
flatpak_builtin_build_sign (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(GFile) repofile = NULL;
g_autoptr(OstreeRepo) repo = NULL;
g_autoptr(GError) my_error = NULL;
const char *location;
const char *branch;
const char *id = NULL;
g_autofree char *commit_checksum = NULL;
int i;
char **iter;
g_autoptr(GPtrArray) refs = g_ptr_array_new_with_free_func (g_free);
context = g_option_context_new (_("LOCATION [ID [BRANCH]] - Sign an application or runtime"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
if (!flatpak_option_context_parse (context, options, &argc, &argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error))
return FALSE;
if (argc < 2)
return usage_error (context, _("LOCATION must be specified"), error);
if (argc > 4)
return usage_error (context, _("Too many arguments"), error);
location = argv[1];
if (argc >= 3)
id = argv[2];
if (argc >= 4)
branch = argv[3];
else
branch = "master";
if (id != NULL && !flatpak_is_valid_name (id, &my_error))
return flatpak_fail (error, _("'%s' is not a valid name: %s"), id, my_error->message);
if (!flatpak_is_valid_branch (branch, &my_error))
return flatpak_fail (error, _("'%s' is not a valid branch name: %s"), branch, my_error->message);
if (opt_gpg_key_ids == NULL)
return flatpak_fail (error, _("No gpg key ids specified"));
repofile = g_file_new_for_commandline_arg (location);
repo = ostree_repo_new (repofile);
if (!ostree_repo_open (repo, cancellable, error))
return FALSE;
if (id)
{
g_autofree char *ref = NULL;
if (opt_runtime)
ref = flatpak_build_runtime_ref (id, branch, opt_arch);
else
ref = flatpak_build_app_ref (id, branch, opt_arch);
g_ptr_array_add (refs, g_steal_pointer (&ref));
}
else
{
g_autoptr(GHashTable) all_refs = NULL;
GHashTableIter hashiter;
gpointer key, value;
if (!ostree_repo_list_refs_ext (repo, NULL, &all_refs,
OSTREE_REPO_LIST_REFS_EXT_NONE,
cancellable, error))
return FALSE;
/* Merge the prefix refs to the full refs table */
g_hash_table_iter_init (&hashiter, all_refs);
while (g_hash_table_iter_next (&hashiter, &key, &value))
{
if (g_str_has_prefix (key, "app/") ||
g_str_has_prefix (key, "runtime/"))
g_ptr_array_add (refs, g_strdup (key));
}
}
for (i = 0; i < refs->len; i++)
{
const char *ref = g_ptr_array_index (refs, i);
if (!ostree_repo_resolve_rev (repo, ref, FALSE, &commit_checksum, error))
return FALSE;
for (iter = opt_gpg_key_ids; iter && *iter; iter++)
{
const char *keyid = *iter;
g_autoptr(GError) local_error = NULL;
if (!ostree_repo_sign_commit (repo,
commit_checksum,
keyid,
opt_gpg_homedir,
cancellable,
&local_error))
{
if (!g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_EXISTS))
{
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}
}
}
}
return TRUE;
}
gboolean
flatpak_complete_build_sign (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
context = g_option_context_new ("");
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv,
FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, NULL, NULL))
return FALSE;
switch (completion->argc)
{
case 0:
case 1: /* LOCATION */
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, options);
flatpak_complete_dir (completion);
break;
case 2: /* ID */
break;
case 3: /* BRANCH */
break;
}
return TRUE;
}

View File

@ -1,440 +0,0 @@
/*
* Copyright © 2014 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 <errno.h>
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
#include "flatpak-builtins.h"
#include "flatpak-utils.h"
#include "flatpak-run.h"
static gboolean opt_runtime;
static char *opt_build_dir;
static char **opt_bind_mounts;
static char *opt_sdk_dir;
static char *opt_metadata;
static GOptionEntry options[] = {
{ "runtime", 'r', 0, G_OPTION_ARG_NONE, &opt_runtime, N_("Use Platform runtime rather than Sdk"), NULL },
{ "bind-mount", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_bind_mounts, N_("Add bind mount"), N_("DEST=SRC") },
{ "build-dir", 0, 0, G_OPTION_ARG_STRING, &opt_build_dir, N_("Start build in this directory"), N_("DIR") },
{ "sdk-dir", 0, 0, G_OPTION_ARG_STRING, &opt_sdk_dir, N_("Where to look for custom sdk dir (defaults to 'usr')"), N_("DIR") },
{ "metadata", 0, 0, G_OPTION_ARG_STRING, &opt_metadata, N_("Use alternative file for the metadata"), N_("FILE") },
{ NULL }
};
static void
add_args (GPtrArray *argv_array, ...)
{
va_list args;
const gchar *arg;
va_start (args, argv_array);
while ((arg = va_arg (args, const gchar *)))
g_ptr_array_add (argv_array, g_strdup (arg));
va_end (args);
}
gboolean
flatpak_builtin_build (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDeploy) runtime_deploy = NULL;
g_autoptr(FlatpakDeploy) extensionof_deploy = NULL;
g_autoptr(GFile) var = NULL;
g_autoptr(GFile) usr = NULL;
g_autoptr(GFile) res_deploy = NULL;
g_autoptr(GFile) res_files = NULL;
g_autoptr(GFile) app_files = NULL;
gboolean app_files_ro = FALSE;
g_autoptr(GFile) runtime_files = NULL;
g_autoptr(GFile) metadata = NULL;
g_autofree char *metadata_contents = NULL;
g_autofree char *runtime = NULL;
g_autofree char *runtime_ref = NULL;
g_autofree char *extensionof_ref = NULL;
g_autofree char *extension_point = NULL;
g_autofree char *extension_tmpfs_point = NULL;
g_autoptr(GKeyFile) metakey = NULL;
g_autoptr(GKeyFile) runtime_metakey = NULL;
g_autoptr(GPtrArray) argv_array = NULL;
g_auto(GStrv) envp = NULL;
gsize metadata_size;
const char *directory = NULL;
const char *command = "/bin/sh";
g_autofree char *id = NULL;
int i;
int rest_argv_start, rest_argc;
g_autoptr(FlatpakContext) arg_context = NULL;
g_autoptr(FlatpakContext) app_context = NULL;
gboolean custom_usr;
g_auto(GStrv) runtime_ref_parts = NULL;
FlatpakRunFlags run_flags;
const char *group = NULL;
const char *runtime_key = NULL;
const char *dest = NULL;
gboolean is_app = FALSE;
gboolean is_extension = FALSE;
gboolean is_app_extension = FALSE;
g_autofree char *app_info_path = NULL;
context = g_option_context_new (_("DIRECTORY [COMMAND [args...]] - Build in directory"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
rest_argc = 0;
for (i = 1; i < argc; i++)
{
/* The non-option is the directory, take it out of the arguments */
if (argv[i][0] != '-')
{
rest_argv_start = i;
rest_argc = argc - i;
argc = i;
break;
}
}
arg_context = flatpak_context_new ();
g_option_context_add_group (context, flatpak_context_get_options (arg_context));
if (!flatpak_option_context_parse (context, options, &argc, &argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error))
return FALSE;
if (rest_argc == 0)
return usage_error (context, _("DIRECTORY must be specified"), error);
directory = argv[rest_argv_start];
if (rest_argc >= 2)
command = argv[rest_argv_start + 1];
res_deploy = g_file_new_for_commandline_arg (directory);
metadata = g_file_get_child (res_deploy, opt_metadata ? opt_metadata : "metadata");
if (!g_file_query_exists (res_deploy, NULL) ||
!g_file_query_exists (metadata, NULL))
return flatpak_fail (error, _("Build directory %s not initialized, use flatpak build-init"), directory);
if (!g_file_load_contents (metadata, cancellable, &metadata_contents, &metadata_size, NULL, error))
return FALSE;
metakey = g_key_file_new ();
if (!g_key_file_load_from_data (metakey, metadata_contents, metadata_size, 0, error))
return FALSE;
if (g_key_file_has_group (metakey, FLATPAK_METADATA_GROUP_APPLICATION))
{
group = FLATPAK_METADATA_GROUP_APPLICATION;
is_app = TRUE;
}
else if (g_key_file_has_group (metakey, FLATPAK_METADATA_GROUP_RUNTIME))
{
group = FLATPAK_METADATA_GROUP_RUNTIME;
}
else
return flatpak_fail (error, _("metadata invalid, not application or runtime"));
extensionof_ref = g_key_file_get_string (metakey,
FLATPAK_METADATA_GROUP_EXTENSION_OF,
FLATPAK_METADATA_KEY_REF, NULL);
if (extensionof_ref != NULL)
{
is_extension = TRUE;
if (g_str_has_prefix (extensionof_ref, "app/"))
is_app_extension = TRUE;
}
id = g_key_file_get_string (metakey, group, FLATPAK_METADATA_KEY_NAME, error);
if (id == NULL)
return FALSE;
if (opt_runtime)
runtime_key = FLATPAK_METADATA_KEY_RUNTIME;
else
runtime_key = FLATPAK_METADATA_KEY_SDK;
runtime = g_key_file_get_string (metakey, group, runtime_key, error);
if (runtime == NULL)
return FALSE;
runtime_ref = g_build_filename ("runtime", runtime, NULL);
runtime_ref_parts = flatpak_decompose_ref (runtime_ref, error);
if (runtime_ref_parts == NULL)
return FALSE;
custom_usr = FALSE;
usr = g_file_get_child (res_deploy, opt_sdk_dir ? opt_sdk_dir : "usr");
if (g_file_query_exists (usr, cancellable))
{
custom_usr = TRUE;
runtime_files = g_object_ref (usr);
}
else
{
runtime_deploy = flatpak_find_deploy_for_ref (runtime_ref, cancellable, error);
if (runtime_deploy == NULL)
return FALSE;
runtime_metakey = flatpak_deploy_get_metadata (runtime_deploy);
runtime_files = flatpak_deploy_get_files (runtime_deploy);
}
var = g_file_get_child (res_deploy, "var");
if (!flatpak_mkdir_p (var, cancellable, error))
return FALSE;
res_files = g_file_get_child (res_deploy, "files");
if (is_app)
app_files = g_object_ref (res_files);
else if (is_extension)
{
g_autoptr(GKeyFile) x_metakey = NULL;
g_autofree char *x_group = NULL;
g_autofree char *x_dir = NULL;
g_autofree char *x_subdir_suffix = NULL;
char *x_subdir = NULL;
g_autofree char *bare_extension_point = NULL;
extensionof_deploy = flatpak_find_deploy_for_ref (extensionof_ref, cancellable, error);
if (extensionof_deploy == NULL)
return FALSE;
x_metakey = flatpak_deploy_get_metadata (extensionof_deploy);
x_group = g_strconcat (FLATPAK_METADATA_GROUP_PREFIX_EXTENSION, id, NULL);
if (!g_key_file_has_group (x_metakey, x_group))
{
/* Failed, look for subdirectories=true parent */
char *last_dot = strrchr (id, '.');
if (last_dot != NULL)
{
char *parent_id = g_strndup (id, last_dot - id);
g_free (x_group);
x_group = g_strconcat (FLATPAK_METADATA_GROUP_PREFIX_EXTENSION,
parent_id, NULL);
if (g_key_file_get_boolean (x_metakey, x_group,
FLATPAK_METADATA_KEY_SUBDIRECTORIES,
NULL))
x_subdir = last_dot + 1;
}
if (x_subdir == NULL)
return flatpak_fail (error, _("No extension point matching %s in %s"), id, extensionof_ref);
}
x_dir = g_key_file_get_string (x_metakey, x_group,
FLATPAK_METADATA_KEY_DIRECTORY, error);
if (x_dir == NULL)
return FALSE;
x_subdir_suffix = g_key_file_get_string (x_metakey, x_group,
FLATPAK_METADATA_KEY_SUBDIRECTORY_SUFFIX,
NULL);
if (is_app_extension)
{
app_files = flatpak_deploy_get_files (extensionof_deploy);
app_files_ro = TRUE;
if (x_subdir != NULL)
extension_tmpfs_point = g_build_filename ("/app", x_dir, NULL);
bare_extension_point = g_build_filename ("/app", x_dir, x_subdir, NULL);
}
else
{
if (x_subdir != NULL)
extension_tmpfs_point = g_build_filename ("/usr", x_dir, NULL);
bare_extension_point = g_build_filename ("/usr", x_dir, x_subdir, NULL);
}
extension_point = g_build_filename (bare_extension_point, x_subdir_suffix, NULL);
}
argv_array = g_ptr_array_new_with_free_func (g_free);
g_ptr_array_add (argv_array, g_strdup (flatpak_get_bwrap ()));
run_flags =
FLATPAK_RUN_FLAG_DEVEL | FLATPAK_RUN_FLAG_NO_SESSION_HELPER |
FLATPAK_RUN_FLAG_SET_PERSONALITY | FLATPAK_RUN_FLAG_DIE_WITH_PARENT;
if (custom_usr)
run_flags |= FLATPAK_RUN_FLAG_WRITABLE_ETC;
/* Unless manually specified, we disable dbus proxy */
if (!flatpak_context_get_needs_session_bus_proxy (arg_context))
run_flags |= FLATPAK_RUN_FLAG_NO_SESSION_BUS_PROXY;
if (!flatpak_context_get_needs_system_bus_proxy (arg_context))
run_flags |= FLATPAK_RUN_FLAG_NO_SYSTEM_BUS_PROXY;
if (!flatpak_run_setup_base_argv (argv_array, NULL, runtime_files, NULL, runtime_ref_parts[2],
run_flags, error))
return FALSE;
add_args (argv_array,
custom_usr ? "--bind" : "--ro-bind", flatpak_file_get_path_cached (runtime_files), "/usr",
NULL);
if (!custom_usr)
add_args (argv_array,
"--lock-file", "/usr/.ref",
NULL);
if (app_files)
add_args (argv_array,
app_files_ro ? "--ro-bind" : "--bind", flatpak_file_get_path_cached (app_files), "/app",
NULL);
else
add_args (argv_array,
"--dir", "/app",
NULL);
if (extension_tmpfs_point)
add_args (argv_array,
"--tmpfs", extension_tmpfs_point,
NULL);
if (extension_point)
add_args (argv_array,
"--bind", flatpak_file_get_path_cached (res_files), extension_point,
NULL);
if (extension_point)
dest = extension_point;
else if (is_app)
dest = g_strdup ("/app");
else
dest = g_strdup ("/usr");
add_args (argv_array,
"--setenv", "FLATPAK_DEST", dest,
NULL);
app_context = flatpak_app_compute_permissions (metakey,
runtime_metakey,
error);
if (app_context == NULL)
return FALSE;
flatpak_context_allow_host_fs (app_context);
flatpak_context_merge (app_context, arg_context);
if (!flatpak_run_add_app_info_args (argv_array,
NULL,
app_files,
runtime_files,
id, NULL,
runtime_ref,
app_context,
&app_info_path,
error))
return FALSE;
envp = flatpak_run_get_minimal_env (TRUE);
envp = flatpak_run_apply_env_vars (envp, app_context);
if (!custom_usr && !(is_extension && !is_app_extension) &&
!flatpak_run_add_extension_args (argv_array, &envp, runtime_metakey, runtime_ref, cancellable, error))
return FALSE;
if (!flatpak_run_add_environment_args (argv_array, NULL, &envp, app_info_path, run_flags, id,
app_context, NULL, NULL, cancellable, error))
return FALSE;
/* After setup_base to avoid conflicts with /var symlinks */
add_args (argv_array,
"--bind", flatpak_file_get_path_cached (var), "/var",
NULL);
for (i = 0; opt_bind_mounts != NULL && opt_bind_mounts[i] != NULL; i++)
{
char *split = strchr (opt_bind_mounts[i], '=');
if (split == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
_("Missing '=' in bind mount option '%s'"), opt_bind_mounts[i]);
return FALSE;
}
*split++ = 0;
add_args (argv_array,
"--bind", split, opt_bind_mounts[i],
NULL);
}
if (opt_build_dir != NULL)
{
add_args (argv_array,
"--chdir", opt_build_dir,
NULL);
}
g_ptr_array_add (argv_array, g_strdup (command));
for (i = 2; i < rest_argc; i++)
g_ptr_array_add (argv_array, g_strdup (argv[rest_argv_start + i]));
g_ptr_array_add (argv_array, NULL);
if (execvpe (flatpak_get_bwrap (), (char **) argv_array->pdata, envp) == -1)
{
g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno),
_("Unable to start app"));
return FALSE;
}
/* Not actually reached... */
return TRUE;
}
gboolean
flatpak_complete_build (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
context = g_option_context_new ("");
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv,
FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, NULL, NULL))
return FALSE;
switch (completion->argc)
{
case 0:
case 1: /* DIR */
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, options);
flatpak_complete_dir (completion);
break;
}
return TRUE;
}

View File

@ -1,103 +0,0 @@
/*
* Copyright © 2014 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 <unistd.h>
#include <string.h>
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
#include "flatpak-builtins.h"
static gboolean opt_force;
static GOptionEntry delete_options[] = {
{ "force", 0, 0, G_OPTION_ARG_NONE, &opt_force, N_("Remove remote even if in use"), NULL },
{ NULL }
};
gboolean
flatpak_builtin_delete_remote (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDir) dir = NULL;
const char *remote_name;
context = g_option_context_new (_("NAME - Delete a remote repository"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
g_option_context_add_main_entries (context, delete_options, NULL);
if (!flatpak_option_context_parse (context, NULL, &argc, &argv, 0, &dir, cancellable, error))
return FALSE;
if (argc < 2)
return usage_error (context, _("NAME must be specified"), error);
remote_name = argv[1];
if (argc > 2)
return usage_error (context, _("Too many arguments"), error);
if (!flatpak_dir_remove_remote (dir, opt_force, remote_name,
cancellable, error))
return FALSE;
return TRUE;
}
gboolean
flatpak_complete_delete_remote (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDir) dir = NULL;
int i;
context = g_option_context_new ("");
if (!flatpak_option_context_parse (context, delete_options, &completion->argc, &completion->argv, 0, &dir, NULL, NULL))
return FALSE;
switch (completion->argc)
{
case 0:
case 1: /* REMOTE */
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, delete_options);
flatpak_complete_options (completion, user_entries);
{
g_auto(GStrv) remotes = flatpak_dir_list_remotes (dir, NULL, NULL);
if (remotes == NULL)
return FALSE;
for (i = 0; remotes[i] != NULL; i++)
flatpak_complete_word (completion, "%s ", remotes[i]);
}
break;
}
return TRUE;
}

View File

@ -1,245 +0,0 @@
/*
* Copyright © 2014 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 <errno.h>
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
#include "document-portal/xdp-dbus.h"
#include <gio/gunixfdlist.h>
#include "flatpak-builtins.h"
#include "flatpak-utils.h"
#include "flatpak-run.h"
static gboolean opt_unique = FALSE;
static gboolean opt_transient = FALSE;
static gboolean opt_noexist = FALSE;
static gboolean opt_allow_read = TRUE;
static gboolean opt_forbid_read = FALSE;
static gboolean opt_allow_write = FALSE;
static gboolean opt_forbid_write = FALSE;
static gboolean opt_allow_delete = FALSE;
static gboolean opt_forbid_delete = FALSE;
static gboolean opt_allow_grant_permissions = FALSE;
static gboolean opt_forbid_grant_permissions = FALSE;
static char **opt_apps = NULL;
static GOptionEntry options[] = {
{ "unique", 'u', 0, G_OPTION_ARG_NONE, &opt_unique, N_("Create a unique document reference"), NULL },
{ "transient", 't', 0, G_OPTION_ARG_NONE, &opt_transient, N_("Make the document transient for the current session"), NULL },
{ "noexist", 'n', 0, G_OPTION_ARG_NONE, &opt_noexist, N_("Don't require the file to exist already"), NULL },
{ "allow-read", 'r', 0, G_OPTION_ARG_NONE, &opt_allow_read, N_("Give the app read permissions"), NULL },
{ "allow-write", 'w', 0, G_OPTION_ARG_NONE, &opt_allow_write, N_("Give the app write permissions"), NULL },
{ "allow-delete", 'd', 0, G_OPTION_ARG_NONE, &opt_allow_delete, N_("Give the app delete permissions"), NULL },
{ "allow-grant-permission", 'g', 0, G_OPTION_ARG_NONE, &opt_allow_grant_permissions, N_("Give the app permissions to grant further permissions"), NULL },
{ "forbid-read", 0, 0, G_OPTION_ARG_NONE, &opt_forbid_read, N_("Revoke read permissions of the app"), NULL },
{ "forbid-write", 0, 0, G_OPTION_ARG_NONE, &opt_forbid_write, N_("Revoke write permissions of the app"), NULL },
{ "forbid-delete", 0, 0, G_OPTION_ARG_NONE, &opt_forbid_delete, N_("Revoke delete permissions of the app"), NULL },
{ "forbid-grant-permission", 0, 0, G_OPTION_ARG_NONE, &opt_forbid_grant_permissions, N_("Revoke the permission to grant further permissions"), NULL },
{ "app", 'a', 0, G_OPTION_ARG_STRING_ARRAY, &opt_apps, N_("Add permissions for this app"), N_("APPID") },
{ NULL }
};
gboolean
flatpak_builtin_document_export (int argc, char **argv,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(GVariant) reply = NULL;
g_autoptr(GDBusConnection) session_bus = NULL;
g_autoptr(GPtrArray) permissions = NULL;
g_autoptr(GPtrArray) revocations = NULL;
const char *file;
g_autofree char *mountpoint = NULL;
g_autofree char *basename = NULL;
g_autofree char *dirname = NULL;
g_autofree char *doc_path = NULL;
XdpDbusDocuments *documents;
int fd, fd_id;
int i;
GUnixFDList *fd_list = NULL;
const char *doc_id;
context = g_option_context_new (_("FILE - Export a file to apps"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
if (!flatpak_option_context_parse (context, options, &argc, &argv,
FLATPAK_BUILTIN_FLAG_NO_DIR,
NULL, cancellable, error))
return FALSE;
if (argc < 2)
return usage_error (context, _("FILE must be specified"), error);
if (argc > 2)
return usage_error (context, _("Too many arguments"), error);
file = argv[1];
dirname = g_path_get_dirname (file);
basename = g_path_get_basename (file);
session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
if (session_bus == NULL)
return FALSE;
documents = xdp_dbus_documents_proxy_new_sync (session_bus, 0,
"org.freedesktop.portal.Documents",
"/org/freedesktop/portal/documents",
NULL, error);
if (documents == NULL)
return FALSE;
if (!xdp_dbus_documents_call_get_mount_point_sync (documents, &mountpoint,
NULL, error))
return FALSE;
if (opt_noexist)
fd = open (dirname, O_PATH | O_CLOEXEC);
else
fd = open (file, O_PATH | O_CLOEXEC);
if (fd == -1)
{
glnx_set_error_from_errno (error);
return FALSE;
}
fd_list = g_unix_fd_list_new ();
fd_id = g_unix_fd_list_append (fd_list, fd, error);
close (fd);
if (opt_noexist)
{
reply = g_dbus_connection_call_with_unix_fd_list_sync (session_bus,
"org.freedesktop.portal.Documents",
"/org/freedesktop/portal/documents",
"org.freedesktop.portal.Documents",
"AddNamed",
g_variant_new ("(h^aybb)", fd_id, basename, !opt_unique, !opt_transient),
G_VARIANT_TYPE ("(s)"),
G_DBUS_CALL_FLAGS_NONE,
30000,
fd_list, NULL,
NULL,
error);
}
else
{
reply = g_dbus_connection_call_with_unix_fd_list_sync (session_bus,
"org.freedesktop.portal.Documents",
"/org/freedesktop/portal/documents",
"org.freedesktop.portal.Documents",
"Add",
g_variant_new ("(hbb)", fd_id, !opt_unique, !opt_transient),
G_VARIANT_TYPE ("(s)"),
G_DBUS_CALL_FLAGS_NONE,
30000,
fd_list, NULL,
NULL,
error);
}
g_object_unref (fd_list);
if (reply == NULL)
return FALSE;
g_variant_get (reply, "(&s)", &doc_id);
permissions = g_ptr_array_new ();
if (opt_allow_read)
g_ptr_array_add (permissions, "read");
if (opt_allow_write)
g_ptr_array_add (permissions, "write");
if (opt_allow_delete)
g_ptr_array_add (permissions, "delete");
if (opt_allow_grant_permissions)
g_ptr_array_add (permissions, "grant-permissions");
g_ptr_array_add (permissions, NULL);
revocations = g_ptr_array_new ();
if (opt_forbid_read)
g_ptr_array_add (revocations, "read");
if (opt_forbid_write)
g_ptr_array_add (revocations, "write");
if (opt_forbid_delete)
g_ptr_array_add (revocations, "delete");
if (opt_forbid_grant_permissions)
g_ptr_array_add (revocations, "grant-permissions");
g_ptr_array_add (revocations, NULL);
for (i = 0; opt_apps != NULL && opt_apps[i] != NULL; i++)
{
if (!xdp_dbus_documents_call_grant_permissions_sync (documents,
doc_id,
opt_apps[i],
(const char **) permissions->pdata,
NULL,
error))
return FALSE;
if (!xdp_dbus_documents_call_revoke_permissions_sync (documents,
doc_id,
opt_apps[i],
(const char **) revocations->pdata,
NULL,
error))
return FALSE;
}
doc_path = g_build_filename (mountpoint, doc_id, basename, NULL);
g_print ("%s\n", doc_path);
return TRUE;
}
gboolean
flatpak_complete_document_export (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
context = g_option_context_new ("");
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv,
FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, NULL, NULL))
return FALSE;
switch (completion->argc)
{
case 0:
case 1: /* FILE */
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, options);
flatpak_complete_file (completion);
break;
}
return TRUE;
}

View File

@ -1,156 +0,0 @@
/*
* Copyright © 2016 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:
* Matthias Clasen <mclasen@redhat.com>
*/
#include "config.h"
#include <locale.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
#include "document-portal/xdp-dbus.h"
#include <gio/gunixfdlist.h>
#include "flatpak-builtins.h"
#include "flatpak-utils.h"
#include "flatpak-run.h"
static GOptionEntry options[] = {
{ NULL }
};
gboolean
flatpak_builtin_document_info (int argc, char **argv,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(GDBusConnection) session_bus = NULL;
const char *file;
XdpDbusDocuments *documents;
g_autofree char *mountpoint = NULL;
g_autofree char *basename = NULL;
g_autofree char *doc_id = NULL;
g_autofree char *doc_path = NULL;
g_autofree char *origin = NULL;
const char *app_id;
const char **perms;
g_autoptr(GVariant) apps = NULL;
g_autoptr(GVariantIter) iter = NULL;
context = g_option_context_new (_("FILE - Get information about an exported file"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
if (!flatpak_option_context_parse (context, options, &argc, &argv,
FLATPAK_BUILTIN_FLAG_NO_DIR,
NULL, cancellable, error))
return FALSE;
if (argc < 2)
return usage_error (context, _("FILE must be specified"), error);
if (argc > 2)
return usage_error (context, _("Too many arguments"), error);
file = argv[1];
basename = g_path_get_basename (file);
session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
if (session_bus == NULL)
return FALSE;
documents = xdp_dbus_documents_proxy_new_sync (session_bus, 0,
"org.freedesktop.portal.Documents",
"/org/freedesktop/portal/documents",
NULL, error);
if (documents == NULL)
return FALSE;
if (!xdp_dbus_documents_call_get_mount_point_sync (documents, &mountpoint,
NULL, error))
return FALSE;
if (!xdp_dbus_documents_call_lookup_sync (documents, file, &doc_id, NULL, error))
return FALSE;
if (strcmp (doc_id, "") == 0)
{
g_print (_("Not exported\n"));
return TRUE;
}
doc_path = g_build_filename (mountpoint, doc_id, basename, NULL);
if (!xdp_dbus_documents_call_info_sync (documents, doc_id, &origin, &apps,
NULL, error))
return FALSE;
iter = g_variant_iter_new (apps);
g_print ("id: %s\n", doc_id);
g_print ("path: %s\n", doc_path);
g_print ("origin: %s\n", origin);
if (g_variant_iter_n_children (iter) > 0)
g_print ("permissions:\n");
while (g_variant_iter_next (iter, "{&s^a&s}", &app_id, &perms))
{
int i;
g_print ("\t%s\t", app_id);
for (i = 0; perms[i]; i++)
{
if (i > 0)
g_print (", ");
g_print ("%s", perms[i]);
}
g_print ("\n");
}
return TRUE;
}
gboolean
flatpak_complete_document_info (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
context = g_option_context_new ("");
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv,
FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, NULL, NULL))
return FALSE;
switch (completion->argc)
{
case 0:
case 1: /* FILE */
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, options);
flatpak_complete_file (completion);
break;
}
return TRUE;
}

View File

@ -1,150 +0,0 @@
/*
* Copyright © 2016 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:
* Matthias Clasen <mclasen@redhat.com>
*/
#include "config.h"
#include <locale.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
#include "document-portal/xdp-dbus.h"
#include "flatpak-builtins.h"
#include "flatpak-utils.h"
#include "flatpak-run.h"
static GOptionEntry options[] = {
{ NULL }
};
gboolean
flatpak_builtin_document_list (int argc, char **argv,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(GDBusConnection) session_bus = NULL;
XdpDbusDocuments *documents;
g_autoptr(GVariant) apps = NULL;
g_autoptr(GVariantIter) iter = NULL;
const char *app_id;
const char *id;
const char *path;
context = g_option_context_new (_("[APPID] - List exported files"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
if (!flatpak_option_context_parse (context, options, &argc, &argv,
FLATPAK_BUILTIN_FLAG_NO_DIR,
NULL, cancellable, error))
return FALSE;
if (argc < 2)
app_id = "";
else
app_id = argv[1];
if (argc > 2)
return usage_error (context, _("Too many arguments"), error);
session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
if (session_bus == NULL)
return FALSE;
documents = xdp_dbus_documents_proxy_new_sync (session_bus, 0,
"org.freedesktop.portal.Documents",
"/org/freedesktop/portal/documents",
NULL, error);
if (documents == NULL)
return FALSE;
if (!xdp_dbus_documents_call_list_sync (documents, app_id, &apps, NULL, error))
return FALSE;
iter = g_variant_iter_new (apps);
while (g_variant_iter_next (iter, "{&s^&ay}", &id, &path))
g_print ("%s\t%s\n", id, path);
return TRUE;
}
gboolean
flatpak_complete_document_list (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDir) user_dir = NULL;
g_autoptr(FlatpakDir) system_dir = NULL;
g_autoptr(GError) error = NULL;
int i;
context = g_option_context_new ("");
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv,
FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, NULL, NULL))
return FALSE;
switch (completion->argc)
{
case 0:
case 1: /* APPID */
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, options);
user_dir = flatpak_dir_get_user ();
{
g_auto(GStrv) refs = flatpak_dir_find_installed_refs (user_dir, NULL, NULL, NULL,
FLATPAK_KINDS_APP, &error);
if (refs == NULL)
flatpak_completion_debug ("find local refs error: %s", error->message);
for (i = 0; refs != NULL && refs[i] != NULL; i++)
{
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
if (parts)
flatpak_complete_word (completion, "%s ", parts[1]);
}
}
system_dir = flatpak_dir_get_system_default ();
{
g_auto(GStrv) refs = flatpak_dir_find_installed_refs (system_dir, NULL, NULL, NULL,
FLATPAK_KINDS_APP, &error);
if (refs == NULL)
flatpak_completion_debug ("find local refs error: %s", error->message);
for (i = 0; refs != NULL && refs[i] != NULL; i++)
{
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
if (parts)
flatpak_complete_word (completion, "%s ", parts[1]);
}
}
break;
}
return TRUE;
}

View File

@ -1,120 +0,0 @@
/*
* Copyright © 2016 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:
* Matthias Clasen <mclasen@redhat.com>
*/
#include "config.h"
#include <locale.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
#include "document-portal/xdp-dbus.h"
#include <gio/gunixfdlist.h>
#include "flatpak-builtins.h"
#include "flatpak-utils.h"
#include "flatpak-run.h"
static GOptionEntry options[] = {
{ NULL }
};
gboolean
flatpak_builtin_document_unexport (int argc, char **argv,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(GDBusConnection) session_bus = NULL;
XdpDbusDocuments *documents;
const char *file;
g_autofree char *doc_id = NULL;
context = g_option_context_new (_("FILE - Unexport a file to apps"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
if (!flatpak_option_context_parse (context, options, &argc, &argv,
FLATPAK_BUILTIN_FLAG_NO_DIR,
NULL, cancellable, error))
return FALSE;
if (argc < 2)
return usage_error (context, _("FILE must be specified"), error);
if (argc > 2)
return usage_error (context, _("Too many arguments"), error);
file = argv[1];
session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
if (session_bus == NULL)
return FALSE;
documents = xdp_dbus_documents_proxy_new_sync (session_bus, 0,
"org.freedesktop.portal.Documents",
"/org/freedesktop/portal/documents",
NULL, error);
if (documents == NULL)
return FALSE;
if (!xdp_dbus_documents_call_lookup_sync (documents, file, &doc_id, NULL, error))
return FALSE;
if (strcmp (doc_id, "") == 0)
{
g_print (_("Not exported\n"));
return TRUE;
}
if (!xdp_dbus_documents_call_delete_sync (documents, doc_id, NULL, error))
return FALSE;
return TRUE;
}
gboolean
flatpak_complete_document_unexport (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
context = g_option_context_new ("");
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv,
FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, NULL, NULL))
return FALSE;
switch (completion->argc)
{
case 0:
case 1: /* FILE */
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, options);
flatpak_complete_file (completion);
break;
}
return TRUE;
}

View File

@ -1,264 +0,0 @@
/*
* Copyright © 2014 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 <errno.h>
#include <string.h>
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
#include "flatpak-builtins.h"
#include "flatpak-utils.h"
#include "flatpak-dbus.h"
#include "flatpak-run.h"
static GOptionEntry options[] = {
{ NULL }
};
gboolean
flatpak_builtin_enter (int argc,
char **argv,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GOptionContext) context = NULL;
int rest_argv_start, rest_argc;
const char *ns_name[] = { "ipc", "net", "pid", "mnt", "user" };
int ns_fd[G_N_ELEMENTS (ns_name)];
char pid_ns[256] = { 0 };
ssize_t pid_ns_len;
char self_ns[256];
ssize_t self_ns_len;
char *pid_s;
int pid, i;
g_autofree char *environment_path = NULL;
g_autoptr(GPtrArray) argv_array = NULL;
g_autoptr(GPtrArray) envp_array = NULL;
g_autofree char *environment = NULL;
gsize environment_len;
char *e;
g_autofree char *pulse_path = NULL;
g_autofree char *session_bus_path = NULL;
g_autofree char *xdg_runtime_dir = NULL;
g_autofree char *stat_path = NULL;
g_autofree char *root_path = NULL;
char root_link[256] = { 0 };
gssize root_link_len;
g_autofree char *cwd_path = NULL;
char cwd_link[256] = { 0 };
gssize cwd_link_len;
int status;
struct stat stat_buf;
uid_t uid;
gid_t gid;
context = g_option_context_new (_("SANDBOXEDPID [COMMAND [args...]] - Run a command inside a running sandbox"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
rest_argc = 0;
for (i = 1; i < argc; i++)
{
/* The non-option is the command, take it out of the arguments */
if (argv[i][0] != '-')
{
rest_argv_start = i;
rest_argc = argc - i;
argc = i;
break;
}
}
if (!flatpak_option_context_parse (context, options, &argc, &argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error))
return FALSE;
if (rest_argc < 2)
{
usage_error (context, _("SANDBOXEDPID and COMMAND must be specified"), error);
return FALSE;
}
/* Before further checks, warn if we are not already root */
if (geteuid () != 0)
g_printerr ("%s\n", _("Not running as root, may be unable to enter namespace"));
pid_s = argv[rest_argv_start];
pid = atoi (pid_s);
if (pid <= 0)
return flatpak_fail (error, _("Invalid pid %s"), pid_s);
stat_path = g_strdup_printf ("/proc/%d/root", pid);
if (stat (stat_path, &stat_buf))
return flatpak_fail (error, _("No such pid %s"), pid_s);
uid = stat_buf.st_uid;
gid = stat_buf.st_gid;
environment_path = g_strdup_printf ("/proc/%d/environ", pid);
if (!g_file_get_contents (environment_path, &environment, &environment_len, error))
return FALSE;
cwd_path = g_strdup_printf ("/proc/%d/cwd", pid);
cwd_link_len = readlink (cwd_path, cwd_link, sizeof (cwd_link) - 1);
if (cwd_link_len <= 0)
return flatpak_fail (error, _("Can't read cwd"));
root_path = g_strdup_printf ("/proc/%d/root", pid);
root_link_len = readlink (root_path, root_link, sizeof (root_link) - 1);
if (root_link_len <= 0)
return flatpak_fail (error, _("Can't read root"));
for (i = 0; i < G_N_ELEMENTS (ns_name); i++)
{
g_autofree char *path = g_strdup_printf ("/proc/%d/ns/%s", pid, ns_name[i]);
g_autofree char *self_path = g_strdup_printf ("/proc/self/ns/%s", ns_name[i]);
pid_ns_len = readlink (path, pid_ns, sizeof (pid_ns) - 1);
if (pid_ns_len <= 0)
return flatpak_fail (error, _("Invalid %s namespace for pid %d"), ns_name[i], pid);
pid_ns[pid_ns_len] = 0;
self_ns_len = readlink (self_path, self_ns, sizeof (self_ns) - 1);
if (self_ns_len <= 0)
return flatpak_fail (error, _("Invalid %s namespace for self"), ns_name[i]);
self_ns[self_ns_len] = 0;
if (strcmp (self_ns, pid_ns) == 0)
{
/* No need to setns to the same namespace, it will only fail */
ns_fd[i] = -1;
}
else
{
ns_fd[i] = open (path, O_RDONLY);
if (ns_fd[i] == -1)
return flatpak_fail (error, _("Can't open %s namespace: %s"), ns_name[i], g_strerror (errno));
}
}
for (i = 0; i < G_N_ELEMENTS (ns_fd); i++)
{
if (ns_fd[i] != -1)
{
if (setns (ns_fd[i], 0) == -1)
return flatpak_fail (error, _("Can't enter %s namespace: %s"), ns_name[i], g_strerror (errno));
close (ns_fd[i]);
}
}
if (chdir (cwd_link))
return flatpak_fail (error, _("Can't chdir"));
if (chroot (root_link))
return flatpak_fail (error, _("Can't chroot"));
envp_array = g_ptr_array_new_with_free_func (g_free);
for (e = environment; e < environment + environment_len; e = e + strlen (e) + 1)
{
if (*e != 0 &&
!g_str_has_prefix (e, "DISPLAY=") &&
!g_str_has_prefix (e, "PULSE_SERVER=") &&
!g_str_has_prefix (e, "PULSE_CLIENTCONFIG=") &&
!g_str_has_prefix (e, "XDG_RUNTIME_DIR=") &&
!g_str_has_prefix (e, "DBUS_SYSTEM_BUS_ADDRESS=") &&
!g_str_has_prefix (e, "DBUS_SESSION_BUS_ADDRESS="))
{
if (g_str_has_prefix (e, "_LD_LIBRARY_PATH="))
e++;
g_ptr_array_add (envp_array, g_strdup (e));
}
}
xdg_runtime_dir = g_strdup_printf ("/run/user/%d", uid);
g_ptr_array_add (envp_array, g_strdup_printf ("XDG_RUNTIME_DIR=%s", xdg_runtime_dir));
if (g_file_test ("/tmp/.X11-unix/X99", G_FILE_TEST_EXISTS))
g_ptr_array_add (envp_array, g_strdup ("DISPLAY=:99.0"));
pulse_path = g_strdup_printf ("/run/user/%d/pulse/native", uid);
if (g_file_test (pulse_path, G_FILE_TEST_EXISTS))
{
g_ptr_array_add (envp_array, g_strdup_printf ("PULSE_SERVER=unix:%s", pulse_path));
g_ptr_array_add (envp_array, g_strdup_printf ("PULSE_CLIENTCONFIG=/run/user/%d/pulse/config", uid));
}
session_bus_path = g_strdup_printf ("/run/user/%d/bus", uid);
if (g_file_test (session_bus_path, G_FILE_TEST_EXISTS))
g_ptr_array_add (envp_array, g_strdup_printf ("DBUS_SESSION_BUS_ADDRESS=unix:%s", session_bus_path));
if (g_file_test ("/run/dbus/system_bus_socket", G_FILE_TEST_EXISTS))
g_ptr_array_add (envp_array, g_strdup ("DBUS_SYSTEM_BUS_ADDRESS=unix:/run/dbus/system_bus_socket"));
g_ptr_array_add (envp_array, NULL);
argv_array = g_ptr_array_new_with_free_func (g_free);
for (i = 1; i < rest_argc; i++)
g_ptr_array_add (argv_array, g_strdup (argv[rest_argv_start + i]));
g_ptr_array_add (argv_array, NULL);
if (setgid (gid))
return flatpak_fail (error, _("Can't switch gid"));
if (setuid (uid))
return flatpak_fail (error, _("Can't switch uid"));
if (!g_spawn_sync (NULL, (char **) argv_array->pdata, (char **) envp_array->pdata,
G_SPAWN_SEARCH_PATH_FROM_ENVP | G_SPAWN_CHILD_INHERITS_STDIN,
NULL, NULL,
NULL, NULL,
&status, error))
return FALSE;
exit (status);
}
gboolean
flatpak_complete_enter (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
context = g_option_context_new ("");
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, NULL, NULL))
return FALSE;
switch (completion->argc)
{
case 0:
case 1:
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, options);
break;
default:
break;
}
return TRUE;
}

View File

@ -1,433 +0,0 @@
/*
* Copyright © 2016 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 <unistd.h>
#include <string.h>
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
#include "flatpak-builtins.h"
#include "flatpak-utils.h"
#include "flatpak-builtins-utils.h"
static gboolean opt_user;
static gboolean opt_system;
static gboolean opt_show_ref;
static gboolean opt_show_commit;
static gboolean opt_show_origin;
static gboolean opt_show_size;
static gboolean opt_show_metadata;
static gboolean opt_show_extensions;
static char *opt_arch;
static char **opt_installations;
static GOptionEntry options[] = {
{ "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, N_("Arch to use"), N_("ARCH") },
{ "user", 0, 0, G_OPTION_ARG_NONE, &opt_user, N_("Show user installations"), NULL },
{ "system", 0, 0, G_OPTION_ARG_NONE, &opt_system, N_("Show system-wide installations"), NULL },
{ "installation", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_installations, N_("Show specific system-wide installations"), NULL },
{ "show-ref", 'r', 0, G_OPTION_ARG_NONE, &opt_show_ref, N_("Show ref"), NULL },
{ "show-commit", 'c', 0, G_OPTION_ARG_NONE, &opt_show_commit, N_("Show commit"), NULL },
{ "show-origin", 'o', 0, G_OPTION_ARG_NONE, &opt_show_origin, N_("Show origin"), NULL },
{ "show-size", 's', 0, G_OPTION_ARG_NONE, &opt_show_size, N_("Show size"), NULL },
{ "show-metadata", 'm', 0, G_OPTION_ARG_NONE, &opt_show_metadata, N_("Show metadata"), NULL },
{ "show-extensions", 'e', 0, G_OPTION_ARG_NONE, &opt_show_extensions, N_("Show extensions"), NULL },
{ NULL }
};
/* Print space unless this is the first item */
static void
maybe_print_space (gboolean *first)
{
if (*first)
*first = FALSE;
else
g_print (" ");
}
gboolean
flatpak_builtin_info (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autofree char *ref = NULL;
FlatpakDir *dir = NULL;
g_autoptr(GVariant) deploy_data = NULL;
g_autoptr(FlatpakDeploy) deploy = NULL;
g_autoptr(GKeyFile) metakey = NULL;
const char *commit = NULL;
const char *alt_id = NULL;
const char *pref = NULL;
const char *default_branch = NULL;
const char *origin = NULL;
guint64 size;
gboolean search_all = FALSE;
gboolean first = TRUE;
FlatpakKinds kinds;
const char *on = "";
const char *off = "";
g_auto(GStrv) parts = NULL;
g_autofree char *path = NULL;
g_autofree char *formatted = NULL;
gboolean friendly = TRUE;
g_autofree const char **subpaths = NULL;
context = g_option_context_new (_("NAME [BRANCH] - Get info about installed app and/or runtime"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
if (!flatpak_option_context_parse (context, options, &argc, &argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error))
return FALSE;
if (argc < 2)
return usage_error (context, _("NAME must be specified"), error);
pref = argv[1];
if (argc >= 3)
default_branch = argv[2];
if (argc > 3)
return usage_error (context, _("Too many arguments"), error);
kinds = FLATPAK_KINDS_APP | FLATPAK_KINDS_RUNTIME;
if (!opt_user && !opt_system && opt_installations == NULL)
search_all = TRUE;
dir = flatpak_find_installed_pref (pref, kinds, opt_arch, default_branch,
search_all, opt_user, opt_system, opt_installations,
&ref, cancellable, error);
if (dir == NULL)
return FALSE;
deploy_data = flatpak_dir_get_deploy_data (dir, ref, cancellable, error);
if (deploy_data == NULL)
return FALSE;
deploy = flatpak_find_deploy_for_ref (ref, NULL, error);
if (deploy == NULL)
return FALSE;
if (flatpak_fancy_output ())
{
on = FLATPAK_ANSI_BOLD_ON;
off = FLATPAK_ANSI_BOLD_OFF; /* bold off */
}
parts = g_strsplit (ref, "/", 0);
commit = flatpak_deploy_data_get_commit (deploy_data);
alt_id = flatpak_deploy_data_get_alt_id (deploy_data);
origin = flatpak_deploy_data_get_origin (deploy_data);
size = flatpak_deploy_data_get_installed_size (deploy_data);
formatted = g_format_size (size);
path = g_file_get_path (flatpak_deploy_get_dir (deploy));
subpaths = flatpak_deploy_data_get_subpaths (deploy_data);
metakey = flatpak_deploy_get_metadata (deploy);
if (opt_show_ref || opt_show_origin || opt_show_commit || opt_show_size || opt_show_metadata)
friendly = FALSE;
if (friendly)
{
const char *latest = flatpak_dir_read_latest (dir, origin, ref, NULL, NULL, NULL);
if (latest == NULL)
latest = _("ref not present in origin");
g_print ("%s%s%s %s\n", on, _("Ref:"), off, ref);
g_print ("%s%s%s %s\n", on, _("ID:"), off, parts[1]);
g_print ("%s%s%s %s\n", on, _("Arch:"), off, parts[2]);
g_print ("%s%s%s %s\n", on, _("Branch:"), off, parts[3]);
g_print ("%s%s%s %s\n", on, _("Origin:"), off, origin ? origin : "-");
if (strcmp (commit, latest) != 0)
{
g_print ("%s%s%s %s\n", on, _("Active commit:"), off, commit);
g_print ("%s%s%s %s\n", on, _("Latest commit:"), off, latest);
}
else
g_print ("%s%s%s %s\n", on, _("Commit:"), off, commit);
if (alt_id)
g_print ("%s%s%s %s\n", on, _("alt-id:"), off, alt_id);
g_print ("%s%s%s %s\n", on, _("Location:"), off, path);
g_print ("%s%s%s %s\n", on, _("Installed size:"), off, formatted);
if (strcmp (parts[0], "app") == 0)
{
g_autofree char *runtime = NULL;
runtime = g_key_file_get_string (metakey, "Application", "runtime", error);
g_print ("%s%s%s %s\n", on, _("Runtime:"), off, runtime ? runtime : "-");
}
if (subpaths[0] != NULL)
{
int i;
g_print ("%s%s%s ", on, _("Installed subdirectories:"), off);
for (i = 0; subpaths[i] != NULL; i++)
g_print (i == 0 ? "%s" : ",%s", subpaths[i]);
g_print ("\n");
}
}
else
{
if (opt_show_ref)
{
maybe_print_space (&first);
g_print ("%s", ref);
}
if (opt_show_origin)
{
maybe_print_space (&first);
g_print ("%s", origin ? origin : "-");
}
if (opt_show_commit)
{
maybe_print_space (&first);
g_print ("%s", commit);
}
if (opt_show_size)
{
maybe_print_space (&first);
g_print ("%s", formatted);
}
if (!first)
g_print ("\n");
if (opt_show_metadata)
{
g_autoptr(GFile) deploy_dir = NULL;
g_autoptr(GFile) file = NULL;
g_autofree char *data = NULL;
gsize data_size;
deploy_dir = flatpak_dir_get_if_deployed (dir, ref, NULL, cancellable);
file = g_file_get_child (deploy_dir, "metadata");
if (!g_file_load_contents (file, cancellable, &data, &data_size, NULL, error))
return FALSE;
g_print ("%s", data);
}
}
if (opt_show_extensions)
{
GList *extensions, *l;
extensions = flatpak_list_extensions (metakey, parts[2], parts[3]);
for (l = extensions; l; l = l->next)
{
FlatpakExtension *ext = l->data;
g_autofree const char **subpaths = NULL;
g_autoptr(GVariant) ext_deploy_data = NULL;
g_autofree char *formatted = NULL;
if (ext->is_unmaintained)
{
commit = "unmaintained";
origin = NULL;
size = 0;
formatted = g_strdup ("unknown");
subpaths = NULL;
}
else
{
ext_deploy_data = flatpak_dir_get_deploy_data (dir, ext->ref, cancellable, error);
if (ext_deploy_data == NULL)
return FALSE;
commit = flatpak_deploy_data_get_commit (ext_deploy_data);
origin = flatpak_deploy_data_get_origin (ext_deploy_data);
size = flatpak_deploy_data_get_installed_size (ext_deploy_data);
formatted = g_format_size (size);
subpaths = flatpak_deploy_data_get_subpaths (ext_deploy_data);
}
g_print ("\n%s%s%s %s\n", on, _("Extension:"), off, ext->ref);
g_print ("%s%s%s %s\n", on, _("ID:"), off, ext->id);
g_print ("%s%s%s %s\n", on, _("Origin:"), off, origin ? origin : "-");
g_print ("%s%s%s %s\n", on, _("Commit:"), off, commit);
g_print ("%s%s%s %s%s\n", on, _("Installed size:"), off, subpaths && subpaths[0] ? "<" : "", formatted);
if (subpaths && subpaths[0])
{
g_autofree char *subpath_str = NULL;
subpath_str = g_strjoinv (",", (char **)subpaths);
g_print ("%s%s%s %s\n", on, _("Subpaths:"), off, subpath_str);
}
}
}
return TRUE;
}
gboolean
flatpak_complete_info (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDir) user_dir = NULL;
g_autoptr(FlatpakDir) system_dir = NULL;
g_autoptr(GPtrArray) system_dirs = NULL;
g_autoptr(GError) error = NULL;
gboolean search_all = FALSE;
FlatpakKinds kinds;
int i, j;
context = g_option_context_new ("");
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, NULL, NULL))
return FALSE;
kinds = FLATPAK_KINDS_APP | FLATPAK_KINDS_RUNTIME;
if (!opt_user && !opt_system && opt_installations == NULL)
search_all = TRUE;
if (opt_user || search_all)
user_dir = flatpak_dir_get_user ();
if (search_all)
{
system_dirs = flatpak_dir_get_system_list (NULL, &error);
if (system_dirs == NULL)
{
flatpak_completion_debug ("find system installations error: %s", error->message);
return FALSE;
}
}
if (opt_system)
system_dir = flatpak_dir_get_system_default ();
switch (completion->argc)
{
case 0:
case 1: /* NAME */
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, options);
if (user_dir)
{
g_auto(GStrv) refs = flatpak_dir_find_installed_refs (user_dir, NULL, NULL, opt_arch,
kinds, &error);
if (refs == NULL)
flatpak_completion_debug ("find local refs error: %s", error->message);
for (i = 0; refs != NULL && refs[i] != NULL; i++)
{
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
if (parts)
flatpak_complete_word (completion, "%s ", parts[1]);
}
}
if (system_dirs)
{
for (i = 0; i < system_dirs->len; i++)
{
FlatpakDir *dir = g_ptr_array_index (system_dirs, i);
g_auto(GStrv) refs = flatpak_dir_find_installed_refs (dir, NULL, NULL, opt_arch,
kinds, &error);
if (refs == NULL)
flatpak_completion_debug ("find local refs error: %s", error->message);
for (j = 0; refs != NULL && refs[j] != NULL; j++)
{
g_auto(GStrv) parts = flatpak_decompose_ref (refs[j], NULL);
if (parts)
flatpak_complete_word (completion, "%s ", parts[1]);
}
}
}
if (system_dir)
{
g_auto(GStrv) refs = flatpak_dir_find_installed_refs (system_dir, NULL, NULL, opt_arch,
kinds, &error);
if (refs == NULL)
flatpak_completion_debug ("find local refs error: %s", error->message);
for (i = 0; refs != NULL && refs[i] != NULL; i++)
{
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
if (parts)
flatpak_complete_word (completion, "%s ", parts[1]);
}
}
break;
case 2: /* BRANCH */
if (user_dir)
{
g_auto(GStrv) refs = flatpak_dir_find_installed_refs (user_dir, completion->argv[1], NULL, opt_arch,
kinds, &error);
if (refs == NULL)
flatpak_completion_debug ("find remote refs error: %s", error->message);
for (i = 0; refs != NULL && refs[i] != NULL; i++)
{
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
if (parts)
flatpak_complete_word (completion, "%s ", parts[3]);
}
}
if (system_dirs)
{
for (i = 0; i < system_dirs->len; i++)
{
FlatpakDir *dir = g_ptr_array_index (system_dirs, i);
g_auto(GStrv) refs = flatpak_dir_find_installed_refs (dir, completion->argv[1], NULL, opt_arch,
kinds, &error);
if (refs == NULL)
flatpak_completion_debug ("find remote refs error: %s", error->message);
for (j = 0; refs != NULL && refs[j] != NULL; j++)
{
g_auto(GStrv) parts = flatpak_decompose_ref (refs[j], NULL);
if (parts)
flatpak_complete_word (completion, "%s ", parts[3]);
}
}
}
if (system_dir)
{
g_auto(GStrv) refs = flatpak_dir_find_installed_refs (system_dir, completion->argv[1], NULL, opt_arch,
kinds, &error);
if (refs == NULL)
flatpak_completion_debug ("find remote refs error: %s", error->message);
for (i = 0; refs != NULL && refs[i] != NULL; i++)
{
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
if (parts)
flatpak_complete_word (completion, "%s ", parts[3]);
}
}
break;
default:
break;
}
return TRUE;
}

View File

@ -1,511 +0,0 @@
/*
* Copyright © 2014 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 <unistd.h>
#include <string.h>
#include <glib/gi18n.h>
#include <gio/gunixinputstream.h>
#include "libglnx/libglnx.h"
#include "flatpak-builtins.h"
#include "flatpak-builtins-utils.h"
#include "flatpak-transaction.h"
#include "flatpak-utils.h"
#include "lib/flatpak-error.h"
#include "flatpak-chain-input-stream.h"
static char *opt_arch;
static char **opt_gpg_file;
static char **opt_subpaths;
static gboolean opt_no_pull;
static gboolean opt_no_deploy;
static gboolean opt_no_related;
static gboolean opt_no_deps;
static gboolean opt_no_static_deltas;
static gboolean opt_runtime;
static gboolean opt_app;
static gboolean opt_bundle;
static gboolean opt_from;
static gboolean opt_yes;
static GOptionEntry options[] = {
{ "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, N_("Arch to install for"), N_("ARCH") },
{ "no-pull", 0, 0, G_OPTION_ARG_NONE, &opt_no_pull, N_("Don't pull, only install from local cache"), NULL },
{ "no-deploy", 0, 0, G_OPTION_ARG_NONE, &opt_no_deploy, N_("Don't deploy, only download to local cache"), NULL },
{ "no-related", 0, 0, G_OPTION_ARG_NONE, &opt_no_related, N_("Don't install related refs"), NULL },
{ "no-deps", 0, 0, G_OPTION_ARG_NONE, &opt_no_deps, N_("Don't verify/install runtime dependencies"), NULL },
{ "no-static-deltas", 0, 0, G_OPTION_ARG_NONE, &opt_no_static_deltas, N_("Don't use static deltas"), NULL },
{ "runtime", 0, 0, G_OPTION_ARG_NONE, &opt_runtime, N_("Look for runtime with the specified name"), NULL },
{ "app", 0, 0, G_OPTION_ARG_NONE, &opt_app, N_("Look for app with the specified name"), NULL },
{ "bundle", 0, 0, G_OPTION_ARG_NONE, &opt_bundle, N_("Assume LOCATION is a .flatpak single-file bundle"), NULL },
{ "from", 0, 0, G_OPTION_ARG_NONE, &opt_from, N_("Assume LOCATION is a .flatpakref application description"), NULL },
{ "gpg-file", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_gpg_file, N_("Check bundle signatures with GPG key from FILE (- for stdin)"), N_("FILE") },
{ "subpath", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_subpaths, N_("Only install this subpath"), N_("PATH") },
{ "assumeyes", 'y', 0, G_OPTION_ARG_NONE, &opt_yes, N_("Automatically answer yes for all questions"), NULL },
{ NULL }
};
static GBytes *
read_gpg_data (GCancellable *cancellable,
GError **error)
{
g_autoptr(GInputStream) source_stream = NULL;
guint n_keyrings = 0;
g_autoptr(GPtrArray) streams = NULL;
if (opt_gpg_file != NULL)
n_keyrings = g_strv_length (opt_gpg_file);
guint ii;
streams = g_ptr_array_new_with_free_func (g_object_unref);
for (ii = 0; ii < n_keyrings; ii++)
{
GInputStream *input_stream = NULL;
if (strcmp (opt_gpg_file[ii], "-") == 0)
{
input_stream = g_unix_input_stream_new (STDIN_FILENO, FALSE);
}
else
{
g_autoptr(GFile) file = g_file_new_for_commandline_arg (opt_gpg_file[ii]);
input_stream = G_INPUT_STREAM (g_file_read (file, cancellable, error));
if (input_stream == NULL)
return NULL;
}
/* Takes ownership. */
g_ptr_array_add (streams, input_stream);
}
/* Chain together all the --keyring options as one long stream. */
source_stream = (GInputStream *) flatpak_chain_input_stream_new (streams);
return flatpak_read_stream (source_stream, FALSE, error);
}
static gboolean
handle_runtime_repo_deps (FlatpakDir *dir, const char *dep_url, GError **error)
{
g_autoptr(GBytes) dep_data = NULL;
g_autofree char *runtime_url = NULL;
g_autofree char *old_remote = NULL;
g_autofree char *new_remote = NULL;
g_autofree char *basename = NULL;
g_autoptr(SoupURI) uri = NULL;
g_auto(GStrv) remotes = NULL;
g_autoptr(GKeyFile) config = NULL;
g_autoptr(GBytes) gpg_key = NULL;
g_autofree char *group = NULL;
g_autofree char *runtime_collection_id = NULL;
char *t;
int i;
if (opt_no_deps)
return TRUE;
dep_data = download_uri (dep_url, error);
if (dep_data == NULL)
{
g_prefix_error (error, "Can't load dependent file %s", dep_url);
return FALSE;
}
uri = soup_uri_new (dep_url);
basename = g_path_get_basename (soup_uri_get_path (uri));
/* Strip suffix */
t = strchr (basename, '.');
if (t != NULL)
*t = 0;
/* Find a free remote name */
remotes = flatpak_dir_list_remotes (dir, NULL, NULL);
i = 0;
do
{
g_clear_pointer (&new_remote, g_free);
if (i == 0)
new_remote = g_strdup (basename);
else
new_remote = g_strdup_printf ("%s-%d", basename, i);
i++;
}
while (remotes != NULL && g_strv_contains ((const char * const*)remotes, new_remote));
config = flatpak_dir_parse_repofile (dir, new_remote, dep_data, &gpg_key, NULL, error);
if (config == NULL)
{
g_prefix_error (error, "Can't parse dependent file %s: ", dep_url);
return FALSE;
}
/* See if it already exists */
group = g_strdup_printf ("remote \"%s\"", new_remote);
runtime_url = g_key_file_get_string (config, group, "url", NULL);
g_assert (runtime_url != NULL);
#ifdef FLATPAK_ENABLE_P2P
runtime_collection_id = g_key_file_get_string (config, group, "collection-id", NULL);
#endif /* FLATPAK_ENABLE_P2P */
old_remote = flatpak_dir_find_remote_by_uri (dir, runtime_url, runtime_collection_id);
if (old_remote == NULL && flatpak_dir_is_user (dir))
{
g_autoptr(GPtrArray) system_dirs = NULL;
int i;
system_dirs = flatpak_dir_get_system_list (NULL, error);
if (system_dirs == NULL)
return FALSE;
for (i = 0; i < system_dirs->len; i++)
{
FlatpakDir *system_dir = g_ptr_array_index (system_dirs, i);
old_remote = flatpak_dir_find_remote_by_uri (system_dir, runtime_url, runtime_collection_id);
if (old_remote != NULL)
break;
}
}
if (old_remote != NULL)
return TRUE;
if (opt_yes ||
flatpak_yes_no_prompt (_("This application depends on runtimes from:\n %s\nConfigure this as new remote '%s'"),
runtime_url, new_remote))
{
if (opt_yes)
g_print (_("Configuring %s as new remote '%s'"), runtime_url, new_remote);
if (!flatpak_dir_modify_remote (dir, new_remote, config, gpg_key, NULL, error))
return FALSE;
if (!flatpak_dir_recreate_repo (dir, NULL, error))
return FALSE;
}
return TRUE;
}
static gboolean
handle_runtime_repo_deps_from_bundle (FlatpakDir *dir, GFile *file, GError **error)
{
g_autofree char *dep_url = NULL;
g_autoptr(GVariant) metadata = NULL;
if (opt_no_deps)
return TRUE;
metadata = flatpak_bundle_load (file, NULL,
NULL,
NULL,
&dep_url,
NULL,
NULL,
NULL,
NULL,
NULL);
if (metadata == NULL || dep_url == NULL)
return TRUE;
return handle_runtime_repo_deps (dir, dep_url, error);
}
static gboolean
install_bundle (FlatpakDir *dir,
GOptionContext *context,
int argc, char **argv,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GFile) file = NULL;
const char *filename;
g_autoptr(GBytes) gpg_data = NULL;
g_autoptr(FlatpakTransaction) transaction = NULL;
if (argc < 2)
return usage_error (context, _("Bundle filename must be specified"), error);
if (argc > 2)
return usage_error (context, _("Too many arguments"), error);
filename = argv[1];
file = g_file_new_for_commandline_arg (filename);
if (!g_file_is_native (file))
return flatpak_fail (error, _("Remote bundles are not supported"));
if (opt_gpg_file != NULL)
{
/* Override gpg_data from file */
gpg_data = read_gpg_data (cancellable, error);
if (gpg_data == NULL)
return FALSE;
}
if (!handle_runtime_repo_deps_from_bundle (dir, file, error))
return FALSE;
if (!flatpak_dir_ensure_repo (dir, cancellable, error))
return FALSE;
transaction = flatpak_transaction_new (dir, opt_yes, opt_no_pull, opt_no_deploy,
opt_no_static_deltas, !opt_no_deps, !opt_no_related);
if (!flatpak_transaction_add_install_bundle (transaction, file, gpg_data, error))
return FALSE;
if (!flatpak_transaction_run (transaction, TRUE, cancellable, error))
return FALSE;
return TRUE;
}
static gboolean
handle_runtime_repo_deps_from_keyfile (FlatpakDir *dir, GBytes *data, GError **error)
{
g_autoptr(GKeyFile) keyfile = g_key_file_new ();
g_autofree char *dep_url = NULL;
if (opt_no_deps)
return TRUE;
if (!g_key_file_load_from_data (keyfile, g_bytes_get_data (data, NULL), g_bytes_get_size (data),
0, error))
return FALSE;
dep_url = g_key_file_get_string (keyfile, FLATPAK_REF_GROUP,
FLATPAK_REF_RUNTIME_REPO_KEY, NULL);
if (dep_url == NULL)
return TRUE;
return handle_runtime_repo_deps (dir, dep_url, error);
}
static gboolean
install_from (FlatpakDir *dir,
GOptionContext *context,
int argc, char **argv,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GFile) file = NULL;
g_autoptr(GBytes) file_data = NULL;
g_autofree char *data = NULL;
gsize data_len;
const char *filename;
g_autofree char *remote = NULL;
g_autofree char *ref = NULL;
const char *slash;
FlatpakDir *clone;
g_autoptr(FlatpakTransaction) transaction = NULL;
if (argc < 2)
return usage_error (context, _("Filename or uri must be specified"), error);
if (argc > 2)
return usage_error (context, _("Too many arguments"), error);
filename = argv[1];
if (g_str_has_prefix (filename, "http:") ||
g_str_has_prefix (filename, "https:"))
{
file_data = download_uri (filename, error);
if (file_data == NULL)
{
g_prefix_error (error, "Can't load uri %s: ", filename);
return FALSE;
}
}
else
{
file = g_file_new_for_commandline_arg (filename);
if (!g_file_load_contents (file, cancellable, &data, &data_len, NULL, error))
return FALSE;
file_data = g_bytes_new_take (g_steal_pointer (&data), data_len);
}
if (!handle_runtime_repo_deps_from_keyfile (dir, file_data, error))
return FALSE;
if (!flatpak_dir_create_remote_for_ref_file (dir, file_data, opt_arch, &remote, &ref, error))
return FALSE;
/* Need to pick up the new config, in case it was applied in the system helper. */
clone = flatpak_dir_clone (dir);
if (!flatpak_dir_ensure_repo (clone, cancellable, error))
return FALSE;
slash = strchr (ref, '/');
g_print (_("Installing: %s\n"), slash + 1);
transaction = flatpak_transaction_new (clone, opt_yes, opt_no_pull, opt_no_deploy,
opt_no_static_deltas, !opt_no_deps, !opt_no_related);
if (!flatpak_transaction_add_install (transaction, remote, ref, (const char **)opt_subpaths, error))
return FALSE;
if (!flatpak_transaction_update_metadata (transaction, FALSE, cancellable, error))
return FALSE;
if (!flatpak_transaction_run (transaction, TRUE, cancellable, error))
return FALSE;
return TRUE;
}
gboolean
flatpak_builtin_install (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDir) dir = NULL;
const char *remote;
char **prefs = NULL;
int i, n_prefs;
g_autofree char *target_branch = NULL;
g_autofree char *default_branch = NULL;
FlatpakKinds kinds;
g_autoptr(FlatpakTransaction) transaction = NULL;
context = g_option_context_new (_("LOCATION/REMOTE [REF...] - Install applications or runtimes"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
if (!flatpak_option_context_parse (context, options, &argc, &argv, 0, &dir, cancellable, error))
return FALSE;
if (!opt_bundle && !opt_from && argc >= 2)
{
if (flatpak_file_arg_has_suffix (argv[1], ".flatpakref"))
opt_from = TRUE;
if (flatpak_file_arg_has_suffix (argv[1], ".flatpak"))
opt_bundle = TRUE;
}
if (opt_bundle)
return install_bundle (dir, context, argc, argv, cancellable, error);
if (opt_from)
return install_from (dir, context, argc, argv, cancellable, error);
if (argc < 3)
return usage_error (context, _("REMOTE and REF must be specified"), error);
remote = argv[1];
prefs = &argv[2];
n_prefs = argc - 2;
/* Backwards compat for old "REMOTE NAME [BRANCH]" argument version */
if (argc == 4 && looks_like_branch (argv[3]))
{
target_branch = g_strdup (argv[3]);
n_prefs = 1;
}
default_branch = flatpak_dir_get_remote_default_branch (dir, remote);
kinds = flatpak_kinds_from_bools (opt_app, opt_runtime);
transaction = flatpak_transaction_new (dir, opt_yes, opt_no_pull, opt_no_deploy,
opt_no_static_deltas, !opt_no_deps, !opt_no_related);
for (i = 0; i < n_prefs; i++)
{
const char *pref = prefs[i];
FlatpakKinds matched_kinds;
g_autofree char *id = NULL;
g_autofree char *arch = NULL;
g_autofree char *branch = NULL;
FlatpakKinds kind;
g_autofree char *ref = NULL;
if (!flatpak_split_partial_ref_arg (pref, kinds, opt_arch, target_branch,
&matched_kinds, &id, &arch, &branch, error))
return FALSE;
ref = flatpak_dir_find_remote_ref (dir, remote, id, branch, default_branch, arch,
matched_kinds, &kind, cancellable, error);
if (ref == NULL)
return FALSE;
if (!flatpak_transaction_add_install (transaction, remote, ref, (const char **)opt_subpaths, error))
return FALSE;
}
if (!flatpak_transaction_update_metadata (transaction, FALSE, cancellable, error))
return FALSE;
if (!flatpak_transaction_run (transaction, TRUE, cancellable, error))
return FALSE;
return TRUE;
}
gboolean
flatpak_complete_install (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDir) dir = NULL;
FlatpakKinds kinds;
int i;
context = g_option_context_new ("");
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv, 0, &dir, NULL, NULL))
return FALSE;
kinds = flatpak_kinds_from_bools (opt_app, opt_runtime);
switch (completion->argc)
{
case 0:
case 1: /* REMOTE */
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, options);
flatpak_complete_options (completion, user_entries);
{
g_auto(GStrv) remotes = flatpak_dir_list_remotes (dir, NULL, NULL);
if (remotes == NULL)
return FALSE;
for (i = 0; remotes[i] != NULL; i++)
flatpak_complete_word (completion, "%s ", remotes[i]);
}
break;
default: /* REF */
flatpak_complete_partial_ref (completion, kinds, opt_arch, dir, completion->argv[1]);
break;
}
return TRUE;
}

View File

@ -1,213 +0,0 @@
/*
* Copyright © 2014 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 <glib/gi18n.h>
#include "libglnx/libglnx.h"
#include "flatpak-builtins.h"
#include "flatpak-utils.h"
#include "flatpak-table-printer.h"
static gboolean opt_show_details;
static gboolean opt_user;
static gboolean opt_system;
static gboolean opt_show_disabled;
static char **opt_installations;
static GOptionEntry options[] = {
{ "user", 0, 0, G_OPTION_ARG_NONE, &opt_user, N_("Show user installations"), NULL },
{ "system", 0, 0, G_OPTION_ARG_NONE, &opt_system, N_("Show system-wide installations"), NULL },
{ "installation", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_installations, N_("Show specific system-wide installations"), NULL },
{ "show-details", 'd', 0, G_OPTION_ARG_NONE, &opt_show_details, N_("Show remote details"), NULL },
{ "show-disabled", 0, 0, G_OPTION_ARG_NONE, &opt_show_disabled, N_("Show disabled remotes"), NULL },
{ NULL }
};
gboolean
flatpak_builtin_list_remotes (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(GPtrArray) dirs = NULL;
guint i = 0, j;
FlatpakTablePrinter *printer;
context = g_option_context_new (_(" - List remote repositories"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
if (!flatpak_option_context_parse (context, options, &argc, &argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error))
return FALSE;
if (argc > 1)
return usage_error (context, _("Too many arguments"), error);
if (!opt_user && !opt_system && opt_installations == NULL)
{
/* Default: All system and user remotes */
opt_user = opt_system = TRUE;
}
dirs = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
if (opt_user)
g_ptr_array_add (dirs, flatpak_dir_get_user ());
if (opt_system)
g_ptr_array_add (dirs, flatpak_dir_get_system_default ());
if (opt_installations != NULL)
{
int i = 0;
for (i = 0; opt_installations[i] != NULL; i++)
{
FlatpakDir *installation_dir = NULL;
/* Already included the default system installation. */
if (opt_system && g_strcmp0 (opt_installations[i], "default") == 0)
continue;
installation_dir = flatpak_dir_get_system_by_id (opt_installations[i], cancellable, error);
if (installation_dir == NULL)
return FALSE;
g_ptr_array_add (dirs, installation_dir);
}
}
printer = flatpak_table_printer_new ();
j = 0;
flatpak_table_printer_set_column_title (printer, j++, _("Name"));
if (opt_show_details)
{
flatpak_table_printer_set_column_title (printer, j++, _("Title"));
flatpak_table_printer_set_column_title (printer, j++, _("URL"));
flatpak_table_printer_set_column_title (printer, j++, _("Priority"));
}
flatpak_table_printer_set_column_title (printer, j++, _("Options"));
for (j = 0; j < dirs->len; j++)
{
FlatpakDir *dir = g_ptr_array_index (dirs, j);
g_auto(GStrv) remotes = NULL;
remotes = flatpak_dir_list_remotes (dir, cancellable, error);
if (remotes == NULL)
return FALSE;
for (i = 0; remotes[i] != NULL; i++)
{
char *remote_name = remotes[i];
gboolean disabled;
g_autofree char *remote_url = NULL;
g_autofree char *title = NULL;
int prio;
g_autofree char *prio_as_string = NULL;
gboolean gpg_verify = TRUE;
disabled = flatpak_dir_get_remote_disabled (dir, remote_name);
if (disabled && !opt_show_disabled)
continue;
flatpak_table_printer_add_column (printer, remote_name);
if (opt_show_details)
{
title = flatpak_dir_get_remote_title (dir, remote_name);
if (title)
flatpak_table_printer_add_column (printer, title);
else
flatpak_table_printer_add_column (printer, "-");
if (ostree_repo_remote_get_url (flatpak_dir_get_repo (dir), remote_name, &remote_url, NULL))
flatpak_table_printer_add_column (printer, remote_url);
else
flatpak_table_printer_add_column (printer, "-");
prio = flatpak_dir_get_remote_prio (dir, remote_name);
prio_as_string = g_strdup_printf ("%d", prio);
flatpak_table_printer_add_column (printer, prio_as_string);
}
flatpak_table_printer_add_column (printer, ""); /* Options */
if ((opt_user && opt_system) || (opt_user && opt_installations != NULL)
|| (opt_system && opt_installations != NULL)
|| (opt_installations != NULL && g_strv_length (opt_installations) > 1))
{
g_autofree char *dir_id = flatpak_dir_get_name (dir);
flatpak_table_printer_append_with_comma (printer, dir_id);
}
if (disabled)
flatpak_table_printer_append_with_comma (printer, "disabled");
if (flatpak_dir_get_remote_oci (dir, remote_name))
flatpak_table_printer_append_with_comma (printer, "oci");
if (flatpak_dir_get_remote_noenumerate (dir, remote_name))
flatpak_table_printer_append_with_comma (printer, "no-enumerate");
ostree_repo_remote_get_gpg_verify (flatpak_dir_get_repo (dir), remote_name,
&gpg_verify, NULL);
if (!gpg_verify)
flatpak_table_printer_append_with_comma (printer, "no-gpg-verify");
flatpak_table_printer_finish_row (printer);
}
}
flatpak_table_printer_print (printer);
flatpak_table_printer_free (printer);
return TRUE;
}
gboolean
flatpak_complete_list_remotes (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDir) dir = NULL;
context = g_option_context_new ("");
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv, 0, &dir, NULL, NULL))
return FALSE;
switch (completion->argc)
{
case 0:
case 1: /* REMOTE */
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, options);
flatpak_complete_options (completion, user_entries);
break;
}
return TRUE;
}

View File

@ -1,402 +0,0 @@
/*
* Copyright © 2014 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 <unistd.h>
#include <string.h>
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
#include "flatpak-builtins.h"
#include "flatpak-utils.h"
#include "flatpak-table-printer.h"
static gboolean opt_show_details;
static gboolean opt_user;
static gboolean opt_system;
static gboolean opt_runtime;
static gboolean opt_app;
static gboolean opt_all;
static char **opt_installations;
static char *opt_arch;
static GOptionEntry options[] = {
{ "user", 0, 0, G_OPTION_ARG_NONE, &opt_user, N_("Show user installations"), NULL },
{ "system", 0, 0, G_OPTION_ARG_NONE, &opt_system, N_("Show system-wide installations"), NULL },
{ "installation", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_installations, N_("Show specific system-wide installations"), NULL },
{ "show-details", 'd', 0, G_OPTION_ARG_NONE, &opt_show_details, N_("Show extra information"), NULL },
{ "runtime", 0, 0, G_OPTION_ARG_NONE, &opt_runtime, N_("List installed runtimes"), NULL },
{ "app", 0, 0, G_OPTION_ARG_NONE, &opt_app, N_("List installed applications"), NULL },
{ "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, N_("Arch to show"), N_("ARCH") },
{ "all", 'a', 0, G_OPTION_ARG_NONE, &opt_all, N_("List all refs (including locale/debug)"), NULL },
{ NULL }
};
/* Associates a flatpak installation's directory with
* the list of references for apps and runtimes */
typedef struct
{
FlatpakDir *dir;
GStrv app_refs;
GStrv runtime_refs;
} RefsData;
static RefsData *
refs_data_new (FlatpakDir *dir, const GStrv app_refs, const GStrv runtime_refs)
{
RefsData *refs_data = g_new0 (RefsData, 1);
refs_data->dir = g_object_ref (dir);
refs_data->app_refs = g_strdupv ((char **) app_refs);
refs_data->runtime_refs = g_strdupv ((char **) runtime_refs);
return refs_data;
}
static void
refs_data_free (RefsData *refs_data)
{
g_object_unref (refs_data->dir);
g_strfreev (refs_data->app_refs);
g_strfreev (refs_data->runtime_refs);
g_free (refs_data);
}
static char **
join_strv (char **a, char **b)
{
gsize len = 1, i, j;
char **res;
if (a)
len += g_strv_length (a);
if (b)
len += g_strv_length (b);
res = g_new (char *, len);
i = 0;
for (j = 0; a != NULL && a[j] != NULL; j++)
res[i++] = g_strdup (a[j]);
for (j = 0; b != NULL && b[j] != NULL; j++)
res[i++] = g_strdup (b[j]);
res[i++] = NULL;
return res;
}
static gboolean
find_refs_for_dir (FlatpakDir *dir, GStrv *apps, GStrv *runtimes, GCancellable *cancellable, GError **error)
{
if (flatpak_dir_ensure_repo (dir, cancellable, NULL))
{
if (apps != NULL && !flatpak_dir_list_refs (dir, "app", apps, cancellable, error))
return FALSE;
if (runtimes != NULL && !flatpak_dir_list_refs (dir, "runtime", runtimes, cancellable, error))
return FALSE;
}
return TRUE;
}
static gboolean
print_table_for_refs (gboolean print_apps, GPtrArray* refs_array, const char *arch, GCancellable *cancellable, GError **error)
{
FlatpakTablePrinter *printer = flatpak_table_printer_new ();
int i;
i = 0;
flatpak_table_printer_set_column_title (printer, i++, _("Ref"));
if (opt_show_details)
{
flatpak_table_printer_set_column_title (printer, i++, _("Origin"));
flatpak_table_printer_set_column_title (printer, i++, _("Active commit"));
flatpak_table_printer_set_column_title (printer, i++, _("Latest commit"));
flatpak_table_printer_set_column_title (printer, i++, _("Installed size"));
}
flatpak_table_printer_set_column_title (printer, i++, _("Options"));
for (i = 0; i < refs_array->len; i++)
{
RefsData *refs_data = NULL;
FlatpakDir *dir = NULL;
g_auto(GStrv) dir_refs = NULL;
g_autoptr(GHashTable) pref_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
int j;
refs_data = (RefsData *) g_ptr_array_index (refs_array, i);
dir = refs_data->dir;
dir_refs = join_strv (refs_data->app_refs, refs_data->runtime_refs);
for (j = 0; dir_refs[j] != NULL; j++)
{
char *ref = dir_refs[j];
char *partial_ref = flatpak_make_valid_id_prefix (strchr (ref, '/') + 1);
g_hash_table_insert (pref_hash, partial_ref, ref);
}
for (j = 0; dir_refs[j] != NULL; j++)
{
char *ref, *partial_ref;
g_auto(GStrv) parts = NULL;
const char *repo = NULL;
g_autoptr(GVariant) deploy_data = NULL;
const char *active;
const char *alt_id;
g_autofree char *latest = NULL;
g_autofree char *size_s = NULL;
guint64 size = 0;
g_autofree const char **subpaths = NULL;
ref = dir_refs[j];
parts = g_strsplit (ref, "/", -1);
partial_ref = strchr (ref, '/') + 1;
if (arch != NULL && strcmp (arch, parts[1]) != 0)
continue;
deploy_data = flatpak_dir_get_deploy_data (dir, ref, cancellable, NULL);
if (deploy_data == NULL)
continue;
if (!opt_all && strcmp (parts[0], "runtime") == 0 &&
flatpak_id_has_subref_suffix (parts[1]))
{
g_autofree char *prefix_partial_ref = NULL;
char *last_dot = strrchr (parts[1], '.');
*last_dot = 0;
prefix_partial_ref = g_strconcat (parts[1], "/", parts[2], "/", parts[3], NULL);
*last_dot = '.';
if (g_hash_table_lookup (pref_hash, prefix_partial_ref))
continue;
}
repo = flatpak_deploy_data_get_origin (deploy_data);
active = flatpak_deploy_data_get_commit (deploy_data);
alt_id = flatpak_deploy_data_get_alt_id (deploy_data);
latest = flatpak_dir_read_latest (dir, repo, ref, NULL, NULL, NULL);
if (latest)
{
if (strcmp (active, latest) == 0)
{
g_free (latest);
latest = g_strdup ("-");
}
else
{
latest[MIN (strlen (latest), 12)] = 0;
}
}
else
{
latest = g_strdup ("?");
}
flatpak_table_printer_add_column (printer, partial_ref);
if (opt_show_details)
{
flatpak_table_printer_add_column (printer, repo);
flatpak_table_printer_add_column_len (printer, active, 12);
flatpak_table_printer_add_column_len (printer, latest, 12);
size = flatpak_deploy_data_get_installed_size (deploy_data);
size_s = g_format_size (size);
flatpak_table_printer_add_decimal_column (printer, size_s);
}
flatpak_table_printer_add_column (printer, ""); /* Options */
if (refs_array->len > 1)
{
g_autofree char *source = flatpak_dir_get_name (dir);
flatpak_table_printer_append_with_comma (printer, source);
}
if (alt_id)
{
g_autofree char *alt_id_str = g_strdup_printf ("alt-id=%.12s", alt_id);
flatpak_table_printer_append_with_comma (printer, alt_id_str);
}
if (strcmp (parts[0], "app") == 0)
{
g_autofree char *current = NULL;
current = flatpak_dir_current_ref (dir, parts[1], cancellable);
if (current && strcmp (ref, current) == 0)
flatpak_table_printer_append_with_comma (printer, "current");
}
else
{
if (print_apps)
flatpak_table_printer_append_with_comma (printer, "runtime");
}
subpaths = flatpak_deploy_data_get_subpaths (deploy_data);
if (subpaths[0] != NULL)
{
flatpak_table_printer_append_with_comma (printer, "partial");
}
flatpak_table_printer_finish_row (printer);
}
}
flatpak_table_printer_print (printer);
flatpak_table_printer_free (printer);
return TRUE;
}
static gboolean
print_installed_refs (gboolean app, gboolean runtime, gboolean print_system, gboolean print_user, char **installations, const char *arch, GCancellable *cancellable, GError **error)
{
g_autoptr(GPtrArray) refs_array = NULL;
gboolean print_all = !print_user && !print_system && (installations == NULL);
refs_array = g_ptr_array_new_with_free_func ((GDestroyNotify) refs_data_free);
if (print_user || print_all)
{
g_autoptr(FlatpakDir) user_dir = NULL;
g_auto(GStrv) user_app = NULL;
g_auto(GStrv) user_runtime = NULL;
user_dir =flatpak_dir_get_user ();
if (!find_refs_for_dir (user_dir, app ? &user_app : NULL, runtime ? &user_runtime : NULL, cancellable, error))
return FALSE;
g_ptr_array_add (refs_array, refs_data_new (user_dir, user_app, user_runtime));
}
if (print_all)
{
g_autoptr(GPtrArray) system_dirs = NULL;
int i;
system_dirs = flatpak_dir_get_system_list (cancellable, error);
if (system_dirs == NULL)
return FALSE;
for (i = 0; i < system_dirs->len; i++)
{
FlatpakDir *dir = g_ptr_array_index (system_dirs, i);
g_auto(GStrv) apps = NULL;
g_auto(GStrv) runtimes = NULL;
if (!find_refs_for_dir (dir, app ? &apps : NULL, runtime ? &runtimes : NULL, cancellable, error))
return FALSE;
g_ptr_array_add (refs_array, refs_data_new (dir, apps, runtimes));
}
}
else
{
if (print_system)
{
g_autoptr(FlatpakDir) system_dir = NULL;
g_auto(GStrv) system_app = NULL;
g_auto(GStrv) system_runtime = NULL;
system_dir = flatpak_dir_get_system_default ();
if (!find_refs_for_dir (system_dir, app ? &system_app : NULL, runtime ? &system_runtime : NULL, cancellable, error))
return FALSE;
g_ptr_array_add (refs_array, refs_data_new (system_dir, system_app, system_runtime));
}
if (installations != NULL)
{
g_auto(GStrv) installation_apps = NULL;
g_auto(GStrv) installation_runtimes = NULL;
int i = 0;
for (i = 0; installations[i] != NULL; i++)
{
g_autoptr(FlatpakDir) system_dir = NULL;
/* Already included the default system installation. */
if (print_system && g_strcmp0 (installations[i], "default") == 0)
continue;
system_dir = flatpak_dir_get_system_by_id (installations[i], cancellable, error);
if (system_dir == NULL)
return FALSE;
if (!find_refs_for_dir (system_dir, app ? &installation_apps : NULL, runtime ? &installation_runtimes : NULL, cancellable, error))
return FALSE;
g_ptr_array_add (refs_array, refs_data_new (system_dir, installation_apps, installation_runtimes));
}
}
}
if (!print_table_for_refs (app, refs_array, arch, cancellable, error))
return FALSE;
return TRUE;
}
gboolean
flatpak_builtin_list (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
context = g_option_context_new (_(" - List installed apps and/or runtimes"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
if (!flatpak_option_context_parse (context, options, &argc, &argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error))
return FALSE;
if (argc > 1)
return usage_error (context, _("Too many arguments"), error);
if (!opt_app && !opt_runtime)
{
opt_app = TRUE;
opt_runtime = TRUE;
}
if (!print_installed_refs (opt_app, opt_runtime,
opt_system,
opt_user,
opt_installations,
opt_arch,
cancellable, error))
return FALSE;
return TRUE;
}
gboolean
flatpak_complete_list (FlatpakCompletion *completion)
{
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, options);
return TRUE;
}

View File

@ -1,272 +0,0 @@
/*
* Copyright © 2014 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 <unistd.h>
#include <string.h>
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
#include "flatpak-builtins.h"
#include "flatpak-utils.h"
#include "flatpak-table-printer.h"
static gboolean opt_show_details;
static gboolean opt_runtime;
static gboolean opt_app;
static gboolean opt_all;
static gboolean opt_only_updates;
static char *opt_arch;
static GOptionEntry options[] = {
{ "show-details", 'd', 0, G_OPTION_ARG_NONE, &opt_show_details, N_("Show arches and branches"), NULL },
{ "runtime", 0, 0, G_OPTION_ARG_NONE, &opt_runtime, N_("Show only runtimes"), NULL },
{ "app", 0, 0, G_OPTION_ARG_NONE, &opt_app, N_("Show only apps"), NULL },
{ "updates", 0, 0, G_OPTION_ARG_NONE, &opt_only_updates, N_("Show only those where updates are available"), NULL },
{ "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, N_("Limit to this arch (* for all)"), N_("ARCH") },
{ "all", 'a', 0, G_OPTION_ARG_NONE, &opt_all, N_("List all refs (including locale/debug)"), NULL },
{ NULL }
};
gboolean
flatpak_builtin_ls_remote (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDir) dir = NULL;
g_autoptr(GHashTable) refs = NULL;
GHashTableIter iter;
gpointer key;
gpointer value;
g_autoptr(GHashTable) names = NULL;
guint n_keys;
g_autofree const char **keys = NULL;
int i;
const char *repository;
const char **arches = flatpak_get_arches ();
const char *opt_arches[] = {NULL, NULL};
g_autoptr(GVariant) refdata = NULL;
g_autoptr(GHashTable) pref_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
g_autoptr(GError) local_error = NULL;
context = g_option_context_new (_(" REMOTE - Show available runtimes and applications"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
if (!flatpak_option_context_parse (context, options, &argc, &argv, 0, &dir, cancellable, error))
return FALSE;
if (!opt_app && !opt_runtime)
opt_app = opt_runtime = TRUE;
if (argc < 2)
return usage_error (context, _("REMOTE must be specified"), error);
if (argc > 2)
return usage_error (context, _("Too many arguments"), error);
repository = argv[1];
if (!flatpak_dir_list_remote_refs (dir,
repository,
&refs,
cancellable, error))
return FALSE;
names = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
if (opt_show_details)
{
if (!flatpak_dir_lookup_repo_metadata (dir, repository, cancellable, &local_error,
"xa.cache", "v", &refdata))
{
if (local_error == NULL)
flatpak_fail (&local_error, _("No ref information available in repository"));
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}
}
if (opt_arch != NULL)
{
if (strcmp (opt_arch, "*") == 0)
arches = NULL;
else
{
opt_arches[0] = opt_arch;
arches = opt_arches;
}
}
g_hash_table_iter_init (&iter, refs);
while (g_hash_table_iter_next (&iter, &key, &value))
{
char *ref = key;
char *partial_ref = flatpak_make_valid_id_prefix (strchr (ref, '/') + 1);
g_hash_table_insert (pref_hash, partial_ref, ref);
}
g_hash_table_iter_init (&iter, refs);
while (g_hash_table_iter_next (&iter, &key, &value))
{
const char *ref = key;
const char *checksum = value;
const char *name = NULL;
g_auto(GStrv) parts = NULL;
parts = flatpak_decompose_ref (ref, NULL);
if (parts == NULL)
{
g_debug ("Invalid remote ref %s", ref);
continue;
}
if (opt_only_updates)
{
g_autoptr(GVariant) deploy_data = flatpak_dir_get_deploy_data (dir, ref, cancellable, NULL);
if (deploy_data == NULL)
continue;
if (g_strcmp0 (flatpak_deploy_data_get_commit (deploy_data), checksum) == 0)
continue;
}
if (arches != NULL && !g_strv_contains (arches, parts[2]))
continue;
if (strcmp (parts[0], "runtime") == 0 && !opt_runtime)
continue;
if (strcmp (parts[0], "app") == 0 && !opt_app)
continue;
if (!opt_show_details)
name = parts[1];
else
name = ref;
if (!opt_all &&
strcmp (parts[0], "runtime") == 0 &&
flatpak_id_has_subref_suffix (parts[1]))
{
g_autofree char *prefix_partial_ref = NULL;
char *last_dot = strrchr (parts[1], '.');
*last_dot = 0;
prefix_partial_ref = g_strconcat (parts[1], "/", parts[2], "/", parts[3], NULL);
*last_dot = '.';
if (g_hash_table_lookup (pref_hash, prefix_partial_ref))
continue;
}
if (!opt_all && opt_arch == NULL &&
/* Hide non-primary arches if the primary arch exists */
strcmp (arches[0], parts[2]) != 0)
{
g_autofree char *alt_arch_ref = g_strconcat (parts[0], "/", parts[1], "/", arches[0], "/", parts[3], NULL);
if (g_hash_table_lookup (refs, alt_arch_ref))
continue;
}
if (g_hash_table_lookup (names, name) == NULL)
g_hash_table_insert (names, g_strdup (name), g_strdup (checksum));
}
keys = (const char **) g_hash_table_get_keys_as_array (names, &n_keys);
g_qsort_with_data (keys, n_keys, sizeof (char *), (GCompareDataFunc) flatpak_strcmp0_ptr, NULL);
FlatpakTablePrinter *printer = flatpak_table_printer_new ();
flatpak_table_printer_set_column_title (printer, 0, _("Ref"));
flatpak_table_printer_set_column_title (printer, 1, _("Commit"));
flatpak_table_printer_set_column_title (printer, 2, _("Installed size"));
flatpak_table_printer_set_column_title (printer, 3, _("Download size"));
for (i = 0; i < n_keys; i++)
{
flatpak_table_printer_add_column (printer, keys[i]);
if (opt_show_details)
{
g_autofree char *value = NULL;
guint64 installed_size;
guint64 download_size;
const char *metadata;
value = g_strdup ((char *) g_hash_table_lookup (names, keys[i]));
value[MIN (strlen (value), 12)] = 0;
flatpak_table_printer_add_column (printer, value);
if (g_variant_lookup (refdata, keys[i], "(tt&s)", &installed_size, &download_size, &metadata))
{
g_autofree char *installed = g_format_size (GUINT64_FROM_BE (installed_size));
g_autofree char *download = g_format_size (GUINT64_FROM_BE (download_size));
flatpak_table_printer_add_decimal_column (printer, installed);
flatpak_table_printer_add_decimal_column (printer, download);
}
}
flatpak_table_printer_finish_row (printer);
}
flatpak_table_printer_print (printer);
flatpak_table_printer_free (printer);
return TRUE;
}
gboolean
flatpak_complete_ls_remote (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDir) dir = NULL;
int i;
context = g_option_context_new ("");
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv, 0, &dir, NULL, NULL))
return FALSE;
switch (completion->argc)
{
case 0:
case 1: /* REMOTE */
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, options);
flatpak_complete_options (completion, user_entries);
{
g_auto(GStrv) remotes = flatpak_dir_list_remotes (dir, NULL, NULL);
if (remotes == NULL)
return FALSE;
for (i = 0; remotes[i] != NULL; i++)
flatpak_complete_word (completion, "%s ", remotes[i]);
}
break;
}
return TRUE;
}

View File

@ -1,159 +0,0 @@
/*
* Copyright © 2014 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 <unistd.h>
#include <string.h>
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
#include "flatpak-builtins.h"
#include "flatpak-utils.h"
static char *opt_arch;
static GOptionEntry options[] = {
{ "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, N_("Arch to make current for"), N_("ARCH") },
{ NULL }
};
gboolean
flatpak_builtin_make_current_app (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDir) dir = NULL;
g_autoptr(GFile) deploy_base = NULL;
const char *pref;
const char *default_branch = NULL;
g_autofree char *ref = NULL;
g_auto(GLnxLockFile) lock = GLNX_LOCK_FILE_INIT;
g_autofree char *id = NULL;
g_autofree char *arch = NULL;
g_autofree char *branch = NULL;
FlatpakKinds kinds;
context = g_option_context_new (_("APP BRANCH - Make branch of application current"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
if (!flatpak_option_context_parse (context, options, &argc, &argv, 0, &dir, cancellable, error))
return FALSE;
if (argc < 2)
return usage_error (context, _("APP must be specified"), error);
if (argc > 3)
return usage_error (context, _("Too many arguments"), error);
pref = argv[1];
if (argc >= 3)
default_branch = argv[2];
if (!flatpak_split_partial_ref_arg (pref, FLATPAK_KINDS_APP, opt_arch, default_branch,
&kinds, &id, &arch, &branch, error))
return FALSE;
if (branch == NULL)
return usage_error (context, _("BRANCH must be specified"), error);
ref = flatpak_dir_find_installed_ref (dir, id, branch, arch, FLATPAK_KINDS_APP,
NULL, error);
if (ref == NULL)
return FALSE;
if (!flatpak_dir_lock (dir, &lock,
cancellable, error))
return FALSE;
deploy_base = flatpak_dir_get_deploy_dir (dir, ref);
if (!g_file_query_exists (deploy_base, cancellable))
return flatpak_fail (error, _("App %s branch %s is not installed"), id, branch);
if (!flatpak_dir_make_current_ref (dir, ref, cancellable, error))
return FALSE;
if (!flatpak_dir_update_exports (dir, id, cancellable, error))
return FALSE;
glnx_release_lock_file (&lock);
if (!flatpak_dir_mark_changed (dir, error))
return FALSE;
return TRUE;
}
gboolean
flatpak_complete_make_current_app (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDir) dir = NULL;
g_autoptr(GError) error = NULL;
g_auto(GStrv) refs = NULL;
int i;
context = g_option_context_new ("");
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv, 0, &dir, NULL, NULL))
return FALSE;
switch (completion->argc)
{
case 0:
case 1: /* NAME */
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, options);
flatpak_complete_options (completion, user_entries);
refs = flatpak_dir_find_installed_refs (dir, NULL, NULL, opt_arch,
FLATPAK_KINDS_APP, &error);
if (refs == NULL)
flatpak_completion_debug ("find installed refs error: %s", error->message);
for (i = 0; refs != NULL && refs[i] != NULL; i++)
{
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
if (parts)
flatpak_complete_word (completion, "%s ", parts[1]);
}
break;
case 2: /* Branch */
refs = flatpak_dir_find_installed_refs (dir, completion->argv[1], NULL, opt_arch,
FLATPAK_KINDS_APP, &error);
if (refs == NULL)
flatpak_completion_debug ("find installed refs error: %s", error->message);
for (i = 0; refs != NULL && refs[i] != NULL; i++)
{
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
if (parts)
flatpak_complete_word (completion, "%s ", parts[3]);
}
break;
default:
break;
}
return TRUE;
}

View File

@ -1,158 +0,0 @@
/*
* Copyright © 2014 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 <errno.h>
#include <string.h>
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
#include "flatpak-builtins.h"
#include "flatpak-utils.h"
#include "flatpak-run.h"
static GOptionEntry options[] = {
{ NULL }
};
gboolean
flatpak_builtin_override (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
const char *app;
g_autoptr(FlatpakContext) arg_context = NULL;
g_autoptr(FlatpakDir) dir = NULL;
g_autoptr(GKeyFile) metakey = NULL;
g_autoptr(FlatpakContext) overrides = NULL;
g_autoptr(GError) my_error = NULL;
context = g_option_context_new (_("APP - Override settings for application"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
arg_context = flatpak_context_new ();
g_option_context_add_group (context, flatpak_context_get_options (arg_context));
if (!flatpak_option_context_parse (context, options, &argc, &argv, 0, &dir, cancellable, error))
return FALSE;
if (argc < 2)
return usage_error (context, _("APP must be specified"), error);
if (argc > 2)
return usage_error (context, _("Too many arguments"), error);
app = argv[1];
if (!flatpak_is_valid_name (app, &my_error))
return flatpak_fail (error, _("'%s' is not a valid application name: %s"), app, my_error->message);
metakey = flatpak_load_override_keyfile (app, flatpak_dir_is_user (dir), &my_error);
if (metakey == NULL)
{
if (!g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
g_propagate_error (error, g_steal_pointer (&my_error));
return FALSE;
}
metakey = g_key_file_new ();
}
overrides = flatpak_context_new ();
if (!flatpak_context_load_metadata (overrides, metakey, error))
return FALSE;
flatpak_context_merge (overrides, arg_context);
flatpak_context_save_metadata (overrides, FALSE, metakey);
if (!flatpak_save_override_keyfile (metakey, app, flatpak_dir_is_user (dir), error))
return FALSE;
return TRUE;
}
gboolean
flatpak_complete_override (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDir) user_dir = NULL;
g_autoptr(FlatpakDir) system_dir = NULL;
g_autoptr(GError) error = NULL;
int i;
g_autoptr(FlatpakContext) arg_context = NULL;
context = g_option_context_new ("");
arg_context = flatpak_context_new ();
g_option_context_add_group (context, flatpak_context_get_options (arg_context));
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv,
FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, NULL, NULL))
return FALSE;
switch (completion->argc)
{
case 0:
case 1: /* NAME */
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, options);
flatpak_context_complete (arg_context, completion);
user_dir = flatpak_dir_get_user ();
{
g_auto(GStrv) refs = flatpak_dir_find_installed_refs (user_dir, NULL, NULL, NULL,
FLATPAK_KINDS_APP, &error);
if (refs == NULL)
flatpak_completion_debug ("find local refs error: %s", error->message);
for (i = 0; refs != NULL && refs[i] != NULL; i++)
{
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
if (parts)
flatpak_complete_word (completion, "%s ", parts[1]);
}
}
system_dir = flatpak_dir_get_system_default ();
{
g_auto(GStrv) refs = flatpak_dir_find_installed_refs (system_dir, NULL, NULL, NULL,
FLATPAK_KINDS_APP, &error);
if (refs == NULL)
flatpak_completion_debug ("find local refs error: %s", error->message);
for (i = 0; refs != NULL && refs[i] != NULL; i++)
{
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
if (parts)
flatpak_complete_word (completion, "%s ", parts[1]);
}
}
break;
}
return TRUE;
}

View File

@ -1,569 +0,0 @@
/*
* Copyright © 2014 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 <unistd.h>
#include <string.h>
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
#include "flatpak-builtins.h"
#include "flatpak-utils.h"
#include "flatpak-builtins-utils.h"
static char *opt_title;
static char *opt_redirect_url;
static char *opt_default_branch;
static char *opt_collection_id = NULL;
static gboolean opt_deploy_collection_id = FALSE;
static char **opt_gpg_import;
static char *opt_generate_delta_from;
static char *opt_generate_delta_to;
static char *opt_generate_delta_ref;
static char *opt_gpg_homedir;
static char **opt_gpg_key_ids;
static gboolean opt_prune;
static gboolean opt_generate_deltas;
static gint opt_prune_depth = -1;
static GOptionEntry options[] = {
{ "redirect-url", 0, 0, G_OPTION_ARG_STRING, &opt_redirect_url, N_("Redirect this repo to a new URL"), N_("URL") },
{ "title", 0, 0, G_OPTION_ARG_STRING, &opt_title, N_("A nice name to use for this repository"), N_("TITLE") },
{ "default-branch", 0, 0, G_OPTION_ARG_STRING, &opt_default_branch, N_("Default branch to use for this repository"), N_("BRANCH") },
#ifdef FLATPAK_ENABLE_P2P
{ "collection-id", 0, 0, G_OPTION_ARG_STRING, &opt_collection_id, N_("Collection ID"), N_("COLLECTION-ID") },
{ "deploy-collection-id", 0, 0, G_OPTION_ARG_NONE, &opt_deploy_collection_id, N_("Permanently deploy collection ID to client remote configurations"), NULL },
#endif /* FLATPAK_ENABLE_P2P */
{ "gpg-import", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_gpg_import, N_("Import new default GPG public key from FILE"), N_("FILE") },
{ "gpg-sign", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_gpg_key_ids, N_("GPG Key ID to sign the summary with"), N_("KEY-ID") },
{ "gpg-homedir", 0, 0, G_OPTION_ARG_STRING, &opt_gpg_homedir, N_("GPG Homedir to use when looking for keyrings"), N_("HOMEDIR") },
{ "generate-static-deltas", 0, 0, G_OPTION_ARG_NONE, &opt_generate_deltas, N_("Generate delta files"), NULL },
{ "prune", 0, 0, G_OPTION_ARG_NONE, &opt_prune, N_("Prune unused objects"), NULL },
{ "prune-depth", 0, 0, G_OPTION_ARG_INT, &opt_prune_depth, N_("Only traverse DEPTH parents for each commit (default: -1=infinite)"), N_("DEPTH") },
{ "generate-static-delta-from", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &opt_generate_delta_from, NULL, NULL },
{ "generate-static-delta-to", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &opt_generate_delta_to, NULL, NULL },
{ "generate-static-delta-ref", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &opt_generate_delta_ref, NULL, NULL },
{ NULL }
};
static void
_ostree_parse_delta_name (const char *delta_name,
char **out_from,
char **out_to)
{
g_auto(GStrv) parts = g_strsplit (delta_name, "-", 2);
if (parts[0] && parts[1])
{
*out_from = g_steal_pointer (&parts[0]);
*out_to = g_steal_pointer (&parts[1]);
}
else
{
*out_from = NULL;
*out_to = g_steal_pointer (&parts[0]);
}
}
static char *
_ostree_get_relative_static_delta_path (const char *from,
const char *to,
const char *target)
{
guint8 csum_to[OSTREE_SHA256_DIGEST_LEN];
char to_b64[44];
guint8 csum_to_copy[OSTREE_SHA256_DIGEST_LEN];
GString *ret = g_string_new ("deltas/");
ostree_checksum_inplace_to_bytes (to, csum_to);
ostree_checksum_b64_inplace_from_bytes (csum_to, to_b64);
ostree_checksum_b64_inplace_to_bytes (to_b64, csum_to_copy);
g_assert (memcmp (csum_to, csum_to_copy, OSTREE_SHA256_DIGEST_LEN) == 0);
if (from != NULL)
{
guint8 csum_from[OSTREE_SHA256_DIGEST_LEN];
char from_b64[44];
ostree_checksum_inplace_to_bytes (from, csum_from);
ostree_checksum_b64_inplace_from_bytes (csum_from, from_b64);
g_string_append_c (ret, from_b64[0]);
g_string_append_c (ret, from_b64[1]);
g_string_append_c (ret, '/');
g_string_append (ret, from_b64 + 2);
g_string_append_c (ret, '-');
}
g_string_append_c (ret, to_b64[0]);
g_string_append_c (ret, to_b64[1]);
if (from == NULL)
g_string_append_c (ret, '/');
g_string_append (ret, to_b64 + 2);
if (target != NULL)
{
g_string_append_c (ret, '/');
g_string_append (ret, target);
}
return g_string_free (ret, FALSE);
}
static gboolean
_ostree_repo_static_delta_delete (OstreeRepo *self,
const char *delta_id,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
g_autofree char *from = NULL;
g_autofree char *to = NULL;
g_autofree char *deltadir = NULL;
struct stat buf;
int repo_dir_fd = ostree_repo_get_dfd (self);
_ostree_parse_delta_name (delta_id, &from, &to);
deltadir = _ostree_get_relative_static_delta_path (from, to, NULL);
if (fstatat (repo_dir_fd, deltadir, &buf, 0) != 0)
{
if (errno == ENOENT)
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"Can't find delta %s", delta_id);
else
glnx_set_error_from_errno (error);
goto out;
}
if (!glnx_shutil_rm_rf_at (repo_dir_fd, deltadir,
cancellable, error))
goto out;
ret = TRUE;
out:
return ret;
}
static gboolean
generate_one_delta (OstreeRepo *repo,
const char *from,
const char *to,
const char *ref,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GVariantBuilder) parambuilder = NULL;
g_autoptr(GVariant) params = NULL;
parambuilder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
/* Fall back for 1 meg files */
g_variant_builder_add (parambuilder, "{sv}",
"min-fallback-size", g_variant_new_uint32 (1));
params = g_variant_ref_sink (g_variant_builder_end (parambuilder));
if (ref == NULL)
ref = "";
if (from == NULL)
g_print (_("Generating delta: %s (%.10s)\n"), ref, to);
else
g_print (_("Generating delta: %s (%.10s-%.10s)\n"), ref, from, to);
if (!ostree_repo_static_delta_generate (repo, OSTREE_STATIC_DELTA_GENERATE_OPT_MAJOR,
from, to, NULL,
params,
cancellable, error))
{
if (from == NULL)
g_prefix_error (error, _("Failed to generate delta %s (%.10s): "),
ref, to);
else
g_prefix_error (error, _("Failed to generate delta %s (%.10s-%.10s): "),
ref, from, to);
return FALSE;
}
return TRUE;
}
static void
delta_generation_done (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
{
int *n_spawned_delta_generate = user_data;
(*n_spawned_delta_generate)--;
}
static gboolean
spawn_delete_generation (GMainContext *context,
int *n_spawned_delta_generate,
OstreeRepo *repo,
GVariant *params,
const char *ref,
const char *from,
const char *to,
GError **error)
{
g_autoptr(GSubprocessLauncher) launcher = g_subprocess_launcher_new (0);
g_autoptr(GSubprocess) subprocess = NULL;
const char *argv[] = {
"/proc/self/exe",
"build-update-repo",
"--generate-static-delta-ref",
ref,
"--generate-static-delta-to",
to,
NULL, NULL, NULL, NULL
};
int i = 6;
g_autofree char *exe = NULL;
exe = flatpak_readlink ("/proc/self/exe", NULL);
if (exe)
argv[0] = exe;
if (from)
{
argv[i++] = "--generate-static-delta-from";
argv[i++] = from;
}
argv[i++] = flatpak_file_get_path_cached (ostree_repo_get_path (repo));
argv[i++] = NULL;
g_assert (i <= G_N_ELEMENTS (argv));
while (*n_spawned_delta_generate > g_get_num_processors ())
g_main_context_iteration (context, TRUE);
subprocess = g_subprocess_launcher_spawnv (launcher, argv, error);
if (subprocess == NULL)
return FALSE;
(*n_spawned_delta_generate)++;
g_subprocess_wait_async (subprocess, NULL, delta_generation_done, n_spawned_delta_generate);
return TRUE;
}
static gboolean
generate_all_deltas (OstreeRepo *repo,
GPtrArray **unwanted_deltas,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GMainContext) context = g_main_context_new ();
g_autoptr(GHashTable) all_refs = NULL;
g_autoptr(GHashTable) all_deltas_hash = NULL;
g_autoptr(GHashTable) wanted_deltas_hash = NULL;
g_autoptr(GPtrArray) all_deltas = NULL;
int i;
GHashTableIter iter;
gpointer key, value;
g_autoptr(GVariantBuilder) parambuilder = NULL;
g_autoptr(GVariant) params = NULL;
int n_spawned_delta_generate = 0;
g_print ("Generating static deltas\n");
parambuilder = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}"));
/* Fall back for 1 meg files */
g_variant_builder_add (parambuilder, "{sv}",
"min-fallback-size", g_variant_new_uint32 (1));
params = g_variant_ref_sink (g_variant_builder_end (parambuilder));
if (!ostree_repo_list_static_delta_names (repo, &all_deltas,
cancellable, error))
return FALSE;
wanted_deltas_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
all_deltas_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
for (i = 0; i < all_deltas->len; i++)
g_hash_table_insert (all_deltas_hash,
g_strdup (g_ptr_array_index (all_deltas, i)),
NULL);
if (!ostree_repo_list_refs (repo, NULL, &all_refs,
cancellable, error))
return FALSE;
g_main_context_push_thread_default (context);
g_hash_table_iter_init (&iter, all_refs);
while (g_hash_table_iter_next (&iter, &key, &value))
{
const char *ref = key;
const char *commit = value;
g_autoptr(GVariant) variant = NULL;
g_autoptr(GVariant) parent_variant = NULL;
g_autofree char *parent_commit = NULL;
g_autofree char *grandparent_commit = NULL;
if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT, commit,
&variant, NULL))
{
g_warning ("Couldn't load commit %s", commit);
continue;
}
/* From empty */
if (!g_hash_table_contains (all_deltas_hash, commit))
{
if (!spawn_delete_generation (context, &n_spawned_delta_generate, repo, params,
ref, NULL, commit,
error))
goto error;
}
/* Mark this one as wanted */
g_hash_table_insert (wanted_deltas_hash, g_strdup (commit), GINT_TO_POINTER (1));
parent_commit = ostree_commit_get_parent (variant);
if (parent_commit != NULL &&
!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT, parent_commit,
&parent_variant, NULL))
{
g_warning ("Couldn't load parent commit %s", parent_commit);
continue;
}
/* From parent */
if (parent_variant != NULL)
{
g_autofree char *from_parent = g_strdup_printf ("%s-%s", parent_commit, commit);
if (!g_hash_table_contains (all_deltas_hash, from_parent))
{
if (!spawn_delete_generation (context, &n_spawned_delta_generate, repo, params,
ref, parent_commit, commit,
error))
goto error;
}
/* Mark parent-to-current as wanted */
g_hash_table_insert (wanted_deltas_hash, g_strdup (from_parent), GINT_TO_POINTER (1));
/* We also want to keep around the parent and the grandparent-to-parent deltas
* because otherwise these will be deleted immediately which may cause a race if
* someone is currently downloading them.
* However, there is no need to generate these if they don't exist.
*/
g_hash_table_insert (wanted_deltas_hash, g_strdup (parent_commit), GINT_TO_POINTER (1));
grandparent_commit = ostree_commit_get_parent (parent_variant);
if (grandparent_commit != NULL)
g_hash_table_insert (wanted_deltas_hash,
g_strdup_printf ("%s-%s", grandparent_commit, parent_commit),
GINT_TO_POINTER (1));
}
}
while (n_spawned_delta_generate > 0)
g_main_context_iteration (context, TRUE);
g_main_context_pop_thread_default (context);
*unwanted_deltas = g_ptr_array_new_with_free_func (g_free);
for (i = 0; i < all_deltas->len; i++)
{
const char *delta = g_ptr_array_index (all_deltas, i);
if (!g_hash_table_contains (wanted_deltas_hash, delta))
g_ptr_array_add (*unwanted_deltas, g_strdup (delta));
}
return TRUE;
error:
g_main_context_pop_thread_default (context);
return FALSE;
}
gboolean
flatpak_builtin_build_update_repo (int argc, char **argv,
GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(GFile) repofile = NULL;
g_autoptr(OstreeRepo) repo = NULL;
const char *location;
g_autoptr(GPtrArray) unwanted_deltas = NULL;
context = g_option_context_new (_("LOCATION - Update repository metadata"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
if (!flatpak_option_context_parse (context, options, &argc, &argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error))
return FALSE;
if (argc < 2)
return usage_error (context, _("LOCATION must be specified"), error);
location = argv[1];
repofile = g_file_new_for_commandline_arg (location);
repo = ostree_repo_new (repofile);
if (!ostree_repo_open (repo, cancellable, error))
return FALSE;
if (opt_generate_delta_to)
{
if (!generate_one_delta (repo, opt_generate_delta_from, opt_generate_delta_to, opt_generate_delta_ref, cancellable, error))
return FALSE;
return TRUE;
}
if (opt_title &&
!flatpak_repo_set_title (repo, opt_title[0] ? opt_title : NULL, error))
return FALSE;
if (opt_redirect_url &&
!flatpak_repo_set_redirect_url (repo, opt_redirect_url[0] ? opt_redirect_url : NULL, error))
return FALSE;
if (opt_default_branch &&
!flatpak_repo_set_default_branch (repo, opt_default_branch[0] ? opt_default_branch : NULL, error))
return FALSE;
if (opt_collection_id != NULL)
{
/* Only allow a transition from no collection ID to a non-empty collection ID.
* Changing the collection ID between two different non-empty values is too
* dangerous: it will break all clients who have previously pulled from the repository.
* Require the user to recreate the repository from scratch in that case. */
#ifdef FLATPAK_ENABLE_P2P
const char *old_collection_id = ostree_repo_get_collection_id (repo);
#else /* if !FLATPAK_ENABLE_P2P */
const char *old_collection_id = NULL;
#endif /* !FLATPAK_ENABLE_P2P */
const char *new_collection_id = opt_collection_id[0] ? opt_collection_id : NULL;
if (old_collection_id != NULL &&
g_strcmp0 (old_collection_id, new_collection_id) != 0)
return flatpak_fail (error, "The collection ID of an existing repository cannot be changed. "
"Recreate the repository to change or clear its collection ID.");
if (!flatpak_repo_set_collection_id (repo, new_collection_id, error))
return FALSE;
}
if (opt_deploy_collection_id &&
!flatpak_repo_set_deploy_collection_id (repo, TRUE, error))
return FALSE;
if (opt_gpg_import)
{
g_autoptr(GBytes) gpg_data = flatpak_load_gpg_keys (opt_gpg_import, cancellable, error);
if (gpg_data == NULL)
return FALSE;
if (!flatpak_repo_set_gpg_keys (repo, gpg_data, error))
return FALSE;
}
g_print (_("Updating appstream branch\n"));
if (!flatpak_repo_generate_appstream (repo, (const char **) opt_gpg_key_ids, opt_gpg_homedir, 0, cancellable, error))
return FALSE;
if (opt_generate_deltas &&
!generate_all_deltas (repo, &unwanted_deltas, cancellable, error))
return FALSE;
if (unwanted_deltas != NULL)
{
int i;
for (i = 0; i < unwanted_deltas->len; i++)
{
const char *delta = g_ptr_array_index (unwanted_deltas, i);
g_print ("Deleting unwanted delta: %s\n", delta);
g_autoptr(GError) my_error = NULL;
if (!_ostree_repo_static_delta_delete (repo, delta, cancellable, &my_error))
g_printerr ("Unable to delete delta %s: %s\n", delta, my_error->message);
}
}
g_print (_("Updating summary\n"));
if (!flatpak_repo_update (repo, (const char **) opt_gpg_key_ids, opt_gpg_homedir, cancellable, error))
return FALSE;
if (opt_prune)
{
gint n_objects_total;
gint n_objects_pruned;
guint64 objsize_total;
g_autofree char *formatted_freed_size = NULL;
g_print ("Pruning old commits\n");
if (!ostree_repo_prune (repo, OSTREE_REPO_PRUNE_FLAGS_REFS_ONLY, opt_prune_depth,
&n_objects_total, &n_objects_pruned, &objsize_total,
cancellable, error))
return FALSE;
formatted_freed_size = g_format_size_full (objsize_total, 0);
g_print (_("Total objects: %u\n"), n_objects_total);
if (n_objects_pruned == 0)
g_print (_("No unreachable objects\n"));
else
g_print (_("Deleted %u objects, %s freed\n"),
n_objects_pruned, formatted_freed_size);
}
return TRUE;
}
gboolean
flatpak_complete_build_update_repo (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
context = g_option_context_new ("");
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv,
FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, NULL, NULL))
return FALSE;
switch (completion->argc)
{
case 0:
case 1: /* LOCATION */
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, options);
flatpak_complete_dir (completion);
break;
}
return TRUE;
}

View File

@ -1,245 +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:
* Matthias Clasen <mclasen@redhat.com>
*/
#include "config.h"
#include <locale.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
#include "flatpak-builtins.h"
#include "flatpak-utils.h"
#include "flatpak-table-printer.h"
static void
print_info (GVariant *meta)
{
g_autoptr(GVariant) cache = NULL;
const char *title;
const char *collection_id;
const char *default_branch;
const char *redirect_url;
const char *redirect_collection_id;
g_autoptr(GVariant) gpg_keys = NULL;
if (g_variant_lookup (meta, "xa.title", "&s", &title))
g_print ("Title: %s\n", title);
if (g_variant_lookup (meta, "collection-id", "&s", &collection_id))
g_print ("Collection ID: %s\n", collection_id);
if (g_variant_lookup (meta, "xa.default-branch", "&s", &default_branch))
g_print ("Default branch: %s\n", default_branch);
if (g_variant_lookup (meta, "xa.redirect-url", "&s", &redirect_url))
g_print ("Redirect URL: %s\n", redirect_url);
if (g_variant_lookup (meta, "xa.collection-id", "&s", &redirect_collection_id))
g_print ("Redirect collection ID: %s\n", redirect_collection_id);
if ((gpg_keys = g_variant_lookup_value (meta, "xa.gpg-keys", G_VARIANT_TYPE_BYTESTRING)) != NULL)
{
const guchar *gpg_data = g_variant_get_data (gpg_keys);
gsize gpg_size = g_variant_get_size (gpg_keys);
g_autofree gchar *gpg_data_checksum = g_compute_checksum_for_data (G_CHECKSUM_SHA256, gpg_data, gpg_size);
g_print ("GPG key hash: %s\n", gpg_data_checksum);
}
cache = g_variant_lookup_value (meta, "xa.cache", NULL);
if (cache)
{
g_autoptr(GVariant) refdata = NULL;
refdata = g_variant_get_variant (cache);
g_print ("%zd branches\n", g_variant_n_children (refdata));
}
}
static void
print_branches (GVariant *meta)
{
g_autoptr(GVariant) cache = NULL;
cache = g_variant_lookup_value (meta, "xa.cache", NULL);
if (cache)
{
g_autoptr(GVariant) refdata = NULL;
GVariantIter iter;
const char *ref;
guint64 installed_size;
guint64 download_size;
const char *metadata;
FlatpakTablePrinter *printer;
printer = flatpak_table_printer_new ();
flatpak_table_printer_set_column_title (printer, 0, _("Ref"));
flatpak_table_printer_set_column_title (printer, 1, _("Installed"));
flatpak_table_printer_set_column_title (printer, 2, _("Download"));
refdata = g_variant_get_variant (cache);
g_variant_iter_init (&iter, refdata);
while (g_variant_iter_next (&iter, "{&s(tt&s)}", &ref, &installed_size, &download_size, &metadata))
{
g_autofree char *installed = g_format_size (GUINT64_FROM_BE (installed_size));
g_autofree char *download = g_format_size (GUINT64_FROM_BE (download_size));
flatpak_table_printer_add_column (printer, ref);
flatpak_table_printer_add_decimal_column (printer, installed);
flatpak_table_printer_add_decimal_column (printer, download);
flatpak_table_printer_finish_row (printer);
}
flatpak_table_printer_print (printer);
flatpak_table_printer_free (printer);
}
}
static void
print_metadata (GVariant *meta,
const char *branch)
{
g_autoptr(GVariant) cache = NULL;
cache = g_variant_lookup_value (meta, "xa.cache", NULL);
if (cache)
{
g_autoptr(GVariant) refdata = NULL;
GVariantIter iter;
const char *ref;
guint64 installed_size;
guint64 download_size;
const char *metadata;
refdata = g_variant_get_variant (cache);
g_variant_iter_init (&iter, refdata);
while (g_variant_iter_next (&iter, "{&s(tt&s)}", &ref, &installed_size, &download_size, &metadata))
{
if (strcmp (branch, ref) == 0)
g_print ("%s", metadata);
}
}
}
static gboolean opt_info;
static gboolean opt_branches;
static gchar *opt_metadata_branch;
static GOptionEntry options[] = {
{ "info", 0, 0, G_OPTION_ARG_NONE, &opt_info, N_("Print general information about the repository"), NULL },
{ "branches", 0, 0, G_OPTION_ARG_NONE, &opt_branches, N_("List the branches in the repository"), NULL },
{ "metadata", 0, 0, G_OPTION_ARG_STRING, &opt_metadata_branch, N_("Print metadata for a branch"), N_("BRANCH") },
{ NULL }
};
gboolean
flatpak_builtin_repo (int argc, char **argv,
GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(GFile) location = NULL;
g_autoptr(GVariant) meta = NULL;
g_autoptr(OstreeRepo) repo = NULL;
g_autofree char *ostree_metadata_checksum = NULL;
context = g_option_context_new (_("LOCATION - Repository maintenance"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
if (!flatpak_option_context_parse (context, options, &argc, &argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error))
return FALSE;
if (argc < 2)
return usage_error (context, _("LOCATION must be specified"), error);
location = g_file_new_for_commandline_arg (argv[1]);
repo = ostree_repo_new (location);
if (!ostree_repo_open (repo, cancellable, error))
return FALSE;
#ifdef FLATPAK_ENABLE_P2P
/* Try loading the metadata from the ostree-metadata branch first. If that
* fails, fall back to the summary file. */
if (!ostree_repo_resolve_rev (repo, OSTREE_REPO_METADATA_REF,
TRUE, &ostree_metadata_checksum, error))
return FALSE;
#endif /* FLATPAK_ENABLE_P2P */
if (ostree_metadata_checksum != NULL)
{
g_autoptr(GVariant) commit_v = NULL;
if (!ostree_repo_load_commit (repo, ostree_metadata_checksum, &commit_v, NULL, error))
return FALSE;
meta = g_variant_get_child_value (commit_v, 0);
}
else
{
g_autoptr(GVariant) summary = NULL;
summary = flatpak_repo_load_summary (repo, error);
if (summary == NULL)
return FALSE;
meta = g_variant_get_child_value (summary, 1);
}
/* Print out the metadata. */
if (opt_info)
print_info (meta);
if (opt_branches)
print_branches (meta);
if (opt_metadata_branch)
print_metadata (meta, opt_metadata_branch);
return TRUE;
}
gboolean
flatpak_complete_repo (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
context = g_option_context_new ("");
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv,
FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, NULL, NULL))
return FALSE;
switch (completion->argc)
{
case 0:
case 1: /* LOCATION */
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, options);
flatpak_complete_dir (completion);
break;
}
return TRUE;
}

View File

@ -1,258 +0,0 @@
/*
* Copyright © 2014 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 <errno.h>
#include <string.h>
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
#include "flatpak-builtins.h"
#include "flatpak-utils.h"
#include "flatpak-error.h"
#include "flatpak-dbus.h"
#include "flatpak-run.h"
static char *opt_arch;
static char *opt_branch;
static char *opt_command;
static gboolean opt_devel;
static gboolean opt_log_session_bus;
static gboolean opt_log_system_bus;
static gboolean opt_file_forwarding;
static char *opt_runtime;
static char *opt_runtime_version;
static GOptionEntry options[] = {
{ "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, N_("Arch to use"), N_("ARCH") },
{ "command", 0, 0, G_OPTION_ARG_STRING, &opt_command, N_("Command to run"), N_("COMMAND") },
{ "branch", 0, 0, G_OPTION_ARG_STRING, &opt_branch, N_("Branch to use"), N_("BRANCH") },
{ "devel", 'd', 0, G_OPTION_ARG_NONE, &opt_devel, N_("Use development runtime"), NULL },
{ "runtime", 0, 0, G_OPTION_ARG_STRING, &opt_runtime, N_("Runtime to use"), N_("RUNTIME") },
{ "runtime-version", 0, 0, G_OPTION_ARG_STRING, &opt_runtime_version, N_("Runtime version to use"), N_("VERSION") },
{ "log-session-bus", 0, 0, G_OPTION_ARG_NONE, &opt_log_session_bus, N_("Log session bus calls"), NULL },
{ "log-system-bus", 0, 0, G_OPTION_ARG_NONE, &opt_log_system_bus, N_("Log system bus calls"), NULL },
{ "file-forwarding", 0, 0, G_OPTION_ARG_NONE, &opt_file_forwarding, N_("Enable file forwarding"), NULL },
{ NULL }
};
gboolean
flatpak_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDeploy) app_deploy = NULL;
g_autofree char *app_ref = NULL;
g_autofree char *runtime_ref = NULL;
const char *pref;
int i;
int rest_argv_start, rest_argc;
g_autoptr(FlatpakContext) arg_context = NULL;
g_autofree char *id = NULL;
g_autofree char *arch = NULL;
g_autofree char *branch = NULL;
FlatpakKinds kinds;
g_autoptr(GError) local_error = NULL;
context = g_option_context_new (_("APP [args...] - Run an app"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
rest_argc = 0;
for (i = 1; i < argc; i++)
{
/* The non-option is the command, take it out of the arguments */
if (argv[i][0] != '-')
{
rest_argv_start = i;
rest_argc = argc - i;
argc = i;
break;
}
}
arg_context = flatpak_context_new ();
g_option_context_add_group (context, flatpak_context_get_options (arg_context));
if (!flatpak_option_context_parse (context, options, &argc, &argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error))
return FALSE;
if (rest_argc == 0)
return usage_error (context, _("APP must be specified"), error);
pref = argv[rest_argv_start];
if (!flatpak_split_partial_ref_arg (pref, FLATPAK_KINDS_APP | FLATPAK_KINDS_RUNTIME,
opt_arch, opt_branch,
&kinds, &id, &arch, &branch, error))
return FALSE;
if (branch == NULL || arch == NULL)
{
g_autofree char *current_ref = flatpak_find_current_ref (id, NULL, NULL);
if (current_ref)
{
g_auto(GStrv) parts = flatpak_decompose_ref (current_ref, NULL);
if (parts)
{
if (branch == NULL)
branch = g_strdup (parts[3]);
if (arch == NULL)
arch = g_strdup (parts[2]);
}
}
}
if ((kinds & FLATPAK_KINDS_APP) != 0)
{
app_ref = flatpak_compose_ref (TRUE, id, branch, arch, &local_error);
if (app_ref == NULL)
return FALSE;
app_deploy = flatpak_find_deploy_for_ref (app_ref, cancellable, &local_error);
if (app_deploy == NULL &&
(!g_error_matches (local_error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED) ||
(kinds & FLATPAK_KINDS_RUNTIME) == 0))
{
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}
/* On error, local_error is set after this point so we can reuse
this error rather than later errors, as the app-kind error
is more likely interesting. */
}
if (app_deploy == NULL)
{
g_autoptr(FlatpakDeploy) runtime_deploy = NULL;
g_autoptr(GError) local_error2 = NULL;
runtime_ref = flatpak_compose_ref (FALSE, id, branch, arch, error);
if (runtime_ref == NULL)
return FALSE;
runtime_deploy = flatpak_find_deploy_for_ref (runtime_ref, cancellable, &local_error2);
if (runtime_deploy == NULL)
{
/* Report old app-kind error, as its more likely right */
if (local_error != NULL)
g_propagate_error (error, g_steal_pointer (&local_error));
else
g_propagate_error (error, g_steal_pointer (&local_error2));
return FALSE;
}
/* Clear app-kind error */
g_clear_error (&local_error);
}
if (!flatpak_run_app (app_deploy ? app_ref : runtime_ref,
app_deploy,
arg_context,
opt_runtime,
opt_runtime_version,
(opt_devel ? FLATPAK_RUN_FLAG_DEVEL : 0) |
(opt_log_session_bus ? FLATPAK_RUN_FLAG_LOG_SESSION_BUS : 0) |
(opt_log_system_bus ? FLATPAK_RUN_FLAG_LOG_SYSTEM_BUS : 0) |
(opt_file_forwarding ? FLATPAK_RUN_FLAG_FILE_FORWARDING : 0),
opt_command,
&argv[rest_argv_start + 1],
rest_argc - 1,
cancellable,
error))
return FALSE;
/* Not actually reached... */
return TRUE;
}
gboolean
flatpak_complete_run (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDir) user_dir = NULL;
g_autoptr(GPtrArray) system_dirs = NULL;
g_autoptr(GError) error = NULL;
int i, j;
g_autoptr(FlatpakContext) arg_context = NULL;
context = g_option_context_new ("");
arg_context = flatpak_context_new ();
g_option_context_add_group (context, flatpak_context_get_options (arg_context));
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv,
FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, NULL, NULL))
return FALSE;
switch (completion->argc)
{
case 0:
case 1: /* NAME */
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, options);
flatpak_context_complete (arg_context, completion);
user_dir = flatpak_dir_get_user ();
{
g_auto(GStrv) refs = flatpak_dir_find_installed_refs (user_dir, NULL, NULL, opt_arch,
FLATPAK_KINDS_APP, &error);
if (refs == NULL)
flatpak_completion_debug ("find local refs error: %s", error->message);
for (i = 0; refs != NULL && refs[i] != NULL; i++)
{
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], NULL);
if (parts)
flatpak_complete_word (completion, "%s ", parts[1]);
}
}
system_dirs = flatpak_dir_get_system_list (NULL, &error);
if (system_dirs == NULL) {
flatpak_completion_debug ("find system installations error: %s", error->message);
break;
}
for (i = 0; i < system_dirs->len; i++)
{
FlatpakDir *dir = g_ptr_array_index (system_dirs, i);
g_auto(GStrv) refs = flatpak_dir_find_installed_refs (dir, NULL, NULL, opt_arch,
FLATPAK_KINDS_APP, &error);
if (refs == NULL)
flatpak_completion_debug ("find local refs error: %s", error->message);
for (j = 0; refs != NULL && refs[j] != NULL; j++)
{
g_auto(GStrv) parts = flatpak_decompose_ref (refs[j], NULL);
if (parts)
flatpak_complete_word (completion, "%s ", parts[1]);
}
}
break;
}
return TRUE;
}

View File

@ -1,193 +0,0 @@
/*
* Copyright © 2014 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 <unistd.h>
#include <string.h>
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
#include "flatpak-builtins.h"
#include "flatpak-builtins-utils.h"
#include "flatpak-utils.h"
static char *opt_arch;
static gboolean opt_keep_ref;
static gboolean opt_force_remove;
static gboolean opt_no_related;
static gboolean opt_runtime;
static gboolean opt_app;
static GOptionEntry options[] = {
{ "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, N_("Arch to uninstall"), N_("ARCH") },
{ "keep-ref", 0, 0, G_OPTION_ARG_NONE, &opt_keep_ref, N_("Keep ref in local repository"), NULL },
{ "no-related", 0, 0, G_OPTION_ARG_NONE, &opt_no_related, N_("Don't uninstall related refs"), NULL },
{ "force-remove", 0, 0, G_OPTION_ARG_NONE, &opt_force_remove, N_("Remove files even if running"), NULL },
{ "runtime", 0, 0, G_OPTION_ARG_NONE, &opt_runtime, N_("Look for runtime with the specified name"), NULL },
{ "app", 0, 0, G_OPTION_ARG_NONE, &opt_app, N_("Look for app with the specified name"), NULL },
{ NULL }
};
gboolean
flatpak_builtin_uninstall (int argc, char **argv, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDir) dir = NULL;
char **prefs = NULL;
int i, j, n_prefs;
const char *default_branch = NULL;
g_autofree char *ref = NULL;
FlatpakHelperUninstallFlags flags = 0;
g_autoptr(GPtrArray) related = NULL;
FlatpakKinds kinds;
FlatpakKinds kind;
g_autoptr(GHashTable) uninstall_refs_hash = NULL;
g_autoptr(GPtrArray) uninstall_refs = NULL;
context = g_option_context_new (_("REF... - Uninstall an application"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
if (!flatpak_option_context_parse (context, options, &argc, &argv, 0, &dir, cancellable, error))
return FALSE;
if (argc < 2)
return usage_error (context, _("Must specify at least one REF"), error);
prefs = &argv[1];
n_prefs = argc - 1;
/* Backwards compat for old "REPOSITORY NAME [BRANCH]" argument version */
if (argc == 3 && looks_like_branch (argv[2]))
{
default_branch = argv[2];
n_prefs = 1;
}
kinds = flatpak_kinds_from_bools (opt_app, opt_runtime);
uninstall_refs = g_ptr_array_new_with_free_func (g_free);
uninstall_refs_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
for (j = 0; j < n_prefs; j++)
{
const char *pref = NULL;
FlatpakKinds matched_kinds;
g_autofree char *id = NULL;
g_autofree char *arch = NULL;
g_autofree char *branch = NULL;
g_autoptr(GError) local_error = NULL;
g_autofree char *origin = NULL;
pref = prefs[j];
if (!flatpak_split_partial_ref_arg (pref, kinds, opt_arch, default_branch,
&matched_kinds, &id, &arch, &branch, error))
return FALSE;
ref = flatpak_dir_find_installed_ref (dir, id, branch, arch,
kinds, &kind, error);
if (ref == NULL)
return FALSE;
if (g_hash_table_insert (uninstall_refs_hash, g_strdup (ref), NULL))
g_ptr_array_add (uninstall_refs, g_strdup (ref));
/* TODO: when removing runtimes, look for apps that use it, require --force */
if (opt_no_related)
continue;
origin = flatpak_dir_get_origin (dir, ref, NULL, NULL);
if (origin == NULL)
continue;
related = flatpak_dir_find_local_related (dir, ref, origin,
NULL, &local_error);
if (related == NULL)
{
g_printerr (_("Warning: Problem looking for related refs: %s\n"),
local_error->message);
continue;
}
for (i = 0; i < related->len; i++)
{
FlatpakRelated *rel = g_ptr_array_index (related, i);
g_autoptr(GVariant) deploy_data = NULL;
if (!rel->delete)
continue;
deploy_data = flatpak_dir_get_deploy_data (dir, rel->ref, NULL, NULL);
if (deploy_data != NULL &&
g_hash_table_insert (uninstall_refs_hash, g_strdup (rel->ref), NULL))
g_ptr_array_add (uninstall_refs, g_strdup (rel->ref));
}
}
if (opt_keep_ref)
flags |= FLATPAK_HELPER_UNINSTALL_FLAGS_KEEP_REF;
if (opt_force_remove)
flags |= FLATPAK_HELPER_UNINSTALL_FLAGS_FORCE_REMOVE;
for (i = 0; i < uninstall_refs->len; i++)
{
const char *ref = (char *)g_ptr_array_index (uninstall_refs, i);
const char *pref = strchr (ref, '/') + 1;
g_print ("Uninstalling %s\n", pref);
if (!flatpak_dir_uninstall (dir, ref, flags,
cancellable, error))
return FALSE;
}
return TRUE;
}
gboolean
flatpak_complete_uninstall (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDir) dir = NULL;
FlatpakKinds kinds;
context = g_option_context_new ("");
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv, 0, &dir, NULL, NULL))
return FALSE;
kinds = flatpak_kinds_from_bools (opt_app, opt_runtime);
switch (completion->argc)
{
case 0:
default: /* REF */
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, options);
flatpak_complete_options (completion, user_entries);
flatpak_complete_partial_ref (completion, kinds, opt_arch, dir, NULL);
break;
}
return TRUE;
}

View File

@ -1,282 +0,0 @@
/*
* Copyright © 2014 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 <unistd.h>
#include <string.h>
#include <glib/gi18n.h>
#include "libglnx/libglnx.h"
#include "flatpak-builtins.h"
#include "flatpak-builtins-utils.h"
#include "flatpak-transaction.h"
#include "flatpak-utils.h"
#include "flatpak-error.h"
static char *opt_arch;
static char *opt_commit;
static char **opt_subpaths;
static gboolean opt_force_remove;
static gboolean opt_no_pull;
static gboolean opt_no_deploy;
static gboolean opt_no_related;
static gboolean opt_no_deps;
static gboolean opt_no_static_deltas;
static gboolean opt_runtime;
static gboolean opt_app;
static gboolean opt_appstream;
static gboolean opt_yes;
static GOptionEntry options[] = {
{ "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, N_("Arch to update for"), N_("ARCH") },
{ "commit", 0, 0, G_OPTION_ARG_STRING, &opt_commit, N_("Commit to deploy"), N_("COMMIT") },
{ "force-remove", 0, 0, G_OPTION_ARG_NONE, &opt_force_remove, N_("Remove old files even if running"), NULL },
{ "no-pull", 0, 0, G_OPTION_ARG_NONE, &opt_no_pull, N_("Don't pull, only update from local cache"), NULL },
{ "no-deploy", 0, 0, G_OPTION_ARG_NONE, &opt_no_deploy, N_("Don't deploy, only download to local cache"), NULL },
{ "no-related", 0, 0, G_OPTION_ARG_NONE, &opt_no_related, N_("Don't update related refs"), NULL},
{ "no-deps", 0, 0, G_OPTION_ARG_NONE, &opt_no_deps, N_("Don't verify/install runtime dependencies"), NULL },
{ "no-static-deltas", 0, 0, G_OPTION_ARG_NONE, &opt_no_static_deltas, N_("Don't use static deltas"), NULL },
{ "runtime", 0, 0, G_OPTION_ARG_NONE, &opt_runtime, N_("Look for runtime with the specified name"), NULL },
{ "app", 0, 0, G_OPTION_ARG_NONE, &opt_app, N_("Look for app with the specified name"), NULL },
{ "appstream", 0, 0, G_OPTION_ARG_NONE, &opt_appstream, N_("Update appstream for remote"), NULL },
{ "subpath", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_subpaths, N_("Only update this subpath"), N_("PATH") },
{ "assumeyes", 'y', 0, G_OPTION_ARG_NONE, &opt_yes, N_("Automatically answer yes for all questions"), NULL },
{ NULL }
};
static gboolean
update_appstream (FlatpakDir *dir, const char *remote, GCancellable *cancellable, GError **error)
{
gboolean changed;
gboolean res;
if (opt_arch == NULL)
opt_arch = (char *)flatpak_get_arch ();
if (remote == NULL)
{
g_auto(GStrv) remotes = NULL;
int i;
remotes = flatpak_dir_list_remotes (dir, cancellable, error);
if (remotes == NULL)
return FALSE;
for (i = 0; remotes[i] != NULL; i++)
{
g_autoptr(GError) local_error = NULL;
FlatpakTerminalProgress terminal_progress = { 0 };
if (flatpak_dir_get_remote_disabled (dir, remotes[i]))
continue;
g_print (_("Updating appstream for remote %s\n"), remotes[i]);
g_autoptr(OstreeAsyncProgress) progress = flatpak_progress_new (flatpak_terminal_progress_cb, &terminal_progress);
if (!flatpak_dir_update_appstream (dir, remotes[i], opt_arch, &changed,
progress, cancellable, &local_error))
g_printerr ("Error updating: %s\n", local_error->message);
ostree_async_progress_finish (progress);
flatpak_terminal_progress_end (&terminal_progress);
}
}
else
{
FlatpakTerminalProgress terminal_progress = { 0 };
g_autoptr(OstreeAsyncProgress) progress = flatpak_progress_new (flatpak_terminal_progress_cb, &terminal_progress);
res = flatpak_dir_update_appstream (dir, remote, opt_arch, &changed,
progress, cancellable, error);
ostree_async_progress_finish (progress);
if (!res)
return FALSE;
flatpak_terminal_progress_end (&terminal_progress);
}
return TRUE;
}
gboolean
flatpak_builtin_update (int argc,
char **argv,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDir) dir = NULL;
char **prefs = NULL;
int i, j, n_prefs;
const char *default_branch = NULL;
FlatpakKinds kinds;
g_autoptr(FlatpakTransaction) transaction = NULL;
context = g_option_context_new (_("[REF...] - Update applications or runtimes"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
if (!flatpak_option_context_parse (context, options, &argc, &argv, 0, &dir, cancellable, error))
return FALSE;
if (opt_appstream)
return update_appstream (dir, argc >= 2 ? argv[1] : NULL, cancellable, error);
prefs = &argv[1];
n_prefs = argc - 1;
/* Backwards compat for old "REPOSITORY NAME [BRANCH]" argument version */
if (argc == 3 && looks_like_branch (argv[2]))
{
default_branch = argv[2];
n_prefs = 1;
}
transaction = flatpak_transaction_new (dir, opt_yes, opt_no_pull, opt_no_deploy,
opt_no_static_deltas, !opt_no_deps, !opt_no_related);
kinds = flatpak_kinds_from_bools (opt_app, opt_runtime);
g_print ("Looking for updates...\n");
for (j = 0; j == 0 || j < n_prefs; j++)
{
const char *pref = NULL;
FlatpakKinds matched_kinds;
g_autofree char *id = NULL;
g_autofree char *arch = NULL;
g_autofree char *branch = NULL;
gboolean found = FALSE;
if (n_prefs == 0)
{
matched_kinds = kinds;
}
else
{
pref = prefs[j];
if (!flatpak_split_partial_ref_arg (pref, kinds, opt_arch, default_branch,
&matched_kinds, &id, &arch, &branch, error))
return FALSE;
}
if (kinds & FLATPAK_KINDS_APP)
{
g_auto(GStrv) refs = NULL;
if (!flatpak_dir_list_refs (dir, "app", &refs,
cancellable,
error))
return FALSE;
for (i = 0; refs != NULL && refs[i] != NULL; i++)
{
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], error);
if (parts == NULL)
return FALSE;
if (id != NULL && strcmp (parts[1], id) != 0)
continue;
if (arch != NULL && strcmp (parts[2], arch) != 0)
continue;
if (branch != NULL && strcmp (parts[3], branch) != 0)
continue;
found = TRUE;
if (!flatpak_transaction_add_update (transaction, refs[i], (const char **)opt_subpaths, opt_commit, error))
return FALSE;
}
}
if (kinds & FLATPAK_KINDS_RUNTIME)
{
g_auto(GStrv) refs = NULL;
if (!flatpak_dir_list_refs (dir, "runtime", &refs,
cancellable,
error))
return FALSE;
for (i = 0; refs != NULL && refs[i] != NULL; i++)
{
g_auto(GStrv) parts = flatpak_decompose_ref (refs[i], error);
if (parts == NULL)
return FALSE;
if (id != NULL && strcmp (parts[1], id) != 0)
continue;
if (arch != NULL && strcmp (parts[2], arch) != 0)
continue;
if (branch != NULL && strcmp (parts[3], branch) != 0)
continue;
found = TRUE;
if (!flatpak_transaction_add_update (transaction, refs[i], (const char **)opt_subpaths, opt_commit, error))
return FALSE;
}
}
if (n_prefs > 0 && !found)
{
g_set_error (error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED,
"%s not installed", pref);
return FALSE;
}
}
if (!flatpak_transaction_update_metadata (transaction, n_prefs == 0, cancellable, error))
return FALSE;
if (!flatpak_transaction_run (transaction, FALSE, cancellable, error))
return FALSE;
return TRUE;
}
gboolean
flatpak_complete_update (FlatpakCompletion *completion)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(FlatpakDir) dir = NULL;
FlatpakKinds kinds;
context = g_option_context_new ("");
if (!flatpak_option_context_parse (context, options, &completion->argc, &completion->argv, 0, &dir, NULL, NULL))
return FALSE;
kinds = flatpak_kinds_from_bools (opt_app, opt_runtime);
switch (completion->argc)
{
case 0:
default: /* REF */
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, options);
flatpak_complete_options (completion, user_entries);
flatpak_complete_partial_ref (completion, kinds, opt_arch, dir, NULL);
break;
}
return TRUE;
}

View File

@ -1,328 +0,0 @@
/*
* Copyright © 2014 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 <glib/gi18n.h>
#include <gio/gunixinputstream.h>
#include "flatpak-chain-input-stream.h"
#include "flatpak-builtins-utils.h"
#include "flatpak-utils.h"
gboolean
looks_like_branch (const char *branch)
{
const char *dot;
/* In particular, / is not a valid branch char, so
this lets us distinguish full or partial refs as
non-branches. */
if (!flatpak_is_valid_branch (branch, NULL))
return FALSE;
/* Dots are allowed in branches, but not really used much, while
app ids require at least two, so thats a good check to
distinguish the two */
dot = strchr (branch, '.');
if (dot != NULL)
{
if (strchr (dot + 1, '.') != NULL)
return FALSE;
}
return TRUE;
}
static SoupSession *
get_soup_session (void)
{
static SoupSession *soup_session = NULL;
if (soup_session == NULL)
{
const char *http_proxy;
soup_session = soup_session_new_with_options (SOUP_SESSION_USER_AGENT, "flatpak-builder ",
SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, TRUE,
SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
SOUP_SESSION_TIMEOUT, 60,
SOUP_SESSION_IDLE_TIMEOUT, 60,
NULL);
http_proxy = g_getenv ("http_proxy");
if (http_proxy)
{
g_autoptr(SoupURI) proxy_uri = soup_uri_new (http_proxy);
if (!proxy_uri)
g_warning ("Invalid proxy URI '%s'", http_proxy);
else
g_object_set (soup_session, SOUP_SESSION_PROXY_URI, proxy_uri, NULL);
}
}
return soup_session;
}
GBytes *
download_uri (const char *url,
GError **error)
{
SoupSession *session;
g_autoptr(SoupRequest) req = NULL;
g_autoptr(GInputStream) input = NULL;
g_autoptr(GOutputStream) out = NULL;
session = get_soup_session ();
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));
}
FlatpakDir *
flatpak_find_installed_pref (const char *pref, FlatpakKinds kinds, const char *default_arch, const char *default_branch,
gboolean search_all, gboolean search_user, gboolean search_system, char **search_installations,
char **out_ref, GCancellable *cancellable, GError **error)
{
g_autofree char *id = NULL;
g_autofree char *arch = NULL;
g_autofree char *branch = NULL;
g_autoptr(GError) lookup_error = NULL;
FlatpakDir *dir = NULL;
g_autofree char *ref = NULL;
FlatpakKinds kind = 0;
g_autoptr(FlatpakDir) user_dir = NULL;
g_autoptr(FlatpakDir) system_dir = NULL;
g_autoptr(GPtrArray) system_dirs = NULL;
if (!flatpak_split_partial_ref_arg (pref, kinds, default_arch, default_branch,
&kinds, &id, &arch, &branch, error))
return NULL;
if (search_user || search_all)
{
user_dir = flatpak_dir_get_user ();
ref = flatpak_dir_find_installed_ref (user_dir,
id,
branch,
arch,
kinds, &kind,
&lookup_error);
if (ref)
dir = user_dir;
if (g_error_matches (lookup_error, G_IO_ERROR, G_IO_ERROR_FAILED))
{
g_propagate_error (error, g_steal_pointer (&lookup_error));
return NULL;
}
}
if (ref == NULL && search_all)
{
int i;
system_dirs = flatpak_dir_get_system_list (cancellable, error);
if (system_dirs == NULL)
return FALSE;
for (i = 0; i < system_dirs->len; i++)
{
FlatpakDir *system_dir = g_ptr_array_index (system_dirs, i);
g_clear_error (&lookup_error);
ref = flatpak_dir_find_installed_ref (system_dir,
id,
branch,
arch,
kinds, &kind,
&lookup_error);
if (ref)
{
dir = system_dir;
break;
}
if (g_error_matches (lookup_error, G_IO_ERROR, G_IO_ERROR_FAILED))
{
g_propagate_error (error, g_steal_pointer (&lookup_error));
return NULL;
}
}
}
else
{
if (ref == NULL && search_installations != NULL)
{
int i = 0;
for (i = 0; search_installations[i] != NULL; i++)
{
g_autoptr(FlatpakDir) installation_dir = NULL;
installation_dir = flatpak_dir_get_system_by_id (search_installations[i], cancellable, error);
if (installation_dir == NULL)
return FALSE;
if (installation_dir)
{
g_clear_error (&lookup_error);
ref = flatpak_dir_find_installed_ref (installation_dir,
id,
branch,
arch,
kinds, &kind,
&lookup_error);
if (ref)
{
dir = installation_dir;
break;
}
if (g_error_matches (lookup_error, G_IO_ERROR, G_IO_ERROR_FAILED))
{
g_propagate_error (error, g_steal_pointer (&lookup_error));
return NULL;
}
}
}
}
if (ref == NULL && search_system)
{
system_dir = flatpak_dir_get_system_default ();
g_clear_error (&lookup_error);
ref = flatpak_dir_find_installed_ref (system_dir,
id,
branch,
arch,
kinds, &kind,
&lookup_error);
if (ref)
dir = system_dir;
}
}
if (ref == NULL)
{
g_propagate_error (error, g_steal_pointer (&lookup_error));
return NULL;
}
*out_ref = g_steal_pointer (&ref);
return g_object_ref (dir);
}
static gboolean
open_source_stream (char **gpg_import,
GInputStream **out_source_stream,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GInputStream) source_stream = NULL;
guint n_keyrings = 0;
g_autoptr(GPtrArray) streams = NULL;
if (gpg_import != NULL)
n_keyrings = g_strv_length (gpg_import);
guint ii;
streams = g_ptr_array_new_with_free_func (g_object_unref);
for (ii = 0; ii < n_keyrings; ii++)
{
GInputStream *input_stream = NULL;
if (strcmp (gpg_import[ii], "-") == 0)
{
input_stream = g_unix_input_stream_new (STDIN_FILENO, FALSE);
}
else
{
g_autoptr(GFile) file = g_file_new_for_commandline_arg (gpg_import[ii]);
input_stream = G_INPUT_STREAM (g_file_read (file, cancellable, error));
if (input_stream == NULL)
{
g_prefix_error (error, "The file %s specified for --gpg-import was not found: ", gpg_import[ii]);
return FALSE;
}
}
/* Takes ownership. */
g_ptr_array_add (streams, input_stream);
}
/* Chain together all the --keyring options as one long stream. */
source_stream = (GInputStream *) flatpak_chain_input_stream_new (streams);
*out_source_stream = g_steal_pointer (&source_stream);
return TRUE;
}
GBytes *
flatpak_load_gpg_keys (char **gpg_import,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GInputStream) input_stream = NULL;
g_autoptr(GOutputStream) output_stream = NULL;
gssize n_bytes_written;
if (!open_source_stream (gpg_import, &input_stream, cancellable, error))
return FALSE;
output_stream = g_memory_output_stream_new_resizable ();
n_bytes_written = g_output_stream_splice (output_stream, input_stream,
G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
NULL, error);
if (n_bytes_written < 0)
return NULL;
return g_memory_output_stream_steal_as_bytes (G_MEMORY_OUTPUT_STREAM (output_stream));
}

View File

@ -1,49 +0,0 @@
/*
* Copyright © 2014 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 __FLATPAK_BUILTINS_UTILS_H__
#define __FLATPAK_BUILTINS_UTILS_H__
#include <glib.h>
#include "libglnx/libglnx.h"
#include "flatpak-utils.h"
#include "flatpak-dir.h"
gboolean looks_like_branch (const char *branch);
GBytes * download_uri (const char *url,
GError **error);
GBytes * flatpak_load_gpg_keys (char **gpg_import,
GCancellable *cancellable,
GError **error);
FlatpakDir * flatpak_find_installed_pref (const char *pref,
FlatpakKinds kinds,
const char *default_arch,
const char *default_branch,
gboolean search_all,
gboolean search_user,
gboolean search_system,
char **search_installations,
char **out_ref,
GCancellable *cancellable,
GError **error);
#endif /* __FLATPAK_BUILTINS_UTILS_H__ */

View File

@ -1,92 +0,0 @@
/*
* Copyright © 2014 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 __FLATPAK_BUILTINS_H__
#define __FLATPAK_BUILTINS_H__
#include <ostree.h>
#include <gio/gio.h>
#include "flatpak-utils.h"
#include "flatpak-dir.h"
G_BEGIN_DECLS
typedef enum {
FLATPAK_BUILTIN_FLAG_NO_DIR = 1 << 0,
FLATPAK_BUILTIN_FLAG_NO_REPO = 1 << 1,
} FlatpakBuiltinFlags;
gboolean flatpak_option_context_parse (GOptionContext *context,
const GOptionEntry *main_entries,
int *argc,
char ***argv,
FlatpakBuiltinFlags flags,
FlatpakDir **out_dir,
GCancellable *cancellable,
GError **error);
extern GOptionEntry user_entries[];
extern GOptionEntry global_entries[];
gboolean usage_error (GOptionContext *context,
const char *message,
GError **error);
#define BUILTINPROTO(name) \
gboolean flatpak_builtin_ ## name (int argc, char **argv, GCancellable * cancellable, GError * *error); \
gboolean flatpak_complete_ ## name (FlatpakCompletion *completion);
BUILTINPROTO (add_remote)
BUILTINPROTO (modify_remote)
BUILTINPROTO (delete_remote)
BUILTINPROTO (ls_remote)
BUILTINPROTO (list_remotes)
BUILTINPROTO (install)
BUILTINPROTO (update)
BUILTINPROTO (make_current_app)
BUILTINPROTO (uninstall)
BUILTINPROTO (install_bundle)
BUILTINPROTO (list)
BUILTINPROTO (info)
BUILTINPROTO (run)
BUILTINPROTO (enter)
BUILTINPROTO (build_init)
BUILTINPROTO (build)
BUILTINPROTO (build_finish)
BUILTINPROTO (build_sign)
BUILTINPROTO (build_export)
BUILTINPROTO (build_bundle)
BUILTINPROTO (build_import)
BUILTINPROTO (build_commit_from)
BUILTINPROTO (build_update_repo)
BUILTINPROTO (document_export)
BUILTINPROTO (document_unexport)
BUILTINPROTO (document_info)
BUILTINPROTO (document_list)
BUILTINPROTO (override)
BUILTINPROTO (repo)
#undef BUILTINPROTO
G_END_DECLS
#endif /* __FLATPAK_BUILTINS_H__ */

View File

@ -1,496 +0,0 @@
/*
* Copyright © 2014 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 <stdio.h>
#include <glib/gi18n.h>
#include <gio/gio.h>
#include "libglnx/libglnx.h"
#include "flatpak-builtins.h"
#include "flatpak-utils.h"
static gboolean opt_verbose;
static gboolean opt_ostree_verbose;
static gboolean opt_version;
static gboolean opt_default_arch;
static gboolean opt_supported_arches;
static gboolean opt_gl_drivers;
static gboolean opt_user;
static char *opt_installation;
typedef struct
{
const char *name;
const char *description;
gboolean (*fn)(int argc,
char **argv,
GCancellable *cancellable,
GError **error);
gboolean (*complete)(FlatpakCompletion *completion);
gboolean deprecated;
} FlatpakCommand;
static FlatpakCommand commands[] = {
/* translators: please keep the leading space */
{ N_(" Manage installed apps and runtimes") },
{ "install", N_("Install an application or runtime"), flatpak_builtin_install, flatpak_complete_install },
{ "update", N_("Update an installed application or runtime"), flatpak_builtin_update, flatpak_complete_update },
{ "uninstall", N_("Uninstall an installed application or runtime"), flatpak_builtin_uninstall, flatpak_complete_uninstall },
{ "list", N_("List installed apps and/or runtimes"), flatpak_builtin_list, flatpak_complete_list },
{ "info", N_("Show info for installed app or runtime"), flatpak_builtin_info, flatpak_complete_info },
/* translators: please keep the leading newline and space */
{ N_("\n Running applications") },
{ "run", N_("Run an application"), flatpak_builtin_run, flatpak_complete_run },
{ "override", N_("Override permissions for an application"), flatpak_builtin_override, flatpak_complete_override },
{ "make-current", N_("Specify default version to run"), flatpak_builtin_make_current_app, flatpak_complete_make_current_app },
{ "enter", N_("Enter the namespace of a running application"), flatpak_builtin_enter, flatpak_complete_enter },
/* translators: please keep the leading newline and space */
{ N_("\n Manage file access") },
{ "document-export", N_("Grant an application access to a specific file"), flatpak_builtin_document_export, flatpak_complete_document_export },
{ "document-unexport", N_("Revoke access to a specific file"), flatpak_builtin_document_unexport, flatpak_complete_document_unexport },
{ "document-info", N_("Show information about a specific file"), flatpak_builtin_document_info, flatpak_complete_document_info },
{ "document-list", N_("List exported files"), flatpak_builtin_document_list, flatpak_complete_document_list },
/* translators: please keep the leading newline and space */
{ N_("\n Manage remote repositories") },
{ "remotes", N_("List all configured remotes"), flatpak_builtin_list_remotes, flatpak_complete_list_remotes },
{ "remote-add", N_("Add a new remote repository (by URL)"), flatpak_builtin_add_remote, flatpak_complete_add_remote },
{ "remote-modify", N_("Modify properties of a configured remote"), flatpak_builtin_modify_remote, flatpak_complete_modify_remote },
{ "remote-delete", N_("Delete a configured remote"), flatpak_builtin_delete_remote, flatpak_complete_delete_remote },
{ "remote-list", NULL, flatpak_builtin_list_remotes, flatpak_complete_list_remotes, TRUE },
{ "remote-ls", N_("List contents of a configured remote"), flatpak_builtin_ls_remote, flatpak_complete_ls_remote },
/* translators: please keep the leading newline and space */
{ N_("\n Build applications") },
{ "build-init", N_("Initialize a directory for building"), flatpak_builtin_build_init, flatpak_complete_build_init },
{ "build", N_("Run a build command inside the build dir"), flatpak_builtin_build, flatpak_complete_build },
{ "build-finish", N_("Finish a build dir for export"), flatpak_builtin_build_finish, flatpak_complete_build_finish },
{ "build-export", N_("Export a build dir to a repository"), flatpak_builtin_build_export, flatpak_complete_build_export },
{ "build-bundle", N_("Create a bundle file from a build directory"), flatpak_builtin_build_bundle, flatpak_complete_build_bundle },
{ "build-import-bundle", N_("Import a bundle file"), flatpak_builtin_build_import, flatpak_complete_build_import },
{ "build-sign", N_("Sign an application or runtime"), flatpak_builtin_build_sign, flatpak_complete_build_sign },
{ "build-update-repo", N_("Update the summary file in a repository"), flatpak_builtin_build_update_repo, flatpak_complete_build_update_repo },
{ "build-commit-from", N_("Create new commit based on existing ref"), flatpak_builtin_build_commit_from, flatpak_complete_build_commit_from },
{ "repo", N_("Print information about a repo"), flatpak_builtin_repo, flatpak_complete_repo },
{ NULL }
};
GOptionEntry global_entries[] = {
{ "verbose", 'v', 0, G_OPTION_ARG_NONE, &opt_verbose, N_("Print debug information during command processing"), NULL },
{ "ostree-verbose", 0, 0, G_OPTION_ARG_NONE, &opt_ostree_verbose, N_("Print OSTree debug information during command processing"), NULL },
{ "help", '?', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, N_("Show help options"), NULL, NULL },
{ NULL }
};
static GOptionEntry empty_entries[] = {
{ "version", 0, 0, G_OPTION_ARG_NONE, &opt_version, N_("Print version information and exit"), NULL },
{ "default-arch", 0, 0, G_OPTION_ARG_NONE, &opt_default_arch, N_("Print default arch and exit"), NULL },
{ "supported-arches", 0, 0, G_OPTION_ARG_NONE, &opt_supported_arches, N_("Print supported arches and exit"), NULL },
{ "gl-drivers", 0, 0, G_OPTION_ARG_NONE, &opt_gl_drivers, N_("Print active gl drivers and exit"), NULL },
{ NULL }
};
GOptionEntry user_entries[] = {
{ "user", 0, 0, G_OPTION_ARG_NONE, &opt_user, N_("Work on user installations"), NULL },
{ "system", 0, G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &opt_user, N_("Work on system-wide installations (default)"), NULL },
{ "installation", 0, 0, G_OPTION_ARG_STRING, &opt_installation, N_("Work on a specific system-wide installation"), N_("NAME") },
{ 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 ("XA: %s\n", message);
else
g_printerr ("%s: %s\n", g_get_prgname (), message);
}
static GOptionContext *
flatpak_option_context_new_with_commands (FlatpakCommand *commands)
{
GOptionContext *context;
GString *summary;
context = g_option_context_new (_("COMMAND"));
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
summary = g_string_new (_("Builtin Commands:"));
while (commands->name != NULL)
{
if (!commands->deprecated)
{
if (commands->fn != NULL)
{
g_string_append_printf (summary, "\n %s", commands->name);
if (commands->description)
g_string_append_printf (summary, "%*s%s", (int) (20 - strlen (commands->name)), "", _(commands->description));
}
else
{
g_string_append_printf (summary, "\n%s", _(commands->name));
}
}
commands++;
}
g_option_context_set_summary (context, summary->str);
g_string_free (summary, TRUE);
return context;
}
static int
flatpak_usage (FlatpakCommand *commands,
gboolean is_error)
{
GOptionContext *context;
g_autofree char *help = NULL;
context = flatpak_option_context_new_with_commands (commands);
g_option_context_add_main_entries (context, global_entries, NULL);
help = g_option_context_get_help (context, FALSE, NULL);
if (is_error)
g_printerr ("%s", help);
else
g_print ("%s", help);
g_option_context_free (context);
return is_error ? 1 : 0;
}
gboolean
flatpak_option_context_parse (GOptionContext *context,
const GOptionEntry *main_entries,
int *argc,
char ***argv,
FlatpakBuiltinFlags flags,
FlatpakDir **out_dir,
GCancellable *cancellable,
GError **error)
{
g_autoptr(FlatpakDir) dir = NULL;
if (!(flags & FLATPAK_BUILTIN_FLAG_NO_DIR))
g_option_context_add_main_entries (context, user_entries, NULL);
if (main_entries != NULL)
g_option_context_add_main_entries (context, main_entries, NULL);
g_option_context_add_main_entries (context, global_entries, NULL);
if (!g_option_context_parse (context, argc, argv, error))
return FALSE;
if (opt_version)
{
g_print ("%s\n", PACKAGE_STRING);
exit (EXIT_SUCCESS);
}
if (opt_default_arch)
{
g_print ("%s\n", flatpak_get_arch ());
exit (EXIT_SUCCESS);
}
if (opt_supported_arches)
{
const char **arches = flatpak_get_arches ();
int i;
for (i = 0; arches[i] != NULL; i++)
g_print ("%s\n", arches[i]);
exit (EXIT_SUCCESS);
}
if (opt_gl_drivers)
{
const char **drivers = flatpak_get_gl_drivers ();
int i;
for (i = 0; drivers[i] != NULL; i++)
g_print ("%s\n", drivers[i]);
exit (EXIT_SUCCESS);
}
if (!(flags & FLATPAK_BUILTIN_FLAG_NO_DIR))
{
if (opt_user)
dir = flatpak_dir_get_user ();
else if (opt_installation == NULL)
dir = flatpak_dir_get_system_default ();
else
{
dir = flatpak_dir_get_system_by_id (opt_installation, cancellable, error);
if (dir == NULL)
return FALSE;
}
if (!flatpak_dir_ensure_path (dir, cancellable, error))
return FALSE;
if (!(flags & FLATPAK_BUILTIN_FLAG_NO_REPO) &&
!flatpak_dir_ensure_repo (dir, cancellable, error))
return FALSE;
}
if (opt_verbose)
g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, message_handler, NULL);
if (opt_ostree_verbose)
g_log_set_handler ("OSTree", G_LOG_LEVEL_DEBUG, message_handler, NULL);
if (out_dir)
*out_dir = g_steal_pointer (&dir);
return TRUE;
}
gboolean
usage_error (GOptionContext *context, const char *message, GError **error)
{
g_autofree gchar *help = g_option_context_get_help (context, TRUE, NULL);
g_printerr ("%s", help);
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, message);
return FALSE;
}
static FlatpakCommand *
extract_command (int *argc,
char **argv,
const char **command_name_out)
{
FlatpakCommand *command;
const char *command_name = NULL;
int in, out;
/*
* Parse the global options. We rearrange the options as
* necessary, in order to pass relevant options through
* to the commands, but also have them take effect globally.
*/
for (in = 1, out = 1; in < *argc; in++, out++)
{
/* The non-option is the command, take it out of the arguments */
if (argv[in][0] != '-')
{
if (command_name == NULL)
{
command_name = argv[in];
out--;
continue;
}
}
argv[out] = argv[in];
}
*argc = out;
argv[out] = NULL;
command = commands;
while (command->name)
{
if (command->fn != NULL &&
g_strcmp0 (command_name, command->name) == 0)
break;
command++;
}
*command_name_out = command_name;
return command;
}
static int
flatpak_run (int argc,
char **argv,
GError **res_error)
{
FlatpakCommand *command;
GError *error = NULL;
GCancellable *cancellable = NULL;
g_autofree char *prgname = NULL;
gboolean success = FALSE;
const char *command_name = NULL;
command = extract_command (&argc, argv, &command_name);
if (!command->fn)
{
GOptionContext *context;
g_autofree char *help = NULL;
context = flatpak_option_context_new_with_commands (commands);
if (command_name != NULL)
{
g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
_("Unknown command '%s'"), command_name);
}
else
{
/* This will not return for some options (e.g. --version). */
if (flatpak_option_context_parse (context, empty_entries, &argc, &argv, FLATPAK_BUILTIN_FLAG_NO_DIR, NULL, cancellable, &error))
{
g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
_("No command specified"));
}
}
help = g_option_context_get_help (context, FALSE, NULL);
g_printerr ("%s", help);
g_option_context_free (context);
goto out;
}
prgname = g_strdup_printf ("%s %s", g_get_prgname (), command_name);
g_set_prgname (prgname);
if (!command->fn (argc, argv, cancellable, &error))
goto out;
success = TRUE;
out:
g_assert (success || error);
if (error)
{
g_propagate_error (res_error, error);
return 1;
}
return 0;
}
static int
complete (int argc,
char **argv)
{
FlatpakCommand *command;
FlatpakCompletion *completion;
const char *command_name = NULL;
completion = flatpak_completion_new (argv[2], argv[3], argv[4]);
if (completion == NULL)
return 1;
command = extract_command (&completion->argc, completion->argv, &command_name);
flatpak_completion_debug ("command=%p '%s'", command->fn, command->name);
if (!command->fn)
{
FlatpakCommand *c = commands;
while (c->name)
{
if (c->fn != NULL)
flatpak_complete_word (completion, "%s ", c->name);
c++;
}
flatpak_complete_options (completion, global_entries);
flatpak_complete_options (completion, empty_entries);
flatpak_complete_options (completion, user_entries);
}
else if (command->complete)
{
if (!command->complete (completion))
return 1;
}
else
{
flatpak_complete_options (completion, global_entries);
}
return 0;
}
int
main (int argc,
char **argv)
{
GError *error = NULL;
g_autofree const char *old_env = NULL;
int ret;
setlocale (LC_ALL, "");
bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
textdomain (GETTEXT_PACKAGE);
g_log_set_handler (G_LOG_DOMAIN, 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");
if (argc >= 4 && strcmp (argv[1], "complete") == 0)
return complete (argc, argv);
flatpak_migrate_from_xdg_app ();
ret = flatpak_run (argc, argv, &error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
flatpak_usage (commands, TRUE);
if (error != NULL)
{
const char *prefix = "";
const char *suffix = "";
if (flatpak_fancy_output ())
{
prefix = FLATPAK_ANSI_RED FLATPAK_ANSI_BOLD_ON;
suffix = FLATPAK_ANSI_BOLD_OFF FLATPAK_ANSI_COLOR_RESET;
}
g_printerr ("%s%s %s%s\n", prefix, _("error:"), suffix, error->message);
g_error_free (error);
}
return ret;
}

View File

@ -1,807 +0,0 @@
/*
* Copyright © 2016 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 <stdio.h>
#include <glib/gi18n.h>
#include "flatpak-transaction.h"
#include "flatpak-utils.h"
#include "flatpak-builtins-utils.h"
#include "flatpak-error.h"
typedef struct FlatpakTransactionOp FlatpakTransactionOp;
typedef enum {
FLATPAK_TRANSACTION_OP_KIND_INSTALL,
FLATPAK_TRANSACTION_OP_KIND_UPDATE,
FLATPAK_TRANSACTION_OP_KIND_INSTALL_OR_UPDATE,
FLATPAK_TRANSACTION_OP_KIND_BUNDLE
} FlatpakTransactionOpKind;
struct FlatpakTransactionOp {
char *remote;
char *ref;
char **subpaths;
char *commit;
GFile *bundle;
FlatpakTransactionOpKind kind;
gboolean non_fatal;
};
struct FlatpakTransaction {
FlatpakDir *dir;
GHashTable *refs;
GPtrArray *system_dirs;
GList *ops;
gboolean no_interaction;
gboolean no_pull;
gboolean no_deploy;
gboolean no_static_deltas;
gboolean add_deps;
gboolean add_related;
};
/* Check if the ref is in the dir, or in the system dir, in case its a
* user-dir or another system-wide installation. We want to avoid depending
* on user-installed things when installing to the system dir.
*/
static gboolean
ref_is_installed (FlatpakTransaction *self,
const char *ref,
GError **error)
{
g_autoptr(GFile) deploy_dir = NULL;
FlatpakDir *dir = self->dir;
int i;
deploy_dir = flatpak_dir_get_if_deployed (dir, ref, NULL, NULL);
if (deploy_dir != NULL)
return TRUE;
/* Don't try to fallback for the system's default directory. */
if (!flatpak_dir_is_user (dir) && flatpak_dir_get_id (dir) == NULL)
return FALSE;
/* Lazy initialization of this, once per transaction */
if (self->system_dirs == NULL)
{
self->system_dirs = flatpak_dir_get_system_list (NULL, error);
if (self->system_dirs == NULL)
return FALSE;
}
for (i = 0; i < self->system_dirs->len; i++)
{
FlatpakDir *system_dir = g_ptr_array_index (self->system_dirs, i);
if (g_strcmp0 (flatpak_dir_get_id (dir), flatpak_dir_get_id (system_dir)) == 0)
continue;
deploy_dir = flatpak_dir_get_if_deployed (system_dir, ref, NULL, NULL);
if (deploy_dir != NULL)
return TRUE;
}
return FALSE;
}
static gboolean
dir_ref_is_installed (FlatpakDir *dir, const char *ref, char **remote_out, GVariant **deploy_data_out)
{
g_autoptr(GVariant) deploy_data = NULL;
deploy_data = flatpak_dir_get_deploy_data (dir, ref, NULL, NULL);
if (deploy_data == NULL)
return FALSE;
if (remote_out)
*remote_out = g_strdup (flatpak_deploy_data_get_origin (deploy_data));
if (deploy_data_out)
*deploy_data_out = g_variant_ref (deploy_data);
return TRUE;
}
static FlatpakTransactionOp *
flatpak_transaction_operation_new (const char *remote,
const char *ref,
const char **subpaths,
const char *commit,
GFile *bundle,
FlatpakTransactionOpKind kind)
{
FlatpakTransactionOp *self = g_new0 (FlatpakTransactionOp, 1);
self->remote = g_strdup (remote);
self->ref = g_strdup (ref);
self->subpaths = g_strdupv ((char **)subpaths);
self->commit = g_strdup (commit);
if (bundle)
self->bundle = g_object_ref (bundle);
self->kind = kind;
return self;
}
static void
flatpak_transaction_operation_free (FlatpakTransactionOp *self)
{
g_free (self->remote);
g_free (self->ref);
g_free (self->commit);
g_strfreev (self->subpaths);
g_clear_object (&self->bundle);
g_free (self);
}
FlatpakTransaction *
flatpak_transaction_new (FlatpakDir *dir,
gboolean no_interaction,
gboolean no_pull,
gboolean no_deploy,
gboolean no_static_deltas,
gboolean add_deps,
gboolean add_related)
{
FlatpakTransaction *t = g_new0 (FlatpakTransaction, 1);
t->dir = g_object_ref (dir);
t->refs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
t->no_interaction = no_interaction;
t->no_pull = no_pull;
t->no_deploy = no_deploy;
t->no_static_deltas = no_static_deltas;
t->add_deps = add_deps;
t->add_related = add_related;
return t;
}
void
flatpak_transaction_free (FlatpakTransaction *self)
{
g_hash_table_unref (self->refs);
g_list_free_full (self->ops, (GDestroyNotify)flatpak_transaction_operation_free);
g_object_unref (self->dir);
if (self->system_dirs != NULL)
g_ptr_array_free (self->system_dirs, TRUE);
g_free (self);
}
static gboolean
flatpak_transaction_contains_ref (FlatpakTransaction *self,
const char *ref)
{
FlatpakTransactionOp *op;
op = g_hash_table_lookup (self->refs, ref);
return op != NULL;
}
static char *
subpaths_to_string (const char **subpaths)
{
GString *s = NULL;
int i;
if (subpaths == NULL)
return g_strdup ("[$old]");
if (*subpaths == 0)
return g_strdup ("[*]");
s = g_string_new ("[");
for (i = 0; subpaths[i] != NULL; i++)
{
if (i != 0)
g_string_append (s, ", ");
g_string_append (s, subpaths[i]);
}
g_string_append (s, "]");
return g_string_free (s, FALSE);
}
static const char *
kind_to_str (FlatpakTransactionOpKind kind)
{
switch (kind)
{
case FLATPAK_TRANSACTION_OP_KIND_INSTALL:
return "install";
case FLATPAK_TRANSACTION_OP_KIND_UPDATE:
return "update";
case FLATPAK_TRANSACTION_OP_KIND_INSTALL_OR_UPDATE:
return "install/update";
case FLATPAK_TRANSACTION_OP_KIND_BUNDLE:
return "install bundle";
}
return "unknown";
}
static FlatpakTransactionOp *
flatpak_transaction_add_op (FlatpakTransaction *self,
const char *remote,
const char *ref,
const char **subpaths,
const char *commit,
GFile *bundle,
FlatpakTransactionOpKind kind)
{
FlatpakTransactionOp *op;
g_autofree char *subpaths_str = NULL;
subpaths_str = subpaths_to_string (subpaths);
g_debug ("Transaction: %s %s:%s%s%s%s",
kind_to_str (kind), remote, ref,
commit != NULL ? "@" : "",
commit != NULL ? commit : "",
subpaths_str);
op = g_hash_table_lookup (self->refs, ref);
if (op != NULL)
{
/* Only override subpaths if already specified,
we always want the un-subpathed to win if specified. */
if (op->subpaths != NULL && op->subpaths[0] != NULL && subpaths != NULL)
{
g_strfreev (op->subpaths);
op->subpaths = g_strdupv ((char **)subpaths);
}
return op;
}
op = flatpak_transaction_operation_new (remote, ref, subpaths, commit, bundle, kind);
g_hash_table_insert (self->refs, g_strdup (ref), op);
self->ops = g_list_prepend (self->ops, op);
return op;
}
static char *
ask_for_remote (FlatpakTransaction *self, const char **remotes)
{
int n_remotes = g_strv_length ((char **)remotes);
int chosen = 0;
int i;
if (self->no_interaction)
{
chosen = 1;
g_print ("Found in remote %s\n", remotes[0]);
}
else if (n_remotes == 1)
{
if (flatpak_yes_no_prompt (_("Found in remote %s, do you want to install it?"), remotes[0]))
chosen = 1;
}
else
{
g_print (_("Found in several remotes:\n"));
for (i = 0; remotes[i] != NULL; i++)
{
g_print ("%d) %s\n", i + 1, remotes[i]);
}
chosen = flatpak_number_prompt (0, n_remotes, _("Which do you want to install (0 to abort)?"));
}
if (chosen == 0)
return NULL;
return g_strdup (remotes[chosen-1]);
}
static gboolean
add_related (FlatpakTransaction *self,
const char *remote,
const char *ref,
GError **error)
{
g_autoptr(GPtrArray) related = NULL;
g_autoptr(GError) local_error = NULL;
int i;
if (!self->add_related)
return TRUE;
if (self->no_pull)
related = flatpak_dir_find_local_related (self->dir, ref, remote, NULL, &local_error);
else
related = flatpak_dir_find_remote_related (self->dir, ref, remote, NULL, &local_error);
if (related == NULL)
{
g_printerr (_("Warning: Problem looking for related refs: %s\n"), local_error->message);
g_clear_error (&local_error);
}
else
{
for (i = 0; i < related->len; i++)
{
FlatpakRelated *rel = g_ptr_array_index (related, i);
FlatpakTransactionOp *op;
if (!rel->download)
continue;
op = flatpak_transaction_add_op (self, remote, rel->ref,
(const char **)rel->subpaths,
NULL, NULL,
FLATPAK_TRANSACTION_OP_KIND_INSTALL_OR_UPDATE);
op->non_fatal = TRUE;
}
}
return TRUE;
}
static gboolean
add_deps (FlatpakTransaction *self,
GKeyFile *metakey,
const char *remote,
const char *ref,
GError **error)
{
g_autofree char *runtime_ref = NULL;
g_autofree char *full_runtime_ref = NULL;
g_autofree char *runtime_remote = NULL;
const char *pref;
if (!g_str_has_prefix (ref, "app/"))
return TRUE;
if (metakey)
runtime_ref = g_key_file_get_string (metakey, "Application", "runtime", NULL);
if (runtime_ref == NULL)
return TRUE;
pref = strchr (ref, '/') + 1;
full_runtime_ref = g_strconcat ("runtime/", runtime_ref, NULL);
if (!flatpak_transaction_contains_ref (self, full_runtime_ref))
{
g_autoptr(GError) local_error = NULL;
if (!ref_is_installed (self, full_runtime_ref, &local_error))
{
g_auto(GStrv) remotes = NULL;
if (local_error != NULL)
{
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}
g_print (_("Required runtime for %s (%s) is not installed, searching...\n"),
pref, runtime_ref);
remotes = flatpak_dir_search_for_dependency (self->dir, full_runtime_ref, NULL, NULL);
if (remotes == NULL || *remotes == NULL)
{
g_print (_("The required runtime %s was not found in a configured remote.\n"),
runtime_ref);
}
else
{
runtime_remote = ask_for_remote (self, (const char **)remotes);
}
if (runtime_remote == NULL)
return flatpak_fail (error,
"The Application %s requires the runtime %s which is not installed",
pref, runtime_ref);
flatpak_transaction_add_op (self, runtime_remote, full_runtime_ref, NULL, NULL, NULL,
FLATPAK_TRANSACTION_OP_KIND_INSTALL_OR_UPDATE);
}
else
{
/* Update if in same dir */
if (dir_ref_is_installed (self->dir, full_runtime_ref, &runtime_remote, NULL))
{
FlatpakTransactionOp *op;
g_debug ("Updating dependent runtime %s", full_runtime_ref);
op = flatpak_transaction_add_op (self, runtime_remote, full_runtime_ref, NULL, NULL, NULL,
FLATPAK_TRANSACTION_OP_KIND_UPDATE);
op->non_fatal = TRUE;
}
}
}
if (runtime_remote != NULL &&
!add_related (self, runtime_remote, full_runtime_ref, error))
return FALSE;
return TRUE;
}
static gboolean
flatpak_transaction_add_ref (FlatpakTransaction *self,
const char *remote,
const char *ref,
const char **subpaths,
const char *commit,
FlatpakTransactionOpKind kind,
GFile *bundle,
const char *metadata,
GError **error)
{
g_autofree char *origin = NULL;
const char *pref;
g_autofree char *remote_metadata = NULL;
g_autoptr(GKeyFile) metakey = NULL;
g_autoptr(GError) local_error = NULL;
pref = strchr (ref, '/') + 1;
if (kind == FLATPAK_TRANSACTION_OP_KIND_UPDATE)
{
if (!dir_ref_is_installed (self->dir, ref, &origin, NULL))
{
g_set_error (error, FLATPAK_ERROR, FLATPAK_ERROR_NOT_INSTALLED,
_("%s not installed"), pref);
return FALSE;
}
if (flatpak_dir_get_remote_disabled (self->dir, origin))
{
g_debug (_("Remote %s disabled, ignoring %s update"), origin, pref);
return TRUE;
}
remote = origin;
}
else if (kind == FLATPAK_TRANSACTION_OP_KIND_INSTALL)
{
g_assert (remote != NULL);
if (dir_ref_is_installed (self->dir, ref, NULL, NULL))
{
g_printerr (_("%s already installed, skipping\n"), pref);
return TRUE;
}
}
if (metadata == NULL && remote != NULL)
{
if (flatpak_dir_fetch_ref_cache (self->dir, remote, ref, NULL, NULL, &remote_metadata, NULL, &local_error))
metadata = remote_metadata;
else
{
g_print ("Warning: Can't find dependencies: %s\n", local_error->message);
g_clear_error (&local_error);
}
}
if (metadata)
{
metakey = g_key_file_new ();
if (!g_key_file_load_from_data (metakey, metadata, -1, 0, NULL))
g_clear_object (&metakey);
}
if (metakey)
{
g_autofree char *required_version = NULL;
const char *group;
int required_major, required_minor, required_micro;
if (g_str_has_prefix (ref, "app/"))
group = "Application";
else
group = "Runtime";
required_version = g_key_file_get_string (metakey, group, "required-flatpak", NULL);
if (required_version)
{
if (sscanf (required_version, "%d.%d.%d", &required_major, &required_minor, &required_micro) != 3)
g_print ("Invalid require-flatpak argument %s\n", required_version);
else
{
if (required_major > PACKAGE_MAJOR_VERSION ||
(required_major == PACKAGE_MAJOR_VERSION && required_minor > PACKAGE_MINOR_VERSION) ||
(required_major == PACKAGE_MAJOR_VERSION && required_minor == PACKAGE_MINOR_VERSION && required_micro > PACKAGE_MICRO_VERSION))
return flatpak_fail (error, _("%s needs a later flatpak version (%s)"), ref, required_version);
}
}
}
if (self->add_deps)
{
if (!add_deps (self, metakey, remote, ref, error))
return FALSE;
}
flatpak_transaction_add_op (self, remote, ref, subpaths, commit, bundle, kind);
if (!add_related (self, remote, ref, error))
return FALSE;
return TRUE;
}
gboolean
flatpak_transaction_add_install (FlatpakTransaction *self,
const char *remote,
const char *ref,
const char **subpaths,
GError **error)
{
const char *all_paths[] = { NULL };
/* If we install with no special args pull all subpaths */
if (subpaths == NULL)
subpaths = all_paths;
return flatpak_transaction_add_ref (self, remote, ref, subpaths, NULL, FLATPAK_TRANSACTION_OP_KIND_INSTALL, NULL, NULL, error);
}
gboolean
flatpak_transaction_add_install_bundle (FlatpakTransaction *self,
GFile *file,
GBytes *gpg_data,
GError **error)
{
g_autofree char *remote = NULL;
g_autofree char *ref = NULL;
g_autofree char *metadata = NULL;
gboolean created_remote;
remote = flatpak_dir_ensure_bundle_remote (self->dir, file, gpg_data,
&ref, &metadata, &created_remote,
NULL, error);
if (remote == NULL)
return FALSE;
if (!flatpak_dir_recreate_repo (self->dir, NULL, error))
return FALSE;
return flatpak_transaction_add_ref (self, remote, ref, NULL, NULL, FLATPAK_TRANSACTION_OP_KIND_BUNDLE, file, metadata, error);
}
gboolean
flatpak_transaction_add_update (FlatpakTransaction *self,
const char *ref,
const char **subpaths,
const char *commit,
GError **error)
{
const char *all_paths[] = { NULL };
/* If specify an empty subpath, that means all subpaths */
if (subpaths != NULL && subpaths[0] != NULL && subpaths[0][0] == 0)
subpaths = all_paths;
return flatpak_transaction_add_ref (self, NULL, ref, subpaths, commit, FLATPAK_TRANSACTION_OP_KIND_UPDATE, NULL, NULL, error);
}
gboolean
flatpak_transaction_update_metadata (FlatpakTransaction *self,
gboolean all_remotes,
GCancellable *cancellable,
GError **error)
{
g_auto(GStrv) remotes = NULL;
int i;
GList *l;
/* Collect all dir+remotes used in this transaction */
if (all_remotes)
{
remotes = flatpak_dir_list_remotes (self->dir, NULL, error);
if (remotes == NULL)
return FALSE;
}
else
{
g_autoptr(GHashTable) ht = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
for (l = self->ops; l != NULL; l = l->next)
{
FlatpakTransactionOp *op = l->data;
g_hash_table_add (ht, g_strdup (op->remote));
}
remotes = (char **)g_hash_table_get_keys_as_array (ht, NULL);
g_hash_table_steal_all (ht); /* Move ownership to remotes */
}
/* Update metadata for said remotes */
for (i = 0; remotes[i] != NULL; i++)
{
char *remote = remotes[i];
g_debug ("Updating remote metadata for %s", remote);
if (!flatpak_dir_update_remote_configuration (self->dir, remote, cancellable, error))
return FALSE;
}
/* Reload changed configuration */
if (!flatpak_dir_recreate_repo (self->dir, cancellable, error))
return FALSE;
return TRUE;
}
gboolean
flatpak_transaction_run (FlatpakTransaction *self,
gboolean stop_on_first_error,
GCancellable *cancellable,
GError **error)
{
GList *l;
gboolean succeeded = TRUE;
self->ops = g_list_reverse (self->ops);
for (l = self->ops; l != NULL; l = l->next)
{
FlatpakTransactionOp *op = l->data;
g_autoptr(GError) local_error = NULL;
gboolean res;
const char *pref;
const char *opname;
FlatpakTransactionOpKind kind;
FlatpakTerminalProgress terminal_progress = { 0 };
kind = op->kind;
if (kind == FLATPAK_TRANSACTION_OP_KIND_INSTALL_OR_UPDATE)
{
g_autoptr(GVariant) deploy_data = NULL;
if (dir_ref_is_installed (self->dir, op->ref, NULL, &deploy_data))
{
g_autofree const char **current_subpaths = NULL;
/* When we update a dependency, we always inherit the subpaths
rather than use the default. */
g_strfreev (op->subpaths);
current_subpaths = flatpak_deploy_data_get_subpaths (deploy_data);
op->subpaths = g_strdupv ((char **)current_subpaths);
/* Don't use the remote from related ref on update, always use
the current remote. */
g_free (op->remote);
op->remote = g_strdup (flatpak_deploy_data_get_origin (deploy_data));
kind = FLATPAK_TRANSACTION_OP_KIND_UPDATE;
}
else
kind = FLATPAK_TRANSACTION_OP_KIND_INSTALL;
}
pref = strchr (op->ref, '/') + 1;
if (kind == FLATPAK_TRANSACTION_OP_KIND_INSTALL)
{
g_autoptr(OstreeAsyncProgress) progress = flatpak_progress_new (flatpak_terminal_progress_cb, &terminal_progress);
opname = _("install");
g_print (_("Installing: %s from %s\n"), pref, op->remote);
res = flatpak_dir_install (self->dir,
self->no_pull,
self->no_deploy,
self->no_static_deltas,
op->ref, op->remote,
(const char **)op->subpaths,
progress,
cancellable, &local_error);
ostree_async_progress_finish (progress);
flatpak_terminal_progress_end (&terminal_progress);
}
else if (kind == FLATPAK_TRANSACTION_OP_KIND_UPDATE)
{
g_auto(OstreeRepoFinderResultv) check_results = NULL;
opname = _("update");
g_autofree char *target_commit = flatpak_dir_check_for_update (self->dir, op->ref, op->remote, op->commit,
(const char **)op->subpaths,
self->no_pull,
&check_results,
cancellable, &local_error);
if (target_commit != NULL)
{
g_print (_("Updating: %s from %s\n"), pref, op->remote);
g_autoptr(OstreeAsyncProgress) progress = flatpak_progress_new (flatpak_terminal_progress_cb, &terminal_progress);
res = flatpak_dir_update (self->dir,
self->no_pull,
self->no_deploy,
self->no_static_deltas,
op->commit != NULL, /* Allow downgrade if we specify commit */
op->ref, op->remote, target_commit,
(const OstreeRepoFinderResult * const *) check_results,
(const char **)op->subpaths,
progress,
cancellable, &local_error);
ostree_async_progress_finish (progress);
flatpak_terminal_progress_end (&terminal_progress);
if (res)
{
g_autoptr(GVariant) deploy_data = NULL;
g_autofree char *commit = NULL;
deploy_data = flatpak_dir_get_deploy_data (self->dir, op->ref, NULL, NULL);
commit = g_strndup (flatpak_deploy_data_get_commit (deploy_data), 12);
g_print (_("Now at %s.\n"), commit);
}
/* Handle noop-updates */
if (!res && g_error_matches (local_error, FLATPAK_ERROR, FLATPAK_ERROR_ALREADY_INSTALLED))
{
g_print (_("No updates.\n"));
res = TRUE;
g_clear_error (&local_error);
}
}
else
{
res = FALSE;
if (g_error_matches (local_error, FLATPAK_ERROR, FLATPAK_ERROR_ALREADY_INSTALLED))
{
res = TRUE;
g_clear_error (&local_error);
}
}
}
else if (kind == FLATPAK_TRANSACTION_OP_KIND_BUNDLE)
{
g_autofree char *bundle_basename = g_file_get_basename (op->bundle);
opname = _("install bundle");
g_print (_("Installing: %s from bundle %s\n"), pref, bundle_basename);
res = flatpak_dir_install_bundle (self->dir, op->bundle,
op->remote, NULL,
cancellable, &local_error);
}
else
g_assert_not_reached ();
if (!res)
{
if (op->non_fatal)
{
g_printerr (_("Warning: Failed to %s %s: %s\n"),
opname, pref, local_error->message);
}
else if (!stop_on_first_error)
{
g_printerr (_("Error: Failed to %s %s: %s\n"),
opname, pref, local_error->message);
if (succeeded)
{
succeeded = FALSE;
flatpak_fail (error, _("One or more operations failed"));
}
}
else
{
g_propagate_error (error, g_steal_pointer (&local_error));
return FALSE;
}
}
}
return succeeded;
}

View File

@ -1,65 +0,0 @@
/*
* Copyright © 2016 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 __FLATPAK_TRANSACTION_H__
#define __FLATPAK_TRANSACTION_H__
#include <glib.h>
#include "libglnx/libglnx.h"
#include "flatpak-dir.h"
typedef struct FlatpakTransaction FlatpakTransaction;
FlatpakTransaction *flatpak_transaction_new (FlatpakDir *dir,
gboolean no_interaction,
gboolean no_pull,
gboolean no_deploy,
gboolean no_static_deltas,
gboolean add_deps,
gboolean add_related);
void flatpak_transaction_free (FlatpakTransaction *self);
gboolean flatpak_transaction_update_metadata (FlatpakTransaction *self,
gboolean all_remotes,
GCancellable *cancellable,
GError **error);
gboolean flatpak_transaction_run (FlatpakTransaction *self,
gboolean stop_on_first_errror,
GCancellable *cancellable,
GError **error);
gboolean flatpak_transaction_add_install (FlatpakTransaction *self,
const char *remote,
const char *ref,
const char **subpaths,
GError **error);
gboolean flatpak_transaction_add_install_bundle (FlatpakTransaction *self,
GFile *file,
GBytes *gpg_data,
GError **error);
gboolean flatpak_transaction_add_update (FlatpakTransaction *self,
const char *ref,
const char **subpaths,
const char *commit,
GError **error);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakTransaction, flatpak_transaction_free)
#endif /* __FLATPAK_TRANSACTION_H__ */

View File

@ -23,22 +23,6 @@ if ! test -f libglnx/README.md -a -f bubblewrap/README.md; then
fi
# Workaround automake bug with subdir-objects and computed paths
sed -e 's,$(libglnx_srcpath),libglnx,g' < libglnx/Makefile-libglnx.am >libglnx/Makefile-libglnx.am.inc
sed -e 's,$(bwrap_srcpath),bubblewrap,g' < bubblewrap/Makefile-bwrap.am >bubblewrap/Makefile-bwrap.am.inc
GTKDOCIZE=$(which gtkdocize 2>/dev/null)
if test -z $GTKDOCIZE; then
echo "*** You don't have gtk-doc installed, and thus won't be able to generate the documentation. ***"
rm -f gtk-doc.make
cat > gtk-doc.make <<EOF
EXTRA_DIST =
CLEANFILES =
EOF
else
# gtkdocize needs the macro directory to exist before
# we call autoreconf
mkdir -p m4
gtkdocize || exit $?
fi
autoreconf --force --install --verbose || exit $?

@ -1 +0,0 @@
Subproject commit 30548332a7d04328487906edcd999c3dab67db28

View File

@ -32,7 +32,6 @@
#include "libglnx/libglnx.h"
#include "flatpak-utils.h"
#include "flatpak-run.h"
#include "builder-utils.h"
#include "builder-extension.h"

View File

@ -28,6 +28,7 @@
#include <gio/gio.h>
#include "libglnx/libglnx.h"
#include "flatpak-utils.h"
#include "builder-manifest.h"
#include "builder-utils.h"
#include "builder-git.h"

View File

@ -23,7 +23,7 @@
#include <json-glib/json-glib.h>
#include "flatpak-run.h"
#include "flatpak-utils.h"
#include "builder-options.h"
#include "builder-module.h"
#include "builder-cache.h"

View File

@ -1,65 +1,11 @@
noinst_LTLIBRARIES += libflatpak-common.la
dbus_built_sources = common/flatpak-dbus.c common/flatpak-dbus.h
systemd_dbus_built_sources = common/flatpak-systemd-dbus.c common/flatpak-systemd-dbus.h
common/flatpak-dbus.c: data/org.freedesktop.Flatpak.xml Makefile
mkdir -p $(builddir)/common
$(AM_V_GEN) $(GDBUS_CODEGEN) \
--interface-prefix org.freedesktop.Flatpak. \
--c-namespace Flatpak \
--generate-c-code $(builddir)/common/flatpak-dbus \
$(srcdir)/data/org.freedesktop.Flatpak.xml \
$(NULL)
common/flatpak-systemd-dbus.c: data/org.freedesktop.systemd1.xml Makefile
mkdir -p $(builddir)/common
$(AM_V_GEN) $(GDBUS_CODEGEN) \
--interface-prefix org.freedesktop.systemd1. \
--c-namespace Systemd \
--generate-c-code $(builddir)/common/flatpak-systemd-dbus \
$(srcdir)/data/org.freedesktop.systemd1.xml \
$(NULL)
common/%-dbus.h: common/%-dbus.c
@true # Built as a side-effect of the rules for the .c
nodist_libflatpak_common_la_SOURCES = \
$(dbus_built_sources) \
$(systemd_dbus_built_sources) \
$(xdp_dbus_built_sources) \
$(NULL)
BUILT_SOURCES += $(nodist_libflatpak_common_la_SOURCES)
CLEANFILES += $(nodist_libflatpak_common_la_SOURCES)
libflatpak_common_la_SOURCES = \
common/flatpak-common-types.h \
common/flatpak-dir.c \
common/flatpak-dir.h \
common/flatpak-run.c \
common/flatpak-run.h \
common/flatpak-portal-error.c \
common/flatpak-portal-error.h \
common/flatpak-utils.c \
common/flatpak-utils.h \
common/flatpak-table-printer.c \
common/flatpak-table-printer.h \
common/flatpak-chain-input-stream.c \
common/flatpak-chain-input-stream.h \
common/gvdb/gvdb-reader.h \
common/gvdb/gvdb-format.h \
common/gvdb/gvdb-reader.c \
common/gvdb/gvdb-builder.h \
common/gvdb/gvdb-builder.c \
common/flatpak-db.c \
common/flatpak-db.h \
common/flatpak-json.c \
common/flatpak-json.h \
common/flatpak-json-oci.c \
common/flatpak-json-oci.h \
common/flatpak-oci-registry.c \
common/flatpak-oci-registry.h \
$(NULL)
libflatpak_common_la_CFLAGS = \
@ -72,6 +18,5 @@ libflatpak_common_la_CFLAGS = \
$(XAUTH_CFLAGS) \
$(LIBSECCOMP_CFLAGS) \
$(INTERNAL_GPGME_CFLAGS) \
-I$(srcdir)/dbus-proxy \
$(NULL)
libflatpak_common_la_LIBADD = $(AM_LIBADD) libglnx.la $(BASE_LIBS) $(OSTREE_LIBS) $(SOUP_LIBS) $(JSON_LIBS) $(XAUTH_LIBS) $(LIBSECCOMP_LIBS) $(INTERNAL_GPGME_LIBS)

View File

@ -1,214 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* 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.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, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "flatpak-chain-input-stream.h"
enum {
PROP_0,
PROP_STREAMS
};
G_DEFINE_TYPE (FlatpakChainInputStream, flatpak_chain_input_stream, G_TYPE_INPUT_STREAM)
struct _FlatpakChainInputStreamPrivate
{
GPtrArray *streams;
guint index;
};
static void flatpak_chain_input_stream_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec);
static void flatpak_chain_input_stream_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec);
static void flatpak_chain_input_stream_finalize (GObject *object);
static gssize flatpak_chain_input_stream_read (GInputStream *stream,
void *buffer,
gsize count,
GCancellable *cancellable,
GError **error);
static gboolean flatpak_chain_input_stream_close (GInputStream *stream,
GCancellable *cancellable,
GError **error);
static void
flatpak_chain_input_stream_class_init (FlatpakChainInputStreamClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
g_type_class_add_private (klass, sizeof (FlatpakChainInputStreamPrivate));
gobject_class->get_property = flatpak_chain_input_stream_get_property;
gobject_class->set_property = flatpak_chain_input_stream_set_property;
gobject_class->finalize = flatpak_chain_input_stream_finalize;
stream_class->read_fn = flatpak_chain_input_stream_read;
stream_class->close_fn = flatpak_chain_input_stream_close;
/*
* FlatpakChainInputStream:streams: (element-type GInputStream)
*
* Chain of input streams read in order.
*/
g_object_class_install_property (gobject_class,
PROP_STREAMS,
g_param_spec_pointer ("streams",
"", "",
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
}
static void
flatpak_chain_input_stream_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
FlatpakChainInputStream *self;
self = FLATPAK_CHAIN_INPUT_STREAM (object);
switch (prop_id)
{
case PROP_STREAMS:
self->priv->streams = g_ptr_array_ref (g_value_get_pointer (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
flatpak_chain_input_stream_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
FlatpakChainInputStream *self;
self = FLATPAK_CHAIN_INPUT_STREAM (object);
switch (prop_id)
{
case PROP_STREAMS:
g_value_set_pointer (value, self->priv->streams);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
flatpak_chain_input_stream_finalize (GObject *object)
{
FlatpakChainInputStream *stream;
stream = (FlatpakChainInputStream *) (object);
g_ptr_array_unref (stream->priv->streams);
G_OBJECT_CLASS (flatpak_chain_input_stream_parent_class)->finalize (object);
}
static void
flatpak_chain_input_stream_init (FlatpakChainInputStream *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
FLATPAK_TYPE_CHAIN_INPUT_STREAM,
FlatpakChainInputStreamPrivate);
}
FlatpakChainInputStream *
flatpak_chain_input_stream_new (GPtrArray *streams)
{
FlatpakChainInputStream *stream;
stream = g_object_new (FLATPAK_TYPE_CHAIN_INPUT_STREAM,
"streams", streams,
NULL);
return (FlatpakChainInputStream *) (stream);
}
static gssize
flatpak_chain_input_stream_read (GInputStream *stream,
void *buffer,
gsize count,
GCancellable *cancellable,
GError **error)
{
FlatpakChainInputStream *self = (FlatpakChainInputStream *) stream;
GInputStream *child;
gssize res = -1;
if (g_cancellable_set_error_if_cancelled (cancellable, error))
return -1;
if (self->priv->index >= self->priv->streams->len)
return 0;
res = 0;
while (res == 0 && self->priv->index < self->priv->streams->len)
{
child = self->priv->streams->pdata[self->priv->index];
res = g_input_stream_read (child,
buffer,
count,
cancellable,
error);
if (res == 0)
self->priv->index++;
}
return res;
}
static gboolean
flatpak_chain_input_stream_close (GInputStream *stream,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
FlatpakChainInputStream *self = (gpointer) stream;
guint i;
for (i = 0; i < self->priv->streams->len; i++)
{
GInputStream *child = self->priv->streams->pdata[i];
if (!g_input_stream_close (child, cancellable, error))
goto out;
}
ret = TRUE;
out:
return ret;
}

View File

@ -1,68 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* 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.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, write to the
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
*/
#pragma once
#ifndef __GI_SCANNER__
#include <gio/gio.h>
G_BEGIN_DECLS
#define FLATPAK_TYPE_CHAIN_INPUT_STREAM (flatpak_chain_input_stream_get_type ())
#define FLATPAK_CHAIN_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), FLATPAK_TYPE_CHAIN_INPUT_STREAM, FlatpakChainInputStream))
#define FLATPAK_CHAIN_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), FLATPAK_TYPE_CHAIN_INPUT_STREAM, FlatpakChainInputStreamClass))
#define FLATPAK_IS_CHAIN_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), FLATPAK_TYPE_CHAIN_INPUT_STREAM))
#define FLATPAK_IS_CHAIN_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), FLATPAK_TYPE_CHAIN_INPUT_STREAM))
#define FLATPAK_CHAIN_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), FLATPAK_TYPE_CHAIN_INPUT_STREAM, FlatpakChainInputStreamClass))
typedef struct _FlatpakChainInputStream FlatpakChainInputStream;
typedef struct _FlatpakChainInputStreamClass FlatpakChainInputStreamClass;
typedef struct _FlatpakChainInputStreamPrivate FlatpakChainInputStreamPrivate;
struct _FlatpakChainInputStream
{
GInputStream parent_instance;
/*< private >*/
FlatpakChainInputStreamPrivate *priv;
};
struct _FlatpakChainInputStreamClass
{
GInputStreamClass parent_class;
/*< private >*/
/* Padding for future expansion */
void (*_g_reserved1) (void);
void (*_g_reserved2) (void);
void (*_g_reserved3) (void);
void (*_g_reserved4) (void);
void (*_g_reserved5) (void);
};
GType flatpak_chain_input_stream_get_type (void) G_GNUC_CONST;
FlatpakChainInputStream * flatpak_chain_input_stream_new (GPtrArray *streams);
G_END_DECLS
#endif

View File

@ -1,35 +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 __FLATPAK_COMMON_TYPES_H__
#define __FLATPAK_COMMON_TYPES_H__
typedef enum {
FLATPAK_KINDS_APP = 1 << 0,
FLATPAK_KINDS_RUNTIME = 1 << 1,
} FlatpakKinds;
typedef struct FlatpakDir FlatpakDir;
typedef struct FlatpakDeploy FlatpakDeploy;
typedef struct FlatpakContext FlatpakContext;
typedef struct FlatpakOciRegistry FlatpakOciRegistry;
typedef struct _FlatpakOciManifest FlatpakOciManifest;
#endif /* __FLATPAK_COMMON_TYPES_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,103 +0,0 @@
/* flatpak-db.h
*
* Copyright © 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>
*/
#ifndef FLATPAK_DB_H
#define FLATPAK_DB_H
#include <string.h>
#include "libglnx/libglnx.h"
#include <glib-object.h>
G_BEGIN_DECLS
typedef struct FlatpakDb FlatpakDb;
typedef struct _FlatpakDbEntry FlatpakDbEntry;
#define FLATPAK_TYPE_DB (flatpak_db_get_type ())
#define FLATPAK_DB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_DB, FlatpakDb))
#define FLATPAK_IS_DB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_DB))
GType flatpak_db_get_type (void);
FlatpakDb * flatpak_db_new (const char *path,
gboolean fail_if_not_found,
GError **error);
char ** flatpak_db_list_ids (FlatpakDb *self);
char ** flatpak_db_list_apps (FlatpakDb *self);
char ** flatpak_db_list_ids_by_app (FlatpakDb *self,
const char *app);
char ** flatpak_db_list_ids_by_value (FlatpakDb *self,
GVariant *data);
FlatpakDbEntry *flatpak_db_lookup (FlatpakDb *self,
const char *id);
GString * flatpak_db_print_string (FlatpakDb *self,
GString *string);
char * flatpak_db_print (FlatpakDb *self);
gboolean flatpak_db_is_dirty (FlatpakDb *self);
void flatpak_db_set_entry (FlatpakDb *self,
const char *id,
FlatpakDbEntry *entry);
void flatpak_db_update (FlatpakDb *self);
GBytes * flatpak_db_get_content (FlatpakDb *self);
const char * flatpak_db_get_path (FlatpakDb *self);
gboolean flatpak_db_save_content (FlatpakDb *self,
GError **error);
void flatpak_db_save_content_async (FlatpakDb *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean flatpak_db_save_content_finish (FlatpakDb *self,
GAsyncResult *res,
GError **error);
void flatpak_db_set_path (FlatpakDb *self,
const char *path);
FlatpakDbEntry *flatpak_db_entry_ref (FlatpakDbEntry *entry);
void flatpak_db_entry_unref (FlatpakDbEntry *entry);
GVariant * flatpak_db_entry_get_data (FlatpakDbEntry *entry);
const char ** flatpak_db_entry_list_apps (FlatpakDbEntry *entry);
const char ** flatpak_db_entry_list_permissions (FlatpakDbEntry *entry,
const char *app);
gboolean flatpak_db_entry_has_permission (FlatpakDbEntry *entry,
const char *app,
const char *permission);
gboolean flatpak_db_entry_has_permissions (FlatpakDbEntry *entry,
const char *app,
const char **permissions);
GString * flatpak_db_entry_print_string (FlatpakDbEntry *entry,
GString *string);
FlatpakDbEntry *flatpak_db_entry_new (GVariant *data);
FlatpakDbEntry *flatpak_db_entry_modify_data (FlatpakDbEntry *entry,
GVariant *data);
FlatpakDbEntry *flatpak_db_entry_set_app_permissions (FlatpakDbEntry *entry,
const char *app,
const char **permissions);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakDb, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakDbEntry, flatpak_db_entry_unref)
G_END_DECLS
#endif /* FLATPAK_DB_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,616 +0,0 @@
/*
* Copyright © 2014 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 __FLATPAK_DIR_H__
#define __FLATPAK_DIR_H__
#include <ostree.h>
#include "libglnx/libglnx.h"
#include <flatpak-common-types.h>
#define FLATPAK_TYPE_DIR flatpak_dir_get_type ()
#define FLATPAK_DIR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_DIR, FlatpakDir))
#define FLATPAK_IS_DIR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_DIR))
#define FLATPAK_TYPE_DEPLOY flatpak_deploy_get_type ()
#define FLATPAK_DEPLOY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_DEPLOY, FlatpakDeploy))
#define FLATPAK_IS_DEPLOY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_DEPLOY))
GType flatpak_dir_get_type (void);
GType flatpak_deploy_get_type (void);
#define FLATPAK_REF_GROUP "Flatpak Ref"
#define FLATPAK_REF_VERSION_KEY "Version"
#define FLATPAK_REF_URL_KEY "Url"
#define FLATPAK_REF_RUNTIME_REPO_KEY "RuntimeRepo"
#define FLATPAK_REF_TITLE_KEY "Title"
#define FLATPAK_REF_GPGKEY_KEY "GPGKey"
#define FLATPAK_REF_IS_RUNTIME_KEY "IsRuntime"
#define FLATPAK_REF_NAME_KEY "Name"
#define FLATPAK_REF_BRANCH_KEY "Branch"
#ifdef FLATPAK_ENABLE_P2P
#define FLATPAK_REF_COLLECTION_ID_KEY "CollectionID"
#endif /* FLATPAK_ENABLE_P2P */
#define FLATPAK_REPO_GROUP "Flatpak Repo"
#define FLATPAK_REPO_VERSION_KEY "Version"
#define FLATPAK_REPO_URL_KEY "Url"
#define FLATPAK_REPO_TITLE_KEY "Title"
#define FLATPAK_REPO_DEFAULT_BRANCH_KEY "DefaultBranch"
#define FLATPAK_REPO_GPGKEY_KEY "GPGKey"
#define FLATPAK_REPO_NODEPS_KEY "NoDeps"
#ifdef FLATPAK_ENABLE_P2P
#define FLATPAK_REPO_COLLECTION_ID_KEY "CollectionID"
#endif /* FLATPAK_ENABLE_P2P */
#define FLATPAK_DEFAULT_UPDATE_FREQUENCY 100
#define FLATPAK_CLI_UPDATE_FREQUENCY 300
typedef struct
{
char *collection_id; /* (nullable) */
char *ref;
char *commit;
char **subpaths;
gboolean download;
gboolean delete;
} FlatpakRelated;
void flatpak_related_free (FlatpakRelated *related);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakDir, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakDeploy, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakRelated, flatpak_related_free)
typedef enum {
FLATPAK_HELPER_DEPLOY_FLAGS_NONE = 0,
FLATPAK_HELPER_DEPLOY_FLAGS_UPDATE = 1 << 0,
FLATPAK_HELPER_DEPLOY_FLAGS_NO_DEPLOY = 1 << 1,
FLATPAK_HELPER_DEPLOY_FLAGS_LOCAL_PULL = 1 << 2,
} FlatpakHelperDeployFlags;
#define FLATPAK_HELPER_DEPLOY_FLAGS_ALL (FLATPAK_HELPER_DEPLOY_FLAGS_UPDATE|FLATPAK_HELPER_DEPLOY_FLAGS_NO_DEPLOY|FLATPAK_HELPER_DEPLOY_FLAGS_LOCAL_PULL)
typedef enum {
FLATPAK_HELPER_UNINSTALL_FLAGS_NONE = 0,
FLATPAK_HELPER_UNINSTALL_FLAGS_KEEP_REF = 1 << 0,
FLATPAK_HELPER_UNINSTALL_FLAGS_FORCE_REMOVE = 1 << 1,
} FlatpakHelperUninstallFlags;
#define FLATPAK_HELPER_UNINSTALL_FLAGS_ALL (FLATPAK_HELPER_UNINSTALL_FLAGS_KEEP_REF | FLATPAK_HELPER_UNINSTALL_FLAGS_FORCE_REMOVE)
typedef enum {
FLATPAK_HELPER_CONFIGURE_REMOTE_FLAGS_NONE = 0,
FLATPAK_HELPER_CONFIGURE_REMOTE_FLAGS_FORCE_REMOVE = 1 << 0,
} FlatpakHelperConfigureRemoteFlags;
#define FLATPAK_HELPER_CONFIGURE_REMOTE_FLAGS_ALL (FLATPAK_HELPER_CONFIGURE_REMOTE_FLAGS_FORCE_REMOVE)
typedef enum {
FLATPAK_HELPER_UPDATE_REMOTE_FLAGS_NONE = 0,
} FlatpakHelperUpdateRemoteFlags;
#define FLATPAK_HELPER_UPDATE_REMOTE_FLAGS_ALL (0)
typedef enum {
FLATPAK_PULL_FLAGS_NONE = 0,
FLATPAK_PULL_FLAGS_DOWNLOAD_EXTRA_DATA = 1 << 0,
FLATPAK_PULL_FLAGS_SIDELOAD_EXTRA_DATA = 1 << 1,
FLATPAK_PULL_FLAGS_ALLOW_DOWNGRADE = 1 << 2,
FLATPAK_PULL_FLAGS_NO_STATIC_DELTAS = 1 << 3,
} FlatpakPullFlags;
typedef enum {
FLATPAK_DIR_STORAGE_TYPE_DEFAULT = 0,
FLATPAK_DIR_STORAGE_TYPE_HARD_DISK,
FLATPAK_DIR_STORAGE_TYPE_SDCARD,
FLATPAK_DIR_STORAGE_TYPE_MMC,
} FlatpakDirStorageType;
GQuark flatpak_dir_error_quark (void);
#ifndef FLATPAK_ENABLE_P2P
/* Rather than putting #ifdefs around all the function arguments for result sets,
* define away OstreeRepoFinderResult if were compiling without P2P support.
* The surrounding code should always pass in NULL if P2P support is disabled. */
typedef void OstreeRepoFinderResult;
typedef void** OstreeRepoFinderResultv;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoFinderResult, void)
G_DEFINE_AUTO_CLEANUP_FREE_FUNC (OstreeRepoFinderResultv, void, NULL)
#endif /* !FLATPAK_ENABLE_P2P */
/**
* FLATPAK_DEPLOY_DATA_GVARIANT_FORMAT:
*
* s - origin
* s - commit
* as - subpaths
* t - installed size
* a{sv} - Metadata
*/
#define FLATPAK_DEPLOY_DATA_GVARIANT_STRING "(ssasta{sv})"
#define FLATPAK_DEPLOY_DATA_GVARIANT_FORMAT G_VARIANT_TYPE (FLATPAK_DEPLOY_DATA_GVARIANT_STRING)
GPtrArray * flatpak_get_system_base_dir_locations (GCancellable *cancellable,
GError **error);
GFile * flatpak_get_system_default_base_dir_location (void);
GFile * flatpak_get_user_base_dir_location (void);
GKeyFile * flatpak_load_override_keyfile (const char *app_id,
gboolean user,
GError **error);
FlatpakContext *flatpak_load_override_file (const char *app_id,
gboolean user,
GError **error);
gboolean flatpak_save_override_keyfile (GKeyFile *metakey,
const char *app_id,
gboolean user,
GError **error);
const char * flatpak_deploy_data_get_origin (GVariant *deploy_data);
const char * flatpak_deploy_data_get_commit (GVariant *deploy_data);
const char ** flatpak_deploy_data_get_subpaths (GVariant *deploy_data);
guint64 flatpak_deploy_data_get_installed_size (GVariant *deploy_data);
const char * flatpak_deploy_data_get_alt_id (GVariant *deploy_data);
GFile * flatpak_deploy_get_dir (FlatpakDeploy *deploy);
GFile * flatpak_deploy_get_files (FlatpakDeploy *deploy);
FlatpakContext *flatpak_deploy_get_overrides (FlatpakDeploy *deploy);
GKeyFile * flatpak_deploy_get_metadata (FlatpakDeploy *deploy);
FlatpakDir * flatpak_dir_new (GFile *basedir,
gboolean user);
FlatpakDir * flatpak_dir_clone (FlatpakDir *self);
FlatpakDir *flatpak_dir_get_user (void);
FlatpakDir *flatpak_dir_get_system_default (void);
GPtrArray *flatpak_dir_get_system_list (GCancellable *cancellable,
GError **error);
FlatpakDir *flatpak_dir_get_system_by_id (const char *id,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_is_user (FlatpakDir *self);
void flatpak_dir_set_no_system_helper (FlatpakDir *self,
gboolean no_system_helper);
GFile * flatpak_dir_get_path (FlatpakDir *self);
GFile * flatpak_dir_get_changed_path (FlatpakDir *self);
const char *flatpak_dir_get_id (FlatpakDir *self);
const char *flatpak_dir_get_display_name (FlatpakDir *self);
char * flatpak_dir_get_name (FlatpakDir *self);
gint flatpak_dir_get_priority (FlatpakDir *self);
FlatpakDirStorageType flatpak_dir_get_storage_type (FlatpakDir *self);
GFile * flatpak_dir_get_deploy_dir (FlatpakDir *self,
const char *ref);
GFile * flatpak_dir_get_unmaintained_extension_dir (FlatpakDir *self,
const char *name,
const char *arch,
const char *branch);
GVariant * flatpak_dir_get_deploy_data (FlatpakDir *dir,
const char *ref,
GCancellable *cancellable,
GError **error);
char * flatpak_dir_get_origin (FlatpakDir *self,
const char *ref,
GCancellable *cancellable,
GError **error);
char ** flatpak_dir_get_subpaths (FlatpakDir *self,
const char *ref,
GCancellable *cancellable,
GError **error);
GFile * flatpak_dir_get_exports_dir (FlatpakDir *self);
GFile * flatpak_dir_get_removed_dir (FlatpakDir *self);
GFile * flatpak_dir_get_if_deployed (FlatpakDir *self,
const char *ref,
const char *checksum,
GCancellable *cancellable);
GFile * flatpak_dir_get_unmaintained_extension_dir_if_exists (FlatpakDir *self,
const char *name,
const char *arch,
const char *branch,
GCancellable *cancellable);
gboolean flatpak_dir_remote_has_ref (FlatpakDir *self,
const char *remote,
const char *ref);
char ** flatpak_dir_search_for_dependency (FlatpakDir *self,
const char *runtime_ref,
GCancellable *cancellable,
GError **error);
char * flatpak_dir_find_remote_ref (FlatpakDir *self,
const char *remote,
const char *name,
const char *opt_branch,
const char *opt_default_branch,
const char *opt_arch,
FlatpakKinds kinds,
FlatpakKinds *out_kind,
GCancellable *cancellable,
GError **error);
char ** flatpak_dir_find_remote_refs (FlatpakDir *self,
const char *remote,
const char *name,
const char *opt_branch,
const char *opt_arch,
FlatpakKinds kinds,
GCancellable *cancellable,
GError **error);
char * flatpak_dir_find_installed_ref (FlatpakDir *self,
const char *opt_name,
const char *opt_branch,
const char *opt_arch,
FlatpakKinds kinds,
FlatpakKinds *out_kind,
GError **error);
char ** flatpak_dir_find_installed_refs (FlatpakDir *self,
const char *opt_name,
const char *opt_branch,
const char *opt_arch,
FlatpakKinds kinds,
GError **error);
FlatpakDeploy *flatpak_dir_load_deployed (FlatpakDir *self,
const char *ref,
const char *checksum,
GCancellable *cancellable,
GError **error);
char * flatpak_dir_load_override (FlatpakDir *dir,
const char *app_id,
gsize *length,
GError **error);
OstreeRepo *flatpak_dir_get_repo (FlatpakDir *self);
gboolean flatpak_dir_ensure_path (FlatpakDir *self,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_use_child_repo (FlatpakDir *self);
gboolean flatpak_dir_ensure_system_child_repo (FlatpakDir *self,
GError **error);
gboolean flatpak_dir_recreate_repo (FlatpakDir *self,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_ensure_repo (FlatpakDir *self,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_mark_changed (FlatpakDir *self,
GError **error);
gboolean flatpak_dir_remove_appstream (FlatpakDir *self,
const char *remote,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_deploy_appstream (FlatpakDir *self,
const char *remote,
const char *arch,
gboolean *out_changed,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_update_appstream (FlatpakDir *self,
const char *remote,
const char *arch,
gboolean *out_changed,
OstreeAsyncProgress *progress,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_pull (FlatpakDir *self,
const char *repository,
const char *ref,
const char *opt_rev,
const OstreeRepoFinderResult * const *results,
const char **subpaths,
OstreeRepo *repo,
FlatpakPullFlags flatpak_flags,
OstreeRepoPullFlags flags,
OstreeAsyncProgress *progress,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_pull_untrusted_local (FlatpakDir *self,
const char *src_path,
const char *remote_name,
const char *ref,
const char **subpaths,
OstreeAsyncProgress *progress,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_list_refs_for_name (FlatpakDir *self,
const char *kind,
const char *name,
char ***refs,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_list_refs (FlatpakDir *self,
const char *kind,
char ***refs,
GCancellable *cancellable,
GError **error);
char * flatpak_dir_read_latest (FlatpakDir *self,
const char *remote,
const char *ref,
char **out_alt_id,
GCancellable *cancellable,
GError **error);
char * flatpak_dir_read_active (FlatpakDir *self,
const char *ref,
GCancellable *cancellable);
gboolean flatpak_dir_set_active (FlatpakDir *self,
const char *ref,
const char *checksum,
GCancellable *cancellable,
GError **error);
char * flatpak_dir_current_ref (FlatpakDir *self,
const char *name,
GCancellable *cancellable);
gboolean flatpak_dir_drop_current_ref (FlatpakDir *self,
const char *name,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_make_current_ref (FlatpakDir *self,
const char *ref,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_list_deployed (FlatpakDir *self,
const char *ref,
char ***deployed_checksums,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_lock (FlatpakDir *self,
GLnxLockFile *lockfile,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_deploy (FlatpakDir *self,
const char *origin,
const char *ref,
const char *checksum_or_latest,
const char * const * subpaths,
GVariant *old_deploy_data,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_deploy_update (FlatpakDir *self,
const char *ref,
const char *checksum,
const char **opt_subpaths,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_deploy_install (FlatpakDir *self,
const char *ref,
const char *origin,
const char **subpaths,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_install (FlatpakDir *self,
gboolean no_pull,
gboolean no_deploy,
gboolean no_static_deltas,
const char *ref,
const char *remote_name,
const char **subpaths,
OstreeAsyncProgress *progress,
GCancellable *cancellable,
GError **error);
char *flatpak_dir_ensure_bundle_remote (FlatpakDir *self,
GFile *file,
GBytes *extra_gpg_data,
char **out_ref,
char **out_metadata,
gboolean *out_created_remote,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_install_bundle (FlatpakDir *self,
GFile *file,
const char *remote,
char **out_ref,
GCancellable *cancellable,
GError **error);
char * flatpak_dir_check_for_update (FlatpakDir *self,
const char *ref,
const char *remote_name,
const char *checksum_or_latest,
const char **opt_subpaths,
gboolean no_pull,
OstreeRepoFinderResult ***out_results,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_update (FlatpakDir *self,
gboolean no_pull,
gboolean no_deploy,
gboolean no_static_deltas,
gboolean allow_downgrade,
const char *ref,
const char *remote_name,
const char *checksum_or_latest,
const OstreeRepoFinderResult * const *results,
const char **opt_subpaths,
OstreeAsyncProgress *progress,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_uninstall (FlatpakDir *self,
const char *ref,
FlatpakHelperUninstallFlags flags,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_undeploy (FlatpakDir *self,
const char *ref,
const char *checksum,
gboolean is_update,
gboolean force_remove,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_undeploy_all (FlatpakDir *self,
const char *ref,
gboolean force_remove,
gboolean *was_deployed_out,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_remove_ref (FlatpakDir *self,
const char *remote_name,
const char *ref,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_update_exports (FlatpakDir *self,
const char *app,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_prune (FlatpakDir *self,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_cleanup_removed (FlatpakDir *self,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_collect_deployed_refs (FlatpakDir *self,
const char *type,
const char *name_prefix,
const char *branch,
const char *arch,
GHashTable *hash,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_collect_unmaintained_refs (FlatpakDir *self,
const char *name_prefix,
const char *arch,
const char *branch,
GHashTable *hash,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_remote_has_deploys (FlatpakDir *self,
const char *remote);
char *flatpak_dir_create_origin_remote (FlatpakDir *self,
const char *url,
const char *id,
const char *title,
const char *main_ref,
GBytes *gpg_data,
const char *collection_id,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_create_remote_for_ref_file (FlatpakDir *self,
GBytes *data,
const char *default_arch,
char **remote_name_out,
char **ref_out,
GError **error);
GKeyFile * flatpak_dir_parse_repofile (FlatpakDir *self,
const char *remote_name,
GBytes *data,
GBytes **gpg_data_out,
GCancellable *cancellable,
GError **error);
char *flatpak_dir_find_remote_by_uri (FlatpakDir *self,
const char *uri,
const char *collection_id);
char **flatpak_dir_list_remotes (FlatpakDir *self,
GCancellable *cancellable,
GError **error);
char **flatpak_dir_list_enumerated_remotes (FlatpakDir *self,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_modify_remote (FlatpakDir *self,
const char *remote_name,
GKeyFile *config,
GBytes *gpg_data,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_remove_remote (FlatpakDir *self,
gboolean force_remove,
const char *remote_name,
GCancellable *cancellable,
GError **error);
char *flatpak_dir_get_remote_title (FlatpakDir *self,
const char *remote_name);
char *flatpak_dir_get_remote_collection_id (FlatpakDir *self,
const char *remote_name);
char *flatpak_dir_get_remote_main_ref (FlatpakDir *self,
const char *remote_name);
gboolean flatpak_dir_get_remote_oci (FlatpakDir *self,
const char *remote_name);
char *flatpak_dir_get_remote_default_branch (FlatpakDir *self,
const char *remote_name);
int flatpak_dir_get_remote_prio (FlatpakDir *self,
const char *remote_name);
gboolean flatpak_dir_get_remote_noenumerate (FlatpakDir *self,
const char *remote_name);
gboolean flatpak_dir_get_remote_nodeps (FlatpakDir *self,
const char *remote_name);
gboolean flatpak_dir_get_remote_disabled (FlatpakDir *self,
const char *remote_name);
gboolean flatpak_dir_list_remote_refs (FlatpakDir *self,
const char *remote,
GHashTable **refs,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_fetch_remote_repo_metadata (FlatpakDir *self,
const char *remote_name,
GCancellable *cancellable,
GError **error);
char * flatpak_dir_fetch_remote_title (FlatpakDir *self,
const char *remote,
GCancellable *cancellable,
GError **error);
char * flatpak_dir_fetch_remote_default_branch (FlatpakDir *self,
const char *remote,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_update_remote_configuration (FlatpakDir *self,
const char *remote,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_update_remote_configuration_for_summary (FlatpakDir *self,
const char *remote,
GVariant *summary,
gboolean dry_run,
gboolean *has_changed_out,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_update_remote_configuration_for_repo_metadata (FlatpakDir *self,
const char *remote,
GVariant *summary,
gboolean dry_run,
gboolean *has_changed_out,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_fetch_ref_cache (FlatpakDir *self,
const char *remote_name,
const char *ref,
guint64 *download_size,
guint64 *installed_size,
char **metadata,
GCancellable *cancellable,
GError **error);
GPtrArray * flatpak_dir_find_remote_related (FlatpakDir *dir,
const char *remote_name,
const char *ref,
GCancellable *cancellable,
GError **error);
GPtrArray * flatpak_dir_find_local_related (FlatpakDir *self,
const char *remote_name,
const char *ref,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_lookup_repo_metadata (FlatpakDir *self,
const char *remote_name,
GCancellable *cancellable,
GError **error,
const char *key,
const char *format_string,
...);
char ** flatpak_dir_get_locale_subpaths (FlatpakDir *self);
#endif /* __FLATPAK_DIR_H__ */

View File

@ -1,941 +0,0 @@
/*
* 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 "flatpak-json-oci.h"
#include "flatpak-utils.h"
#include "libglnx.h"
const char *
flatpak_arch_to_oci_arch (const char *flatpak_arch)
{
if (strcmp (flatpak_arch, "x86_64") == 0)
return "amd64";
if (strcmp (flatpak_arch, "aarch64") == 0)
return "arm64";
if (strcmp (flatpak_arch, "i386") == 0)
return "386";
return flatpak_arch;
}
FlatpakOciDescriptor *
flatpak_oci_descriptor_new (const char *mediatype,
const char *digest,
gint64 size)
{
FlatpakOciDescriptor *desc = g_new0 (FlatpakOciDescriptor, 1);
desc->mediatype = g_strdup (mediatype);
desc->digest = g_strdup (digest);
desc->size = size;
desc->annotations = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
return desc;
}
void
flatpak_oci_descriptor_copy (FlatpakOciDescriptor *source,
FlatpakOciDescriptor *dest)
{
flatpak_oci_descriptor_destroy (dest);
dest->mediatype = g_strdup (source->mediatype);
dest->digest = g_strdup (source->digest);
dest->size = source->size;
dest->urls = g_strdupv ((char **)source->urls);
dest->annotations = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
if (source->annotations)
flatpak_oci_copy_annotations (source->annotations, dest->annotations);
}
void
flatpak_oci_descriptor_destroy (FlatpakOciDescriptor *self)
{
g_free (self->mediatype);
g_free (self->digest);
g_strfreev (self->urls);
if (self->annotations)
g_hash_table_destroy (self->annotations);
}
void
flatpak_oci_descriptor_free (FlatpakOciDescriptor *self)
{
flatpak_oci_descriptor_destroy (self);
g_free (self);
}
static FlatpakJsonProp flatpak_oci_descriptor_props[] = {
FLATPAK_JSON_STRING_PROP (FlatpakOciDescriptor, mediatype, "mediaType"),
FLATPAK_JSON_STRING_PROP (FlatpakOciDescriptor, digest, "digest"),
FLATPAK_JSON_INT64_PROP (FlatpakOciDescriptor, size, "size"),
FLATPAK_JSON_STRV_PROP (FlatpakOciDescriptor, urls, "urls"),
FLATPAK_JSON_STRMAP_PROP(FlatpakOciDescriptor, annotations, "annotations"),
FLATPAK_JSON_LAST_PROP
};
static void
flatpak_oci_manifest_platform_destroy (FlatpakOciManifestPlatform *self)
{
g_free (self->architecture);
g_free (self->os);
g_free (self->os_version);
g_strfreev (self->os_features);
g_free (self->variant);
g_strfreev (self->features);
}
FlatpakOciManifestDescriptor *
flatpak_oci_manifest_descriptor_new (void)
{
return g_new0 (FlatpakOciManifestDescriptor, 1);
}
void
flatpak_oci_manifest_descriptor_destroy (FlatpakOciManifestDescriptor *self)
{
flatpak_oci_manifest_platform_destroy (&self->platform);
flatpak_oci_descriptor_destroy (&self->parent);
}
void
flatpak_oci_manifest_descriptor_free (FlatpakOciManifestDescriptor *self)
{
flatpak_oci_manifest_descriptor_destroy (self);
g_free (self);
}
static FlatpakJsonProp flatpak_oci_manifest_platform_props[] = {
FLATPAK_JSON_STRING_PROP (FlatpakOciManifestPlatform, architecture, "architecture"),
FLATPAK_JSON_STRING_PROP (FlatpakOciManifestPlatform, os, "os"),
FLATPAK_JSON_STRING_PROP (FlatpakOciManifestPlatform, os_version, "os.version"),
FLATPAK_JSON_STRING_PROP (FlatpakOciManifestPlatform, variant, "variant"),
FLATPAK_JSON_STRV_PROP (FlatpakOciManifestPlatform, os_features, "os.features"),
FLATPAK_JSON_STRV_PROP (FlatpakOciManifestPlatform, features, "features"),
FLATPAK_JSON_LAST_PROP
};
static FlatpakJsonProp flatpak_oci_manifest_descriptor_props[] = {
FLATPAK_JSON_PARENT_PROP (FlatpakOciManifestDescriptor, parent, flatpak_oci_descriptor_props),
FLATPAK_JSON_OPT_STRUCT_PROP (FlatpakOciManifestDescriptor, platform, "platform", flatpak_oci_manifest_platform_props),
FLATPAK_JSON_LAST_PROP
};
G_DEFINE_TYPE (FlatpakOciVersioned, flatpak_oci_versioned, FLATPAK_TYPE_JSON);
static void
flatpak_oci_versioned_finalize (GObject *object)
{
FlatpakOciVersioned *self = FLATPAK_OCI_VERSIONED (object);
g_free (self->mediatype);
G_OBJECT_CLASS (flatpak_oci_versioned_parent_class)->finalize (object);
}
static void
flatpak_oci_versioned_class_init (FlatpakOciVersionedClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
FlatpakJsonClass *json_class = FLATPAK_JSON_CLASS (klass);
static FlatpakJsonProp props[] = {
FLATPAK_JSON_INT64_PROP (FlatpakOciVersioned, version, "schemaVersion"),
FLATPAK_JSON_STRING_PROP (FlatpakOciVersioned, mediatype, "mediaType"),
FLATPAK_JSON_LAST_PROP
};
object_class->finalize = flatpak_oci_versioned_finalize;
json_class->props = props;
}
static void
flatpak_oci_versioned_init (FlatpakOciVersioned *self)
{
}
FlatpakOciVersioned *
flatpak_oci_versioned_from_json (GBytes *bytes, GError **error)
{
g_autoptr(JsonParser) parser = NULL;
JsonNode *root = NULL;
const gchar *mediatype;
JsonObject *object;
parser = json_parser_new ();
if (!json_parser_load_from_data (parser,
g_bytes_get_data (bytes, NULL),
g_bytes_get_size (bytes),
error))
return NULL;
root = json_parser_get_root (parser);
object = json_node_get_object (root);
mediatype = json_object_get_string_member (object, "mediaType");
if (mediatype == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
"Versioned object lacks mediatype");
return NULL;
}
if (strcmp (mediatype, FLATPAK_OCI_MEDIA_TYPE_IMAGE_MANIFEST) == 0)
return (FlatpakOciVersioned *) flatpak_json_from_node (root, FLATPAK_TYPE_OCI_MANIFEST, error);
if (strcmp (mediatype, FLATPAK_OCI_MEDIA_TYPE_IMAGE_INDEX) == 0)
return (FlatpakOciVersioned *) flatpak_json_from_node (root, FLATPAK_TYPE_OCI_INDEX, error);
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
"Unsupported media type %s", mediatype);
return NULL;
}
const char *
flatpak_oci_versioned_get_mediatype (FlatpakOciVersioned *self)
{
return self->mediatype;
}
gint64
flatpak_oci_versioned_get_version (FlatpakOciVersioned *self)
{
return self->version;
}
G_DEFINE_TYPE (FlatpakOciManifest, flatpak_oci_manifest, FLATPAK_TYPE_OCI_VERSIONED);
static void
flatpak_oci_manifest_finalize (GObject *object)
{
FlatpakOciManifest *self = (FlatpakOciManifest *) object;
int i;
for (i = 0; self->layers != NULL && self->layers[i] != NULL; i++)
flatpak_oci_descriptor_free (self->layers[i]);
g_free (self->layers);
flatpak_oci_descriptor_destroy (&self->config);
if (self->annotations)
g_hash_table_destroy (self->annotations);
G_OBJECT_CLASS (flatpak_oci_manifest_parent_class)->finalize (object);
}
static void
flatpak_oci_manifest_class_init (FlatpakOciManifestClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
FlatpakJsonClass *json_class = FLATPAK_JSON_CLASS (klass);
static FlatpakJsonProp props[] = {
FLATPAK_JSON_STRUCT_PROP(FlatpakOciManifest, config, "config", flatpak_oci_descriptor_props),
FLATPAK_JSON_STRUCTV_PROP(FlatpakOciManifest, layers, "layers", flatpak_oci_descriptor_props),
FLATPAK_JSON_STRMAP_PROP(FlatpakOciManifest, annotations, "annotations"),
FLATPAK_JSON_LAST_PROP
};
object_class->finalize = flatpak_oci_manifest_finalize;
json_class->props = props;
json_class->mediatype = FLATPAK_OCI_MEDIA_TYPE_IMAGE_MANIFEST;
}
static void
flatpak_oci_manifest_init (FlatpakOciManifest *self)
{
}
FlatpakOciManifest *
flatpak_oci_manifest_new (void)
{
FlatpakOciManifest *manifest;
manifest = g_object_new (FLATPAK_TYPE_OCI_MANIFEST, NULL);
manifest->parent.version = 2;
manifest->parent.mediatype = g_strdup (FLATPAK_OCI_MEDIA_TYPE_IMAGE_MANIFEST);
manifest->annotations = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
return manifest;
}
void
flatpak_oci_manifest_set_config (FlatpakOciManifest *self,
FlatpakOciDescriptor *desc)
{
g_free (self->config.mediatype);
self->config.mediatype = g_strdup (desc->mediatype);
g_free (self->config.digest);
self->config.digest = g_strdup (desc->digest);
self->config.size = desc->size;
}
static int
ptrv_count (gpointer *ptrs)
{
int count;
for (count = 0; ptrs != NULL && ptrs[count] != NULL; count++)
;
return count;
}
void
flatpak_oci_manifest_set_layer (FlatpakOciManifest *self,
FlatpakOciDescriptor *desc)
{
FlatpakOciDescriptor *descs[2] = { desc, NULL };
flatpak_oci_manifest_set_layers (self, descs);
}
void
flatpak_oci_manifest_set_layers (FlatpakOciManifest *self,
FlatpakOciDescriptor **descs)
{
int i, count;
for (i = 0; self->layers != NULL && self->layers[i] != NULL; i++)
flatpak_oci_descriptor_free (self->layers[i]);
g_free (self->layers);
count = ptrv_count ((gpointer *)descs);
self->layers = g_new0 (FlatpakOciDescriptor *, count + 1);
for (i = 0; i < count; i++)
{
self->layers[i] = g_new0 (FlatpakOciDescriptor, 1);
self->layers[i]->mediatype = g_strdup (descs[i]->mediatype);
self->layers[i]->digest = g_strdup (descs[i]->digest);
self->layers[i]->size = descs[i]->size;
}
}
int
flatpak_oci_manifest_get_n_layers (FlatpakOciManifest *self)
{
return ptrv_count ((gpointer *)self->layers);
}
const char *
flatpak_oci_manifest_get_layer_digest (FlatpakOciManifest *self,
int i)
{
return self->layers[i]->digest;
}
GHashTable *
flatpak_oci_manifest_get_annotations (FlatpakOciManifest *self)
{
return self->annotations;
}
G_DEFINE_TYPE (FlatpakOciIndex, flatpak_oci_index, FLATPAK_TYPE_OCI_VERSIONED);
static void
flatpak_oci_index_finalize (GObject *object)
{
FlatpakOciIndex *self = (FlatpakOciIndex *) object;
int i;
for (i = 0; self->manifests != NULL && self->manifests[i] != NULL; i++)
flatpak_oci_manifest_descriptor_free (self->manifests[i]);
g_free (self->manifests);
if (self->annotations)
g_hash_table_destroy (self->annotations);
G_OBJECT_CLASS (flatpak_oci_index_parent_class)->finalize (object);
}
static void
flatpak_oci_index_class_init (FlatpakOciIndexClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
FlatpakJsonClass *json_class = FLATPAK_JSON_CLASS (klass);
static FlatpakJsonProp props[] = {
FLATPAK_JSON_STRUCTV_PROP(FlatpakOciIndex, manifests, "manifests", flatpak_oci_manifest_descriptor_props),
FLATPAK_JSON_STRMAP_PROP(FlatpakOciIndex, annotations, "annotations"),
FLATPAK_JSON_LAST_PROP
};
object_class->finalize = flatpak_oci_index_finalize;
json_class->props = props;
json_class->mediatype = FLATPAK_OCI_MEDIA_TYPE_IMAGE_INDEX;
}
static void
flatpak_oci_index_init (FlatpakOciIndex *self)
{
}
FlatpakOciIndex *
flatpak_oci_index_new (void)
{
FlatpakOciIndex *index;
index = g_object_new (FLATPAK_TYPE_OCI_INDEX, NULL);
index->parent.version = 2;
index->parent.mediatype = g_strdup (FLATPAK_OCI_MEDIA_TYPE_IMAGE_INDEX);
index->annotations = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
return index;
}
static FlatpakOciManifestDescriptor *
manifest_desc_for_desc (FlatpakOciDescriptor *src_descriptor)
{
FlatpakOciManifestDescriptor *desc;
desc = flatpak_oci_manifest_descriptor_new ();
flatpak_oci_descriptor_copy (src_descriptor, &desc->parent);
return desc;
}
int
flatpak_oci_index_get_n_manifests (FlatpakOciIndex *self)
{
return ptrv_count ((gpointer *)self->manifests);
}
void
flatpak_oci_index_add_manifest (FlatpakOciIndex *self,
FlatpakOciDescriptor *desc)
{
FlatpakOciManifestDescriptor *m;
const char *m_ref = NULL;
int count;
if (desc->annotations != NULL)
m_ref = g_hash_table_lookup (desc->annotations, "org.opencontainers.image.ref.name");
if (m_ref != NULL)
flatpak_oci_index_remove_manifest (self, m_ref);
count = flatpak_oci_index_get_n_manifests (self);
m = manifest_desc_for_desc (desc);
self->manifests = g_renew (FlatpakOciManifestDescriptor *, self->manifests, count + 2);
self->manifests[count] = m;
self->manifests[count+1] = NULL;
}
const char *
flatpak_oci_manifest_descriptor_get_ref (FlatpakOciManifestDescriptor *m)
{
if (m->parent.mediatype == NULL ||
strcmp (m->parent.mediatype, FLATPAK_OCI_MEDIA_TYPE_IMAGE_MANIFEST) != 0)
return NULL;
if (m->parent.annotations == NULL)
return NULL;
return g_hash_table_lookup (m->parent.annotations, "org.opencontainers.image.ref.name");
}
static int
index_find_ref (FlatpakOciIndex *self,
const char *ref)
{
int i;
if (self->manifests == NULL)
return -1;
for (i = 0; self->manifests[i] != NULL; i++)
{
const char *m_ref = flatpak_oci_manifest_descriptor_get_ref (self->manifests[i]);
if (m_ref == NULL)
continue;
if (strcmp (ref, m_ref) == 0)
return i;
}
return -1;
}
FlatpakOciManifestDescriptor *
flatpak_oci_index_get_manifest (FlatpakOciIndex *self,
const char *ref)
{
int i = index_find_ref (self, ref);
if (i >= 0)
return self->manifests[i];
return NULL;
}
FlatpakOciManifestDescriptor *
flatpak_oci_index_get_only_manifest (FlatpakOciIndex *self)
{
int i, found = -1;
if (self->manifests == NULL)
return NULL;
for (i = 0; self->manifests[i] != NULL; i++)
{
const char *m_ref = flatpak_oci_manifest_descriptor_get_ref (self->manifests[i]);
if (m_ref == NULL)
continue;
if (found == -1)
found = i;
else
return NULL;
}
if (found >= 0)
return self->manifests[found];
return NULL;
}
gboolean
flatpak_oci_index_remove_manifest (FlatpakOciIndex *self,
const char *ref)
{
int i = index_find_ref (self, ref);
if (i < 0)
return FALSE;
for (; self->manifests[i] != NULL; i++)
self->manifests[i] = self->manifests[i+1];
return TRUE;
}
G_DEFINE_TYPE (FlatpakOciImage, flatpak_oci_image, FLATPAK_TYPE_JSON);
static void
flatpak_oci_image_rootfs_destroy (FlatpakOciImageRootfs *self)
{
g_free (self->type);
g_strfreev (self->diff_ids);
}
static void
flatpak_oci_image_config_destroy (FlatpakOciImageConfig *self)
{
g_free (self->user);
g_free (self->working_dir);
g_strfreev (self->env);
g_strfreev (self->cmd);
g_strfreev (self->entrypoint);
g_strfreev (self->exposed_ports);
g_strfreev (self->volumes);
if (self->labels)
g_hash_table_destroy (self->labels);
}
static void
flatpak_oci_image_history_free (FlatpakOciImageHistory *self)
{
g_free (self->created);
g_free (self->created_by);
g_free (self->author);
g_free (self->comment);
g_free (self);
}
static void
flatpak_oci_image_finalize (GObject *object)
{
FlatpakOciImage *self = (FlatpakOciImage *) object;
int i;
g_free (self->created);
g_free (self->author);
g_free (self->architecture);
g_free (self->os);
flatpak_oci_image_rootfs_destroy (&self->rootfs);
flatpak_oci_image_config_destroy (&self->config);
for (i = 0; self->history != NULL && self->history[i] != NULL; i++)
flatpak_oci_image_history_free (self->history[i]);
g_free (self->history);
G_OBJECT_CLASS (flatpak_oci_image_parent_class)->finalize (object);
}
static void
flatpak_oci_image_class_init (FlatpakOciImageClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
FlatpakJsonClass *json_class = FLATPAK_JSON_CLASS (klass);
static FlatpakJsonProp config_props[] = {
FLATPAK_JSON_STRING_PROP (FlatpakOciImageConfig, user, "User"),
FLATPAK_JSON_INT64_PROP (FlatpakOciImageConfig, memory, "Memory"),
FLATPAK_JSON_INT64_PROP (FlatpakOciImageConfig, memory_swap, "MemorySwap"),
FLATPAK_JSON_INT64_PROP (FlatpakOciImageConfig, cpu_shares, "CpuShares"),
FLATPAK_JSON_BOOLMAP_PROP (FlatpakOciImageConfig, exposed_ports, "ExposedPorts"),
FLATPAK_JSON_STRV_PROP (FlatpakOciImageConfig, env, "Env"),
FLATPAK_JSON_STRV_PROP (FlatpakOciImageConfig, entrypoint, "Entrypoint"),
FLATPAK_JSON_STRV_PROP (FlatpakOciImageConfig, cmd, "Cmd"),
FLATPAK_JSON_BOOLMAP_PROP (FlatpakOciImageConfig, volumes, "Volumes"),
FLATPAK_JSON_STRING_PROP (FlatpakOciImageConfig, working_dir, "WorkingDir"),
FLATPAK_JSON_STRMAP_PROP(FlatpakOciImageConfig, labels, "Labels"),
FLATPAK_JSON_LAST_PROP
};
static FlatpakJsonProp rootfs_props[] = {
FLATPAK_JSON_STRING_PROP (FlatpakOciImageRootfs, type, "type"),
FLATPAK_JSON_STRV_PROP (FlatpakOciImageRootfs, diff_ids, "diff_ids"),
FLATPAK_JSON_LAST_PROP
};
static FlatpakJsonProp history_props[] = {
FLATPAK_JSON_STRING_PROP (FlatpakOciImageHistory, created, "created"),
FLATPAK_JSON_STRING_PROP (FlatpakOciImageHistory, created_by, "created_by"),
FLATPAK_JSON_STRING_PROP (FlatpakOciImageHistory, author, "author"),
FLATPAK_JSON_STRING_PROP (FlatpakOciImageHistory, comment, "comment"),
FLATPAK_JSON_BOOL_PROP (FlatpakOciImageHistory, empty_layer, "empty_layer"),
FLATPAK_JSON_LAST_PROP
};
static FlatpakJsonProp props[] = {
FLATPAK_JSON_STRING_PROP (FlatpakOciImage, created, "created"),
FLATPAK_JSON_STRING_PROP (FlatpakOciImage, author, "author"),
FLATPAK_JSON_STRING_PROP (FlatpakOciImage, architecture, "architecture"),
FLATPAK_JSON_STRING_PROP (FlatpakOciImage, os, "os"),
FLATPAK_JSON_STRUCT_PROP (FlatpakOciImage, config, "config", config_props),
FLATPAK_JSON_STRUCT_PROP (FlatpakOciImage, rootfs, "rootfs", rootfs_props),
FLATPAK_JSON_STRUCTV_PROP (FlatpakOciImage, history, "history", history_props),
FLATPAK_JSON_LAST_PROP
};
object_class->finalize = flatpak_oci_image_finalize;
json_class->props = props;
json_class->mediatype = FLATPAK_OCI_MEDIA_TYPE_IMAGE_CONFIG;
}
static void
flatpak_oci_image_init (FlatpakOciImage *self)
{
}
FlatpakOciImage *
flatpak_oci_image_new (void)
{
FlatpakOciImage *image;
GTimeVal stamp;
stamp.tv_sec = time (NULL);
stamp.tv_usec = 0;
image = g_object_new (FLATPAK_TYPE_OCI_IMAGE, NULL);
/* Some default values */
image->created = g_time_val_to_iso8601 (&stamp);
image->architecture = g_strdup ("arm64");
image->os = g_strdup ("linux");
image->rootfs.type = g_strdup ("layers");
image->rootfs.diff_ids = g_new0 (char *, 1);
return image;
}
void
flatpak_oci_image_set_created (FlatpakOciImage *image,
const char *created)
{
g_free (image->created);
image->created = g_strdup (created);
}
void
flatpak_oci_image_set_architecture (FlatpakOciImage *image,
const char *arch)
{
g_free (image->architecture);
image->architecture = g_strdup (arch);
}
void
flatpak_oci_image_set_os (FlatpakOciImage *image,
const char *os)
{
g_free (image->os);
image->os = g_strdup (os);
}
void
flatpak_oci_image_set_layers (FlatpakOciImage *image,
const char **layers)
{
g_strfreev (image->rootfs.diff_ids);
image->rootfs.diff_ids = g_strdupv ((char **)layers);
}
void
flatpak_oci_image_set_layer (FlatpakOciImage *image,
const char *layer)
{
const char *layers[] = {layer, NULL};
flatpak_oci_image_set_layers (image, layers);
}
void
flatpak_oci_export_annotations (GHashTable *source,
GHashTable *dest)
{
const char *keys[] = {
"org.opencontainers.image.ref.name",
"org.flatpak.installed-size",
"org.flatpak.download-size",
"org.flatpak.metadata",
};
int i;
for (i = 0; i < G_N_ELEMENTS (keys); i++)
{
const char *key = keys[i];
const char *value = g_hash_table_lookup (source, key);
if (value)
g_hash_table_replace (dest,
g_strdup (key),
g_strdup (value));
}
}
void
flatpak_oci_copy_annotations (GHashTable *source,
GHashTable *dest)
{
GHashTableIter iter;
gpointer key, value;
g_hash_table_iter_init (&iter, source);
while (g_hash_table_iter_next (&iter, &key, &value))
g_hash_table_replace (dest,
g_strdup ((char *)key),
g_strdup ((char *)value));
}
static void
add_annotation (GHashTable *annotations, const char *key, const char *value)
{
g_hash_table_replace (annotations,
g_strdup (key),
g_strdup (value));
}
void
flatpak_oci_add_annotations_for_commit (GHashTable *annotations,
const char *ref,
const char *commit,
GVariant *commit_data)
{
if (ref)
add_annotation (annotations,"org.opencontainers.image.ref.name", ref);
if (commit)
add_annotation (annotations,"org.flatpak.commit", commit);
if (commit_data)
{
g_autofree char *parent = NULL;
g_autofree char *subject = NULL;
g_autofree char *body = NULL;
g_autofree char *timestamp = NULL;
g_autoptr(GVariant) metadata = NULL;
int i;
parent = ostree_commit_get_parent (commit_data);
if (parent)
add_annotation (annotations, "org.flatpak.parent-commit", parent);
metadata = g_variant_get_child_value (commit_data, 0);
for (i = 0; i < g_variant_n_children (metadata); i++)
{
g_autoptr(GVariant) elm = g_variant_get_child_value (metadata, i);
g_autoptr(GVariant) value = g_variant_get_child_value (elm, 1);
g_autofree char *key = NULL;
g_autofree char *full_key = NULL;
g_autofree char *value_base64 = NULL;
g_variant_get_child (elm, 0, "s", &key);
full_key = g_strdup_printf ("org.flatpak.commit-metadata.%s", key);
value_base64 = g_base64_encode (g_variant_get_data (value), g_variant_get_size (value));
add_annotation (annotations, full_key, value_base64);
}
timestamp = g_strdup_printf ("%"G_GUINT64_FORMAT, ostree_commit_get_timestamp (commit_data));
add_annotation (annotations, "org.flatpak.timestamp", timestamp);
g_variant_get_child (commit_data, 3, "s", &subject);
add_annotation (annotations, "org.flatpak.subject", subject);
g_variant_get_child (commit_data, 4, "s", &body);
add_annotation (annotations, "org.flatpak.body", body);
}
}
void
flatpak_oci_parse_commit_annotations (GHashTable *annotations,
guint64 *out_timestamp,
char **out_subject,
char **out_body,
char **out_ref,
char **out_commit,
char **out_parent_commit,
GVariantBuilder *metadata_builder)
{
const char *oci_timestamp, *oci_subject, *oci_body, *oci_parent_commit, *oci_commit, *oci_ref;
GHashTableIter iter;
gpointer _key, _value;
oci_ref = g_hash_table_lookup (annotations, "org.opencontainers.image.ref.name");
if (oci_ref != NULL && out_ref != NULL && *out_ref == NULL)
*out_ref = g_strdup (oci_ref);
oci_commit = g_hash_table_lookup (annotations, "org.flatpak.commit");
if (oci_commit != NULL && out_commit != NULL && *out_commit == NULL)
*out_commit = g_strdup (oci_commit);
oci_parent_commit = g_hash_table_lookup (annotations, "org.flatpak.parent-commit");
if (oci_parent_commit != NULL && out_parent_commit != NULL && *out_parent_commit == NULL)
*out_parent_commit = g_strdup (oci_parent_commit);
oci_timestamp = g_hash_table_lookup (annotations, "org.flatpak.timestamp");
if (oci_timestamp != NULL && out_timestamp != NULL && *out_timestamp == 0)
*out_timestamp = g_ascii_strtoull (oci_timestamp, NULL, 10);
oci_subject = g_hash_table_lookup (annotations, "org.flatpak.subject");
if (oci_subject != NULL && out_subject != NULL && *out_subject == NULL)
*out_subject = g_strdup (oci_subject);
oci_body = g_hash_table_lookup (annotations, "org.flatpak.body");
if (oci_body != NULL && out_body != NULL && *out_body == NULL)
*out_body = g_strdup (oci_body);
if (metadata_builder)
{
g_hash_table_iter_init (&iter, annotations);
while (g_hash_table_iter_next (&iter, &_key, &_value))
{
const char *key = _key;
const char *value = _value;
guchar *bin;
gsize bin_len;
g_autoptr(GVariant) data = NULL;
if (!g_str_has_prefix (key, "org.flatpak.commit-metadata."))
continue;
key += strlen ("org.flatpak.commit-metadata.");
bin = g_base64_decode (value, &bin_len);
data = g_variant_ref_sink (g_variant_new_from_data (G_VARIANT_TYPE("v"), bin, bin_len, FALSE,
g_free, bin));
g_variant_builder_add (metadata_builder, "{s@v}", key, data);
}
}
}
G_DEFINE_TYPE (FlatpakOciSignature, flatpak_oci_signature, FLATPAK_TYPE_JSON);
static void
flatpak_oci_signature_critical_destroy (FlatpakOciSignatureCritical *self)
{
g_free (self->type);
g_free (self->image.digest);
g_free (self->identity.ref);
}
static void
flatpak_oci_signature_optional_destroy (FlatpakOciSignatureOptional *self)
{
g_free (self->creator);
}
static void
flatpak_oci_signature_finalize (GObject *object)
{
FlatpakOciSignature *self = (FlatpakOciSignature *) object;
flatpak_oci_signature_critical_destroy (&self->critical);
flatpak_oci_signature_optional_destroy (&self->optional);
G_OBJECT_CLASS (flatpak_oci_signature_parent_class)->finalize (object);
}
static void
flatpak_oci_signature_class_init (FlatpakOciSignatureClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
FlatpakJsonClass *json_class = FLATPAK_JSON_CLASS (klass);
static FlatpakJsonProp image_props[] = {
FLATPAK_JSON_MANDATORY_STRING_PROP (FlatpakOciSignatureCriticalImage, digest, "oci-image-manifest-digest"),
FLATPAK_JSON_LAST_PROP
};
static FlatpakJsonProp identity_props[] = {
FLATPAK_JSON_MANDATORY_STRING_PROP (FlatpakOciSignatureCriticalIdentity, ref, "oci-image-ref"),
FLATPAK_JSON_LAST_PROP
};
static FlatpakJsonProp critical_props[] = {
FLATPAK_JSON_MANDATORY_STRING_PROP (FlatpakOciSignatureCritical, type, "type"),
FLATPAK_JSON_MANDATORY_STRICT_STRUCT_PROP(FlatpakOciSignatureCritical, image, "image", image_props),
FLATPAK_JSON_MANDATORY_STRICT_STRUCT_PROP(FlatpakOciSignatureCritical, identity, "identity", identity_props),
FLATPAK_JSON_LAST_PROP
};
static FlatpakJsonProp optional_props[] = {
FLATPAK_JSON_STRING_PROP (FlatpakOciSignatureOptional, creator, "creator"),
FLATPAK_JSON_INT64_PROP (FlatpakOciSignatureOptional, timestamp, "timestamp"),
FLATPAK_JSON_LAST_PROP
};
static FlatpakJsonProp props[] = {
FLATPAK_JSON_MANDATORY_STRICT_STRUCT_PROP (FlatpakOciSignature, critical, "critical", critical_props),
FLATPAK_JSON_STRUCT_PROP (FlatpakOciSignature, optional, "optional", optional_props),
FLATPAK_JSON_LAST_PROP
};
object_class->finalize = flatpak_oci_signature_finalize;
json_class->props = props;
}
static void
flatpak_oci_signature_init (FlatpakOciSignature *self)
{
}
FlatpakOciSignature *
flatpak_oci_signature_new (const char *digest, const char *ref)
{
FlatpakOciSignature *signature;
signature = g_object_new (FLATPAK_TYPE_OCI_SIGNATURE, NULL);
/* Some default values */
signature->critical.type = g_strdup (FLATPAK_OCI_SIGNATURE_TYPE_FLATPAK);
signature->critical.image.digest = g_strdup (digest);
signature->critical.identity.ref = g_strdup (ref);
signature->optional.creator = g_strdup ("flatpak " PACKAGE_VERSION);
signature->optional.timestamp = time (NULL);
return signature;
}

View File

@ -1,275 +0,0 @@
/*
* Copyright © 2016 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 __FLATPAK_JSON_OCI_H__
#define __FLATPAK_JSON_OCI_H__
#include "flatpak-json.h"
G_BEGIN_DECLS
#define FLATPAK_OCI_MEDIA_TYPE_DESCRIPTOR "application/vnd.oci.descriptor.v1+json"
#define FLATPAK_OCI_MEDIA_TYPE_IMAGE_MANIFEST "application/vnd.oci.image.manifest.v1+json"
#define FLATPAK_OCI_MEDIA_TYPE_IMAGE_INDEX "application/vnd.oci.image.index.v1+json"
#define FLATPAK_OCI_MEDIA_TYPE_IMAGE_LAYER "application/vnd.oci.image.layer.v1.tar+gzip"
#define FLATPAK_OCI_MEDIA_TYPE_IMAGE_LAYER_NONDISTRIBUTABLE "application/vnd.oci.image.layer.nondistributable.v1.tar+gzip"
#define FLATPAK_OCI_MEDIA_TYPE_IMAGE_CONFIG "application/vnd.oci.image.config.v1+json"
#define FLATPAK_OCI_SIGNATURE_TYPE_FLATPAK "flatpak oci image signature"
const char * flatpak_arch_to_oci_arch (const char *flatpak_arch);
void flatpak_oci_export_annotations (GHashTable *source,
GHashTable *dest);
void flatpak_oci_copy_annotations (GHashTable *source,
GHashTable *dest);
typedef struct {
char *mediatype;
char *digest;
gint64 size;
char **urls;
GHashTable *annotations;
} FlatpakOciDescriptor;
FlatpakOciDescriptor *flatpak_oci_descriptor_new (const char *mediatype,
const char *digest,
gint64 size);
void flatpak_oci_descriptor_copy (FlatpakOciDescriptor *source,
FlatpakOciDescriptor *dest);
void flatpak_oci_descriptor_destroy (FlatpakOciDescriptor *self);
void flatpak_oci_descriptor_free (FlatpakOciDescriptor *self);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakOciDescriptor, flatpak_oci_descriptor_free)
typedef struct
{
char *architecture;
char *os;
char *os_version;
char **os_features;
char *variant;
char **features;
} FlatpakOciManifestPlatform;
typedef struct
{
FlatpakOciDescriptor parent;
FlatpakOciManifestPlatform platform;
} FlatpakOciManifestDescriptor;
FlatpakOciManifestDescriptor * flatpak_oci_manifest_descriptor_new (void);
const char * flatpak_oci_manifest_descriptor_get_ref (FlatpakOciManifestDescriptor *m);
void flatpak_oci_manifest_descriptor_destroy (FlatpakOciManifestDescriptor *self);
void flatpak_oci_manifest_descriptor_free (FlatpakOciManifestDescriptor *self);
#define FLATPAK_TYPE_OCI_VERSIONED flatpak_oci_versioned_get_type ()
G_DECLARE_FINAL_TYPE (FlatpakOciVersioned, flatpak_oci_versioned, FLATPAK_OCI, VERSIONED, FlatpakJson)
struct _FlatpakOciVersioned {
FlatpakJson parent;
int version;
char *mediatype;
};
struct _FlatpakOciVersionedClass {
FlatpakJsonClass parent_class;
};
FlatpakOciVersioned *flatpak_oci_versioned_from_json (GBytes *bytes,
GError **error);
const char * flatpak_oci_versioned_get_mediatype (FlatpakOciVersioned *self);
gint64 flatpak_oci_versioned_get_version (FlatpakOciVersioned *self);
#define FLATPAK_TYPE_OCI_MANIFEST flatpak_oci_manifest_get_type ()
G_DECLARE_FINAL_TYPE (FlatpakOciManifest, flatpak_oci_manifest, FLATPAK, OCI_MANIFEST, FlatpakOciVersioned)
struct _FlatpakOciManifest
{
FlatpakOciVersioned parent;
FlatpakOciDescriptor config;
FlatpakOciDescriptor **layers;
GHashTable *annotations;
};
struct _FlatpakOciManifestClass
{
FlatpakOciVersionedClass parent_class;
};
FlatpakOciManifest *flatpak_oci_manifest_new (void);
void flatpak_oci_manifest_set_config (FlatpakOciManifest *self,
FlatpakOciDescriptor *desc);
void flatpak_oci_manifest_set_layers (FlatpakOciManifest *self,
FlatpakOciDescriptor **descs);
void flatpak_oci_manifest_set_layer (FlatpakOciManifest *self,
FlatpakOciDescriptor *desc);
int flatpak_oci_manifest_get_n_layers (FlatpakOciManifest *self);
const char * flatpak_oci_manifest_get_layer_digest (FlatpakOciManifest *self,
int i);
GHashTable * flatpak_oci_manifest_get_annotations (FlatpakOciManifest *self);
#define FLATPAK_TYPE_OCI_INDEX flatpak_oci_index_get_type ()
G_DECLARE_FINAL_TYPE (FlatpakOciIndex, flatpak_oci_index, FLATPAK, OCI_INDEX, FlatpakOciVersioned)
struct _FlatpakOciIndex
{
FlatpakOciVersioned parent;
FlatpakOciManifestDescriptor **manifests;
GHashTable *annotations;
};
struct _FlatpakOciIndexClass
{
FlatpakOciVersionedClass parent_class;
};
FlatpakOciIndex * flatpak_oci_index_new (void);
void flatpak_oci_index_add_manifest (FlatpakOciIndex *self,
FlatpakOciDescriptor *desc);
gboolean flatpak_oci_index_remove_manifest (FlatpakOciIndex *self,
const char *ref);
FlatpakOciManifestDescriptor *flatpak_oci_index_get_manifest (FlatpakOciIndex *self,
const char *ref);
FlatpakOciManifestDescriptor *flatpak_oci_index_get_only_manifest (FlatpakOciIndex *self);
int flatpak_oci_index_get_n_manifests (FlatpakOciIndex *self);
#define FLATPAK_TYPE_OCI_IMAGE flatpak_oci_image_get_type ()
G_DECLARE_FINAL_TYPE (FlatpakOciImage, flatpak_oci_image, FLATPAK, OCI_IMAGE, FlatpakJson)
typedef struct
{
char *type;
char **diff_ids;
} FlatpakOciImageRootfs;
typedef struct
{
char *user;
char *working_dir;
gint64 memory;
gint64 memory_swap;
gint64 cpu_shares;
char **env;
char **cmd;
char **entrypoint;
char **exposed_ports;
char **volumes;
GHashTable *labels;
} FlatpakOciImageConfig;
typedef struct
{
char *created;
char *created_by;
char *author;
char *comment;
gboolean empty_layer;
} FlatpakOciImageHistory;
struct _FlatpakOciImage
{
FlatpakJson parent;
char *created;
char *author;
char *architecture;
char *os;
FlatpakOciImageRootfs rootfs;
FlatpakOciImageConfig config;
FlatpakOciImageHistory **history;
};
struct _FlatpakOciImageClass
{
FlatpakJsonClass parent_class;
};
FlatpakOciImage *flatpak_oci_image_new (void);
void flatpak_oci_image_set_created (FlatpakOciImage *image,
const char *created);
void flatpak_oci_image_set_architecture (FlatpakOciImage *image,
const char *arch);
void flatpak_oci_image_set_os (FlatpakOciImage *image,
const char *os);
void flatpak_oci_image_set_layers (FlatpakOciImage *image,
const char **layers);
void flatpak_oci_image_set_layer (FlatpakOciImage *image,
const char *layer);
void flatpak_oci_add_annotations_for_commit (GHashTable *annotations,
const char *ref,
const char *commit,
GVariant *commit_data);
void flatpak_oci_parse_commit_annotations (GHashTable *annotations,
guint64 *out_timestamp,
char **out_subject,
char **out_body,
char **out_ref,
char **out_commit,
char **out_parent_commit,
GVariantBuilder *metadata_builder);
#define FLATPAK_TYPE_OCI_SIGNATURE flatpak_oci_signature_get_type ()
G_DECLARE_FINAL_TYPE (FlatpakOciSignature, flatpak_oci_signature, FLATPAK, OCI_SIGNATURE, FlatpakJson)
typedef struct
{
char *digest;
} FlatpakOciSignatureCriticalImage;
typedef struct
{
char *ref;
} FlatpakOciSignatureCriticalIdentity;
typedef struct
{
char *type;
FlatpakOciSignatureCriticalImage image;
FlatpakOciSignatureCriticalIdentity identity;
} FlatpakOciSignatureCritical;
typedef struct
{
char *creator;
gint64 timestamp;
} FlatpakOciSignatureOptional;
struct _FlatpakOciSignature
{
FlatpakJson parent;
FlatpakOciSignatureCritical critical;
FlatpakOciSignatureOptional optional;
};
struct _FlatpakOciSignatureClass
{
FlatpakJsonClass parent_class;
};
FlatpakOciSignature *flatpak_oci_signature_new (const char *digest, const char *ref);
#endif /* __FLATPAK_JSON_OCI_H__ */

View File

@ -1,634 +0,0 @@
/*
* 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 "flatpak-json.h"
#include "flatpak-utils.h"
#include "libglnx.h"
G_DEFINE_TYPE (FlatpakJson, flatpak_json, G_TYPE_OBJECT);
static void
flatpak_json_finalize (GObject *object)
{
G_OBJECT_CLASS (flatpak_json_parent_class)->finalize (object);
}
static void
flatpak_json_class_init (FlatpakJsonClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = flatpak_json_finalize;
}
static void
flatpak_json_init (FlatpakJson *self)
{
}
static gboolean
demarshal (JsonNode *parent_node,
const char *name,
gpointer dest,
FlatpakJsonPropType type,
gpointer type_data,
gpointer type_data2,
FlatpakJsonPropFlags flags,
GError **error)
{
JsonObject *parent_object;
JsonNode *node;
if (type != FLATPAK_JSON_PROP_TYPE_PARENT)
{
parent_object = json_node_get_object (parent_node);
node = json_object_get_member (parent_object, name);
if (node == NULL && (flags & FLATPAK_JSON_PROP_FLAGS_MANDATORY) != 0)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"No value for mandatory property %s", name);
return FALSE;
}
}
else
node = parent_node;
if (node == NULL || JSON_NODE_TYPE (node) == JSON_NODE_NULL)
return TRUE;
switch (type)
{
case FLATPAK_JSON_PROP_TYPE_STRING:
if (!JSON_NODE_HOLDS_VALUE (node) ||
json_node_get_value_type (node) != G_TYPE_STRING)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Expecting string for property %s", name);
return FALSE;
}
*(char **)dest = g_strdup (json_node_get_string (node));
break;
case FLATPAK_JSON_PROP_TYPE_INT64:
if (!JSON_NODE_HOLDS_VALUE (node) ||
json_node_get_value_type (node) != G_TYPE_INT64)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Expecting int64 for property %s", name);
return FALSE;
}
*(gint64 *)dest = json_node_get_int (node);
break;
case FLATPAK_JSON_PROP_TYPE_BOOL:
if (!JSON_NODE_HOLDS_VALUE (node) ||
json_node_get_value_type (node) != G_TYPE_BOOLEAN)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Expecting bool for property %s", name);
return FALSE;
}
*(gboolean *)dest = json_node_get_boolean (node);
break;
case FLATPAK_JSON_PROP_TYPE_STRV:
if (!JSON_NODE_HOLDS_ARRAY (node))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Expecting array for property %s", name);
return FALSE;
}
{
JsonArray *array = json_node_get_array (node);
guint i, array_len = json_array_get_length (array);
g_autoptr(GPtrArray) str_array = g_ptr_array_sized_new (array_len + 1);
for (i = 0; i < array_len; i++)
{
JsonNode *val = json_array_get_element (array, i);
if (JSON_NODE_TYPE (val) != JSON_NODE_VALUE)
continue;
if (json_node_get_string (val) != NULL)
g_ptr_array_add (str_array, (gpointer) g_strdup (json_node_get_string (val)));
}
g_ptr_array_add (str_array, NULL);
*(char ***)dest = (char **)g_ptr_array_free (g_steal_pointer (&str_array), FALSE);
}
break;
case FLATPAK_JSON_PROP_TYPE_PARENT:
case FLATPAK_JSON_PROP_TYPE_STRUCT:
if (!JSON_NODE_HOLDS_OBJECT (node))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Expecting object for property %s", name);
return FALSE;
}
{
FlatpakJsonProp *struct_props = type_data;
int i;
if ((struct_props->flags & FLATPAK_JSON_PROP_FLAGS_STRICT) != 0)
{
JsonObject *object = json_node_get_object (node);
g_autoptr(GList) members = json_object_get_members (object);
GList *l;
/* Verify that all members are known properties if strict flag is set */
for (l = members; l != NULL; l = l->next)
{
const char *name = l->data;
for (i = 0; struct_props[i].name != NULL; i++)
{
if (strcmp (struct_props[i].name, name) == 0)
break;
}
if (struct_props[i].name == NULL)
return flatpak_fail (error, "Unknown property named %s", name);
}
}
for (i = 0; struct_props[i].name != NULL; i++)
{
if (!demarshal (node, struct_props[i].name,
G_STRUCT_MEMBER_P (dest, struct_props[i].offset),
struct_props[i].type, struct_props[i].type_data, struct_props[i].type_data2,
struct_props[i].flags, error))
return FALSE;
}
}
break;
case FLATPAK_JSON_PROP_TYPE_STRUCTV:
if (!JSON_NODE_HOLDS_ARRAY (node))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Expecting array for property %s", name);
return FALSE;
}
{
JsonArray *array = json_node_get_array (node);
guint array_len = json_array_get_length (array);
FlatpakJsonProp *struct_props = type_data;
g_autoptr(GPtrArray) obj_array = g_ptr_array_sized_new (array_len + 1);
int i, j;
gboolean res = TRUE;
for (j = 0; res && j < array_len; j++)
{
JsonNode *val = json_array_get_element (array, j);
gpointer new_element;
if (!JSON_NODE_HOLDS_OBJECT (val))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Expecting object elemen for property %s", name);
res = FALSE;
break;
}
new_element = g_malloc0 ((gsize)type_data2);
g_ptr_array_add (obj_array, new_element);
for (i = 0; struct_props[i].name != NULL; i++)
{
if (!demarshal (val, struct_props[i].name,
G_STRUCT_MEMBER_P (new_element, struct_props[i].offset),
struct_props[i].type, struct_props[i].type_data, struct_props[i].type_data2,
struct_props[i].flags, error))
{
res = FALSE;
break;
}
}
}
/* NULL terminate */
g_ptr_array_add (obj_array, NULL);
/* We always set the array, even if it is partial, because we don't know how
to free what we demarshalled so far */
*(gpointer *)dest = (gpointer *)g_ptr_array_free (g_steal_pointer (&obj_array), FALSE);
return res;
}
break;
case FLATPAK_JSON_PROP_TYPE_STRMAP:
if (!JSON_NODE_HOLDS_OBJECT (node))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Expecting object for property %s", name);
return FALSE;
}
{
g_autoptr(GHashTable) h = NULL;
JsonObject *object = json_node_get_object (node);
g_autoptr(GList) members = NULL;
GList *l;
h = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
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)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Wrong type for string member %s", member_name);
return FALSE;
}
g_hash_table_insert (h, g_strdup (member_name), g_strdup (val_str));
}
*(GHashTable **)dest = g_steal_pointer (&h);
}
break;
case FLATPAK_JSON_PROP_TYPE_BOOLMAP:
if (!JSON_NODE_HOLDS_OBJECT (node))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Expecting object for property %s", name);
return FALSE;
}
{
JsonObject *object = json_node_get_object (node);
g_autoptr(GPtrArray) res = 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;
g_ptr_array_add (res, g_strdup (member_name));
}
g_ptr_array_add (res, NULL);
*(char ***)dest = (char **)g_ptr_array_free (g_steal_pointer (&res), FALSE);
}
break;
default:
g_assert_not_reached ();
}
return TRUE;
}
FlatpakJson *
flatpak_json_from_node (JsonNode *node, GType type, GError **error)
{
g_autoptr(FlatpakJson) json = NULL;
FlatpakJsonProp *props = NULL;
gpointer class;
int i;
/* We should handle these before we get here */
g_assert (node != NULL);
g_assert (JSON_NODE_TYPE (node) != JSON_NODE_NULL);
if (JSON_NODE_TYPE (node) != JSON_NODE_OBJECT)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Expecting a JSON object, but the node is of type `%s'",
json_node_type_name (node));
return NULL;
}
json = g_object_new (type, NULL);
class = FLATPAK_JSON_GET_CLASS (json);
while (FLATPAK_JSON_CLASS (class)->props != NULL)
{
props = FLATPAK_JSON_CLASS (class)->props;
for (i = 0; props[i].name != NULL; i++)
{
if (!demarshal (node, props[i].name,
G_STRUCT_MEMBER_P (json, props[i].offset),
props[i].type, props[i].type_data, props[i].type_data2,
props[i].flags, error))
return NULL;
}
class = g_type_class_peek_parent (class);
}
return g_steal_pointer (&json);
}
FlatpakJson *
flatpak_json_from_bytes (GBytes *bytes,
GType type,
GError **error)
{
g_autoptr(JsonParser) parser = NULL;
JsonNode *root = NULL;
parser = json_parser_new ();
if (!json_parser_load_from_data (parser,
g_bytes_get_data (bytes, NULL),
g_bytes_get_size (bytes),
error))
return NULL;
root = json_parser_get_root (parser);
return flatpak_json_from_node (root, type, error);
}
static JsonNode *
marshal (JsonObject *parent,
const char *name,
gpointer src,
FlatpakJsonPropType type,
gpointer type_data,
FlatpakJsonPropFlags flags)
{
JsonNode *retval = NULL;
switch (type)
{
case FLATPAK_JSON_PROP_TYPE_STRING:
{
const char *str = *(const char **)src;
if (str != NULL)
retval = json_node_init_string (json_node_alloc (), str);
break;
}
case FLATPAK_JSON_PROP_TYPE_INT64:
{
retval = json_node_init_int (json_node_alloc (), *(gint64 *)src);
break;
}
case FLATPAK_JSON_PROP_TYPE_BOOL:
{
gboolean val = *(gboolean *)src;
if (val)
retval = json_node_init_boolean (json_node_alloc (), val);
break;
}
case FLATPAK_JSON_PROP_TYPE_STRV:
{
char **strv = *(char ***)src;
int i;
JsonArray *array;
if (strv != NULL && strv[0] != NULL)
{
array = json_array_sized_new (g_strv_length (strv));
for (i = 0; strv[i] != NULL; i++)
{
JsonNode *str = json_node_new (JSON_NODE_VALUE);
json_node_set_string (str, strv[i]);
json_array_add_element (array, str);
}
retval = json_node_init_array (json_node_alloc (), array);
json_array_unref (array);
}
break;
}
case FLATPAK_JSON_PROP_TYPE_PARENT:
case FLATPAK_JSON_PROP_TYPE_STRUCT:
{
FlatpakJsonProp *struct_props = type_data;
JsonObject *obj;
int i;
gboolean empty = TRUE;
if (type == FLATPAK_JSON_PROP_TYPE_PARENT)
obj = parent;
else
obj = json_object_new ();
for (i = 0; struct_props[i].name != NULL; i++)
{
JsonNode *val = marshal (obj, struct_props[i].name,
G_STRUCT_MEMBER_P (src, struct_props[i].offset),
struct_props[i].type, struct_props[i].type_data, struct_props[i].flags);
if (val == NULL)
continue;
empty = FALSE;
json_object_set_member (obj, struct_props[i].name, val);
}
if (type != FLATPAK_JSON_PROP_TYPE_PARENT &&
(!empty || (flags & FLATPAK_JSON_PROP_FLAGS_OPTIONAL) == 0))
{
retval = json_node_new (JSON_NODE_OBJECT);
json_node_take_object (retval, obj);
}
break;
}
case FLATPAK_JSON_PROP_TYPE_STRUCTV:
{
FlatpakJsonProp *struct_props = type_data;
gpointer *structv = *(gpointer **)src;
int i, j;
JsonArray *array;
if (structv != NULL && structv[0] != NULL)
{
array = json_array_new ();
for (j = 0; structv[j] != NULL; j++)
{
JsonObject *obj = json_object_new ();
JsonNode *node;
for (i = 0; struct_props[i].name != NULL; i++)
{
JsonNode *val = marshal (obj, struct_props[i].name,
G_STRUCT_MEMBER_P (structv[j], struct_props[i].offset),
struct_props[i].type, struct_props[i].type_data, struct_props[i].flags);
if (val == NULL)
continue;
json_object_set_member (obj, struct_props[i].name, val);
}
node = json_node_new (JSON_NODE_OBJECT);
json_node_take_object (node, obj);
json_array_add_element (array, node);
}
retval = json_node_init_array (json_node_alloc (), array);
json_array_unref (array);
}
break;
}
case FLATPAK_JSON_PROP_TYPE_STRMAP:
{
GHashTable *map = *(GHashTable **)src;
if (map != NULL && g_hash_table_size (map) > 0)
{
GHashTableIter iter;
gpointer _key, _value;
JsonObject *object;
object = json_object_new ();
g_hash_table_iter_init (&iter, map);
while (g_hash_table_iter_next (&iter, &_key, &_value))
{
const char *key = _key;
const char *value = _value;
JsonNode *str = json_node_new (JSON_NODE_VALUE);
json_node_set_string (str, value);
json_object_set_member (object, key, str);
}
retval = json_node_init_object (json_node_alloc (), object);
json_object_unref (object);
}
break;
}
case FLATPAK_JSON_PROP_TYPE_BOOLMAP:
{
char **map = *(char ***)src;
if (map != NULL && map[0] != NULL)
{
JsonObject *object;
int i;
object = json_object_new ();
for (i = 0; map[i] != NULL; i++)
{
const char *element = map[i];
JsonObject *empty_o = json_object_new ();
JsonNode *empty = json_node_init_object (json_node_alloc (), empty_o);
json_object_unref (empty_o);
json_object_set_member (object, element, empty);
}
retval = json_node_init_object (json_node_alloc (), object);
json_object_unref (object);
}
break;
}
default:
g_assert_not_reached ();
}
return retval;
}
static void
marshal_props_for_class (FlatpakJson *self,
FlatpakJsonClass *class,
JsonObject *obj)
{
FlatpakJsonProp *props = NULL;
int i;
gpointer parent_class;
parent_class = g_type_class_peek_parent (class);
if (FLATPAK_JSON_CLASS (parent_class)->props != NULL)
marshal_props_for_class (self,
FLATPAK_JSON_CLASS(parent_class),
obj);
props = FLATPAK_JSON_CLASS (class)->props;
for (i = 0; props[i].name != NULL; i++)
{
JsonNode *val = marshal (obj, props[i].name,
G_STRUCT_MEMBER_P (self, props[i].offset),
props[i].type, props[i].type_data, props[i].flags);
if (val == NULL)
continue;
json_object_set_member (obj, props[i].name, val);
}
}
JsonNode *
flatpak_json_to_node (FlatpakJson *self)
{
JsonNode *retval;
JsonObject *obj;
gpointer class;
if (self == NULL)
return json_node_new (JSON_NODE_NULL);
obj = json_object_new ();
class = FLATPAK_JSON_GET_CLASS (self);
marshal_props_for_class (self, FLATPAK_JSON_CLASS (class), obj);
retval = json_node_new (JSON_NODE_OBJECT);
json_node_take_object (retval, obj);
return retval;
}
GBytes *
flatpak_json_to_bytes (FlatpakJson *self)
{
g_autoptr(JsonNode) node = NULL;
g_autoptr(JsonGenerator) generator = NULL;
char *str;
node = flatpak_json_to_node (FLATPAK_JSON (self));
generator = json_generator_new ();
json_generator_set_pretty (generator, TRUE);
json_generator_set_root (generator, node);
str = json_generator_to_data (generator, NULL);
return g_bytes_new_take (str, strlen (str));
}

View File

@ -1,109 +0,0 @@
/*
* Copyright © 2016 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 __FLATPAK_JSON_H__
#define __FLATPAK_JSON_H__
#include <json-glib/json-glib.h>
G_BEGIN_DECLS
#define FLATPAK_TYPE_JSON flatpak_json_get_type ()
typedef struct _FlatpakJsonProp FlatpakJsonProp;
typedef enum {
FLATPAK_JSON_PROP_TYPE_PARENT,
FLATPAK_JSON_PROP_TYPE_INT64,
FLATPAK_JSON_PROP_TYPE_BOOL,
FLATPAK_JSON_PROP_TYPE_STRING,
FLATPAK_JSON_PROP_TYPE_STRUCT,
FLATPAK_JSON_PROP_TYPE_STRUCTV,
FLATPAK_JSON_PROP_TYPE_STRV,
FLATPAK_JSON_PROP_TYPE_STRMAP,
FLATPAK_JSON_PROP_TYPE_BOOLMAP,
} FlatpakJsonPropType;
typedef enum {
FLATPAK_JSON_PROP_FLAGS_NONE = 0,
FLATPAK_JSON_PROP_FLAGS_OPTIONAL = 1<<0,
FLATPAK_JSON_PROP_FLAGS_STRICT = 1<<1,
FLATPAK_JSON_PROP_FLAGS_MANDATORY = 1<<2,
} FlatpakJsonPropFlags;
struct _FlatpakJsonProp {
const char *name;
gsize offset;
FlatpakJsonPropType type;
gpointer type_data;
gpointer type_data2;
FlatpakJsonPropFlags flags;
} ;
#define FLATPAK_JSON_STRING_PROP(_struct, _field, _name) \
{ _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRING }
#define FLATPAK_JSON_MANDATORY_STRING_PROP(_struct, _field, _name) \
{ _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRING, 0, 0, FLATPAK_JSON_PROP_FLAGS_MANDATORY }
#define FLATPAK_JSON_INT64_PROP(_struct, _field, _name) \
{ _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_INT64 }
#define FLATPAK_JSON_BOOL_PROP(_struct, _field, _name) \
{ _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_BOOL }
#define FLATPAK_JSON_STRV_PROP(_struct, _field, _name) \
{ _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRV }
#define FLATPAK_JSON_STRMAP_PROP(_struct, _field, _name) \
{ _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRMAP }
#define FLATPAK_JSON_BOOLMAP_PROP(_struct, _field, _name) \
{ _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_BOOLMAP }
#define FLATPAK_JSON_STRUCT_PROP(_struct, _field, _name, _props) \
{ _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRUCT, (gpointer)_props}
#define FLATPAK_JSON_OPT_STRUCT_PROP(_struct, _field, _name, _props) \
{ _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRUCT, (gpointer)_props, 0, FLATPAK_JSON_PROP_FLAGS_OPTIONAL}
#define FLATPAK_JSON_STRICT_STRUCT_PROP(_struct, _field, _name, _props) \
{ _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRUCT, (gpointer)_props, 0, FLATPAK_JSON_PROP_FLAGS_STRICT}
#define FLATPAK_JSON_MANDATORY_STRICT_STRUCT_PROP(_struct, _field, _name, _props) \
{ _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRUCT, (gpointer)_props, 0, FLATPAK_JSON_PROP_FLAGS_STRICT | FLATPAK_JSON_PROP_FLAGS_MANDATORY}
#define FLATPAK_JSON_PARENT_PROP(_struct, _field, _props) \
{ "parent", G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_PARENT, (gpointer)_props}
#define FLATPAK_JSON_STRUCTV_PROP(_struct, _field, _name, _props) \
{ _name, G_STRUCT_OFFSET (_struct, _field), FLATPAK_JSON_PROP_TYPE_STRUCTV, (gpointer)_props, (gpointer) sizeof (**((_struct *) 0)->_field) }
#define FLATPAK_JSON_LAST_PROP { NULL }
G_DECLARE_DERIVABLE_TYPE (FlatpakJson, flatpak_json, FLATPAK, JSON, GObject)
struct _FlatpakJsonClass {
GObjectClass parent_class;
FlatpakJsonProp *props;
const char *mediatype;
};
FlatpakJson *flatpak_json_from_node (JsonNode *node,
GType type,
GError **error);
JsonNode *flatpak_json_to_node (FlatpakJson *self);
FlatpakJson *flatpak_json_from_bytes (GBytes *bytes,
GType type,
GError **error);
GBytes *flatpak_json_to_bytes (FlatpakJson *self);
G_END_DECLS
#endif /* __FLATPAK_JSON_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -1,129 +0,0 @@
/*
* Copyright © 2016 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 __FLATPAK_OCI_REGISTRY_H__
#define __FLATPAK_OCI_REGISTRY_H__
#include "libglnx/libglnx.h"
#include <glib.h>
#include <gio/gio.h>
#include <archive.h>
#include "flatpak-json-oci.h"
#include "flatpak-utils.h"
#define FLATPAK_TYPE_OCI_REGISTRY flatpak_oci_registry_get_type ()
#define FLATPAK_OCI_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_OCI_REGISTRY, FlatpakOciRegistry))
#define FLATPAK_IS_OCI_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_OCI_REGISTRY))
GType flatpak_oci_registry_get_type (void);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakOciRegistry, g_object_unref)
#define FLATPAK_TYPE_OCI_LAYER_WRITER flatpak_oci_layer_writer_get_type ()
#define FLATPAK_OCI_LAYER_WRITER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_OCI_LAYER_WRITER, FlatpakOciLayerWriter))
#define FLATPAK_IS_OCI_LAYER_WRITER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_OCI_LAYER_WRITER))
GType flatpak_oci_layer_writer_get_type (void);
typedef enum {
FLATPAK_OCI_ERROR_NOT_CHANGED = 0,
} FlatpakOciErrorEnum;
#define FLATPAK_OCI_ERROR flatpak_oci_error_quark ()
FLATPAK_EXTERN GQuark flatpak_oci_error_quark (void);
typedef struct FlatpakOciLayerWriter FlatpakOciLayerWriter;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakOciLayerWriter, g_object_unref)
FlatpakOciRegistry * flatpak_oci_registry_new (const char *uri,
gboolean for_write,
int tmp_dfd,
GCancellable *cancellable,
GError **error);
const char * flatpak_oci_registry_get_uri (FlatpakOciRegistry *self);
FlatpakOciIndex * flatpak_oci_registry_load_index (FlatpakOciRegistry *self,
const char *etag,
char **etag_out,
GCancellable *cancellable,
GError **error);
gboolean flatpak_oci_registry_save_index (FlatpakOciRegistry *self,
FlatpakOciIndex *index,
GCancellable *cancellable,
GError **error);
int flatpak_oci_registry_download_blob (FlatpakOciRegistry *self,
const char *digest,
FlatpakLoadUriProgress progress_cb,
gpointer user_data,
GCancellable *cancellable,
GError **error);
GBytes * flatpak_oci_registry_load_blob (FlatpakOciRegistry *self,
const char *digest,
GCancellable *cancellable,
GError **error);
char * flatpak_oci_registry_store_blob (FlatpakOciRegistry *self,
GBytes *data,
GCancellable *cancellable,
GError **error);
gboolean flatpak_oci_registry_mirror_blob (FlatpakOciRegistry *self,
FlatpakOciRegistry *source_registry,
const char *digest,
FlatpakLoadUriProgress progress_cb,
gpointer user_data,
GCancellable *cancellable,
GError **error);
FlatpakOciDescriptor * flatpak_oci_registry_store_json (FlatpakOciRegistry *self,
FlatpakJson *json,
GCancellable *cancellable,
GError **error);
FlatpakOciVersioned * flatpak_oci_registry_load_versioned (FlatpakOciRegistry *self,
const char *digest,
gsize *out_size,
GCancellable *cancellable,
GError **error);
FlatpakOciLayerWriter *flatpak_oci_registry_write_layer (FlatpakOciRegistry *self,
GCancellable *cancellable,
GError **error);
struct archive *flatpak_oci_layer_writer_get_archive (FlatpakOciLayerWriter *self);
gboolean flatpak_oci_layer_writer_close (FlatpakOciLayerWriter *self,
char **uncompressed_digest_out,
FlatpakOciDescriptor **res_out,
GCancellable *cancellable,
GError **error);
gboolean flatpak_archive_read_open_fd_with_checksum (struct archive *a,
int fd,
GChecksum *checksum,
GError **error);
GBytes *flatpak_oci_sign_data (GBytes *data,
const gchar **okey_ids,
const char *homedir,
GError **error);
FlatpakOciSignature *flatpak_oci_verify_signature (OstreeRepo *repo,
const char *remote_name,
GBytes *signature,
GError **error);
#endif /* __FLATPAK_OCI_REGISTRY_H__ */

View File

@ -1,48 +0,0 @@
/* flatpak-error.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 "flatpak-portal-error.h"
#include <gio/gio.h>
static const GDBusErrorEntry flatpak_error_entries[] = {
{FLATPAK_PORTAL_ERROR_FAILED, "org.freedesktop.portal.Error.Failed"},
{FLATPAK_PORTAL_ERROR_INVALID_ARGUMENT, "org.freedesktop.portal.Error.InvalidArgument"},
{FLATPAK_PORTAL_ERROR_NOT_FOUND, "org.freedesktop.portal.Error.NotFound"},
{FLATPAK_PORTAL_ERROR_EXISTS, "org.freedesktop.portal.Error.Exists"},
{FLATPAK_PORTAL_ERROR_NOT_ALLOWED, "org.freedesktop.portal.Error.NotAllowed"},
{FLATPAK_PORTAL_ERROR_CANCELLED, "org.freedesktop.portal.Error.Cancelled"},
{FLATPAK_PORTAL_ERROR_WINDOW_DESTROYED, "org.freedesktop.portal.Error.WindowDestroyed"},
};
GQuark
flatpak_portal_error_quark (void)
{
static volatile gsize quark_volatile = 0;
g_dbus_error_register_error_domain ("flatpak-portal-error-quark",
&quark_volatile,
flatpak_error_entries,
G_N_ELEMENTS (flatpak_error_entries));
return (GQuark) quark_volatile;
}

View File

@ -1,49 +0,0 @@
/* flatpak-portal-error.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>
*/
#ifndef FLATPAK_PORTAL_ERROR_H
#define FLATPAK_PORTAL_ERROR_H
#include <glib.h>
G_BEGIN_DECLS
/**
* XdpErrorEnum:
*/
typedef enum {
FLATPAK_PORTAL_ERROR_FAILED = 0,
FLATPAK_PORTAL_ERROR_INVALID_ARGUMENT,
FLATPAK_PORTAL_ERROR_NOT_FOUND,
FLATPAK_PORTAL_ERROR_EXISTS,
FLATPAK_PORTAL_ERROR_NOT_ALLOWED,
FLATPAK_PORTAL_ERROR_CANCELLED,
FLATPAK_PORTAL_ERROR_WINDOW_DESTROYED,
} FlatpakErrorEnum;
#define FLATPAK_PORTAL_ERROR flatpak_portal_error_quark ()
FLATPAK_EXTERN GQuark flatpak_portal_error_quark (void);
G_END_DECLS
#endif /* FLATPAK_PORTAL_ERROR_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,217 +0,0 @@
/*
* Copyright © 2014 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 __FLATPAK_RUN_H__
#define __FLATPAK_RUN_H__
#include "libglnx/libglnx.h"
#include "dbus-proxy/flatpak-proxy.h"
#include "flatpak-common-types.h"
#include "flatpak-utils.h"
gboolean flatpak_run_in_transient_unit (const char *app_id,
GError **error);
/* See flatpak-metadata(5) */
#define FLATPAK_METADATA_GROUP_APPLICATION "Application"
#define FLATPAK_METADATA_GROUP_RUNTIME "Runtime"
#define FLATPAK_METADATA_KEY_COMMAND "command"
#define FLATPAK_METADATA_KEY_NAME "name"
#define FLATPAK_METADATA_KEY_REQUIRED_FLATPAK "required-flatpak"
#define FLATPAK_METADATA_KEY_RUNTIME "runtime"
#define FLATPAK_METADATA_KEY_SDK "sdk"
#define FLATPAK_METADATA_KEY_TAGS "tags"
#define FLATPAK_METADATA_GROUP_CONTEXT "Context"
#define FLATPAK_METADATA_KEY_SHARED "shared"
#define FLATPAK_METADATA_KEY_SOCKETS "sockets"
#define FLATPAK_METADATA_KEY_FILESYSTEMS "filesystems"
#define FLATPAK_METADATA_KEY_PERSISTENT "persistent"
#define FLATPAK_METADATA_KEY_DEVICES "devices"
#define FLATPAK_METADATA_KEY_FEATURES "features"
#define FLATPAK_METADATA_GROUP_INSTANCE "Instance"
#define FLATPAK_METADATA_KEY_APP_PATH "app-path"
#define FLATPAK_METADATA_KEY_BRANCH "branch"
#define FLATPAK_METADATA_KEY_FLATPAK_VERSION "flatpak-version"
#define FLATPAK_METADATA_KEY_RUNTIME_PATH "runtime-path"
#define FLATPAK_METADATA_KEY_SESSION_BUS_PROXY "session-bus-proxy"
#define FLATPAK_METADATA_KEY_SYSTEM_BUS_PROXY "system-bus-proxy"
#define FLATPAK_METADATA_GROUP_SESSION_BUS_POLICY "Session Bus Policy"
#define FLATPAK_METADATA_GROUP_SYSTEM_BUS_POLICY "System Bus Policy"
#define FLATPAK_METADATA_GROUP_PREFIX_POLICY "Policy "
#define FLATPAK_METADATA_GROUP_ENVIRONMENT "Environment"
#define FLATPAK_METADATA_GROUP_PREFIX_EXTENSION "Extension "
#define FLATPAK_METADATA_KEY_ADD_LD_PATH "add-ld-path"
#define FLATPAK_METADATA_KEY_AUTODELETE "autodelete"
#define FLATPAK_METADATA_KEY_DIRECTORY "directory"
#define FLATPAK_METADATA_KEY_DOWNLOAD_IF "download-if"
#define FLATPAK_METADATA_KEY_ENABLE_IF "enable-if"
#define FLATPAK_METADATA_KEY_MERGE_DIRS "merge-dirs"
#define FLATPAK_METADATA_KEY_NO_AUTODOWNLOAD "no-autodownload"
#define FLATPAK_METADATA_KEY_SUBDIRECTORIES "subdirectories"
#define FLATPAK_METADATA_KEY_SUBDIRECTORY_SUFFIX "subdirectory-suffix"
#define FLATPAK_METADATA_KEY_VERSION "version"
#define FLATPAK_METADATA_KEY_VERSIONS "versions"
#ifdef FLATPAK_ENABLE_P2P
#define FLATPAK_METADATA_KEY_COLLECTION_ID "collection-id"
#endif /* FLATPAK_ENABLE_P2P */
#define FLATPAK_METADATA_GROUP_EXTRA_DATA "Extra Data"
#define FLATPAK_METADATA_KEY_EXTRA_DATA_CHECKSUM "checksum"
#define FLATPAK_METADATA_KEY_EXTRA_DATA_INSTALLED_SIZE "installed-size"
#define FLATPAK_METADATA_KEY_EXTRA_DATA_NAME "name"
#define FLATPAK_METADATA_KEY_EXTRA_DATA_SIZE "size"
#define FLATPAK_METADATA_KEY_EXTRA_DATA_URI "uri"
#define FLATPAK_METADATA_KEY_NO_RUNTIME "NoRuntime"
#define FLATPAK_METADATA_GROUP_EXTENSION_OF "ExtensionOf"
#define FLATPAK_METADATA_KEY_PRIORITY "priority"
#define FLATPAK_METADATA_KEY_REF "ref"
extern const char *flatpak_context_sockets[];
extern const char *flatpak_context_devices[];
extern const char *flatpak_context_features[];
extern const char *flatpak_context_shares[];
FlatpakContext *flatpak_context_new (void);
void flatpak_context_free (FlatpakContext *context);
void flatpak_context_merge (FlatpakContext *context,
FlatpakContext *other);
GOptionGroup *flatpak_context_get_options (FlatpakContext *context);
void flatpak_context_complete (FlatpakContext *context,
FlatpakCompletion *completion);
gboolean flatpak_context_load_metadata (FlatpakContext *context,
GKeyFile *metakey,
GError **error);
void flatpak_context_save_metadata (FlatpakContext *context,
gboolean flatten,
GKeyFile *metakey);
void flatpak_context_allow_host_fs (FlatpakContext *context);
void flatpak_context_set_session_bus_policy (FlatpakContext *context,
const char *name,
FlatpakPolicy policy);
void flatpak_context_set_system_bus_policy (FlatpakContext *context,
const char *name,
FlatpakPolicy policy);
void flatpak_context_to_args (FlatpakContext *context,
GPtrArray *args);
gboolean flatpak_context_get_needs_session_bus_proxy (FlatpakContext *context);
gboolean flatpak_context_get_needs_system_bus_proxy (FlatpakContext *context);
FlatpakContext *flatpak_context_load_for_app (const char *app_id,
GError **error);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakContext, flatpak_context_free)
typedef enum {
FLATPAK_RUN_FLAG_DEVEL = (1 << 0),
FLATPAK_RUN_FLAG_BACKGROUND = (1 << 1),
FLATPAK_RUN_FLAG_LOG_SESSION_BUS = (1 << 2),
FLATPAK_RUN_FLAG_LOG_SYSTEM_BUS = (1 << 3),
FLATPAK_RUN_FLAG_NO_SESSION_HELPER = (1 << 4),
FLATPAK_RUN_FLAG_MULTIARCH = (1 << 5),
FLATPAK_RUN_FLAG_WRITABLE_ETC = (1 << 6),
FLATPAK_RUN_FLAG_NO_SESSION_BUS_PROXY = (1 << 7),
FLATPAK_RUN_FLAG_NO_SYSTEM_BUS_PROXY = (1 << 8),
FLATPAK_RUN_FLAG_SET_PERSONALITY = (1 << 9),
FLATPAK_RUN_FLAG_FILE_FORWARDING = (1 << 10),
FLATPAK_RUN_FLAG_DIE_WITH_PARENT = (1 << 11),
} FlatpakRunFlags;
typedef struct _FlatpakExports FlatpakExports;
void flatpak_exports_free (FlatpakExports *exports);
gboolean flatpak_exports_path_is_visible (FlatpakExports *exports,
const char *path);
FlatpakExports *flatpak_exports_from_context (FlatpakContext *context,
const char *app_id);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakExports, flatpak_exports_free);
gboolean flatpak_run_add_extension_args (GPtrArray *argv_array,
char ***envp_p,
GKeyFile *metakey,
const char *full_ref,
GCancellable *cancellable,
GError **error);
gboolean flatpak_run_add_environment_args (GPtrArray *argv_array,
GArray *fd_array,
char ***envp_p,
const char *app_info_path,
FlatpakRunFlags flags,
const char *app_id,
FlatpakContext *context,
GFile *app_id_dir,
FlatpakExports **exports_out,
GCancellable *cancellable,
GError **error);
char ** flatpak_run_get_minimal_env (gboolean devel);
char ** flatpak_run_apply_env_default (char **envp);
char ** flatpak_run_apply_env_appid (char **envp,
GFile *app_dir);
char ** flatpak_run_apply_env_vars (char **envp,
FlatpakContext *context);
FlatpakContext *flatpak_app_compute_permissions (GKeyFile *app_metadata,
GKeyFile *runtime_metadata,
GError **error);
GFile *flatpak_get_data_dir (const char *app_id);
GFile *flatpak_ensure_data_dir (const char *app_id,
GCancellable *cancellable,
GError **error);
gboolean flatpak_run_setup_base_argv (GPtrArray *argv_array,
GArray *fd_array,
GFile *runtime_files,
GFile *app_id_dir,
const char *arch,
FlatpakRunFlags flags,
GError **error);
gboolean flatpak_run_add_app_info_args (GPtrArray *argv_array,
GArray *fd_array,
GFile *app_files,
GFile *runtime_files,
const char *app_id,
const char *app_branch,
const char *runtime_ref,
FlatpakContext *final_app_context,
char **app_info_path_out,
GError **error);
gboolean flatpak_run_app (const char *app_ref,
FlatpakDeploy *app_deploy,
FlatpakContext *extra_context,
const char *custom_runtime,
const char *custom_runtime_version,
FlatpakRunFlags flags,
const char *custom_command,
char *args[],
int n_args,
GCancellable *cancellable,
GError **error);
#endif /* __FLATPAK_RUN_H__ */

View File

@ -1,236 +0,0 @@
/*
* Copyright © 2014 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 "flatpak-table-printer.h"
#include "flatpak-utils.h"
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <locale.h>
typedef struct {
char *text;
int align;
} Cell;
static void
free_cell (gpointer data)
{
Cell *cell = data;
g_free (cell->text);
g_free (cell);
}
struct FlatpakTablePrinter
{
GPtrArray *titles;
GPtrArray *rows;
GPtrArray *current;
int n_columns;
};
FlatpakTablePrinter *
flatpak_table_printer_new (void)
{
FlatpakTablePrinter *printer = g_new0 (FlatpakTablePrinter, 1);
printer->titles = g_ptr_array_new_with_free_func (g_free);
printer->rows = g_ptr_array_new_with_free_func ((GDestroyNotify) g_ptr_array_unref);
printer->current = g_ptr_array_new_with_free_func (free_cell);
return printer;
}
void
flatpak_table_printer_free (FlatpakTablePrinter *printer)
{
g_ptr_array_free (printer->titles, TRUE);
g_ptr_array_free (printer->rows, TRUE);
g_ptr_array_free (printer->current, TRUE);
g_free (printer);
}
void
flatpak_table_printer_set_column_title (FlatpakTablePrinter *printer,
int column,
const char *text)
{
g_ptr_array_insert (printer->titles, column, g_strdup (text));
}
void
flatpak_table_printer_add_aligned_column (FlatpakTablePrinter *printer,
const char *text,
int align)
{
Cell *cell = g_new (Cell, 1);
cell->text = text ? g_strdup (text) : g_strdup ("");
cell->align = align;
g_ptr_array_add (printer->current, cell);
}
static const char *
find_decimal_point (const char *text)
{
struct lconv *locale_data;
locale_data = localeconv ();
return strstr (text, locale_data->decimal_point);
}
void
flatpak_table_printer_add_decimal_column (FlatpakTablePrinter *printer,
const char *text)
{
const char *decimal;
int align = -1;
decimal = find_decimal_point (text);
if (decimal)
align = decimal - text;
flatpak_table_printer_add_aligned_column (printer, text, align);
}
void
flatpak_table_printer_add_column (FlatpakTablePrinter *printer,
const char *text)
{
flatpak_table_printer_add_aligned_column (printer, text, -1);
}
void
flatpak_table_printer_add_column_len (FlatpakTablePrinter *printer,
const char *text,
gsize len)
{
Cell *cell = g_new (Cell, 1);
cell->text = text ? g_strndup (text, len) : g_strdup ("");
cell->align = -1;
g_ptr_array_add (printer->current, cell);
}
void
flatpak_table_printer_append_with_comma (FlatpakTablePrinter *printer,
const char *text)
{
Cell *cell;
char *new;
g_assert (printer->current->len > 0);
cell = g_ptr_array_index (printer->current, printer->current->len - 1);
if (cell->text[0] != 0)
new = g_strconcat (cell->text, ",", text, NULL);
else
new = g_strdup (text);
g_free (cell->text);
cell->text = new;
}
void
flatpak_table_printer_finish_row (FlatpakTablePrinter *printer)
{
if (printer->current->len == 0)
return; /* Ignore empty rows */
printer->n_columns = MAX (printer->n_columns, printer->current->len);
g_ptr_array_add (printer->rows, printer->current);
printer->current = g_ptr_array_new_with_free_func (free_cell);
}
void
flatpak_table_printer_print (FlatpakTablePrinter *printer)
{
g_autofree int *widths = NULL;
g_autofree int *lwidths = NULL;
g_autofree int *rwidths = NULL;
int i, j;
if (printer->current->len != 0)
flatpak_table_printer_finish_row (printer);
widths = g_new0 (int, printer->n_columns);
lwidths = g_new0 (int, printer->n_columns);
rwidths = g_new0 (int, printer->n_columns);
for (i = 0; i < printer->titles->len && i < printer->n_columns; i++)
{
char *title = g_ptr_array_index (printer->titles, i);
if (title)
widths[i] = MAX (widths[i], strlen (title));
}
for (i = 0; i < printer->rows->len; i++)
{
GPtrArray *row = g_ptr_array_index (printer->rows, i);
for (j = 0; j < row->len; j++)
{
Cell *cell = g_ptr_array_index (row, j);
int width;
width = strlen (cell->text);
widths[j] = MAX (widths[j], width);
if (cell->align >= 0)
{
lwidths[j] = MAX (lwidths[j], cell->align);
rwidths[j] = MAX (rwidths[j], width - cell->align);
}
}
}
if (flatpak_fancy_output () && printer->titles->len > 0)
{
g_print (FLATPAK_ANSI_BOLD_ON);
for (i = 0; i < printer->titles->len && i < printer->n_columns; i++)
{
char *title = g_ptr_array_index (printer->titles, i);
g_print ("%s%-*s", (i == 0) ? "" : " ", widths[i], title);
}
g_print (FLATPAK_ANSI_BOLD_OFF);
g_print ("\n");
}
for (i = 0; i < printer->rows->len; i++)
{
GPtrArray *row = g_ptr_array_index (printer->rows, i);
for (j = 0; j < row->len; j++)
{
Cell *cell = g_ptr_array_index (row, j);
if (cell->align < 0)
g_print ("%s%-*s", (j == 0) ? "" : " ", widths[j], cell->text);
else
g_print ("%s%*s%-*s", (j == 0) ? "" : " ", lwidths[j] - cell->align, "", widths[j] - (lwidths[j] - cell->align), cell->text);
}
g_print ("\n");
}
}

View File

@ -1,48 +0,0 @@
/*
* Copyright © 2014 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 __FLATPAK_TABLE_PRINTER_H__
#define __FLATPAK_TABLE_PRINTER_H__
#include <gio/gio.h>
typedef struct FlatpakTablePrinter FlatpakTablePrinter;
FlatpakTablePrinter *flatpak_table_printer_new (void);
void flatpak_table_printer_free (FlatpakTablePrinter *printer);
void flatpak_table_printer_set_column_title (FlatpakTablePrinter *printer,
int column,
const char *title);
void flatpak_table_printer_add_column (FlatpakTablePrinter *printer,
const char *text);
void flatpak_table_printer_add_aligned_column (FlatpakTablePrinter *printer,
const char *text,
int align);
void flatpak_table_printer_add_decimal_column (FlatpakTablePrinter *printer,
const char *text);
void flatpak_table_printer_add_column_len (FlatpakTablePrinter *printer,
const char *text,
gsize len);
void flatpak_table_printer_append_with_comma (FlatpakTablePrinter *printer,
const char *text);
void flatpak_table_printer_finish_row (FlatpakTablePrinter *printer);
void flatpak_table_printer_print (FlatpakTablePrinter *printer);
#endif /* __FLATPAK_TABLE_PRINTER_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -24,14 +24,11 @@
#include <string.h>
#include "libglnx/libglnx.h"
#include <flatpak-common-types.h>
#include <gio/gio.h>
#include <gio/gunixfdlist.h>
#include <libsoup/soup.h>
#include "flatpak-dbus.h"
#include <ostree.h>
#include <json-glib/json-glib.h>
#include "document-portal/xdp-dbus.h"
typedef enum {
FLATPAK_HOST_COMMAND_FLAGS_CLEAR_ENV = 1 << 0,
@ -41,19 +38,27 @@ typedef void (*FlatpakLoadUriProgress) (guint64 downloaded_bytes,
gpointer user_data);
#define FLATPAK_ANSI_BOLD_ON "\x1b[1m"
#define FLATPAK_ANSI_BOLD_OFF "\x1b[22m"
#define FLATPAK_ANSI_RED "\x1b[31m"
#define FLATPAK_ANSI_COLOR_RESET "\x1b[0m"
#define FLATPAK_METADATA_GROUP_PREFIX_EXTENSION "Extension "
#define FLATPAK_METADATA_KEY_ADD_LD_PATH "add-ld-path"
#define FLATPAK_METADATA_KEY_AUTODELETE "autodelete"
#define FLATPAK_METADATA_KEY_DIRECTORY "directory"
#define FLATPAK_METADATA_KEY_DOWNLOAD_IF "download-if"
#define FLATPAK_METADATA_KEY_ENABLE_IF "enable-if"
#define FLATPAK_METADATA_KEY_MERGE_DIRS "merge-dirs"
#define FLATPAK_METADATA_KEY_NO_AUTODOWNLOAD "no-autodownload"
#define FLATPAK_METADATA_KEY_SUBDIRECTORIES "subdirectories"
#define FLATPAK_METADATA_KEY_SUBDIRECTORY_SUFFIX "subdirectory-suffix"
#define FLATPAK_METADATA_KEY_VERSION "version"
#define FLATPAK_METADATA_KEY_VERSIONS "versions"
/* https://bugzilla.gnome.org/show_bug.cgi?id=766370 */
#if !GLIB_CHECK_VERSION(2, 49, 3)
#define FLATPAK_VARIANT_BUILDER_INITIALIZER {{0,}}
#define FLATPAK_VARIANT_DICT_INITIALIZER {{0,}}
#else
#define FLATPAK_VARIANT_BUILDER_INITIALIZER {{{0,}}}
#define FLATPAK_VARIANT_DICT_INITIALIZER {{{0,}}}
#endif
#define FLATPAK_METADATA_GROUP_APPLICATION "Application"
#define FLATPAK_METADATA_GROUP_RUNTIME "Runtime"
#define FLATPAK_METADATA_KEY_COMMAND "command"
#define FLATPAK_METADATA_KEY_NAME "name"
#define FLATPAK_METADATA_KEY_REQUIRED_FLATPAK "required-flatpak"
#define FLATPAK_METADATA_KEY_RUNTIME "runtime"
#define FLATPAK_METADATA_KEY_SDK "sdk"
#define FLATPAK_METADATA_KEY_TAGS "tags"
/* https://github.com/GNOME/libglnx/pull/38
* Note by using #define rather than wrapping via a static inline, we
@ -76,19 +81,9 @@ gboolean flatpak_fancy_output (void);
const char * flatpak_get_arch (void);
const char ** flatpak_get_arches (void);
gboolean flatpak_is_linux32_arch (const char *arch);
const char ** flatpak_get_gl_drivers (void);
gboolean flatpak_extension_matches_reason (const char *extension_id,
const char *reason,
gboolean default_value);
const char * flatpak_get_bwrap (void);
char ** flatpak_get_current_locale_subpaths (void);
void flatpak_migrate_from_xdg_app (void);
GFile *flatpak_file_new_tmp_in (GFile *dir,
const char *templatename,
GError **error);
@ -115,27 +110,6 @@ GBytes * flatpak_read_stream (GInputStream *in,
gboolean null_terminate,
GError **error);
gboolean flatpak_variant_save (GFile *dest,
GVariant *variant,
GCancellable *cancellable,
GError **error);
GVariant * flatpak_gvariant_new_empty_string_dict (void);
void flatpak_variant_builder_init_from_variant (GVariantBuilder *builder,
const char *type,
GVariant *variant);
gboolean flatpak_variant_bsearch_str (GVariant *array,
const char *str,
int *out_pos);
GVariant *flatpak_repo_load_summary (OstreeRepo *repo,
GError **error);
char ** flatpak_summary_match_subrefs (GVariant *summary,
const char *collection_id,
const char *ref);
gboolean flatpak_summary_lookup_ref (GVariant *summary,
const char *collection_id,
const char *ref,
char **out_checksum,
GVariant **out_variant);
gboolean flatpak_has_name_prefix (const char *string,
const char *name);
@ -150,26 +124,6 @@ gboolean flatpak_id_has_subref_suffix (const char *id);
char **flatpak_decompose_ref (const char *ref,
GError **error);
FlatpakKinds flatpak_kinds_from_bools (gboolean app, gboolean runtime);
gboolean flatpak_split_partial_ref_arg (const char *partial_ref,
FlatpakKinds default_kinds,
const char *default_arch,
const char *default_branch,
FlatpakKinds *out_kinds,
char **out_id,
char **out_arch,
char **out_branch,
GError **error);
gboolean flatpak_split_partial_ref_arg_novalidate (const char *partial_ref,
FlatpakKinds default_kinds,
const char *default_arch,
const char *default_branch,
FlatpakKinds *out_kinds,
char **out_id,
char **out_arch,
char **out_branch);
char * flatpak_compose_ref (gboolean app,
const char *name,
const char *branch,
@ -185,54 +139,6 @@ char * flatpak_build_runtime_ref (const char *runtime,
char * flatpak_build_app_ref (const char *app,
const char *branch,
const char *arch);
char * flatpak_find_current_ref (const char *app_id,
GCancellable *cancellable,
GError **error);
GFile *flatpak_find_deploy_dir_for_ref (const char *ref,
FlatpakDir **dir_out,
GCancellable *cancellable,
GError **error);
GFile * flatpak_find_files_dir_for_ref (const char *ref,
GCancellable *cancellable,
GError **error);
GFile * flatpak_find_unmaintained_extension_dir_if_exists (const char *name,
const char *arch,
const char *branch,
GCancellable *cancellable);
FlatpakDeploy * flatpak_find_deploy_for_ref (const char *ref,
GCancellable *cancellable,
GError **error);
char ** flatpak_list_deployed_refs (const char *type,
const char *name_prefix,
const char *branch,
const char *arch,
GCancellable *cancellable,
GError **error);
char ** flatpak_list_unmaintained_refs (const char *name_prefix,
const char *branch,
const char *arch,
GCancellable *cancellable,
GError **error);
gboolean flatpak_overlay_symlink_tree (GFile *source,
GFile *destination,
const char *symlink_prefix,
GCancellable *cancellable,
GError **error);
gboolean flatpak_remove_dangling_symlinks (GFile *dir,
GCancellable *cancellable,
GError **error);
void flatpak_invocation_lookup_app_info (GDBusMethodInvocation *invocation,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
GKeyFile *flatpak_invocation_lookup_app_info_finish (GDBusMethodInvocation *invocation,
GAsyncResult *result,
GError **error);
void flatpak_connection_track_name_owners (GDBusConnection *connection);
#if !GLIB_CHECK_VERSION (2, 40, 0)
static inline gboolean
@ -291,118 +197,6 @@ gint flatpak_mkstempat (int dir_fd,
int flags,
int mode);
gboolean flatpak_repo_set_title (OstreeRepo *repo,
const char *title,
GError **error);
gboolean flatpak_repo_set_redirect_url (OstreeRepo *repo,
const char *redirect_url,
GError **error);
gboolean flatpak_repo_set_default_branch (OstreeRepo *repo,
const char *branch,
GError **error);
gboolean flatpak_repo_set_collection_id (OstreeRepo *repo,
const char *collection_id,
GError **error);
gboolean flatpak_repo_set_deploy_collection_id (OstreeRepo *repo,
gboolean deploy_collection_id,
GError **error);
gboolean flatpak_repo_set_gpg_keys (OstreeRepo *repo,
GBytes *bytes,
GError **error);
gboolean flatpak_repo_update (OstreeRepo *repo,
const char **gpg_key_ids,
const char *gpg_homedir,
GCancellable *cancellable,
GError **error);
gboolean flatpak_repo_collect_sizes (OstreeRepo *repo,
GFile *root,
guint64 *installed_size,
guint64 *download_size,
GCancellable *cancellable,
GError **error);
GVariant *flatpak_commit_get_extra_data_sources (GVariant *commitv,
GError **error);
GVariant *flatpak_repo_get_extra_data_sources (OstreeRepo *repo,
const char *rev,
GCancellable *cancellable,
GError **error);
void flatpak_repo_parse_extra_data_sources (GVariant *extra_data_sources,
int index,
const char **name,
guint64 *download_size,
guint64 *installed_size,
const guchar **sha256,
const char **uri);
gboolean flatpak_mtree_create_root (OstreeRepo *repo,
OstreeMutableTree *mtree,
GCancellable *cancellable,
GError **error);
GVariant * flatpak_bundle_load (GFile *file,
char **commit,
char **ref,
char **origin,
char **runtime_repo,
char **app_metadata,
guint64 *installed_size,
GBytes **gpg_keys,
char **collection_id,
GError **error);
gboolean flatpak_pull_from_bundle (OstreeRepo *repo,
GFile *file,
const char *remote,
const char *ref,
gboolean require_gpg_signature,
GCancellable *cancellable,
GError **error);
typedef void (*FlatpakOciPullProgress) (guint64 total_size, guint64 pulled_size,
guint32 n_layers, guint32 pulled_layers,
gpointer data);
char * flatpak_pull_from_oci (OstreeRepo *repo,
FlatpakOciRegistry *registry,
const char *digest,
FlatpakOciManifest *manifest,
const char *remote,
const char *ref,
const char *signature_digest,
FlatpakOciPullProgress progress_cb,
gpointer progress_data,
GCancellable *cancellable,
GError **error);
gboolean flatpak_mirror_image_from_oci (FlatpakOciRegistry *dst_registry,
FlatpakOciRegistry *registry,
const char *digest,
const char *signature_digest,
FlatpakOciPullProgress progress_cb,
gpointer progress_data,
GCancellable *cancellable,
GError **error);
typedef struct
{
char *id;
char *installed_id;
char *ref;
char *directory;
char *files_path;
char *subdir_suffix;
char *add_ld_path;
char **merge_dirs;
int priority;
gboolean needs_tmpfs;
gboolean is_unmaintained;
} FlatpakExtension;
void flatpak_extension_free (FlatpakExtension *extension);
GList *flatpak_list_extensions (GKeyFile *metakey,
const char *arch,
const char *branch);
char * flatpak_quote_argv (const char *argv[]);
gboolean flatpak_file_arg_has_suffix (const char *arg, const char *suffix);
@ -456,17 +250,6 @@ gboolean flatpak_rm_rf (GFile *dir,
GCancellable *cancellable,
GError **error);
char * flatpak_readlink (const char *path,
GError **error);
char * flatpak_resolve_link (const char *path,
GError **error);
char * flatpak_canonicalize_filename (const char *path);
gboolean flatpak_file_rename (GFile *from,
GFile *to,
GCancellable *cancellable,
GError **error);
gboolean flatpak_open_in_tmpdir_at (int tmpdir_fd,
int mode,
char *tmpl,
@ -490,32 +273,6 @@ typedef GFile FlatpakTempDir;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakTempDir, flatpak_temp_dir_destroy)
typedef OstreeRepo FlatpakRepoTransaction;
static inline void
flatpak_repo_transaction_cleanup (void *p)
{
OstreeRepo *repo = p;
if (repo)
{
g_autoptr(GError) error = NULL;
if (!ostree_repo_abort_transaction (repo, NULL, &error))
g_warning ("Error aborting ostree transaction: %s", error->message);
}
}
static inline FlatpakRepoTransaction *
flatpak_repo_transaction_start (OstreeRepo *repo,
GCancellable *cancellable,
GError **error)
{
if (!ostree_repo_prepare_transaction (repo, NULL, cancellable, error))
return NULL;
return (FlatpakRepoTransaction *)repo;
}
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakRepoTransaction, flatpak_repo_transaction_cleanup)
#define AUTOLOCK(name) G_GNUC_UNUSED __attribute__((cleanup (flatpak_auto_unlock_helper))) GMutex * G_PASTE (auto_unlock, __LINE__) = flatpak_auto_lock_helper (&G_LOCK_NAME (name))
/* OSTREE_CHECK_VERSION was added immediately after the 2017.3 release */
@ -558,63 +315,6 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (JsonReader, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GUnixFDList, g_object_unref)
#endif
/* This uses a weird Auto prefix to avoid conflicts with later added autogenerated autoptr support, per:
* https://git.gnome.org/browse/glib/commit/?id=1c6cd5f0a3104aa9b62c7f1d3086181f63e71b59
*/
typedef FlatpakSessionHelper AutoFlatpakSessionHelper;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (AutoFlatpakSessionHelper, g_object_unref)
G_DEFINE_AUTOPTR_CLEANUP_FUNC (XdpDbusDocuments, g_object_unref)
typedef struct FlatpakXml FlatpakXml;
struct FlatpakXml
{
gchar *element_name; /* NULL == text */
char **attribute_names;
char **attribute_values;
char *text;
FlatpakXml *parent;
FlatpakXml *first_child;
FlatpakXml *last_child;
FlatpakXml *next_sibling;
};
FlatpakXml *flatpak_xml_new (const gchar *element_name);
FlatpakXml *flatpak_xml_new_text (const gchar *text);
void flatpak_xml_add (FlatpakXml *parent,
FlatpakXml *node);
void flatpak_xml_free (FlatpakXml *node);
FlatpakXml *flatpak_xml_parse (GInputStream *in,
gboolean compressed,
GCancellable *cancellable,
GError **error);
void flatpak_xml_to_string (FlatpakXml *node,
GString *res);
FlatpakXml *flatpak_xml_unlink (FlatpakXml *node,
FlatpakXml *prev_sibling);
FlatpakXml *flatpak_xml_find (FlatpakXml *node,
const char *type,
FlatpakXml **prev_child_out);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakXml, flatpak_xml_free);
FlatpakXml *flatpak_appstream_xml_new (void);
gboolean flatpak_appstream_xml_migrate (FlatpakXml *source,
FlatpakXml *dest,
const char *ref,
const char *id,
GKeyFile *metadata);
GBytes *flatpak_appstream_xml_root_to_data (FlatpakXml *appstream_root,
GError **error);
gboolean flatpak_repo_generate_appstream (OstreeRepo *repo,
const char **gpg_key_ids,
const char *gpg_homedir,
guint64 timestamp,
GCancellable *cancellable,
GError **error);
gboolean flatpak_allocate_tmpdir (int tmpdir_dfd,
const char *tmpdir_relpath,
const char *tmpdir_prefix,
@ -626,9 +326,6 @@ gboolean flatpak_allocate_tmpdir (int tmpdir_dfd,
GError **error);
gboolean flatpak_yes_no_prompt (const char *prompt, ...) G_GNUC_PRINTF(1, 2);
long flatpak_number_prompt (int min, int max, const char *prompt, ...) G_GNUC_PRINTF(3, 4);
SoupSession * flatpak_create_soup_session (const char *user_agent);
GBytes * flatpak_load_http_uri (SoupSession *soup_session,
const char *uri,
@ -646,57 +343,15 @@ gboolean flatpak_download_http_uri (SoupSession *soup_session,
GCancellable *cancellable,
GError **error);
typedef struct {
char *shell_cur;
char *cur;
char *prev;
char *line;
int point;
char **argv;
char **original_argv;
int argc;
int original_argc;
} FlatpakCompletion;
typedef struct FlatpakContext FlatpakContext;
void flatpak_completion_debug (const gchar *format, ...);
FlatpakContext *flatpak_context_new (void);
void flatpak_context_free (FlatpakContext *context);
GOptionGroup *flatpak_context_get_options (FlatpakContext *context);
void flatpak_context_to_args (FlatpakContext *context,
GPtrArray *args);
FlatpakCompletion *flatpak_completion_new (const char *arg_line,
const char *arg_point,
const char *arg_cur);
void flatpak_complete_word (FlatpakCompletion *completion,
char *format,
...) G_GNUC_PRINTF(2,3);
void flatpak_complete_ref (FlatpakCompletion *completion,
OstreeRepo *repo);
void flatpak_complete_partial_ref (FlatpakCompletion *completion,
FlatpakKinds kinds,
const char *only_arch,
FlatpakDir *dir,
const char *remote);
void flatpak_complete_file (FlatpakCompletion *completion);
void flatpak_complete_dir (FlatpakCompletion *completion);
void flatpak_complete_options (FlatpakCompletion *completion,
GOptionEntry *entries);
void flatpak_completion_free (FlatpakCompletion *completion);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakContext, flatpak_context_free)
typedef struct {
int inited;
int n_columns;
int last_width;
} FlatpakTerminalProgress;
void flatpak_terminal_progress_cb (const char *status,
guint progress,
gboolean estimating,
gpointer user_data);
void flatpak_terminal_progress_end (FlatpakTerminalProgress *term);
typedef void (*FlatpakProgressCallback)(const char *status,
guint progress,
gboolean estimating,
gpointer user_data);
OstreeAsyncProgress *flatpak_progress_new (FlatpakProgressCallback progress,
gpointer progress_data);
#endif /* __FLATPAK_UTILS_H__ */

View File

@ -1,2 +0,0 @@
libgvdb.a
libgvdb-shared.a

View File

@ -1,7 +0,0 @@
DO NOT MODIFY ANY FILE IN THIS DIRECTORY
(except maybe the Makefile.am)
This directory is the result of a git subtree merge with the 'gvdb'
module on git.gnome.org. Please apply fixes to the 'gvdb' module and
perform a git merge.

View File

@ -1,537 +0,0 @@
/*
* Copyright © 2010 Codethink Limited
*
* 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 licence, 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/>.
*
* Author: Ryan Lortie <desrt@desrt.ca>
*/
#include "gvdb-builder.h"
#include "gvdb-format.h"
#include <glib.h>
#include <fcntl.h>
#if !defined(G_OS_WIN32) || !defined(_MSC_VER)
#include <unistd.h>
#endif
#include <string.h>
struct _GvdbItem
{
gchar *key;
guint32 hash_value;
guint32_le assigned_index;
GvdbItem *parent;
GvdbItem *sibling;
GvdbItem *next;
/* one of:
* this:
*/
GVariant *value;
/* this: */
GHashTable *table;
/* or this: */
GvdbItem *child;
};
static void
gvdb_item_free (gpointer data)
{
GvdbItem *item = data;
g_free (item->key);
if (item->value)
g_variant_unref (item->value);
if (item->table)
g_hash_table_unref (item->table);
g_slice_free (GvdbItem, item);
}
GHashTable *
gvdb_hash_table_new (GHashTable *parent,
const gchar *name_in_parent)
{
GHashTable *table;
table = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, gvdb_item_free);
if (parent)
{
GvdbItem *item;
item = gvdb_hash_table_insert (parent, name_in_parent);
gvdb_item_set_hash_table (item, table);
}
return table;
}
static guint32
djb_hash (const gchar *key)
{
guint32 hash_value = 5381;
while (*key)
hash_value = hash_value * 33 + *(signed char *)key++;
return hash_value;
}
GvdbItem *
gvdb_hash_table_insert (GHashTable *table,
const gchar *key)
{
GvdbItem *item;
item = g_slice_new0 (GvdbItem);
item->key = g_strdup (key);
item->hash_value = djb_hash (key);
g_hash_table_insert (table, g_strdup (key), item);
return item;
}
void
gvdb_hash_table_insert_string (GHashTable *table,
const gchar *key,
const gchar *value)
{
GvdbItem *item;
item = gvdb_hash_table_insert (table, key);
gvdb_item_set_value (item, g_variant_new_string (value));
}
void
gvdb_item_set_value (GvdbItem *item,
GVariant *value)
{
g_return_if_fail (!item->value && !item->table && !item->child);
item->value = g_variant_ref_sink (value);
}
void
gvdb_item_set_hash_table (GvdbItem *item,
GHashTable *table)
{
g_return_if_fail (!item->value && !item->table && !item->child);
item->table = g_hash_table_ref (table);
}
void
gvdb_item_set_parent (GvdbItem *item,
GvdbItem *parent)
{
GvdbItem **node;
g_return_if_fail (g_str_has_prefix (item->key, parent->key));
g_return_if_fail (!parent->value && !parent->table);
g_return_if_fail (!item->parent && !item->sibling);
for (node = &parent->child; *node; node = &(*node)->sibling)
if (strcmp ((*node)->key, item->key) > 0)
break;
item->parent = parent;
item->sibling = *node;
*node = item;
}
typedef struct
{
GvdbItem **buckets;
gint n_buckets;
} HashTable;
static HashTable *
hash_table_new (gint n_buckets)
{
HashTable *table;
table = g_slice_new (HashTable);
table->buckets = g_new0 (GvdbItem *, n_buckets);
table->n_buckets = n_buckets;
return table;
}
static void
hash_table_free (HashTable *table)
{
g_free (table->buckets);
g_slice_free (HashTable, table);
}
static void
hash_table_insert (gpointer key,
gpointer value,
gpointer data)
{
guint32 hash_value, bucket;
HashTable *table = data;
GvdbItem *item = value;
hash_value = djb_hash (key);
bucket = hash_value % table->n_buckets;
item->next = table->buckets[bucket];
table->buckets[bucket] = item;
}
static guint32_le
item_to_index (GvdbItem *item)
{
if (item != NULL)
return item->assigned_index;
return guint32_to_le (-1u);
}
typedef struct
{
GQueue *chunks;
guint64 offset;
gboolean byteswap;
} FileBuilder;
typedef struct
{
gsize offset;
gsize size;
gpointer data;
} FileChunk;
static gpointer
file_builder_allocate (FileBuilder *fb,
guint alignment,
gsize size,
struct gvdb_pointer *pointer)
{
FileChunk *chunk;
if (size == 0)
return NULL;
fb->offset += (-fb->offset) & (alignment - 1);
chunk = g_slice_new (FileChunk);
chunk->offset = fb->offset;
chunk->size = size;
chunk->data = g_malloc (size);
pointer->start = guint32_to_le (fb->offset);
fb->offset += size;
pointer->end = guint32_to_le (fb->offset);
g_queue_push_tail (fb->chunks, chunk);
return chunk->data;
}
static void
file_builder_add_value (FileBuilder *fb,
GVariant *value,
struct gvdb_pointer *pointer)
{
GVariant *variant, *normal;
gpointer data;
gsize size;
if (fb->byteswap)
{
value = g_variant_byteswap (value);
variant = g_variant_new_variant (value);
g_variant_unref (value);
}
else
variant = g_variant_new_variant (value);
normal = g_variant_get_normal_form (variant);
g_variant_unref (variant);
size = g_variant_get_size (normal);
data = file_builder_allocate (fb, 8, size, pointer);
g_variant_store (normal, data);
g_variant_unref (normal);
}
static void
file_builder_add_string (FileBuilder *fb,
const gchar *string,
guint32_le *start,
guint16_le *size)
{
FileChunk *chunk;
gsize length;
length = strlen (string);
chunk = g_slice_new (FileChunk);
chunk->offset = fb->offset;
chunk->size = length;
chunk->data = g_malloc (length);
memcpy (chunk->data, string, length);
*start = guint32_to_le (fb->offset);
*size = guint16_to_le (length);
fb->offset += length;
g_queue_push_tail (fb->chunks, chunk);
}
static void
file_builder_allocate_for_hash (FileBuilder *fb,
gsize n_buckets,
gsize n_items,
guint bloom_shift,
gsize n_bloom_words,
guint32_le **bloom_filter,
guint32_le **hash_buckets,
struct gvdb_hash_item **hash_items,
struct gvdb_pointer *pointer)
{
guint32_le bloom_hdr, table_hdr;
guchar *data;
gsize size;
g_assert (n_bloom_words < (1u << 27));
bloom_hdr = guint32_to_le (bloom_shift << 27 | n_bloom_words);
table_hdr = guint32_to_le (n_buckets);
size = sizeof bloom_hdr + sizeof table_hdr +
n_bloom_words * sizeof (guint32_le) +
n_buckets * sizeof (guint32_le) +
n_items * sizeof (struct gvdb_hash_item);
data = file_builder_allocate (fb, 4, size, pointer);
#define chunk(s) (size -= (s), data += (s), data - (s))
memcpy (chunk (sizeof bloom_hdr), &bloom_hdr, sizeof bloom_hdr);
memcpy (chunk (sizeof table_hdr), &table_hdr, sizeof table_hdr);
*bloom_filter = (guint32_le *) chunk (n_bloom_words * sizeof (guint32_le));
*hash_buckets = (guint32_le *) chunk (n_buckets * sizeof (guint32_le));
*hash_items = (struct gvdb_hash_item *) chunk (n_items *
sizeof (struct gvdb_hash_item));
g_assert (size == 0);
#undef chunk
memset (*bloom_filter, 0, n_bloom_words * sizeof (guint32_le));
/* NOTE - the code to actually fill in the bloom filter here is missing.
* Patches welcome!
*
* http://en.wikipedia.org/wiki/Bloom_filter
* http://0pointer.de/blog/projects/bloom.html
*/
}
static void
file_builder_add_hash (FileBuilder *fb,
GHashTable *table,
struct gvdb_pointer *pointer)
{
guint32_le *buckets, *bloom_filter;
struct gvdb_hash_item *items;
HashTable *mytable;
GvdbItem *item;
guint32 index;
gint bucket;
mytable = hash_table_new (g_hash_table_size (table));
g_hash_table_foreach (table, hash_table_insert, mytable);
index = 0;
for (bucket = 0; bucket < mytable->n_buckets; bucket++)
for (item = mytable->buckets[bucket]; item; item = item->next)
item->assigned_index = guint32_to_le (index++);
file_builder_allocate_for_hash (fb, mytable->n_buckets, index, 5, 0,
&bloom_filter, &buckets, &items, pointer);
index = 0;
for (bucket = 0; bucket < mytable->n_buckets; bucket++)
{
buckets[bucket] = guint32_to_le (index);
for (item = mytable->buckets[bucket]; item; item = item->next)
{
struct gvdb_hash_item *entry = items++;
const gchar *basename;
g_assert (index == guint32_from_le (item->assigned_index));
entry->hash_value = guint32_to_le (item->hash_value);
entry->parent = item_to_index (item->parent);
entry->unused = 0;
if (item->parent != NULL)
basename = item->key + strlen (item->parent->key);
else
basename = item->key;
file_builder_add_string (fb, basename,
&entry->key_start,
&entry->key_size);
if (item->value != NULL)
{
g_assert (item->child == NULL && item->table == NULL);
file_builder_add_value (fb, item->value, &entry->value.pointer);
entry->type = 'v';
}
if (item->child != NULL)
{
guint32 children = 0, i = 0;
guint32_le *offsets;
GvdbItem *child;
g_assert (item->table == NULL);
for (child = item->child; child; child = child->sibling)
children++;
offsets = file_builder_allocate (fb, 4, 4 * children,
&entry->value.pointer);
entry->type = 'L';
for (child = item->child; child; child = child->sibling)
offsets[i++] = child->assigned_index;
g_assert (children == i);
}
if (item->table != NULL)
{
entry->type = 'H';
file_builder_add_hash (fb, item->table, &entry->value.pointer);
}
index++;
}
}
hash_table_free (mytable);
}
static FileBuilder *
file_builder_new (gboolean byteswap)
{
FileBuilder *builder;
builder = g_slice_new (FileBuilder);
builder->chunks = g_queue_new ();
builder->offset = sizeof (struct gvdb_header);
builder->byteswap = byteswap;
return builder;
}
static GString *
file_builder_serialise (FileBuilder *fb,
struct gvdb_pointer root)
{
struct gvdb_header header = { { 0, }, };
GString *result;
if (fb->byteswap)
{
header.signature[0] = GVDB_SWAPPED_SIGNATURE0;
header.signature[1] = GVDB_SWAPPED_SIGNATURE1;
}
else
{
header.signature[0] = GVDB_SIGNATURE0;
header.signature[1] = GVDB_SIGNATURE1;
}
result = g_string_new (NULL);
header.root = root;
g_string_append_len (result, (gpointer) &header, sizeof header);
while (!g_queue_is_empty (fb->chunks))
{
FileChunk *chunk = g_queue_pop_head (fb->chunks);
if (result->len != chunk->offset)
{
gchar zero[8] = { 0, };
g_assert (chunk->offset > result->len);
g_assert (chunk->offset - result->len < 8);
g_string_append_len (result, zero, chunk->offset - result->len);
g_assert (result->len == chunk->offset);
}
g_string_append_len (result, chunk->data, chunk->size);
g_free (chunk->data);
g_slice_free (FileChunk, chunk);
}
g_queue_free (fb->chunks);
g_slice_free (FileBuilder, fb);
return result;
}
GBytes *
gvdb_table_get_content (GHashTable *table,
gboolean byteswap)
{
struct gvdb_pointer root;
FileBuilder *fb;
GString *str;
GBytes *res;
fb = file_builder_new (byteswap);
file_builder_add_hash (fb, table, &root);
str = file_builder_serialise (fb, root);
res = g_bytes_new_take (str->str, str->len);
g_string_free (str, FALSE);
return res;
}
gboolean
gvdb_table_write_contents (GHashTable *table,
const gchar *filename,
gboolean byteswap,
GError **error)
{
GBytes *content;
gboolean status;
content = gvdb_table_get_content (table, byteswap);
status = g_file_set_contents (filename, g_bytes_get_data (content, NULL), g_bytes_get_size (content), error);
g_bytes_unref (content);
return status;
}

View File

@ -1,60 +0,0 @@
/*
* Copyright © 2010 Codethink Limited
*
* 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 licence, 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/>.
*
* Author: Ryan Lortie <desrt@desrt.ca>
*/
#ifndef __gvdb_builder_h__
#define __gvdb_builder_h__
#include <gio/gio.h>
typedef struct _GvdbItem GvdbItem;
G_GNUC_INTERNAL
GHashTable * gvdb_hash_table_new (GHashTable *parent,
const gchar *key);
G_GNUC_INTERNAL
GvdbItem * gvdb_hash_table_insert (GHashTable *table,
const gchar *key);
G_GNUC_INTERNAL
void gvdb_hash_table_insert_string (GHashTable *table,
const gchar *key,
const gchar *value);
G_GNUC_INTERNAL
void gvdb_item_set_value (GvdbItem *item,
GVariant *value);
G_GNUC_INTERNAL
void gvdb_item_set_hash_table (GvdbItem *item,
GHashTable *table);
G_GNUC_INTERNAL
void gvdb_item_set_parent (GvdbItem *item,
GvdbItem *parent);
G_GNUC_INTERNAL
gboolean gvdb_table_write_contents (GHashTable *table,
const gchar *filename,
gboolean byteswap,
GError **error);
G_GNUC_INTERNAL
GBytes * gvdb_table_get_content (GHashTable *table,
gboolean byteswap);
#endif /* __gvdb_builder_h__ */

View File

@ -1,85 +0,0 @@
/*
* Copyright © 2010 Codethink Limited
*
* 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 licence, 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/>.
*
* Author: Ryan Lortie <desrt@desrt.ca>
*/
#ifndef __gvdb_format_h__
#define __gvdb_format_h__
#include <glib.h>
typedef struct { guint16 value; } guint16_le;
typedef struct { guint32 value; } guint32_le;
struct gvdb_pointer {
guint32_le start;
guint32_le end;
};
struct gvdb_hash_header {
guint32_le n_bloom_words;
guint32_le n_buckets;
};
struct gvdb_hash_item {
guint32_le hash_value;
guint32_le parent;
guint32_le key_start;
guint16_le key_size;
gchar type;
gchar unused;
union
{
struct gvdb_pointer pointer;
gchar direct[8];
} value;
};
struct gvdb_header {
guint32 signature[2];
guint32_le version;
guint32_le options;
struct gvdb_pointer root;
};
static inline guint32_le guint32_to_le (guint32 value) {
guint32_le result = { GUINT32_TO_LE (value) };
return result;
}
static inline guint32 guint32_from_le (guint32_le value) {
return GUINT32_FROM_LE (value.value);
}
static inline guint16_le guint16_to_le (guint16 value) {
guint16_le result = { GUINT16_TO_LE (value) };
return result;
}
static inline guint16 guint16_from_le (guint16_le value) {
return GUINT16_FROM_LE (value.value);
}
#define GVDB_SIGNATURE0 1918981703
#define GVDB_SIGNATURE1 1953390953
#define GVDB_SWAPPED_SIGNATURE0 GUINT32_SWAP_LE_BE (GVDB_SIGNATURE0)
#define GVDB_SWAPPED_SIGNATURE1 GUINT32_SWAP_LE_BE (GVDB_SIGNATURE1)
#endif /* __gvdb_format_h__ */

View File

@ -1,718 +0,0 @@
/*
* Copyright © 2010 Codethink Limited
*
* 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 licence, 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/>.
*
* Author: Ryan Lortie <desrt@desrt.ca>
*/
#include "gvdb-reader.h"
#include "gvdb-format.h"
#include <string.h>
struct _GvdbTable {
GBytes *bytes;
const gchar *data;
gsize size;
gboolean byteswapped;
gboolean trusted;
const guint32_le *bloom_words;
guint32 n_bloom_words;
guint bloom_shift;
const guint32_le *hash_buckets;
guint32 n_buckets;
struct gvdb_hash_item *hash_items;
guint32 n_hash_items;
};
static const gchar *
gvdb_table_item_get_key (GvdbTable *file,
const struct gvdb_hash_item *item,
gsize *size)
{
guint32 start, end;
start = guint32_from_le (item->key_start);
*size = guint16_from_le (item->key_size);
end = start + *size;
if G_UNLIKELY (start > end || end > file->size)
return NULL;
return file->data + start;
}
static gconstpointer
gvdb_table_dereference (GvdbTable *file,
const struct gvdb_pointer *pointer,
gint alignment,
gsize *size)
{
guint32 start, end;
start = guint32_from_le (pointer->start);
end = guint32_from_le (pointer->end);
if G_UNLIKELY (start > end || end > file->size || start & (alignment - 1))
return NULL;
*size = end - start;
return file->data + start;
}
static void
gvdb_table_setup_root (GvdbTable *file,
const struct gvdb_pointer *pointer)
{
const struct gvdb_hash_header *header;
guint32 n_bloom_words;
guint32 n_buckets;
gsize size;
header = gvdb_table_dereference (file, pointer, 4, &size);
if G_UNLIKELY (header == NULL || size < sizeof *header)
return;
size -= sizeof *header;
n_bloom_words = guint32_from_le (header->n_bloom_words);
n_buckets = guint32_from_le (header->n_buckets);
n_bloom_words &= (1u << 27) - 1;
if G_UNLIKELY (n_bloom_words * sizeof (guint32_le) > size)
return;
file->bloom_words = (gpointer) (header + 1);
size -= n_bloom_words * sizeof (guint32_le);
file->n_bloom_words = n_bloom_words;
if G_UNLIKELY (n_buckets > G_MAXUINT / sizeof (guint32_le) ||
n_buckets * sizeof (guint32_le) > size)
return;
file->hash_buckets = file->bloom_words + file->n_bloom_words;
size -= n_buckets * sizeof (guint32_le);
file->n_buckets = n_buckets;
if G_UNLIKELY (size % sizeof (struct gvdb_hash_item))
return;
file->hash_items = (gpointer) (file->hash_buckets + n_buckets);
file->n_hash_items = size / sizeof (struct gvdb_hash_item);
}
/**
* gvdb_table_new_from_bytes:
* @bytes: the #GBytes with the data
* @trusted: if the contents of @bytes are trusted
* @error: %NULL, or a pointer to a %NULL #GError
* @returns: a new #GvdbTable
*
* Creates a new #GvdbTable from the contents of @bytes.
*
* This call can fail if the header contained in @bytes is invalid.
*
* You should call gvdb_table_free() on the return result when you no
* longer require it.
**/
GvdbTable *
gvdb_table_new_from_bytes (GBytes *bytes,
gboolean trusted,
GError **error)
{
const struct gvdb_header *header;
GvdbTable *file;
file = g_slice_new0 (GvdbTable);
file->bytes = g_bytes_ref (bytes);
file->data = g_bytes_get_data (bytes, &file->size);
file->trusted = trusted;
if (file->size < sizeof (struct gvdb_header))
goto invalid;
header = (gpointer) file->data;
if (header->signature[0] == GVDB_SIGNATURE0 &&
header->signature[1] == GVDB_SIGNATURE1 &&
guint32_from_le (header->version) == 0)
file->byteswapped = FALSE;
else if (header->signature[0] == GVDB_SWAPPED_SIGNATURE0 &&
header->signature[1] == GVDB_SWAPPED_SIGNATURE1 &&
guint32_from_le (header->version) == 0)
file->byteswapped = TRUE;
else
goto invalid;
gvdb_table_setup_root (file, &header->root);
return file;
invalid:
g_set_error_literal (error, G_FILE_ERROR, G_FILE_ERROR_INVAL, "invalid gvdb header");
g_bytes_unref (file->bytes);
g_slice_free (GvdbTable, file);
return NULL;
}
/**
* gvdb_table_new:
* @filename: a filename
* @trusted: if the contents of @bytes are trusted
* @error: %NULL, or a pointer to a %NULL #GError
* @returns: a new #GvdbTable
*
* Creates a new #GvdbTable using the #GMappedFile for @filename as the
* #GBytes.
**/
GvdbTable *
gvdb_table_new (const gchar *filename,
gboolean trusted,
GError **error)
{
GMappedFile *mapped;
GvdbTable *table;
GBytes *bytes;
mapped = g_mapped_file_new (filename, FALSE, error);
if (!mapped)
return NULL;
bytes = g_mapped_file_get_bytes (mapped);
table = gvdb_table_new_from_bytes (bytes, trusted, error);
g_mapped_file_unref (mapped);
g_bytes_unref (bytes);
g_prefix_error (error, "%s: ", filename);
return table;
}
static gboolean
gvdb_table_bloom_filter (GvdbTable *file,
guint32 hash_value)
{
guint32 word, mask;
if (file->n_bloom_words == 0)
return TRUE;
word = (hash_value / 32) % file->n_bloom_words;
mask = 1 << (hash_value & 31);
mask |= 1 << ((hash_value >> file->bloom_shift) & 31);
return (guint32_from_le (file->bloom_words[word]) & mask) == mask;
}
static gboolean
gvdb_table_check_name (GvdbTable *file,
struct gvdb_hash_item *item,
const gchar *key,
guint key_length)
{
const gchar *this_key;
gsize this_size;
guint32 parent;
this_key = gvdb_table_item_get_key (file, item, &this_size);
if G_UNLIKELY (this_key == NULL || this_size > key_length)
return FALSE;
key_length -= this_size;
if G_UNLIKELY (memcmp (this_key, key + key_length, this_size) != 0)
return FALSE;
parent = guint32_from_le (item->parent);
if (key_length == 0 && parent == 0xffffffffu)
return TRUE;
if G_LIKELY (parent < file->n_hash_items && this_size > 0)
return gvdb_table_check_name (file,
&file->hash_items[parent],
key, key_length);
return FALSE;
}
static const struct gvdb_hash_item *
gvdb_table_lookup (GvdbTable *file,
const gchar *key,
gchar type)
{
guint32 hash_value = 5381;
guint key_length;
guint32 bucket;
guint32 lastno;
guint32 itemno;
if G_UNLIKELY (file->n_buckets == 0 || file->n_hash_items == 0)
return NULL;
for (key_length = 0; key[key_length]; key_length++)
hash_value = (hash_value * 33) + ((signed char *) key)[key_length];
if (!gvdb_table_bloom_filter (file, hash_value))
return NULL;
bucket = hash_value % file->n_buckets;
itemno = guint32_from_le (file->hash_buckets[bucket]);
if (bucket == file->n_buckets - 1 ||
(lastno = guint32_from_le(file->hash_buckets[bucket + 1])) > file->n_hash_items)
lastno = file->n_hash_items;
while G_LIKELY (itemno < lastno)
{
struct gvdb_hash_item *item = &file->hash_items[itemno];
if (hash_value == guint32_from_le (item->hash_value))
if G_LIKELY (gvdb_table_check_name (file, item, key, key_length))
if G_LIKELY (item->type == type)
return item;
itemno++;
}
return NULL;
}
static gboolean
gvdb_table_list_from_item (GvdbTable *table,
const struct gvdb_hash_item *item,
const guint32_le **list,
guint *length)
{
gsize size;
*list = gvdb_table_dereference (table, &item->value.pointer, 4, &size);
if G_LIKELY (*list == NULL || size % 4)
return FALSE;
*length = size / 4;
return TRUE;
}
/**
* gvdb_table_get_names:
* @table: a #GvdbTable
* @length: the number of items returned, or %NULL
*
* Gets a list of all names contained in @table.
*
* No call to gvdb_table_get_table(), gvdb_table_list() or
* gvdb_table_get_value() will succeed unless it is for one of the
* names returned by this function.
*
* Note that some names that are returned may still fail for all of the
* above calls in the case of the corrupted file. Note also that the
* returned strings may not be utf8.
*
* Returns: a %NULL-terminated list of strings, of length @length
**/
gchar **
gvdb_table_get_names (GvdbTable *table,
gint *length)
{
gchar **names;
gint n_names;
gint filled;
gint total;
gint i;
/* We generally proceed by iterating over the list of items in the
* hash table (in order of appearance) recording them into an array.
*
* Each item has a parent item (except root items). The parent item
* forms part of the name of the item. We could go fetching the
* parent item chain at the point that we encounter each item but then
* we would need to implement some sort of recursion along with checks
* for self-referential items.
*
* Instead, we do a number of passes. Each pass will build up one
* level of names (starting from the root). We continue to do passes
* until no more items are left. The first pass will only add root
* items and each further pass will only add items whose direct parent
* is an item added in the immediately previous pass. It's also
* possible that items get filled if they follow their parent within a
* particular pass.
*
* At most we will have a number of passes equal to the depth of the
* tree. Self-referential items will never be filled in (since their
* parent will have never been filled in). We continue until we have
* a pass that fills in no additional items.
*
* This takes an O(n) algorithm and turns it into O(n*m) where m is
* the depth of the tree, but in all sane cases the tree won't be very
* deep and the constant factor of this algorithm is lower (and the
* complexity of coding it, as well).
*/
n_names = table->n_hash_items;
names = g_new0 (gchar *, n_names + 1);
/* 'names' starts out all-NULL. On each pass we record the number
* of items changed from NULL to non-NULL in 'filled' so we know if we
* should repeat the loop. 'total' counts the total number of items
* filled. If 'total' ends up equal to 'n_names' then we know that
* 'names' has been completely filled.
*/
total = 0;
do
{
/* Loop until we have filled no more entries */
filled = 0;
for (i = 0; i < n_names; i++)
{
const struct gvdb_hash_item *item = &table->hash_items[i];
const gchar *name;
gsize name_length;
guint32 parent;
/* already got it on a previous pass */
if (names[i] != NULL)
continue;
parent = guint32_from_le (item->parent);
if (parent == 0xffffffffu)
{
/* it's a root item */
name = gvdb_table_item_get_key (table, item, &name_length);
if (name != NULL)
{
names[i] = g_strndup (name, name_length);
filled++;
}
}
else if (parent < n_names && names[parent] != NULL)
{
/* It's a non-root item whose parent was filled in already.
*
* Calculate the name of this item by combining it with
* its parent name.
*/
name = gvdb_table_item_get_key (table, item, &name_length);
if (name != NULL)
{
const gchar *parent_name = names[parent];
gsize parent_length;
gchar *fullname;
parent_length = strlen (parent_name);
fullname = g_malloc (parent_length + name_length + 1);
memcpy (fullname, parent_name, parent_length);
memcpy (fullname + parent_length, name, name_length);
fullname[parent_length + name_length] = '\0';
names[i] = fullname;
filled++;
}
}
}
total += filled;
}
while (filled && total < n_names);
/* If the table was corrupted then 'names' may have holes in it.
* Collapse those.
*/
if G_UNLIKELY (total != n_names)
{
GPtrArray *fixed_names;
fixed_names = g_ptr_array_new ();
for (i = 0; i < n_names; i++)
if (names[i] != NULL)
g_ptr_array_add (fixed_names, names[i]);
g_free (names);
n_names = fixed_names->len;
g_ptr_array_add (fixed_names, NULL);
names = (gchar **) g_ptr_array_free (fixed_names, FALSE);
}
if (length)
*length = n_names;
return names;
}
/**
* gvdb_table_list:
* @file: a #GvdbTable
* @key: a string
* @returns: a %NULL-terminated string array
*
* List all of the keys that appear below @key. The nesting of keys
* within the hash file is defined by the program that created the hash
* file. One thing is constant: each item in the returned array can be
* concatenated to @key to obtain the full name of that key.
*
* It is not possible to tell from this function if a given key is
* itself a path, a value, or another hash table; you are expected to
* know this for yourself.
*
* You should call g_strfreev() on the return result when you no longer
* require it.
**/
gchar **
gvdb_table_list (GvdbTable *file,
const gchar *key)
{
const struct gvdb_hash_item *item;
const guint32_le *list;
gchar **strv;
guint length;
guint i;
if ((item = gvdb_table_lookup (file, key, 'L')) == NULL)
return NULL;
if (!gvdb_table_list_from_item (file, item, &list, &length))
return NULL;
strv = g_new (gchar *, length + 1);
for (i = 0; i < length; i++)
{
guint32 itemno = guint32_from_le (list[i]);
if (itemno < file->n_hash_items)
{
const struct gvdb_hash_item *item;
const gchar *string;
gsize strsize;
item = file->hash_items + itemno;
string = gvdb_table_item_get_key (file, item, &strsize);
if (string != NULL)
strv[i] = g_strndup (string, strsize);
else
strv[i] = g_malloc0 (1);
}
else
strv[i] = g_malloc0 (1);
}
strv[i] = NULL;
return strv;
}
/**
* gvdb_table_has_value:
* @file: a #GvdbTable
* @key: a string
* @returns: %TRUE if @key is in the table
*
* Checks for a value named @key in @file.
*
* Note: this function does not consider non-value nodes (other hash
* tables, for example).
**/
gboolean
gvdb_table_has_value (GvdbTable *file,
const gchar *key)
{
static const struct gvdb_hash_item *item;
gsize size;
item = gvdb_table_lookup (file, key, 'v');
if (item == NULL)
return FALSE;
return gvdb_table_dereference (file, &item->value.pointer, 8, &size) != NULL;
}
static GVariant *
gvdb_table_value_from_item (GvdbTable *table,
const struct gvdb_hash_item *item)
{
GVariant *variant, *value;
gconstpointer data;
GBytes *bytes;
gsize size;
data = gvdb_table_dereference (table, &item->value.pointer, 8, &size);
if G_UNLIKELY (data == NULL)
return NULL;
bytes = g_bytes_new_from_bytes (table->bytes, ((gchar *) data) - table->data, size);
variant = g_variant_new_from_bytes (G_VARIANT_TYPE_VARIANT, bytes, table->trusted);
value = g_variant_get_variant (variant);
g_variant_unref (variant);
g_bytes_unref (bytes);
return value;
}
/**
* gvdb_table_get_value:
* @file: a #GvdbTable
* @key: a string
* @returns: a #GVariant, or %NULL
*
* Looks up a value named @key in @file.
*
* If the value is not found then %NULL is returned. Otherwise, a new
* #GVariant instance is returned. The #GVariant does not depend on the
* continued existence of @file.
*
* You should call g_variant_unref() on the return result when you no
* longer require it.
**/
GVariant *
gvdb_table_get_value (GvdbTable *file,
const gchar *key)
{
const struct gvdb_hash_item *item;
GVariant *value;
if ((item = gvdb_table_lookup (file, key, 'v')) == NULL)
return NULL;
value = gvdb_table_value_from_item (file, item);
if (value && file->byteswapped)
{
GVariant *tmp;
tmp = g_variant_byteswap (value);
g_variant_unref (value);
value = tmp;
}
return value;
}
/**
* gvdb_table_get_raw_value:
* @table: a #GvdbTable
* @key: a string
* @returns: a #GVariant, or %NULL
*
* Looks up a value named @key in @file.
*
* This call is equivalent to gvdb_table_get_value() except that it
* never byteswaps the value.
**/
GVariant *
gvdb_table_get_raw_value (GvdbTable *table,
const gchar *key)
{
const struct gvdb_hash_item *item;
if ((item = gvdb_table_lookup (table, key, 'v')) == NULL)
return NULL;
return gvdb_table_value_from_item (table, item);
}
/**
* gvdb_table_get_table:
* @file: a #GvdbTable
* @key: a string
* @returns: a new #GvdbTable, or %NULL
*
* Looks up the hash table named @key in @file.
*
* The toplevel hash table in a #GvdbTable can contain reference to
* child hash tables (and those can contain further references...).
*
* If @key is not found in @file then %NULL is returned. Otherwise, a
* new #GvdbTable is returned, referring to the child hashtable as
* contained in the file. This newly-created #GvdbTable does not depend
* on the continued existence of @file.
*
* You should call gvdb_table_free() on the return result when you no
* longer require it.
**/
GvdbTable *
gvdb_table_get_table (GvdbTable *file,
const gchar *key)
{
const struct gvdb_hash_item *item;
GvdbTable *new;
item = gvdb_table_lookup (file, key, 'H');
if (item == NULL)
return NULL;
new = g_slice_new0 (GvdbTable);
new->bytes = g_bytes_ref (file->bytes);
new->byteswapped = file->byteswapped;
new->trusted = file->trusted;
new->data = file->data;
new->size = file->size;
gvdb_table_setup_root (new, &item->value.pointer);
return new;
}
/**
* gvdb_table_free:
* @file: a #GvdbTable
*
* Frees @file.
**/
void
gvdb_table_free (GvdbTable *file)
{
g_bytes_unref (file->bytes);
g_slice_free (GvdbTable, file);
}
/**
* gvdb_table_is_valid:
* @table: a #GvdbTable
* @returns: %TRUE if @table is still valid
*
* Checks if the table is still valid.
*
* An on-disk GVDB can be marked as invalid. This happens when the file
* has been replaced. The appropriate action is typically to reopen the
* file.
**/
gboolean
gvdb_table_is_valid (GvdbTable *table)
{
return !!*table->data;
}

View File

@ -1,63 +0,0 @@
/*
* Copyright © 2010 Codethink Limited
*
* 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 licence, 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/>.
*
* Author: Ryan Lortie <desrt@desrt.ca>
*/
#ifndef __gvdb_reader_h__
#define __gvdb_reader_h__
#include <glib.h>
typedef struct _GvdbTable GvdbTable;
G_BEGIN_DECLS
G_GNUC_INTERNAL
GvdbTable * gvdb_table_new_from_bytes (GBytes *bytes,
gboolean trusted,
GError **error);
G_GNUC_INTERNAL
GvdbTable * gvdb_table_new (const gchar *filename,
gboolean trusted,
GError **error);
G_GNUC_INTERNAL
void gvdb_table_free (GvdbTable *table);
G_GNUC_INTERNAL
gchar ** gvdb_table_get_names (GvdbTable *table,
gint *length);
G_GNUC_INTERNAL
gchar ** gvdb_table_list (GvdbTable *table,
const gchar *key);
G_GNUC_INTERNAL
GvdbTable * gvdb_table_get_table (GvdbTable *table,
const gchar *key);
G_GNUC_INTERNAL
GVariant * gvdb_table_get_raw_value (GvdbTable *table,
const gchar *key);
G_GNUC_INTERNAL
GVariant * gvdb_table_get_value (GvdbTable *table,
const gchar *key);
G_GNUC_INTERNAL
gboolean gvdb_table_has_value (GvdbTable *table,
const gchar *key);
G_GNUC_INTERNAL
gboolean gvdb_table_is_valid (GvdbTable *table);
G_END_DECLS
#endif /* __gvdb_reader_h__ */

View File

@ -1,32 +0,0 @@
<?xml version='1.0' encoding='utf-8'?>
<Project xmlns='http://usefulinc.com/ns/doap#'
xmlns:foaf='http://xmlns.com/foaf/0.1/'
xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'
xmlns:gnome='http://api.gnome.org/doap-extensions#'>
<name xml:lang='en'>gvdb</name>
<shortdesc xml:lang='en'>GVariant Database file</shortdesc>
<description xml:lang='en'>
A simple database file format that stores a mapping from strings to
GVariant values in a way that is extremely efficient for lookups.
The database is written once and can not be modified.
Included here is reader code and a first-pass implementation of a
writer (that does not currently produce particularly optimised
output).
It is intended that this code be used by copy-pasting into your
project or by making use of git-merge(1).
</description>
<maintainer>
<foaf:Person>
<foaf:name>Ryan Lortie</foaf:name>
<foaf:mbox rdf:resource='mailto:desrt@desrt.ca'/>
<gnome:userid>ryanl</gnome:userid>
</foaf:Person>
</maintainer>
</Project>

View File

@ -1,35 +0,0 @@
# Check for bash
[ -z "$BASH_VERSION" ] && return
####################################################################################################
__flatpak() {
local IFS=$'\n'
local cur=`_get_cword :`
RES=($(flatpak complete "${COMP_LINE}" "${COMP_POINT}" "${cur}"))
COMPREPLY=()
for i in "${!RES[@]}"; do
if [[ "${RES[$i]}" = "__FLATPAK_FILE" ]]; then
if [[ "${cur}" = "=" ]]; then
CUR=""
else
CUR="${cur}"
fi
COMPREPLY=("${COMPREPLY[@]}" $(compgen -f -- "${CUR}") )
elif [[ "${RES[$i]}" = "__FLATPAK_DIR" ]]; then
if [[ "${cur}" = "=" ]]; then
CUR=""
else
CUR="${cur}"
fi
COMPREPLY=("${COMPREPLY[@]}" $(compgen -d -- "${CUR}") )
else
COMPREPLY=("${COMPREPLY[@]}" "${RES[$i]}")
fi
done
}
####################################################################################################
complete -o nospace -F __flatpak flatpak

View File

@ -22,14 +22,13 @@ m4_define([flatpak_binary_age],
m4_define([flatpak_version],
[flatpak_major_version.flatpak_minor_version.flatpak_micro_version])
AC_INIT([Flatpak],
AC_INIT([flatpak-builder],
[flatpak_version],
[https://github.com/flatpak/flatpak/issues],
[flatpak],
[http://flatpak.org/])
GLIB_REQS=2.44
SYSTEM_BWRAP_REQS=0.1.8
OSTREE_REQS=2017.10
AC_USE_SYSTEM_EXTENSIONS
@ -42,7 +41,7 @@ AC_DISABLE_STATIC
LT_PREREQ([2.2.6])
LT_INIT([disable-static])
AC_CONFIG_SRCDIR([common/flatpak-dir.c])
AC_CONFIG_SRCDIR([common/flatpak-utils.c])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([1.13.4 no-define no-dist-gzip dist-xz tar-ustar foreign subdir-objects])
@ -81,77 +80,7 @@ AX_VALGRIND_CHECK
PKG_PROG_PKG_CONFIG([0.24])
AC_ARG_WITH(privileged_group,
AS_HELP_STRING([--with-privileged-group=GROUP],[Name of privileged group, [default=wheel]]),
with_privileged_group="$withval", with_privileged_group=wheel)
PRIVILEGED_GROUP=$with_privileged_group
AC_SUBST(PRIVILEGED_GROUP)
AC_ARG_WITH(dbus_service_dir,
AS_HELP_STRING([--with-dbus-service-dir=PATH],[choose directory for dbus service files, [default=PREFIX/share/dbus-1/services]]),
with_dbus_service_dir="$withval", with_dbus_service_dir=$datadir/dbus-1/services)
DBUS_SERVICE_DIR=$with_dbus_service_dir
AC_SUBST(DBUS_SERVICE_DIR)
AC_ARG_WITH(dbus_config_dir,
AS_HELP_STRING([--with-dbus-config-dir=PATH],[choose directory for dbus config files, [default=SYSCONFDIR/dbus-1/system.d]]),
with_dbus_config_dir="$withval", with_dbus_config_dir=${sysconfdir}/dbus-1/system.d)
DBUS_CONFIG_DIR=$with_dbus_config_dir
AC_SUBST(DBUS_CONFIG_DIR)
AC_ARG_WITH([systemduserunitdir],
[AS_HELP_STRING([--with-systemduserunitdir=DIR],
[Directory for systemd user service files (default=PREFIX/lib/systemd/user)])],
[],
dnl This is deliberately not ${libdir}: systemd units always go in
dnl .../lib, never .../lib64 or .../lib/x86_64-linux-gnu
[with_systemduserunitdir='${prefix}/lib/systemd/user'])
AC_SUBST([systemduserunitdir], [$with_systemduserunitdir])
AC_ARG_WITH([systemdsystemunitdir],
[AS_HELP_STRING([--with-systemdsystemunitdir=DIR],
[Directory for systemd system service files (default=PREFIX/lib/systemd/system)])],
[],
dnl This is deliberately not ${libdir}: systemd units always go in
dnl .../lib, never .../lib64 or .../lib/x86_64-linux-gnu
[with_systemdsystemunitdir='${prefix}/lib/systemd/system'])
AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
AC_ARG_WITH(system_fonts_dir,
AS_HELP_STRING([--with-system-fonts-dir=PATH],[Directory where system fonts are, [default=/usr/share/fonts]]),
with_system_fonts_dir="$withval", with_system_fonts_dir=/usr/share/fonts)
SYSTEM_FONTS_DIR=$with_system_fonts_dir
AC_SUBST(SYSTEM_FONTS_DIR)
AC_ARG_WITH(profile_dir,
AS_HELP_STRING([--with-profile-dir=PATH],[choose directory for profile.d files, [default=SYSCONFDIR/profile.d]]),
with_profile_dir="$withval", with_profile_dir=${sysconfdir}/profile.d)
PROFILE_DIR=$with_profile_dir
AC_SUBST(PROFILE_DIR)
AC_ARG_VAR([BWRAP], [Bubblewrap executable])
AC_ARG_WITH([system-bubblewrap],
[AS_HELP_STRING([--with-system-bubblewrap], [Use system bwrap executable [default=check $BWRAP]])],
[BWRAP="$withval"],
[BWRAP="${BWRAP:-false}"])
AS_CASE([$BWRAP],
[yes],
[BWRAP=bwrap],
[no],
[BWRAP=false],
[auto],
[AC_CHECK_PROG([BWRAP], [bwrap], [bwrap], [false])])
if test "x$BWRAP" != xfalse; then
BWRAP_VERSION=`$BWRAP --version | sed 's,.*\ \([0-9]*\.[0-9]*\.[0-9]*\)$,\1,'`
AX_COMPARE_VERSION([$SYSTEM_BWRAP_REQS],[gt],[$BWRAP_VERSION],
AC_MSG_ERROR([You need at least version $SYSTEM_BWRAP_REQS of bubblewrap to use the system installed version]))
AM_CONDITIONAL([WITH_SYSTEM_BWRAP], [true])
else
AM_CONDITIONAL([WITH_SYSTEM_BWRAP], [false])
fi
AC_CHECK_FUNCS(fdwalk)
AC_CHECK_HEADER([sys/xattr.h], [], AC_MSG_ERROR([You must have sys/xattr.h from glibc]))
AC_CHECK_HEADER([sys/capability.h], have_caps=yes, AC_MSG_ERROR([sys/capability.h header not found]))
@ -159,112 +88,11 @@ AC_SUBST([GLIB_MKENUMS], [`$PKG_CONFIG --variable glib_mkenums glib-2.0`])
AC_SUBST([GLIB_COMPILE_RESOURCES], [`$PKG_CONFIG --variable glib_compile_resources gio-2.0`])
AC_SUBST([GDBUS_CODEGEN], [`$PKG_CONFIG --variable gdbus_codegen gio-2.0`])
POLKIT_GOBJECT_REQUIRED=0.98
PKG_CHECK_MODULES(BASE, [glib-2.0 >= $GLIB_REQS gio-2.0 gio-unix-2.0 libarchive >= 2.8.0 libxml-2.0 >= 2.4 ])
PKG_CHECK_MODULES(BASE, [glib-2.0 >= $GLIB_REQS gio-2.0 gio-unix-2.0 ])
PKG_CHECK_MODULES(SOUP, [libsoup-2.4])
save_LIBS=$LIBS
LIBS=$BASE_LIBS
AC_CHECK_FUNCS(archive_read_support_filter_all)
LIBS=$save_LIBS
LIBGPGME_DEPENDENCY="1.1.8"
PKG_CHECK_MODULES(DEP_GPGME, gpgme-pthread >= $LIBGPGME_DEPENDENCY, have_gpgme=yes, [
m4_ifdef([AM_PATH_GPGME_PTHREAD], [
AM_PATH_GPGME_PTHREAD($LIBGPGME_DEPENDENCY, have_gpgme=yes, have_gpgme=no)
],[ have_gpgme=no ])
])
AS_IF([ test x$have_gpgme = xno ], [
AC_MSG_ERROR([Need GPGME_PTHREAD version $LIBGPGME_DEPENDENCY or later])
])
AC_ARG_ENABLE([system-helper],
AC_HELP_STRING([--disable-system-helper],
[Disable system helper]),
[],
[enable_system_helper=yes])
if test "x$enable_system_helper" = "xyes"; then
PKG_CHECK_MODULES(POLKIT, \
polkit-gobject-1 >= $POLKIT_GOBJECT_REQUIRED)
AC_DEFINE([USE_SYSTEM_HELPER], [1], [Define if using system-helper])
fi
AM_CONDITIONAL(BUILD_SYSTEM_HELPER, test x$enable_system_helper = xyes)
AC_ARG_ENABLE([xauth],
AC_HELP_STRING([--disable-xauth],
[Disable Xauth use]),
[],
[enable_xauth=yes])
if test "x$enable_xauth" = "xyes"; then
PKG_CHECK_MODULES(XAUTH, [xau])
AC_DEFINE([ENABLE_XAUTH], [1],
[Define if using xauth])
fi
AC_ARG_ENABLE([sandboxed-triggers],
AC_HELP_STRING([--disable-sandboxed-triggers],
[Disable sandboxed triggers]),
[],
[enable_sandboxed_triggers=yes])
if test "x$enable_sandboxed_triggers" = "xno"; then
AC_DEFINE([DISABLE_SANDBOXED_TRIGGERS], [1],
[Define if sandboxed triggers are disabled])
fi
PKG_CHECK_MODULES(OSTREE, [ostree-1 >= $OSTREE_REQS])
PKG_CHECK_MODULES(FUSE, [fuse])
PKG_CHECK_MODULES(JSON, [json-glib-1.0])
AC_ARG_ENABLE([seccomp],
AC_HELP_STRING([--disable-seccomp],
[Disable seccomp]),
[],
[enable_seccomp=yes])
if test "x$enable_seccomp" = "xyes"; then
PKG_CHECK_MODULES(LIBSECCOMP, [libseccomp])
AC_DEFINE([ENABLE_SECCOMP], [1],
[Define if using seccomp])
fi
AC_ARG_WITH(priv-mode,
AS_HELP_STRING([--with-priv-mode=setuid/none],
[How to set privilege-raising during install (only needed if userns not working)]),
[],
[with_priv_mode="none"])
AM_CONDITIONAL(PRIV_MODE_SETUID, test "x$with_priv_mode" = "xsetuid")
AC_ARG_ENABLE(sudo,
AS_HELP_STRING([--enable-sudo],[Use sudo to set setuid flags on binaries during install (only needed if userns disabled)]),
[SUDO_BIN="sudo"], [SUDO_BIN=""])
AC_SUBST([SUDO_BIN])
# Do we enable building peer to peer support using libostrees experimental (non-stable) API?
# If so, OSTREE_ENABLE_EXPERIMENTAL_API needs to be #defined before ostree.h is
# included.
AC_ARG_ENABLE([p2p],
[AS_HELP_STRING([--enable-p2p],
[Enable unstable peer to peer support [default=no]])],,
[enable_p2p=no])
AS_IF([test x$enable_p2p = xyes],[
PKG_CHECK_MODULES(OSTREE, [ostree-1 >= $OSTREE_REQS])
ostree_features=$($PKG_CONFIG --variable=features ostree-1)
AS_CASE(["$ostree_features"],
[*experimental*],[have_ostree_experimental=yes])
AS_IF([test "x$have_ostree_experimental" != "xyes"],
[AC_MSG_ERROR([Experimental API not found in ostree-1, which is needed for --enable-p2p. OSTree must be compiled with --enable-experimental-api.])])
AC_DEFINE([OSTREE_ENABLE_EXPERIMENTAL_API],[1],[Define if libostree experimental API should be enabled])
AC_DEFINE([FLATPAK_ENABLE_P2P],[1],[Define if peer to peer support should be enabled])
])
AM_CONDITIONAL([ENABLE_P2P],[test x$enable_p2p = xyes])
dnl ************************
dnl *** check for libelf ***
dnl ************************
@ -287,14 +115,6 @@ if test x$have_libelf != xyes; then
AC_MSG_ERROR([libelf not found])
fi
AC_ARG_WITH(system-install-dir,
[AS_HELP_STRING([--with-system-install-dir=DIR],
[Location of system installation [LOCALSTATEDIR/lib/flatpak]])],
[],
[with_system_install_dir='$(localstatedir)/lib/flatpak'])
SYSTEM_INSTALL_DIR=$with_system_install_dir
AC_SUBST(SYSTEM_INSTALL_DIR)
dnl This only checks for the header, not the library.
AC_ARG_WITH([dwarf-header],
[AS_HELP_STRING([--with-dwarf-header],
@ -366,7 +186,6 @@ AM_CONDITIONAL([ENABLE_GTK_DOC], [false])
])
AM_CONDITIONAL([ENABLE_GTK_DOC_CHECK], [test "x$enable_gtk_doc_check" = xyes])
AC_ARG_ENABLE(docbook-docs,
[AS_HELP_STRING([--enable-docbook-docs],[build documentation (requires xmlto)])],
enable_docbook_docs=$enableval, enable_docbook_docs=auto)
@ -396,37 +215,6 @@ AM_CONDITIONAL(DOCBOOK_DOCS_ENABLED, test x$enable_docbook_docs = xyes)
AC_ARG_VAR([XMLTO],[Define/override the 'xmlto' location.])
AC_ARG_VAR([XMLTO_FLAGS],[Define/override 'xmlto' options, like '--skip-validation'.])
##################################################
# Visibility handling
##################################################
HIDDEN_VISIBILITY_CFLAGS=""
case "$host" in
*)
dnl on other compilers, check if we can do -fvisibility=hidden
SAVED_CFLAGS="${CFLAGS}"
CFLAGS="-fvisibility=hidden"
AC_MSG_CHECKING([for -fvisibility=hidden compiler flag])
AC_TRY_COMPILE([], [int main (void) { return 0; }],
AC_MSG_RESULT(yes)
enable_fvisibility_hidden=yes,
AC_MSG_RESULT(no)
enable_fvisibility_hidden=no)
CFLAGS="${SAVED_CFLAGS}"
AS_IF([test "${enable_fvisibility_hidden}" = "yes"], [
AC_DEFINE([FLATPAK_EXTERN], [__attribute__((visibility("default"))) extern],
[defines how to decorate public symbols while building])
HIDDEN_VISIBILITY_CFLAGS="-fvisibility=hidden"
], [
AC_DEFINE([FLATPAK_EXTERN], [extern],
[defines how to decorate public symbols while building])
])
;;
esac
AC_SUBST(HIDDEN_VISIBILITY_CFLAGS)
GLIB_TESTS
FLATPAK_MAJOR_VERSION=flatpak_major_version
@ -462,11 +250,7 @@ AC_CONFIG_FILES([
Makefile
doc/Makefile
doc/reference/Makefile
flatpak.pc
lib/flatpak-version-macros.h
doc/reference/version.xml
doc/flatpak-docs.xml
po/Makefile.in
doc/flatpak-builder-docs.xml
])
AC_OUTPUT
@ -477,14 +261,6 @@ else
fi
echo ""
echo " Flatpak $FLATPAK_VERSION"
echo " ============="
echo ""
echo " Build system helper: $enable_system_helper"
echo " Build bubblewrap: $build_bwrap"
echo " Use sandboxed triggers: $enable_sandboxed_triggers"
echo " Use seccomp: $enable_seccomp"
echo " Privileged group: $PRIVILEGED_GROUP"
echo " Privilege mode: $with_priv_mode"
echo " Peer to peer support: $enable_p2p"
echo " flatpak-builder $FLATPAK_VERSION"
echo " ============================="
echo ""

View File

@ -1,13 +0,0 @@
introspectiondir = $(datadir)/dbus-1/interfaces
introspection_DATA = \
data/org.freedesktop.impl.portal.PermissionStore.xml \
data/org.freedesktop.portal.Documents.xml \
data/org.freedesktop.Flatpak.xml \
$(NULL)
EXTRA_DIST += \
data/org.freedesktop.portal.Documents.xml \
data/org.freedesktop.impl.portal.PermissionStore.xml \
data/org.freedesktop.systemd1.xml \
data/org.freedesktop.Flatpak.xml \
$(NULL)

View File

@ -1,116 +0,0 @@
<!DOCTYPE node PUBLIC
"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<!--
Copyright (C) 2015 Red Hat, Inc.
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
Author: Alexander Larsson <alexl@redhat.com>
-->
<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
<interface name='org.freedesktop.Flatpak.SessionHelper'>
<property name="version" type="u" access="read"/>
<method name="RequestMonitor">
<arg type='ay' name='path' direction='out'/>
</method>
</interface>
<interface name='org.freedesktop.Flatpak.Development'>
<property name="version" type="u" access="read"/>
<!-- This methods let you start processes, sandboxed or not on the
host, so its not generally safe to allow access to it to any
application. However, at times it is very useful to be able
to do this. For instance for developer tools this lets you
build flatpaks from inside a flatpak. -->
<method name="HostCommand">
<arg type='ay' name='cwd_path' direction='in'/>
<arg type='aay' name='argv' direction='in'/>
<arg type='a{uh}' name='fds' direction='in'/>
<arg type='a{ss}' name='envs' direction='in'/>
<arg type='u' name='flags' direction='in'/>
<arg type='u' name='pid' direction='out'/>
</method>
<method name="HostCommandSignal">
<arg type='u' name='pid' direction='in'/>
<arg type='u' name='signal' direction='in'/>
<arg type='b' name='to_process_group' direction='in'/>
</method>
<signal name="HostCommandExited">
<arg type='u' name='pid' direction='out'/>
<arg type='u' name='exit_status' direction='out'/>
</signal>
</interface>
<interface name='org.freedesktop.Flatpak.SystemHelper'>
<property name="version" type="u" access="read"/>
<method name="Deploy">
<arg type='ay' name='repo_path' direction='in'/>
<arg type='u' name='flags' direction='in'/>
<arg type='s' name='ref' direction='in'/>
<arg type='s' name='origin' direction='in'/>
<arg type='as' name='subpaths' direction='in'/>
<arg type='s' name='installation' direction='in'/>
</method>
<method name="DeployAppstream">
<arg type='ay' name='repo_path' direction='in'/>
<arg type='s' name='origin' direction='in'/>
<arg type='s' name='arch' direction='in'/>
<arg type='s' name='installation' direction='in'/>
</method>
<method name="Uninstall">
<arg type='u' name='flags' direction='in'/>
<arg type='s' name='ref' direction='in'/>
<arg type='s' name='installation' direction='in'/>
</method>
<method name="InstallBundle">
<arg type='ay' name='bundle_path' direction='in'/>
<arg type='u' name='flags' direction='in'/>
<arg type='s' name='remote' direction='in'/>
<arg type='s' name='installation' direction='in'/>
<arg type='s' name='ref' direction='out'/>
</method>
<method name="ConfigureRemote">
<arg type='u' name='flags' direction='in'/>
<arg type='s' name='remote' direction='in'/>
<arg type='s' name='config' direction='in'/>
<arg type='ay' name='gpg_key' direction='in'>
<annotation name="org.gtk.GDBus.C.ForceGVariant" value="true"/>
</arg>
<arg type='s' name='installation' direction='in'/>
</method>
<method name="UpdateRemote">
<arg type='u' name='flags' direction='in'/>
<arg type='s' name='remote' direction='in'/>
<arg type='s' name='installation' direction='in'/>
<arg type='ay' name='summary_path' direction='in'/>
<arg type='ay' name='summary_sig_path' direction='in'/>
</method>
</interface>
</node>

View File

@ -1,163 +0,0 @@
<!DOCTYPE node PUBLIC
"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<!--
Copyright (C) 2015 Red Hat, Inc.
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
Author: Alexander Larsson <alexl@redhat.com>
-->
<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
<!--
org.freedesktop.impl.portal.PermissionStore:
@short_description: Database to store permissions
The permission store can be used by portals to store permissions
that sandboxed applications have to various resources, such as
files outside the sandbox.
Since the resources managed by portals can be varied, the permission
store is fairly free-form: there can be multiple tables; resources are
identified by an ID, as are applications, and permissions are stored as
string arrays. None of these strings are interpreted by the permission
store in any way.
In addition, the permission store allows to associate extra data
(in the form of a GVariant) with each resource.
-->
<interface name='org.freedesktop.impl.portal.PermissionStore'>
<property name="version" type="u" access="read"/>
<!--
Lookup:
@table: the name of the table to use
@id: the resource ID to look up
@permissions: map from application ID to permissions
@data: data that is associated with the resource
Looks up the entry for a resource in one of the tables and returns
all associated application permissions and data.
-->
<method name="Lookup">
<arg name='table' type='s' direction='in'/>
<arg name='id' type='s' direction='in'/>
<arg name='permissions' type='a{sas}' direction='out'/>
<arg name='data' type='v' direction='out'/>
</method>
<!--
Set:
@table: the name of the table to use
@create: whether to create the table if it does not exist
@id: the resource ID to modify
@app_permissions: map from application ID to permissions
@data: data to associate with the resource
Writes the entry for a resource in the given table.
-->
<method name="Set">
<arg name='table' type='s' direction='in'/>
<arg name='create' type='b' direction='in'/>
<arg name='id' type='s' direction='in'/>
<arg name='app_permissions' type='a{sas}' direction='in'/>
<arg name='data' type='v' direction='in'/>
</method>
<!--
Delete:
@table: the name of the table to use
@id: the resource ID to delete
Removes the entry for a resource in the given table.
-->
<method name="Delete">
<arg name='table' type='s' direction='in'/>
<arg name='id' type='s' direction='in'/>
</method>
<!--
SetValue:
@table: the name of the table to use
@create: whether to create the table if it does not exist
@id: the resource ID to modify
@data: data to associate with the resource
Sets just the data for a resource in the given table.
-->
<method name="SetValue">
<arg name='table' type='s' direction='in'/>
<arg name='create' type='b' direction='in'/>
<arg name='id' type='s' direction='in'/>
<arg name='data' type='v' direction='in'/>
</method>
<!--
SetPermission:
@table: the name of the table to use
@create: whether to create the table if it does not exist
@id: the resource ID to modify
@app: the application ID to modify
@permissions: permissions to set
Sets the permissions for an application and a resource
in the given table.
-->
<method name="SetPermission">
<arg name='table' type='s' direction='in'/>
<arg name='create' type='b' direction='in'/>
<arg name='id' type='s' direction='in'/>
<arg name='app' type='s' direction='in'/>
<arg name='permissions' type='as' direction='in'/>
</method>
<!--
List:
@table: the name of the table to use
@ids: IDs of all resources that are present in the table
Returns all the resources that are present in the table.
-->
<method name="List">
<arg name='table' type='s' direction='in'/>
<arg name='ids' type='as' direction='out'/>
</method>
<!--
Changed:
@table: the name of the table
@ids: IDs of the changed resource
@deleted: whether the resource was deleted
@data: the data that is associated the resource
@permissions: the permissions that are associated with the resource
The Changed signal is emitted when the entry for a resource
is modified or deleted. If the entry was deleted, then @data
and @permissions contain the last values that were found in the
database. If the entry was modified, they contain the new values.
-->
<signal name="Changed">
<arg name='table' type='s' direction='out'/>
<arg name='id' type='s' direction='out'/>
<arg name='deleted' type='b' direction='out'/>
<arg name='data' type='v' direction='out'/>
<arg name='permissions' type='a{sas}' direction='out'/>
</signal>
</interface>
</node>

View File

@ -1,231 +0,0 @@
<!DOCTYPE node PUBLIC
"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<!--
Copyright (C) 2015 Red Hat, Inc.
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., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
Author: Alexander Larsson <alexl@redhat.com>
-->
<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
<!--
org.freedesktop.portal.Documents:
@short_description: Document portal
The document portal allows to make files from the outside world
available to sandboxed applications in a controlled way.
Exported files will be made accessible to the application via
a fuse filesystem that gets mounted at /run/user/$UID/doc/. The
filesystem gets mounted both outside and inside the sandbox, but
the view inside the sandbox is restricted to just those files
that the application is allowed to access.
Individual files will appear at /run/user/$UID/doc/$DOC_ID/filename,
where $DOC_ID is the ID of the file in the document store. It is
returned by the org.freedesktop.portal.Documents.Add() and
org.freedesktop.portal.Documents.AddNamed() calls.
The permissions that the application has for a document store entry
(see org.freedesktop.portal.Documents.GrantPermissions()) are reflected
in the POSIX mode bits in the fuse filesystem.
-->
<interface name='org.freedesktop.portal.Documents'>
<property name="version" type="u" access="read"/>
<!--
GetMountPoint:
@path: the path at which the fuse filesystem is mounted
Returns the path at which the document store fuse filesystem
is mounted. This will typically be /run/user/$UID/doc/.
-->
<method name="GetMountPoint">
<arg type='ay' name='path' direction='out'/>
</method>
<!--
Add:
@o_path_fd: open file descriptor for the file to add
@reuse_existing: whether to reuse an existing document store entry for the file
@persistent: whether to add the file only for this session or permanently
@doc_id: the ID of the file in the document store
Adds a file to the document store. The file is passed in the
form of an open file descriptor to prove that the caller has
access to the file.
-->
<method name="Add">
<arg type='h' name='o_path_fd' direction='in'/>
<arg type='b' name='reuse_existing' direction='in'/>
<arg type='b' name='persistent' direction='in'/>
<arg type='s' name='doc_id' direction='out'/>
</method>
<!--
AddNamed:
@o_path_parent_fd: open file descriptor for the parent directory
@filename: the basename for the file
@reuse_existing: whether to reuse an existing document store entry for the file
@persistent: whether to add the file only for this session or permanently
@doc_id: the ID of the file in the document store
Creates an entry in the document store for writing a new file.
-->
<method name="AddNamed">
<arg type='h' name='o_path_parent_fd' direction='in'/>
<arg type='ay' name='filename' direction='in'/>
<arg type='b' name='reuse_existing' direction='in'/>
<arg type='b' name='persistent' direction='in'/>
<arg type='s' name='doc_id' direction='out'/>
</method>
<!--
AddFull:
@o_path_fds: open file descriptors for the files to export
@flags: flags, 1 == reuse_existing, 2 == persistent, 3 == as-needed-by-app
@app_id: an application ID, or empty string
@permissions: the permissions to grant, possible values are 'read', 'write', 'grant-permissions' and 'delete'
@doc_ids: the IDs of the files in the document store
@extra_info: Extra info returned
Adds multiple files to the document store. The file is passed in the
form of an open file descriptor to prove that the caller has
access to the file.
If the as-needed-by-app flag is given, files will only be added to
the document store if the application does not already have access to them.
For files that are not added to the document store, the doc_ids array will
contain an empty string.
Additionally, if app_id is specified, it will be given the permissions
listed in GrantPermission.
The method also returns some extra info that can be used to avoid
multiple roundtrips. For now it only contains as "mountpoint", the
fuse mountpoint of the document portal.
This method was added in version 2 of the org.freedesktop.portal.Documents interface.
-->
<method name="AddFull">
<arg type='ah' name='o_path_fds' direction='in'/>
<arg type='u' name='flags' direction='in'/>
<arg type='s' name='app_id' direction='in'/>
<arg type='as' name='permissions' direction='in'/>
<arg type='as' name='doc_ids' direction='out'/>
<arg type='a{sv}' name='extra_out' direction='out'/>
</method>
<!--
GrantPermissions:
@doc_id: the ID of the file in the document store
@app_id: the ID of the application to which permissions are granted
@permissions: the permissions to grant, possible values are 'read', 'write', 'grant-permissions' and 'delete'
Grants access permissions for a file in the document store
to an application.
This call is available inside the sandbox if the application
has the 'grant-permissions' permission for the document.
-->
<method name="GrantPermissions">
<arg type='s' name='doc_id' direction='in'/>
<arg type='s' name='app_id' direction='in'/>
<arg type='as' name='permissions' direction='in'/>
</method>
<!--
RevokePermissions:
@doc_id: the ID of the file in the document store
@app_id: the ID of the application to which permissions are granted
@permissions: the permissions to grant, possible values are 'read', 'write', 'grant-permissions' and 'delete'
Revokes access permissions for a file in the document store
from an application.
This call is available inside the sandbox if the application
has the 'grant-permissions' permission for the document.
-->
<method name="RevokePermissions">
<arg type='s' name='doc_id' direction='in'/>
<arg type='s' name='app_id' direction='in'/>
<arg type='as' name='permissions' direction='in'/>
</method>
<!--
Delete:
@doc_id: the ID of the file in the document store
Removes an entry from the document store. The file itself is
not deleted.
This call is available inside the sandbox if the application
has the 'delete' permission for the document.
-->
<method name="Delete">
<arg type='s' name='doc_id' direction='in'/>
</method>
<!--
Lookup:
@filename: a path in the host filesystem
@doc_id: the ID of the file in the document store, or '' if the file is not in the document store
Looks up the document ID for a file.
This call is no not available inside the sandbox.
-->
<method name="Lookup">
<arg type='ay' name='filename' direction='in'/>
<arg type='s' name='doc_id' direction='out'/>
</method>
<!--
Info:
@doc_id: the ID of the file in the document store
@path: the path for the file in the host filesystem
@apps: a dictionary mapping application IDs to the permissions for that application
Gets the filesystem path and application permissions for a document store
entry.
This call is not available inside the sandbox.
-->
<method name="Info">
<arg type='s' name='doc_id' direction='in'/>
<arg type='ay' name='path' direction='out'/>
<arg type='a{sas}' name='apps' direction='out'/>
</method>
<!--
List:
@app_id: an application ID, or '' to list all documents
@docs: a dictonary mapping document IDs to their filesystem path
Lists documents in the document store for an application (or for
all applications).
This call is not available inside the sandbox.
-->
<method name="List">
<arg type='s' name='app_id' direction='in'/>
<arg type='a{say}' name='docs' direction='out'/>
</method>
</interface>
</node>

View File

@ -1,19 +0,0 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.freedesktop.systemd1.Manager">
<method name="StartTransientUnit">
<arg type="s" direction="in" name="name"/>
<arg type="s" direction="in" name="mode"/>
<arg type="a(sv)" direction="in" name="properties"/>
<arg type="a(sa(sv))" direction="in" name="aux"/>
<arg type="o" direction="out" name="job"/>
</method>
<signal name="JobRemoved">
<arg type="u" name="id"/>
<arg type="o" name="job"/>
<arg type="s" name="unit"/>
<arg type="s" name="result"/>
</signal>
</interface>
</node>

View File

@ -1,12 +0,0 @@
libexec_PROGRAMS += \
flatpak-dbus-proxy \
$(NULL)
flatpak_dbus_proxy_SOURCES = \
dbus-proxy/flatpak-proxy.c \
dbus-proxy/flatpak-proxy.h \
dbus-proxy/dbus-proxy.c \
$(NULL)
flatpak_dbus_proxy_LDADD = $(AM_LDADD) $(BASE_LIBS) libglnx.la
flatpak_dbus_proxy_CFLAGS = $(AM_CFLAGS) $(BASE_CFLAGS) -I$(srcdir)/dbus-proxy

View File

@ -1,223 +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 <string.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include "libglnx/libglnx.h"
#include "flatpak-proxy.h"
static GList *proxies;
static int sync_fd = -1;
static int
parse_generic_args (int n_args, const char *args[])
{
if (g_str_has_prefix (args[0], "--fd="))
{
const char *fd_s = args[0] + strlen ("--fd=");
char *endptr;
int fd;
fd = strtol (fd_s, &endptr, 10);
if (fd < 0 || endptr == fd_s || *endptr != 0)
{
g_printerr ("Invalid fd %s\n", fd_s);
return -1;
}
sync_fd = fd;
return 1;
}
else
{
g_printerr ("Unknown argument %s\n", args[0]);
return -1;
}
}
static int
start_proxy (int n_args, const char *args[])
{
g_autoptr(FlatpakProxy) proxy = NULL;
g_autoptr(GError) error = NULL;
const char *bus_address, *socket_path;
int n;
n = 0;
if (n_args < n + 1 || args[n][0] == '-')
{
g_printerr ("No bus address given\n");
return -1;
}
bus_address = args[n++];
if (n_args < n + 1 || args[n][0] == '-')
{
g_printerr ("No socket path given\n");
return -1;
}
socket_path = args[n++];
proxy = flatpak_proxy_new (bus_address, socket_path);
while (n < n_args)
{
if (args[n][0] != '-')
break;
if (g_str_has_prefix (args[n], "--see=") ||
g_str_has_prefix (args[n], "--talk=") ||
g_str_has_prefix (args[n], "--own="))
{
FlatpakPolicy policy = FLATPAK_POLICY_SEE;
g_autofree char *name = NULL;
gboolean wildcard = FALSE;
if (args[n][2] == 't')
policy = FLATPAK_POLICY_TALK;
else if (args[n][2] == 'o')
policy = FLATPAK_POLICY_OWN;
name = g_strdup (strchr (args[n], '=') + 1);
if (g_str_has_suffix (name, ".*"))
{
name[strlen (name) - 2] = 0;
wildcard = TRUE;
}
if (name[0] == ':' || !g_dbus_is_name (name))
{
g_printerr ("'%s' is not a valid dbus name\n", name);
return -1;
}
if (wildcard)
flatpak_proxy_add_wildcarded_policy (proxy, name, policy);
else
flatpak_proxy_add_policy (proxy, name, policy);
}
else if (g_str_equal (args[n], "--log"))
{
flatpak_proxy_set_log_messages (proxy, TRUE);
}
else if (g_str_equal (args[n], "--filter"))
{
flatpak_proxy_set_filter (proxy, TRUE);
}
else
{
int res = parse_generic_args (n_args - n, &args[n]);
if (res == -1)
return -1;
n += res - 1; /* res - 1, because we ++ below */
}
n++;
}
if (!flatpak_proxy_start (proxy, &error))
{
g_printerr ("Failed to start proxy for %s: %s\n", bus_address, error->message);
return -1;
}
proxies = g_list_prepend (proxies, g_object_ref (proxy));
return n;
}
static gboolean
sync_closed_cb (GIOChannel *source,
GIOCondition condition,
gpointer data)
{
GList *l;
for (l = proxies; l != NULL; l = l->next)
flatpak_proxy_stop (FLATPAK_PROXY (l->data));
exit (0);
return TRUE;
}
int
main (int argc, const char *argv[])
{
GMainLoop *service_loop;
int n_args, res;
const char **args;
n_args = argc - 1;
args = &argv[1];
while (n_args > 0)
{
if (args[0][0] == '-')
{
res = parse_generic_args (n_args, &args[0]);
if (res == -1)
return 1;
}
else
{
res = start_proxy (n_args, args);
if (res == -1)
return 1;
}
g_assert (res > 0);
n_args -= res;
args += res;
}
if (proxies == NULL)
{
g_printerr ("No proxies specified\n");
return 1;
}
if (sync_fd >= 0)
{
ssize_t written;
GIOChannel *sync_channel;
written = write (sync_fd, "x", 1);
if (written != 1)
g_warning ("Can't write to sync socket");
sync_channel = g_io_channel_unix_new (sync_fd);
g_io_add_watch (sync_channel, G_IO_ERR | G_IO_HUP,
sync_closed_cb, NULL);
}
service_loop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (service_loop);
g_main_loop_unref (service_loop);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,60 +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 __FLATPAK_PROXY_H__
#define __FLATPAK_PROXY_H__
#include <gio/gio.h>
#include "libglnx/libglnx.h"
typedef enum {
FLATPAK_POLICY_NONE,
FLATPAK_POLICY_SEE,
FLATPAK_POLICY_TALK,
FLATPAK_POLICY_OWN
} FlatpakPolicy;
typedef struct FlatpakProxy FlatpakProxy;
#define FLATPAK_TYPE_PROXY flatpak_proxy_get_type ()
#define FLATPAK_PROXY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FLATPAK_TYPE_PROXY, FlatpakProxy))
#define FLATPAK_IS_PROXY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FLATPAK_TYPE_PROXY))
G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakProxy, g_object_unref)
GType flatpak_proxy_get_type (void);
FlatpakProxy *flatpak_proxy_new (const char *dbus_address,
const char *socket_path);
void flatpak_proxy_set_log_messages (FlatpakProxy *proxy,
gboolean log);
void flatpak_proxy_set_filter (FlatpakProxy *proxy,
gboolean filter);
void flatpak_proxy_add_policy (FlatpakProxy *proxy,
const char *name,
FlatpakPolicy policy);
void flatpak_proxy_add_wildcarded_policy (FlatpakProxy *proxy,
const char *name,
FlatpakPolicy policy);
gboolean flatpak_proxy_start (FlatpakProxy *proxy,
GError **error);
void flatpak_proxy_stop (FlatpakProxy *proxy);
#endif /* __FLATPAK_PROXY_H__ */

View File

@ -1,2 +0,0 @@
[Service]
Environment=XDG_DATA_DIRS=%h/.local/share/flatpak/exports/share/:@localstatedir@/lib/flatpak/exports/share/:/usr/local/share/:/usr/share/

View File

@ -1,7 +1,5 @@
NULL =
SUBDIRS = reference
XSLTPROC_FLAGS = \
--nonet \
--stringparam man.output.quietly 1 \
@ -18,45 +16,11 @@ XSLTPROC_FLAGS = \
$(AM_V_GEN) $(XSLTPROC) $(XSLTPROC_FLAGS) http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
man1 = \
flatpak.1 \
flatpak-remotes.1 \
flatpak-remote-add.1 \
flatpak-remote-delete.1 \
flatpak-remote-modify.1 \
flatpak-remote-ls.1 \
flatpak-install.1 \
flatpak-update.1 \
flatpak-uninstall.1 \
flatpak-list.1 \
flatpak-info.1 \
flatpak-make-current.1 \
flatpak-run.1 \
flatpak-override.1 \
flatpak-enter.1 \
flatpak-document-export.1 \
flatpak-document-unexport.1 \
flatpak-document-info.1 \
flatpak-document-list.1 \
flatpak-build-init.1 \
flatpak-build.1 \
flatpak-build-bundle.1 \
flatpak-build-import-bundle.1 \
flatpak-build-finish.1 \
flatpak-build-export.1 \
flatpak-build-update-repo.1 \
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 \
flatpak-remote.5 \
flatpak-installation.5 \
$(NULL)
man_MANS = \
@ -72,26 +36,26 @@ xml_files = \
EXTRA_DIST = \
$(xml_files) \
docbook.css \
flatpak-docs.xml.in \
flatpak-builder-docs.xml.in \
xmlto-config.xsl \
$(NULL)
CLEANFILES = $(NULL)
DISTCLEANFILES = \
$(man_MANS) \
flatpak-docs.xml \
flatpak-builder-docs.xml \
$(NULL)
if DOCBOOK_DOCS_ENABLED
doc_DATA = \
flatpak-docs.html \
flatpak-builder-docs.html \
docbook.css \
$(NULL)
CLEANFILES += flatpak-docs.html
CLEANFILES += flatpak-builder-docs.html
flatpak-docs.html: flatpak-docs.xml $(xml_files) xmlto-config.xsl
flatpak-builder-docs.html: flatpak-builder-docs.xml $(xml_files) xmlto-config.xsl
$(AM_V_GEN) $(XMLTO) $(XMLTO_FLAGS) --skip-validation xhtml-nochunks -m $(srcdir)/xmlto-config.xsl $<
endif # DOCBOOK_DOCS_ENABLED

View File

@ -1,174 +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-build-bundle">
<refentryinfo>
<title>flatpak build-bundle</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 build-bundle</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>flatpak-build-bundle</refname>
<refpurpose>Create a single-file bundle from a local repository</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>flatpak build-bundle</command>
<arg choice="opt" rep="repeat">OPTION</arg>
<arg choice="plain">LOCATION</arg>
<arg choice="plain">FILENAME</arg>
<arg choice="plain">NAME</arg>
<arg choice="opt">BRANCH</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
Creates a single-file named <arg choice="plain">FILENAME</arg>
for the application (or runtime) named <arg choice="plain">NAME</arg>
in the repository at <arg choice="plain">LOCATION</arg>. If
a <arg choice="plain">BRANCH</arg> is specified, this branch of
the application is used.
<!-- FIXME: Uncomment this when enable-p2p is enabled unconditionally.
The collection ID set on the repository at
<arg choice="plain">LOCATION</arg> (if set) will be used for the
bundle.
-->
</para>
<para>
The format of the bundle file is that of an ostree static delta
(against an empty base) with some flatpak specific metadata for
the application icons and appdata.
</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>--runtime</option></term>
<listitem><para>
Export a runtime instead of an application.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--arch=ARCH</option></term>
<listitem><para>
The arch to create a bundle for.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--repo-url=URL</option></term>
<listitem><para>
The URL for the repository from which the
application can be updated. Installing the
bundle will automatically configure a remote
for this URL.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--runtime-repo=URL</option></term>
<listitem><para>
The URL for a .flatpakrepo file that contains
the information about the repository that supplies
the runtimes required by the app.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--gpg-keys=FILE</option></term>
<listitem><para>
Add the GPG key from FILE (use - for stdin).
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--gpg-homedir=PATH</option></term>
<listitem><para>
GPG Homedir to use when looking for keyrings.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--oci</option></term>
<listitem><para>
Export to an OCI image instead of a Flatpak bundle.
</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>
</variablelist>
</refsect1>
<refsect1>
<title>See also</title>
<para>
<citerefentry><refentrytitle>ostree</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak</refentrytitle><manvolnum>1</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-import-bundle</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak-repo-update</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@ -1,231 +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-build-commit-from">
<refentryinfo>
<title>flatpak build-commit-from</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 build-commit-from</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>flatpak-build-commit-from</refname>
<refpurpose>Create new commits based on existing one (possibly from another repository)</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>flatpak build-commit-from</command>
<arg choice="opt" rep="repeat">OPTION</arg>
<arg choice="plain">DST-REPO</arg>
<arg choice="plain" rep="repeat">DST-REF</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
Creates new commits on the <arg choice="plain">DST-REF</arg>
branch in the <arg choice="plain">DST-REPO</arg>, with the
contents (and most of the metadata) taken from another
branch, either from another repo, or from another branch in
the same repository.
<!-- FIXME: Uncomment this when enable-p2p is enabled unconditionally.
The collection ID set on
<arg choice="plain">DST-REPO</arg> (if set) will be used for the
newly created commits.
-->
</para>
<para>
This command is very useful when you want to maintain a branch
with a clean history that has no unsigned or broken commits.
For instance, you can import the head from a different repository
from an automatic builder when you've verified that it worked.
The new commit will have no parents or signatures from the
autobuilder, and can be properly signed with the official
key.
</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>--src-repo=SRC-REPO</option></term>
<listitem><para>
The (local) repository to pull the source branch from. Defaults to the
destination repository.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--src-ref=SRC-REF</option></term>
<listitem><para>
The branch to use as the source for the new commit. Defaults to the same
as the destination ref, which is useful only if a different source repo
has been specified.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--untrusted</option></term>
<listitem><para>
The source repostory is not trusted, all objects are copied (not hardlinked) and
all checksums are verified.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-s</option></term>
<term><option>--subject=SUBJECT</option></term>
<listitem><para>
One line subject for the commit message. If not specified, will be taken from the source commit.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-b</option></term>
<term><option>--body=BODY</option></term>
<listitem><para>
Full description for the commit message. If not specified, will be taken from the source commit.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--update-appstream</option></term>
<listitem><para>
Run appstream-builder and to update the appstream branch after build.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--no-update-summary</option></term>
<listitem><para>
Don't update the summary file after the new commit is added. This means
the repository will not be useful for serving over http until build-repo-update
has been run. This is useful is you want to do multiple repo operations before
finally updating the summary.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--force</option></term>
<listitem><para>
Create new commit even if the content didn't change from the existing branch head.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--gpg-sign=KEYID</option></term>
<listitem><para>
Sign the commit with this GPG key.
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
</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>--ostree-verbose</option></term>
<listitem><para>
Print OSTree debug information during command processing.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--version</option></term>
<listitem><para>
Print version information and exit.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Examples</title>
<para>
<command>$ flatpak build-export ~/repos/gnome-calculator/ ~/build/gnome-calculator/ org.gnome.Calculator</command>
</para>
<programlisting>
Commit: 9d0044ea480297114d03aec85c3d7ae3779438f9d2cb69d717fb54237acacb8c
Metadata Total: 605
Metadata Written: 5
Content Total: 1174
Content Written: 1
Content Bytes Written: 305
</programlisting>
</refsect1>
<refsect1>
<title>See also</title>
<para>
<citerefentry><refentrytitle>ostree</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak</refentrytitle><manvolnum>1</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-sign</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak-repo-update</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@ -1,280 +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-build-export">
<refentryinfo>
<title>flatpak build-export</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 build-export</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>flatpak-build-export</refname>
<refpurpose>Create a repository from a build directory</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>flatpak build-export</command>
<arg choice="opt" rep="repeat">OPTION</arg>
<arg choice="plain">LOCATION</arg>
<arg choice="plain">DIRECTORY</arg>
<arg choice="opt">BRANCH</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
Creates or updates a repository with an application build.
<arg choice="plain">LOCATION</arg> is the location of the
repository. <arg choice="plain">DIRECTORY</arg> must be a
finalized build directory. If <arg choice="plain">BRANCH</arg>
is not specified, it is assumed to be "master".
</para>
<para>
If <arg choice="plain">LOCATION</arg> exists, it is assumed to
be an OSTree repository, otherwise a new OSTree repository is
created at this location. The repository can be inspected with
the <command>ostree</command> tool.
</para>
<para>
The contents of <arg choice="plain">DIRECTORY</arg> are committed
on the branch with name <literal>app/APPNAME/ARCH/BRANCH</literal>,
where ARCH is the architecture of the runtime that the application
is using. A commit filter is used to enforce that only the contents
of the <filename>files/</filename> and <filename>export/</filename>
subdirectories and the <filename>metadata</filename> file are included
in the commit, anything else is ignored.
</para>
<!-- FIXME: Uncomment this when enable-p2p is enabled unconditionally.
<para>
When exporting 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>
-->
<para>
The build-update-repo command should be used to update repository
metadata whenever application builds are added to a repository.
</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>-s</option></term>
<term><option>--subject=SUBJECT</option></term>
<listitem><para>
One line subject for the commit message.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-b</option></term>
<term><option>--body=BODY</option></term>
<listitem><para>
Full description for the commit message.
</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 exporting to an existing repository, the collection ID
must match the existing configured collection ID for that
repository.
</para></listitem>
</varlistentry>
-->
<varlistentry>
<term><option>--arch=ARCH</option></term>
<listitem><para>
Specify the architecture component of the branch to export. Only host compatible architectures can be specified.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--exclude=PATTERN</option></term>
<listitem><para>
Exclude files matching PATTERN from the commit.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--include=PATTERN</option></term>
<listitem><para>
Don't exclude files matching PATTERN from the commit, even if they match the --export patterns.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--metadata=FILENAME</option></term>
<listitem><para>
Use the specified filename as metadata in the exported app instead of
the default file (called <filename>metadata</filename>). This is useful
if you want to commit multiple things from a single build tree, typically
used in combination with --files and --exclude.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--files=SUBDIR</option></term>
<listitem><para>
Use the files in the specified subdirectory as the file contents, rather
than the regular <filename>files</filename> directory.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--update-appstream</option></term>
<listitem><para>
Run appstream-builder and to update the appstream branch after build.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--no-update-summary</option></term>
<listitem><para>
Don't update the summary file after the new commit is added. This means
the repository will not be useful for serving over http until build-repo-update
has been run. This is useful is you want to do multiple repo operations before
finally updating the summary.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--gpg-sign=KEYID</option></term>
<listitem><para>
Sign the commit with this GPG key.
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
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-r</option></term>
<term><option>--runtime</option></term>
<listitem><para>
Export a runtime instead for an app (this uses the usr subdir as files).
</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>--ostree-verbose</option></term>
<listitem><para>
Print OSTree debug information during command processing.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--version</option></term>
<listitem><para>
Print version information and exit.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Examples</title>
<para>
<command>$ flatpak build-export ~/repos/gnome-calculator/ ~/build/gnome-calculator/ org.gnome.Calculator</command>
</para>
<programlisting>
Commit: 9d0044ea480297114d03aec85c3d7ae3779438f9d2cb69d717fb54237acacb8c
Metadata Total: 605
Metadata Written: 5
Content Total: 1174
Content Written: 1
Content Bytes Written: 305
</programlisting>
</refsect1>
<refsect1>
<title>See also</title>
<para>
<citerefentry><refentrytitle>ostree</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak</refentrytitle><manvolnum>1</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-sign</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak-repo-update</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@ -1,417 +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-build-finish">
<refentryinfo>
<title>flatpak build-finish</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 build-finish</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>flatpak-build-finish</refname>
<refpurpose>Finalize a build directory</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>flatpak build-finish</command>
<arg choice="opt" rep="repeat">OPTION</arg>
<arg choice="plain">DIRECTORY</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
Finalizes a build directory, to prepare it for exporting.
<arg choice="plain">DIRECTORY</arg> is the name of the directory.
</para>
<para>
The result of this command is that desktop files, icons and
D-Bus service files from the <filename>files</filename> subdirectory
are copied to a new <filename>export</filename> subdirectory. In the
<filename>metadata</filename> file, the command key is set in the
[Application] group, and the supported keys in the [Environment]
group are set according to the options.
</para>
<para>
You should review the exported files and the application metadata
before creating and distributing an application bundle.
</para>
<para>
It is an error to run build-finish on a directory that has not
been initialized as a build directory, or has already been finalized.
</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>--command=COMMAND</option></term>
<listitem><para>
The command to use. If this option is not specified,
the first executable found in <filename>files/bin</filename>
is used.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--require-version=MAJOR.MINOR.MICRO</option></term>
<listitem><para>
Require this version of later of flatpak to install/update to this build.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--share=SUBSYSTEM</option></term>
<listitem><para>
Share a subsystem with the host session. This updates
the [Context] group in the metadata.
SUBSYSTEM must be one of: network, ipc.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--unshare=SUBSYSTEM</option></term>
<listitem><para>
Don't share a subsystem with the host session. This updates
the [Context] group in the metadata.
SUBSYSTEM must be one of: network, ipc.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--socket=SOCKET</option></term>
<listitem><para>
Expose a well known socket to the application. This updates
the [Context] group in the metadata.
SOCKET must be one of: x11, wayland, pulseaudio, system-bus, session-bus.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--nosocket=SOCKET</option></term>
<listitem><para>
Don't expose a well known socket to the application. This updates
the [Context] group in the metadata.
SOCKET must be one of: x11, wayland, pulseaudio, system-bus, session-bus.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--device=DEVICE</option></term>
<listitem><para>
Expose a device to the application. This updates
the [Context] group in the metadata.
DEVICE must be one of: dri, kvm, all.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--nodevice=DEVICE</option></term>
<listitem><para>
Don't expose a device to the application. This updates
the [Context] group in the metadata.
DEVICE must be one of: dri, kvm, all.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--allow=FEATURE</option></term>
<listitem><para>
Allow access to a specific feature. This updates
the [Context] group in the metadata.
FEATURE must be one of: devel, multiarch.
This option can be used multiple times.
</para><para>
The <code>devel</code> feature allows the application to
access certain syscalls such as <code>ptrace()</code>, and
<code>perf_event_open()</code>.
</para><para>
The <code>multiarch</code> feature allows the application to
execute programs compiled for an ABI other than the one supported
natively by the system. For example, for the <code>x86_64</code>
architecture, 32-bit <code>x86</code> binaries will be allowed as
well.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--disallow=FEATURE</option></term>
<listitem><para>
Disallow access to a specific feature. This updates
the [Context] group in the metadata.
FEATURE must be one of: devel, multiarch.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--filesystem=FS</option></term>
<listitem><para>
Allow the application access to a subset of the filesystem.
This updates the [Context] group in the metadata.
FS can be one of: home, host, xdg-desktop, xdg-documents, xdg-download
xdg-music, xdg-pictures, xdg-public-share, xdg-templates, xdg-videos, xdg-run,
xdg-config, xdg-cache, xdg-data, an absolute path, or a homedir-relative
path like ~/dir or paths relative to the xdg dirs, like xdg-download/subdir.
The optional :ro suffix indicates that the location will be read-only.
The optional :create suffix indicates that the location will be read-write and created if it doesn't exist.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--nofilesystem=FILESYSTEM</option></term>
<listitem><para>
Remove access to the specified subset of the filesystem from
the application. This overrides to the Context section from the
application metadata.
FILESYSTEM can be one of: home, host, xdg-desktop, xdg-documents, xdg-download
xdg-music, xdg-pictures, xdg-public-share, xdg-templates, xdg-videos,
an absolute path, or a homedir-relative path like ~/dir.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--add-policy=SUBSYSTEM.KEY=VALUE</option></term>
<listitem><para>
Add generic policy option. For example, "--add-policy=subsystem.key=v1 --add-policy=subsystem.key=v2" would map to this metadata:
<programlisting>
[Policy subsystem]
key=v1;v2;
</programlisting>
</para></listitem>
<listitem><para>
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--remove-policy=SUBSYSTEM.KEY=VALUE</option></term>
<listitem><para>
Remove generic policy option. This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--env=VAR=VALUE</option></term>
<listitem><para>
Set an environment variable in the application.
This updates the [Environment] group in the metadata.
This overrides to the Context section from the application metadata.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--own-name=NAME</option></term>
<listitem><para>
Allow the application to own the well known name NAME on the session bus.
If NAME ends with .*, it allows the application to own all matching names.
This updates the [Session Bus Policy] group in the metadata.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--talk-name=NAME</option></term>
<listitem><para>
Allow the application to talk to the well known name NAME on the session bus.
If NAME ends with .*, it allows the application to talk to all matching names.
This updates the [Session Bus Policy] group in the metadata.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--system-own-name=NAME</option></term>
<listitem><para>
Allow the application to own the well known name NAME on the system bus.
If NAME ends with .*, it allows the application to own all matching names.
This updates the [System Bus Policy] group in the metadata.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--system-talk-name=NAME</option></term>
<listitem><para>
Allow the application to talk to the well known name NAME on the system bus.
If NAME ends with .*, it allows the application to talk to all matching names.
This updates the [System Bus Policy] group in the metadata.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--persist=FILENAME</option></term>
<listitem><para>
If the application doesn't have access to the real homedir, make the (homedir-relative) path
FILENAME a bind mount to the corresponding path in the per-application directory,
allowing that location to be used for persistent data.
This updates the [Context] group in the metadata.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--runtime=RUNTIME</option></term>
<term><option>--sdk=SDK</option></term>
<listitem><para>
Change the runtime or sdk used by the app to the specified partial ref. Unspecified parts
of the ref are taken from the old values or defaults.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--metadata=GROUP=KEY[=VALUE]</option></term>
<listitem><para>
Set a generic key in the metadata file. If value is left out it will
be set to "true".
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--extension=NAME=VARIABLE[=VALUE]</option></term>
<listitem><para>
Add extension point info.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--extra-data=NAME:SHA256:DOWNLOAD-SIZE:INSTALL-SIZE:URL</option></term>
<listitem><para>
Adds information about extra data uris to the app. These will be downloaded
and verified by the client when the app is installed and placed in the
/app/extra directory. You can also supply an /app/bin/apply_extra script
that will be run after the files are downloaded.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--no-exports</option></term>
<listitem><para>
Don't look for exports in the build.
</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>--ostree-verbose</option></term>
<listitem><para>
Print OSTree debug information during command processing.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--version</option></term>
<listitem><para>
Print version information and exit.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Examples</title>
<para>
<command>$ flatpak build-finish /build/my-app --socket=x11 --share=ipc</command>
</para>
<programlisting>
Exporting share/applications/gnome-calculator.desktop
Exporting share/dbus-1/services/org.gnome.Calculator.SearchProvider.service
More than one executable
Using gcalccmd as command
Please review the exported files and the metadata
</programlisting>
</refsect1>
<refsect1>
<title>See also</title>
<para>
<citerefentry><refentrytitle>flatpak</refentrytitle><manvolnum>1</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-export</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@ -1,158 +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-build-import-bundle">
<refentryinfo>
<title>flatpak build-import-bundle</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 build-import-bundle</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>flatpak-build-import-bundle</refname>
<refpurpose>Import a file bundle into a local repository</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>flatpak build-import-bundle</command>
<arg choice="opt" rep="repeat">OPTION</arg>
<arg choice="plain">LOCATION</arg>
<arg choice="plain">FILENAME</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
Imports a bundle from a file named <arg choice="plain">FILENAME</arg>
into the repository at <arg choice="plain">LOCATION</arg>.
</para>
<para>
The format of the bundle file is that generated by build-bundle.
</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>--ostree-verbose</option></term>
<listitem><para>
Print OSTree debug information during command processing.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--ref=REF</option></term>
<listitem><para>
Override the ref specified in the bundle.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--oci</option></term>
<listitem><para>
Import an OCI image instead of a Flatpak bundle.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--update-appstream</option></term>
<listitem><para>
Run appstream-builder and to update the appstream branch after build.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--no-update-summary</option></term>
<listitem><para>
Don't update the summary file after the new commit is added. This means
the repository will not be useful for serving over http until build-repo-update
has been run. This is useful is you want to do multiple repo operations before
finally updating the summary.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--gpg-sign=KEYID</option></term>
<listitem><para>
Sign the commit with this GPG key.
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
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--version</option></term>
<listitem><para>
Print version information and exit.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>See also</title>
<para>
<citerefentry><refentrytitle>ostree</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak-build-bundle</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak-repo-update</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@ -1,220 +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-build-init">
<refentryinfo>
<title>flatpak build-init</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 build-init</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>flatpak-build-init</refname>
<refpurpose>Initialize a build directory</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>flatpak build-init</command>
<arg choice="opt" rep="repeat">OPTION</arg>
<arg choice="plain">DIRECTORY</arg>
<arg choice="plain">APPNAME</arg>
<arg choice="plain">SDK</arg>
<arg choice="plain">RUNTIME</arg>
<arg choice="opt">BRANCH</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
Initializes a directory for building an application.
<arg choice="plain">DIRECTORY</arg> is the name of the directory.
<arg choice="plain">APPNAME</arg> is the application id of the app
that will be built.
<arg choice="plain">SDK</arg> and <arg choice="plain">RUNTIME</arg>
specify the sdk and runtime that the application should be built
against and run in.
</para>
<para>
The result of this command is that a <filename>metadata</filename>
file is created inside the given directory. Additionally, empty
<filename>files</filename> and <filename>var</filename> subdirectories
are created.
</para>
<para>
It is an error to run build-init on a directory that has already
been initialized as a build directory.
</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>--arch=ARCH</option></term>
<listitem><para>
The architecture to use.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-v</option></term>
<term><option>--var=RUNTIME</option></term>
<listitem><para>
Initialize var from the named runtime.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-w</option></term>
<term><option>--writable-sdk</option></term>
<listitem><para>
Initialize /usr with a copy of the sdk, which is writable during flatpak build. This can be used
if you need to install build tools in /usr during the build. This is stored in the
<filename>usr</filename> subdirectory of the app dir, but will not be part of the final
app.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--tag=TAG</option></term>
<listitem><para>
Add a tag to the metadata file.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--sdk-extension=EXTENSION</option></term>
<listitem><para>
When using --writable-sdk, in addition to the sdk, also install the specified extension.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--sdk-dir</option></term>
<listitem><para>
Specify a custom subdirectory to use instead of <filename>usr</filename> for --writable-sdk.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--update</option></term>
<listitem><para>
Re-initialize the sdk and var, don't fail if already initialized.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--base=APP</option></term>
<listitem><para>
Initialize the application with files from another specified application.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--base-version=VERSION</option></term>
<listitem><para>
Specify the version to use for --base. If not specified, will default to
"master".
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--base-extension=EXTENSION</option></term>
<listitem><para>
When using --base, also install the specified extension from the app.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--type=TYPE</option></term>
<listitem><para>
This can be used to build different types of things. The default
is "app" which is a regular app, but "runtime" creates a runtime
based on an existing runtime, and "extension" creates an extension
for an app or runtime.
</para></listitem>
</varlistentry>
<varlistentry>
<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>
</variablelist>
</refsect1>
<refsect1>
<title>Examples</title>
<para>
<command>$ flatpak build-init /build/my-app org.gnome.Sdk org.gnome.Platform 3.16</command>
</para>
</refsect1>
<refsect1>
<title>See also</title>
<para>
<citerefentry><refentrytitle>flatpak</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>

View File

@ -1,155 +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-build-export">
<refentryinfo>
<title>flatpak build-sign</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 build-sign</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>flatpak-build-sign</refname>
<refpurpose>Sign an application or runtime</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>flatpak build-sign</command>
<arg choice="opt" rep="repeat">OPTION</arg>
<arg choice="plain">LOCATION</arg>
<arg choice="plain">ID</arg>
<arg choice="opt">BRANCH</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
Signs the commit for a specified application or runtime in
a local repository. <arg choice="plain">LOCATION</arg> is
the location of the repository. <arg
choice="plain">ID</arg> is the name of the application, or
runtime if --runtime is specified. If <arg
choice="plain">BRANCH</arg> is not specified, it is
assumed to be "master".
</para>
<para>
Applications can also be signed during build-export, but
it is sometimes useful to add additional signatures later.
</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>--gpg-sign=KEYID</option></term>
<listitem><para>
Sign the commit with this GPG key.
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
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--runtime</option></term>
<listitem><para>
Sign a runtime instead of an app.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--arch=ARCH</option></term>
<listitem><para>
The architecture to use.
</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>--ostree-verbose</option></term>
<listitem><para>
Print OSTree debug information during command processing.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--version</option></term>
<listitem><para>
Print version information and exit.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Examples</title>
<para>
<command>$ flatpak build-sign --gpg-sign=D8BA6573DDD2418027736F1BC33B315E53C1E9D6 /some/repo org.my.App</command>
</para>
</refsect1>
<refsect1>
<title>See also</title>
<para>
<citerefentry><refentrytitle>ostree</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak-build-export</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak-build</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
</para>
</refsect1>
</refentry>

View File

@ -1,214 +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-build-update-repo">
<refentryinfo>
<title>flatpak build-update-repo</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 build-update-repo</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>flatpak-build-update-repo</refname>
<refpurpose>Create a repository from a build directory</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>flatpak build-update-repo</command>
<arg choice="opt" rep="repeat">OPTION</arg>
<arg choice="plain">LOCATION</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
Updates repository metadata for the repository at
<arg choice="plain">LOCATION</arg>. This command generates
an OSTree summary file that lists the contents of the repository.
The summary is used by flatpak repo-contents and other commands
to display the contents of remote repositories.
</para>
<para>
After this command, <arg choice="plain">LOCATION</arg> can be
used as the repository location for flatpak add-repo, either by
exporting it over http, or directly with a file: url.
</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>--redirect-url=URL</option></term>
<listitem><para>
Redirect this repo to a new URL.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--title=TITLE</option></term>
<listitem><para>
A title for the repository, e.g. for display in a UI.
The title is stored in the repository summary.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--default-branch=BRANCH</option></term>
<listitem><para>
A default branch for the repository, mainly for use in a UI.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--gpg-import=FILE</option></term>
<listitem><para>
Import a new default GPG public key from the
given file.
</para></listitem>
</varlistentry>
<!-- FIXME: Uncomment this when enable-p2p is enabled unconditionally.
<varlistentry>
<term><option>-FIXME-collection-id=COLLECTION-ID</option></term>
<listitem><para>
The globally unique identifier of the remote repository, to
allow mirrors to be grouped. This must be set to a globally
unique reverse DNS string if the repository is to be made
publicly available. If a collection ID is already set on an
existing repository, this will update it. If not specified,
the existing collection ID will be left unchanged.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-FIXME-deploy-collection-id</option></term>
<listitem><para>
Deploy the collection ID (set using <option>-FIXME-collection-id</option>
in the static remote configuration for all clients. This is
irrevocable once published in a repository. Use it to decide
when to roll out a collection ID to users of an existing repository.
If constructing a new repository which has a collection ID,
you should typically always pass this option.
</para></listitem>
</varlistentry>
-->
<varlistentry>
<term><option>--gpg-sign=KEYID</option></term>
<listitem><para>
Sign the commit with this GPG key.
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
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--generate-static-deltas</option></term>
<listitem><para>
Generate static deltas for all references. This generates from-empty and
delta static files that allow for faster download.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--prune</option></term>
<listitem><para>
Remove unreferenced objects in repo.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--prune-depth</option></term>
<listitem><para>
Only keep at most this number of old versions for any particular ref. Default is -1 which means infinite.
</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>--ostree-verbose</option></term>
<listitem><para>
Print OSTree debug information during command processing.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--version</option></term>
<listitem><para>
Print version information and exit.
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>See also</title>
<para>
<citerefentry><refentrytitle>ostree</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak-repo-contents</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak-build-export</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@ -1,365 +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-build">
<refentryinfo>
<title>flatpak build</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 build</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>flatpak-build</refname>
<refpurpose>Build in a directory</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>flatpak build</command>
<arg choice="opt" rep="repeat">OPTION</arg>
<arg choice="plain">DIRECTORY</arg>
<arg choice="opt">COMMAND <arg choice="opt" rep="repeat">ARG</arg></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
Runs a build command in a directory. <arg choice="plain">DIRECTORY</arg>
must have been initialized with <command>flatpak build-init</command>.
</para>
<para>
The sdk that is specified in the <filename>metadata</filename> file
in the directory is mounted at <filename>/usr</filename> and the
<filename>files</filename> and <filename>var</filename> subdirectories
are mounted at <filename>/app</filename> and <filename>/var</filename>,
respectively. They are writable, and their contents are preserved between
build commands, to allow accumulating build artifacts there.
</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>-r</option></term>
<term><option>--runtime</option></term>
<listitem><para>
Use the non-devel runtime that is specified in the application metadata instead of the devel runtime.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--bind-mount=DEST=SOURCE</option></term>
<listitem><para>
Add a custom bind mount in the build namespace. Can be specified multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--build-dir=PATH</option></term>
<listitem><para>
Start the build in this directory (default is in the current directory).
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--share=SUBSYSTEM</option></term>
<listitem><para>
Share a subsystem with the host session. This overrides
the Context section from the application metadata.
SUBSYSTEM must be one of: network, ipc.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--unshare=SUBSYSTEM</option></term>
<listitem><para>
Don't share a subsystem with the host session. This overrides
the Context section from the application metadata.
SUBSYSTEM must be one of: network, ipc.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--socket=SOCKET</option></term>
<listitem><para>
Expose a well-known socket to the application. This overrides to
the Context section from the application metadata.
SOCKET must be one of: x11, wayland, pulseaudio, system-bus, session-bus.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--nosocket=SOCKET</option></term>
<listitem><para>
Don't expose a well-known socket to the application. This overrides to
the Context section from the application metadata.
SOCKET must be one of: x11, wayland, pulseaudio, system-bus, session-bus.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--device=DEVICE</option></term>
<listitem><para>
Expose a device to the application. This overrides to
the Context section from the application metadata.
DEVICE must be one of: dri, kvm, all.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--nodevice=DEVICE</option></term>
<listitem><para>
Don't expose a device to the application. This overrides to
the Context section from the application metadata.
DEVICE must be one of: dri, kvm, all.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--allow=FEATURE</option></term>
<listitem><para>
Allow access to a specific feature. This updates
the [Context] group in the metadata.
FEATURE must be one of: devel, multiarch.
This option can be used multiple times.
</para><para>
The <code>devel</code> feature allows the application to
access certain syscalls such as <code>ptrace()</code>, and
<code>perf_event_open()</code>.
</para><para>
The <code>multiarch</code> feature allows the application to
execute programs compiled for an ABI other than the one supported
natively by the system. For example, for the <code>x86_64</code>
architecture, 32-bit <code>x86</code> binaries will be allowed as
well.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--disallow=FEATURE</option></term>
<listitem><para>
Disallow access to a specific feature. This updates
the [Context] group in the metadata.
FEATURE must be one of: devel, multiarch.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--filesystem=FILESYSTEM[:ro|:create]</option></term>
<listitem><para>
Allow the application access to a subset of the filesystem.
This overrides to the Context section from the application metadata.
FILESYSTEM can be one of: home, host, xdg-desktop, xdg-documents, xdg-download
xdg-music, xdg-pictures, xdg-public-share, xdg-templates, xdg-videos, xdg-run,
xdg-config, xdg-cache, xdg-data, an absolute path, or a homedir-relative
path like ~/dir or paths relative to the xdg dirs, like xdg-download/subdir.
The optional :ro suffix indicates that the location will be read-only.
The optional :create suffix indicates that the location will be read-write and created if it doesn't exist.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--nofilesystem=FILESYSTEM</option></term>
<listitem><para>
Remove access to the specified subset of the filesystem from
the application. This overrides to the Context section from the
application metadata.
FILESYSTEM can be one of: home, host, xdg-desktop, xdg-documents, xdg-download
xdg-music, xdg-pictures, xdg-public-share, xdg-templates, xdg-videos,
an absolute path, or a homedir-relative path like ~/dir.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--add-policy=SUBSYSTEM.KEY=VALUE</option></term>
<listitem><para>
Add generic policy option. For example, "--add-policy=subsystem.key=v1 --add-policy=subsystem.key=v2" would map to this metadata:
<programlisting>
[Policy subsystem]
key=v1;v2;
</programlisting>
</para></listitem>
<listitem><para>
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--remove-policy=SUBSYSTEM.KEY=VALUE</option></term>
<listitem><para>
Remove generic policy option. This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--env=VAR=VALUE</option></term>
<listitem><para>
Set an environment variable in the application.
This overrides to the Context section from the application metadata.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--own-name=NAME</option></term>
<listitem><para>
Allow the application to own the well-known name NAME on the session bus.
This overrides to the Context section from the application metadata.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--talk-name=NAME</option></term>
<listitem><para>
Allow the application to talk to the well-known name NAME on the session bus.
This overrides to the Context section from the application metadata.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--system-own-name=NAME</option></term>
<listitem><para>
Allow the application to own the well-known name NAME on the system bus.
This overrides to the Context section from the application metadata.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--system-talk-name=NAME</option></term>
<listitem><para>
Allow the application to talk to the well-known name NAME on the system bus.
This overrides to the Context section from the application metadata.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--persist=FILENAME</option></term>
<listitem><para>
If the application doesn't have access to the real homedir, make the (homedir-relative) path
FILENAME a bind mount to the corresponding path in the per-application directory,
allowing that location to be used for persistent data.
This overrides to the Context section from the application metadata.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--sdk-dir=DIR</option></term>
<listitem><para>
Normally if there is a <filename>usr</filename> directory in the build dir, this is used
for the runtime files (this can be created by --writable-sdk or --type=runtime arguments
to build-init). If you specify --sdk-dir this directoryname will be used instead.
Use this if you passed --sdk-dir to build-init.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--metadata=FILE</option></term>
<listitem><para>
Use the specified filename as metadata in the exported app instead of
the default file (called <filename>metadata</filename>). This is useful
if you build multiple things from a single build tree (such as both a
platform and a sdk).
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Examples</title>
<para>
<command>$ flatpak build /build/my-app rpmbuild my-app.src.rpm</command>
</para>
</refsect1>
<refsect1>
<title>See also</title>
<para>
<citerefentry><refentrytitle>flatpak</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak-build-init</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>

View File

@ -0,0 +1,24 @@
<?xml version="1.0"?>
<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
]>
<reference xmlns:xi="http://www.w3.org/2003/XInclude">
<referenceinfo>
<releaseinfo>Version @VERSION@</releaseinfo>
</referenceinfo>
<title>Flatpak Builder Command Reference</title>
<partintro>
<para>
Flatpak-builder is a tool to build flatpak applications.
</para>
</partintro>
<chapter>
<title>Executables</title>
<xi:include href="@srcdir@/flatpak-builder.xml"/>
</chapter>
<chapter>
<title>File Formats</title>
<xi:include href="@srcdir@/flatpak-manifest.xml"/>
</chapter>
</reference>

View File

@ -1,60 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
<!ENTITY % local.common.attrib "xmlns:xi CDATA #FIXED 'http://www.w3.org/2003/XInclude'">
]>
<reference xmlns:xi="http://www.w3.org/2003/XInclude">
<referenceinfo>
<releaseinfo>Version @VERSION@</releaseinfo>
</referenceinfo>
<title>Flatpak Command Reference</title>
<partintro>
<para>
Flatpak comes with a rich commandline interface.
</para>
</partintro>
<chapter>
<title>Executables</title>
<xi:include href="@srcdir@/flatpak.xml"/>
<xi:include href="@srcdir@/flatpak-builder.xml"/>
</chapter>
<chapter>
<title>Commands</title>
<xi:include href="@srcdir@/flatpak-install.xml"/>
<xi:include href="@srcdir@/flatpak-update.xml"/>
<xi:include href="@srcdir@/flatpak-uninstall.xml"/>
<xi:include href="@srcdir@/flatpak-list.xml"/>
<xi:include href="@srcdir@/flatpak-info.xml"/>
<xi:include href="@srcdir@/flatpak-run.xml"/>
<xi:include href="@srcdir@/flatpak-override.xml"/>
<xi:include href="@srcdir@/flatpak-make-current.xml"/>
<xi:include href="@srcdir@/flatpak-enter.xml"/>
<xi:include href="@srcdir@/flatpak-document-export.xml"/>
<xi:include href="@srcdir@/flatpak-document-unexport.xml"/>
<xi:include href="@srcdir@/flatpak-document-info.xml"/>
<xi:include href="@srcdir@/flatpak-document-list.xml"/>
<xi:include href="@srcdir@/flatpak-remotes.xml"/>
<xi:include href="@srcdir@/flatpak-remote-add.xml"/>
<xi:include href="@srcdir@/flatpak-remote-modify.xml"/>
<xi:include href="@srcdir@/flatpak-remote-delete.xml"/>
<xi:include href="@srcdir@/flatpak-remote-ls.xml"/>
<xi:include href="@srcdir@/flatpak-build-init.xml"/>
<xi:include href="@srcdir@/flatpak-build.xml"/>
<xi:include href="@srcdir@/flatpak-build-finish.xml"/>
<xi:include href="@srcdir@/flatpak-build-export.xml"/>
<xi:include href="@srcdir@/flatpak-build-bundle.xml"/>
<xi:include href="@srcdir@/flatpak-build-import-bundle.xml"/>
<xi:include href="@srcdir@/flatpak-build-sign.xml"/>
<xi:include href="@srcdir@/flatpak-build-update-repo.xml"/>
<xi:include href="@srcdir@/flatpak-build-commit-from.xml"/>
</chapter>
<chapter>
<title>File Formats</title>
<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>
</reference>

View File

@ -1,226 +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-document-export">
<refentryinfo>
<title>flatpak document-export</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 document-export</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>flatpak-document-export</refname>
<refpurpose>Export a file to a sandboxed application</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>flatpak document-export</command>
<arg choice="opt" rep="repeat">OPTION</arg>
<arg choice="plain">FILE</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
Creates a document id for a local file that can be exposed to
sandboxed applications, allowing them access to files that they
would not otherwise see. The exported files are exposed in a
fuse filesystem at /run/user/$UID/doc/.
</para>
<para>
This command also lets you modify the per-application
permissions of the documents, granting or revoking access
to the file on a per-application basis.
</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>-u</option></term>
<term><option>--unique</option></term>
<listitem><para> Don't reuse an existing document id
for the file. This makes it safe to later remove the
document when you're finished with it.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-t</option></term>
<term><option>--transient</option></term>
<listitem><para>
The document will only exist for the length of
the session. This is useful for temporary grants.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-n</option></term>
<term><option>--noexist</option></term>
<listitem><para>
Don't require the file to exist already.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-a</option></term>
<term><option>--app=APPID</option></term>
<listitem><para>
Grant read access to the specified application. The
--allow and --forbid options can be used to grant
or remove additional privileges.
This option can be used multiple times.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-r</option></term>
<term><option>--allow-read</option></term>
<listitem><para>
Grant read access to the applications specified with --app.
This defaults to TRUE.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--forbid-read</option></term>
<listitem><para>
Revoke read access for the applications specified with --app.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-w</option></term>
<term><option>--allow-write</option></term>
<listitem><para>
Grant write access to the applications specified with --app.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--forbid-write</option></term>
<listitem><para>
Revoke write access for the applications specified with --app.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-d</option></term>
<term><option>--allow-delete</option></term>
<listitem><para>
Grant the ability to remove the document from the document portal to the applications specified with --app.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--forbid-delete</option></term>
<listitem><para>
Revoke the ability to remove the document from the document portal from the applications specified with --app.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-g</option></term>
<term><option>--allow-grant-permission</option></term>
<listitem><para>
Grant the ability to grant further permissions to the applications specified with --app.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--forbid-grant-permission</option></term>
<listitem><para>
Revoke the ability to grant further permissions for the applications specified with --app.
</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>
</variablelist>
</refsect1>
<refsect1>
<title>Examples</title>
<para>
<command>$ flatpak document-export --app=org.gnome.GEdit ~/test.txt</command>
</para>
<programlisting>
/run/user/1000/doc/e52f9c6a/test.txt
</programlisting>
</refsect1>
<refsect1>
<title>See also</title>
<para>
<citerefentry><refentrytitle>flatpak</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak-document-unexport</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak-document-info</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak-document-list</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@ -1,116 +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-document-info">
<refentryinfo>
<title>flatpak document-info</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 document-info</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>flatpak-document-info</refname>
<refpurpose>Show information about exported files</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>flatpak document-info</command>
<arg choice="opt" rep="repeat">OPTION</arg>
<arg choice="plain">FILE</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
Shows information about an exported file, such as the
document id, the fuse path, the original location in the
filesystem, and the per-application permissions.
</para>
<para>
FILE can either be a file in the fuse filesystem at /run/user/$UID/doc/,
or a file anywhere else.
</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>
</variablelist>
</refsect1>
<refsect1>
<title>Examples</title>
<para>
<command>$ flatpak document-info ~/Sources/gtk/gail-3.0.pc</command>
</para>
<programlisting>
id: dd32c34a
path: /run/user/1000/doc/dd32c34a/gail-3.0.pc
origin: /home/mclasen/Sources/gtk/gail-3.0.pc
permissions:
org.gnome.gedit read, write
</programlisting>
</refsect1>
<refsect1>
<title>See also</title>
<para>
<citerefentry><refentrytitle>flatpak</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak-document-export</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak-document-unexport</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak-document-list</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@ -1,96 +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-document-list">
<refentryinfo>
<title>flatpak document-list</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 document-list</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>flatpak-document-list</refname>
<refpurpose>List exported files</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>flatpak document-list</command>
<arg choice="opt" rep="repeat">OPTION</arg>
<arg choice="opt">APPID</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
Lists exported files, with their document id and the
full path to their origin. If an APPID is specified,
only the files exported to this app are listed.
</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>
</variablelist>
</refsect1>
<refsect1>
<title>See also</title>
<para>
<citerefentry><refentrytitle>flatpak</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak-document-export</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak-document-unexport</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak-document-info</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@ -1,96 +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-document-unexport">
<refentryinfo>
<title>flatpak document-unexport</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 document-unexport</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>flatpak-document-unexport</refname>
<refpurpose>Stop exporting a file</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>flatpak document-export</command>
<arg choice="opt" rep="repeat">OPTION</arg>
<arg choice="plain">FILE</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
Removes the document id for the file from the
document portal. This will make the document unavailable
to all sandboxed applications.
</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>
</variablelist>
</refsect1>
<refsect1>
<title>See also</title>
<para>
<citerefentry><refentrytitle>flatpak</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak-document-export</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak-document-info</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak-document-list</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@ -1,113 +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-enter">
<refentryinfo>
<title>flatpak enter</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 enter</refentrytitle>
<manvolnum>1</manvolnum>
</refmeta>
<refnamediv>
<refname>flatpak-enter</refname>
<refpurpose>Enter an application</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>flatpak enter</command>
<arg choice="opt" rep="repeat">OPTION</arg>
<arg choice="plain">MONITORPID</arg>
<arg choice="plain">COMMAND</arg>
<arg choice="opt" rep="repeat">ARG</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
Enter a running sandbox.
<arg choice="plain">SANDBOXEDPID</arg> must be the pid of a process running in a flatpak sandbox.
<arg choice="plain">COMMAND</arg> is the command to run in the sandbox.
Extra arguments are passed on to the command.
</para>
<para>
This creates a new process within the running sandbox, with the same environment. This is useful
when you want to debug a problem with a running application.
</para>
<para>
This command requires extra privileges, so must be run as root or via e.g. sudo.
</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>
</variablelist>
</refsect1>
<refsect1>
<title>Examples</title>
<para>
<command>$ flatpak enter 15345 sh</command>
</para>
</refsect1>
<refsect1>
<title>See also</title>
<para>
<citerefentry><refentrytitle>flatpak</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>flatpak-run</refentrytitle><manvolnum>1</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

Some files were not shown because too many files have changed in this diff Show More