forked from Mirrors/flatpak-builder
Delete non-builder files
parent
bbfb53abd6
commit
9d1f1ed59c
|
@ -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
|
||||
|
|
111
Makefile.am
111
Makefile.am
|
@ -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 = \
|
||||
|
|
|
@ -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)\"
|
|
@ -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;
|
||||
}
|
|
@ -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 (¶m_builder, G_VARIANT_TYPE ("a{sv}"));
|
||||
g_variant_builder_add (¶m_builder, "{sv}", "min-fallback-size", g_variant_new_uint32 (0));
|
||||
g_variant_builder_add (¶m_builder, "{sv}", "compression", g_variant_new_byte ('x'));
|
||||
g_variant_builder_add (¶m_builder, "{sv}", "bsdiff-enabled", g_variant_new_boolean (FALSE));
|
||||
g_variant_builder_add (¶m_builder, "{sv}", "inline-parts", g_variant_new_boolean (TRUE));
|
||||
g_variant_builder_add (¶m_builder, "{sv}", "include-detached", g_variant_new_boolean (TRUE));
|
||||
g_variant_builder_add (¶m_builder, "{sv}", "filename", g_variant_new_bytestring (flatpak_file_get_path_cached (file)));
|
||||
|
||||
params = g_variant_ref_sink (g_variant_builder_end (¶m_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;
|
||||
}
|
|
@ -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
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
|
||||
/* Don’t 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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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));
|
||||
}
|
|
@ -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__ */
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
16
autogen.sh
16
autogen.sh
|
@ -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
|
|
@ -32,7 +32,6 @@
|
|||
#include "libglnx/libglnx.h"
|
||||
|
||||
#include "flatpak-utils.h"
|
||||
#include "flatpak-run.h"
|
||||
#include "builder-utils.h"
|
||||
#include "builder-extension.h"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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__ */
|
1224
common/flatpak-db.c
1224
common/flatpak-db.c
File diff suppressed because it is too large
Load Diff
|
@ -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 */
|
9717
common/flatpak-dir.c
9717
common/flatpak-dir.c
File diff suppressed because it is too large
Load Diff
|
@ -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 we’re 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__ */
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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));
|
||||
}
|
|
@ -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
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
4846
common/flatpak-run.c
4846
common/flatpak-run.c
File diff suppressed because it is too large
Load Diff
|
@ -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__ */
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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
|
@ -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__ */
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
libgvdb.a
|
||||
libgvdb-shared.a
|
|
@ -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.
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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>
|
|
@ -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
|
236
configure.ac
236
configure.ac
|
@ -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 libostree’s 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 ""
|
||||
|
|
|
@ -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)
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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
|
|
@ -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
|
@ -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__ */
|
|
@ -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/
|
|
@ -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
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -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
Loading…
Reference in New Issue