diff options
author | Alexander Larsson <alexl@redhat.com> | 2016-04-22 10:38:10 +0200 |
---|---|---|
committer | Alexander Larsson <alexl@redhat.com> | 2016-04-25 18:59:17 +0200 |
commit | 6af6d629a2305cbc94d192399094c1e67ffe46c4 (patch) | |
tree | 7d7647b53471f6ddd24d23aa5ed998c6c4b28201 /common | |
parent | 8ac40150a64e3a491c38bfef01cf5ad40cd7fddb (diff) | |
download | xdg-app-6af6d629a2305cbc94d192399094c1e67ffe46c4.tar.gz |
Initial work on pulling to a child repo
Diffstat (limited to 'common')
-rw-r--r-- | common/xdg-app-dir.c | 167 | ||||
-rw-r--r-- | common/xdg-app-dir.h | 4 |
2 files changed, 152 insertions, 19 deletions
diff --git a/common/xdg-app-dir.c b/common/xdg-app-dir.c index b661f8a..cedeb8c 100644 --- a/common/xdg-app-dir.c +++ b/common/xdg-app-dir.c @@ -44,6 +44,9 @@ struct XdgAppDir { GFile *basedir; OstreeRepo *repo; + OstreeRepo *child_repo; + GLnxLockFile child_repo_lock; + SoupSession *soup_session; }; @@ -163,6 +166,119 @@ xdg_app_get_user_base_dir_location (void) return g_file_new_for_path (base); } +GFile * +xdg_app_get_user_cache_dir_location (void) +{ + g_autoptr(GFile) base_dir = NULL; + + base_dir = xdg_app_get_user_base_dir_location (); + return g_file_get_child (base_dir, "system-cache"); +} + +GFile * +xdg_app_ensure_user_cache_dir_location (GError **error) +{ + g_autoptr(GFile) cache_dir = NULL; + g_autofree char *cache_path = NULL; + + cache_dir = xdg_app_get_user_cache_dir_location (); + cache_path = g_file_get_path (cache_dir); + + if (g_mkdir_with_parents (cache_path, 0755) != 0) + { + glnx_set_error_from_errno (error); + return NULL; + } + + return g_steal_pointer (&cache_dir); +} + +gboolean +xdg_app_dir_use_child_repo (XdgAppDir *self) +{ + return !self->user && getuid () != 0; +} + +static OstreeRepo * +system_ostree_repo_new (GFile *repodir) +{ + return g_object_new (OSTREE_TYPE_REPO, "path", repodir, + "remotes-config-dir", XDG_APP_CONFIGDIR "/remotes.d", + NULL); +} + +gboolean +xdg_app_dir_ensure_system_child_repo (XdgAppDir *self, + GError **error) +{ + g_autoptr(GFile) cache_dir = NULL; + g_autoptr(GFile) repo_dir = NULL; + g_autoptr(GFile) repo_dir_config = NULL; + g_autoptr(OstreeRepo) repo = NULL; + g_autofree char *tmpdir_name = NULL; + g_auto(GLnxLockFile) file_lock = GLNX_LOCK_FILE_INIT; + GLnxLockFile empty_lockfile = GLNX_LOCK_FILE_INIT; + g_autoptr(OstreeRepo) new_repo = NULL; + g_autoptr(GKeyFile) config = NULL; + + g_assert (!self->user); + + if (self->child_repo != NULL) + return TRUE; + + if (!xdg_app_dir_ensure_repo (self, NULL, error)) + return FALSE; + + cache_dir = xdg_app_ensure_user_cache_dir_location (error); + if (cache_dir == NULL) + return FALSE; + + if (!xdg_app_allocate_tmpdir (AT_FDCWD, + gs_file_get_path_cached (cache_dir), + "repo-", &tmpdir_name, + NULL, + &file_lock, + NULL, + NULL, error)) + return FALSE; + + repo_dir = g_file_get_child (cache_dir, tmpdir_name); + + new_repo = ostree_repo_new (repo_dir); + + repo_dir_config = g_file_get_child (repo_dir, "config"); + if (!g_file_query_exists (repo_dir_config, NULL)) + { + if (!ostree_repo_create (new_repo, + OSTREE_REPO_MODE_BARE_USER, + NULL, error)) + return FALSE; + } + else + { + if (!ostree_repo_open (new_repo, NULL, error)) + return FALSE; + } + + /* Ensure the config is updated */ + config = ostree_repo_copy_config (new_repo); + g_key_file_set_string (config, "core", "parent", + gs_file_get_path_cached (ostree_repo_get_path (self->repo))); + + if (!ostree_repo_write_config (new_repo, config, error)) + return FALSE; + + /* We need to reopen to apply the parent config */ + repo = system_ostree_repo_new (repo_dir); + if (!ostree_repo_open (repo, NULL, error)) + return FALSE; + + self->child_repo = g_steal_pointer (&repo); + self->child_repo_lock = file_lock; + file_lock = empty_lockfile; + return TRUE; +} + static void xdg_app_dir_finalize (GObject *object) { @@ -171,6 +287,9 @@ xdg_app_dir_finalize (GObject *object) g_clear_object (&self->repo); g_clear_object (&self->basedir); + g_clear_object (&self->child_repo); + glnx_release_lock_file (&self->child_repo_lock); + g_clear_object (&self->soup_session); G_OBJECT_CLASS (xdg_app_dir_parent_class)->finalize (object); @@ -249,6 +368,8 @@ xdg_app_dir_class_init (XdgAppDirClass *klass) static void xdg_app_dir_init (XdgAppDir *self) { + GLnxLockFile empty_lockfile = GLNX_LOCK_FILE_INIT; + self->child_repo_lock = empty_lockfile; } gboolean @@ -629,24 +750,16 @@ xdg_app_dir_ensure_repo (XdgAppDir *self, repo = ostree_repo_new (repodir); else { - g_autoptr(GFile) base_dir = NULL; g_autoptr(GFile) cache_dir = NULL; g_autofree char *cache_path = NULL; - repo = g_object_new (OSTREE_TYPE_REPO, "path", repodir, - "remotes-config-dir", XDG_APP_CONFIGDIR "/remotes.d", - NULL); - - base_dir = xdg_app_get_user_base_dir_location (); - cache_dir = g_file_get_child (base_dir, "system-cache"); - cache_path = g_file_get_path (cache_dir); + repo = system_ostree_repo_new (repodir); - if (g_mkdir_with_parents (cache_path, 0755) != 0) - { - glnx_set_error_from_errno (error); - goto out; - } + cache_dir = xdg_app_ensure_user_cache_dir_location (error); + if (cache_dir == NULL) + goto out; + cache_path = g_file_get_path (cache_dir); if (!ostree_repo_set_cache_dir (repo, AT_FDCWD, cache_path, cancellable, error)) @@ -940,6 +1053,8 @@ xdg_app_dir_pull (XdgAppDir *self, g_autoptr(OstreeAsyncProgress) console_progress = NULL; const char *refs[2]; g_autofree char *url = NULL; + OstreeRepo *repo; + OstreeRepoPullFlags flags = OSTREE_REPO_PULL_FLAGS_NONE; if (!xdg_app_dir_ensure_repo (self, cancellable, error)) goto out; @@ -953,6 +1068,19 @@ xdg_app_dir_pull (XdgAppDir *self, if (*url == 0) return TRUE; /* Empty url, silently disables updates */ + if (xdg_app_dir_use_child_repo (self)) + { + if (!xdg_app_dir_ensure_system_child_repo (self, error)) + return FALSE; + + repo = self->child_repo; + flags |= OSTREE_REPO_PULL_FLAGS_MIRROR; + } + else + { + repo = self->repo; + } + if (progress == NULL) { console = gs_console_get (); @@ -964,13 +1092,14 @@ xdg_app_dir_pull (XdgAppDir *self, } } + refs[0] = ref; refs[1] = NULL; if (subpaths == NULL || subpaths[0] == NULL) { - if (!ostree_repo_pull (self->repo, repository, - (char **)refs, OSTREE_REPO_PULL_FLAGS_NONE, + if (!ostree_repo_pull (repo, repository, + (char **)refs, flags, progress, cancellable, error)) { @@ -982,9 +1111,9 @@ xdg_app_dir_pull (XdgAppDir *self, { int i; - if (!repo_pull_one_dir (self->repo, repository, + if (!repo_pull_one_dir (repo, repository, "/metadata", - (char **)refs, OSTREE_REPO_PULL_FLAGS_NONE, + (char **)refs, flags, progress, cancellable, error)) { @@ -996,9 +1125,9 @@ xdg_app_dir_pull (XdgAppDir *self, for (i = 0; subpaths[i] != NULL; i++) { g_autofree char *subpath = g_build_filename ("/files", subpaths[i], NULL); - if (!repo_pull_one_dir (self->repo, repository, + if (!repo_pull_one_dir (repo, repository, subpath, - (char **)refs, OSTREE_REPO_PULL_FLAGS_NONE, + (char **)refs, flags, progress, cancellable, error)) { diff --git a/common/xdg-app-dir.h b/common/xdg-app-dir.h index bd55f28..f94f59f 100644 --- a/common/xdg-app-dir.h +++ b/common/xdg-app-dir.h @@ -23,6 +23,7 @@ #include <ostree.h> +#include "libglnx/libglnx.h" #include <xdg-app-common-types.h> #define XDG_APP_TYPE_DIR xdg_app_dir_get_type() @@ -134,6 +135,9 @@ OstreeRepo *xdg_app_dir_get_repo (XdgAppDir *self); gboolean xdg_app_dir_ensure_path (XdgAppDir *self, GCancellable *cancellable, GError **error); +gboolean xdg_app_dir_use_child_repo (XdgAppDir *self); +gboolean xdg_app_dir_ensure_system_child_repo (XdgAppDir *self, + GError **error); gboolean xdg_app_dir_ensure_repo (XdgAppDir *self, GCancellable *cancellable, GError **error); |