static gboolean copy_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) { 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 (!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 (!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; }
int main (int argc, char **argv) { g_autofree const char *old_env = NULL; g_autoptr(GError) error = NULL; g_autoptr(BuilderManifest) manifest = NULL; g_autoptr(GOptionContext) context = NULL; const char *app_dir_path = NULL, *manifest_path; g_autofree gchar *json = NULL; g_autoptr(BuilderContext) build_context = NULL; g_autoptr(GFile) base_dir = NULL; g_autoptr(GFile) manifest_file = NULL; g_autoptr(GFile) app_dir = NULL; g_autoptr(BuilderCache) cache = NULL; g_autofree char *cache_branch = NULL; g_autoptr(GFileEnumerator) dir_enum = NULL; g_autoptr(GFileEnumerator) dir_enum2 = NULL; GFileInfo *next = NULL; const char *platform_id = NULL; g_autofree char **orig_argv; gboolean is_run = FALSE; gboolean is_show_deps = FALSE; gboolean app_dir_is_empty = FALSE; g_autoptr(FlatpakContext) arg_context = NULL; int i, first_non_arg, orig_argc; int argnr; setlocale (LC_ALL, ""); g_log_set_handler (NULL, G_LOG_LEVEL_MESSAGE, message_handler, NULL); g_set_prgname (argv[0]); /* avoid gvfs (http://bugzilla.gnome.org/show_bug.cgi?id=526454) */ old_env = g_strdup (g_getenv ("GIO_USE_VFS")); g_setenv ("GIO_USE_VFS", "local", TRUE); g_vfs_get_default (); if (old_env) g_setenv ("GIO_USE_VFS", old_env, TRUE); else g_unsetenv ("GIO_USE_VFS"); orig_argv = g_memdup (argv, sizeof (char *) * argc); orig_argc = argc; first_non_arg = 1; for (i = 1; i < argc; i++) { if (argv[i][0] != '-') break; first_non_arg = i + 1; if (strcmp (argv[i], "--run") == 0) is_run = TRUE; if (strcmp (argv[i], "--show-deps") == 0) is_show_deps = TRUE; } if (is_run) { context = g_option_context_new ("DIRECTORY MANIFEST COMMAND [args] - Run command in build sandbox"); g_option_context_add_main_entries (context, run_entries, NULL); arg_context = flatpak_context_new (); g_option_context_add_group (context, flatpak_context_get_options (arg_context)); /* We drop the post-command part from the args, these go with the command in the sandbox */ argc = MIN (first_non_arg + 3, argc); } else if (is_show_deps) { context = g_option_context_new ("MANIFEST - Show manifest dependencies"); g_option_context_add_main_entries (context, show_deps_entries, NULL); } else { context = g_option_context_new ("DIRECTORY MANIFEST - Build manifest"); g_option_context_add_main_entries (context, entries, NULL); } if (!g_option_context_parse (context, &argc, &argv, &error)) { g_printerr ("Option parsing failed: %s\n", error->message); return 1; } if (opt_version) { g_print ("%s\n", PACKAGE_STRING); exit (EXIT_SUCCESS); } if (opt_verbose) g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, message_handler, NULL); argnr = 1; if (!is_show_deps) { if (argc == argnr) return usage (context, "DIRECTORY must be specified"); app_dir_path = argv[argnr++]; } if (argc == argnr) return usage (context, "MANIFEST must be specified"); manifest_path = argv[argnr++]; if (!g_file_get_contents (manifest_path, &json, NULL, &error)) { g_printerr ("Can't load '%s': %s\n", manifest_path, error->message); return 1; } manifest = (BuilderManifest *) json_gobject_from_data (BUILDER_TYPE_MANIFEST, json, -1, &error); if (manifest == NULL) { g_printerr ("Can't parse '%s': %s\n", manifest_path, error->message); return 1; } if (is_run && argc == 3) return usage (context, "Program to run must be specified"); if (is_show_deps) { if (!builder_manifest_show_deps (manifest, &error)) { g_printerr ("Error running %s: %s\n", argv[3], error->message); return 1; } return 0; } manifest_file = g_file_new_for_path (manifest_path); base_dir = g_file_get_parent (manifest_file); app_dir = g_file_new_for_path (app_dir_path); build_context = builder_context_new (base_dir, app_dir); builder_context_set_keep_build_dirs (build_context, opt_keep_build_dirs); builder_context_set_sandboxed (build_context, opt_sandboxed); builder_context_set_jobs (build_context, opt_jobs); if (opt_arch) builder_context_set_arch (build_context, opt_arch); if (opt_stop_at) { opt_build_only = TRUE; builder_context_set_stop_at (build_context, opt_stop_at); } if (opt_ccache && !builder_context_enable_ccache (build_context, &error)) { g_printerr ("Can't initialize ccache use: %s\n", error->message); return 1; } app_dir_is_empty = !g_file_query_exists (app_dir, NULL) || directory_is_empty (app_dir_path); if (is_run) { g_assert (opt_run); if (app_dir_is_empty) { g_printerr ("App dir '%s' is empty or doesn't exist.\n", app_dir_path); return 1; } if (!builder_manifest_run (manifest, build_context, arg_context, orig_argv + first_non_arg + 2, orig_argc - first_non_arg - 2, &error)) { g_printerr ("Error running %s: %s\n", argv[3], error->message); return 1; } return 0; } g_assert (!opt_run); g_assert (!opt_show_deps); if (!opt_finish_only && !app_dir_is_empty) { if (opt_force_clean) { g_print ("Emptying app dir '%s'\n", app_dir_path); if (!flatpak_rm_rf (app_dir, NULL, &error)) { g_printerr ("Couldn't empty app dir '%s': %s", app_dir_path, error->message); return 1; } } else { g_printerr ("App dir '%s' is not empty. Please delete " "the existing contents.\n", app_dir_path); return 1; } } if (opt_finish_only && app_dir_is_empty) { g_printerr ("App dir '%s' is empty or doesn't exist.\n", app_dir_path); return 1; } if (!builder_manifest_start (manifest, opt_allow_missing_runtimes, build_context, &error)) { g_printerr ("Failed to init: %s\n", error->message); return 1; } if (!opt_finish_only && !opt_disable_download && !builder_manifest_download (manifest, !opt_disable_updates, build_context, &error)) { g_printerr ("Failed to download sources: %s\n", error->message); return 1; } if (opt_download_only) return 0; cache_branch = g_path_get_basename (manifest_path); cache = builder_cache_new (builder_context_get_cache_dir (build_context), app_dir, cache_branch); if (!builder_cache_open (cache, &error)) { g_printerr ("Error opening cache: %s\n", error->message); return 1; } if (opt_disable_cache) /* This disables *lookups*, but we still build the cache */ builder_cache_disable_lookups (cache); builder_manifest_checksum (manifest, cache, build_context); if (!opt_finish_only) { if (!builder_cache_lookup (cache, "init")) { g_autofree char *body = g_strdup_printf ("Initialized %s\n", builder_manifest_get_id (manifest)); if (!builder_manifest_init_app_dir (manifest, build_context, &error)) { g_printerr ("Error: %s\n", error->message); return 1; } if (!builder_cache_commit (cache, body, &error)) { g_printerr ("Error: %s\n", error->message); return 1; } } if (!builder_manifest_build (manifest, cache, build_context, &error)) { g_printerr ("Error: %s\n", error->message); return 1; } } if (!opt_build_only) { if (!builder_manifest_cleanup (manifest, cache, build_context, &error)) { g_printerr ("Error: %s\n", error->message); return 1; } if (!builder_manifest_finish (manifest, cache, build_context, &error)) { g_printerr ("Error: %s\n", error->message); return 1; } if (!builder_manifest_create_platform (manifest, cache, build_context, &error)) { g_printerr ("Error: %s\n", error->message); return 1; } } if (!opt_require_changes) builder_cache_ensure_checkout (cache); if (!opt_build_only && opt_repo && builder_cache_has_checkout (cache)) { g_autoptr(GFile) debuginfo_metadata = NULL; g_print ("Exporting %s to repo\n", builder_manifest_get_id (manifest)); if (!do_export (build_context, &error, builder_context_get_build_runtime (build_context), "--exclude=/lib/debug/*", "--include=/lib/debug/app", builder_context_get_separate_locales (build_context) ? "--exclude=/share/runtime/locale/*/*" : skip_arg, opt_repo, app_dir_path, builder_manifest_get_branch (manifest), NULL)) { g_printerr ("Export failed: %s\n", error->message); return 1; } /* Export regular locale extensions */ dir_enum = g_file_enumerate_children (app_dir, "standard::name,standard::type", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL); while (dir_enum != NULL && (next = g_file_enumerator_next_file (dir_enum, NULL, NULL))) { g_autoptr(GFileInfo) child_info = next; const char *name = g_file_info_get_name (child_info); g_autofree char *metadata_arg = NULL; g_autofree char *files_arg = NULL; g_autofree char *locale_id = builder_manifest_get_locale_id (manifest); if (strcmp (name, "metadata.locale") == 0) g_print ("Exporting %s to repo\n", locale_id); else continue; metadata_arg = g_strdup_printf ("--metadata=%s", name); files_arg = g_strconcat (builder_context_get_build_runtime (build_context) ? "--files=usr" : "--files=files", "/share/runtime/locale/", NULL); if (!do_export (build_context, &error, TRUE, metadata_arg, files_arg, opt_repo, app_dir_path, builder_manifest_get_branch (manifest), NULL)) { g_printerr ("Export failed: %s\n", error->message); return 1; } } /* Export debug extensions */ debuginfo_metadata = g_file_get_child (app_dir, "metadata.debuginfo"); if (g_file_query_exists (debuginfo_metadata, NULL)) { g_autofree char *debug_id = builder_manifest_get_debug_id (manifest); g_print ("Exporting %s to repo\n", debug_id); if (!do_export (build_context, &error, TRUE, "--metadata=metadata.debuginfo", builder_context_get_build_runtime (build_context) ? "--files=usr/lib/debug" : "--files=files/lib/debug", opt_repo, app_dir_path, builder_manifest_get_branch (manifest), NULL)) { g_printerr ("Export failed: %s\n", error->message); return 1; } } /* Export platform */ platform_id = builder_manifest_get_id_platform (manifest); if (builder_context_get_build_runtime (build_context) && platform_id != NULL) { g_print ("Exporting %s to repo\n", platform_id); if (!do_export (build_context, &error, TRUE, "--metadata=metadata.platform", "--files=platform", builder_context_get_separate_locales (build_context) ? "--exclude=/share/runtime/locale/*/*" : skip_arg, opt_repo, app_dir_path, builder_manifest_get_branch (manifest), NULL)) { g_printerr ("Export failed: %s\n", error->message); return 1; } } /* Export platform locales */ dir_enum2 = g_file_enumerate_children (app_dir, "standard::name,standard::type", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL); while (dir_enum2 != NULL && (next = g_file_enumerator_next_file (dir_enum2, NULL, NULL))) { g_autoptr(GFileInfo) child_info = next; const char *name = g_file_info_get_name (child_info); g_autofree char *metadata_arg = NULL; g_autofree char *files_arg = NULL; g_autofree char *locale_id = builder_manifest_get_locale_id_platform (manifest); if (strcmp (name, "metadata.platform.locale") == 0) g_print ("Exporting %s to repo\n", locale_id); else continue; metadata_arg = g_strdup_printf ("--metadata=%s", name); files_arg = g_strconcat ("--files=platform/share/runtime/locale/", NULL); if (!do_export (build_context, &error, TRUE, metadata_arg, files_arg, opt_repo, app_dir_path, builder_manifest_get_branch (manifest), NULL)) { g_printerr ("Export failed: %s\n", error->message); return 1; } } } if (!builder_gc (cache, &error)) { g_warning ("Failed to GC build cache: %s\n", error->message); g_clear_error (&error); } return 0; }
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; const char *app_id; const char *directory; const char *sdk; const char *runtime; const char *branch = "master"; g_autofree char *runtime_ref = NULL; g_autofree char *var_ref = NULL; g_autofree char *sdk_ref = NULL; int i; 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 = argv[3]; runtime = argv[4]; if (argc >= 6) branch = argv[5]; 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); if (!flatpak_is_valid_name (runtime, &my_error)) return flatpak_fail (error, _("'%s' is not a valid runtime name: %s"), runtime, my_error->message); if (!flatpak_is_valid_name (sdk, &my_error)) return flatpak_fail (error, _("'%s' is not a valid sdk name: %s"), sdk, 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); runtime_ref = flatpak_build_untyped_ref (runtime, branch, opt_arch); sdk_ref = flatpak_build_untyped_ref (sdk, branch, opt_arch); 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"); if (opt_sdk_dir) usr_dir = g_file_get_child (base, opt_sdk_dir); else usr_dir = g_file_get_child (base, "usr"); 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); if (opt_writable_sdk) { g_autofree char *full_sdk_ref = g_strconcat ("runtime/", sdk_ref, NULL); g_autoptr(GFile) sdk_deploy_files = NULL; g_autoptr(FlatpakDeploy) sdk_deploy = NULL; sdk_deploy = flatpak_find_deploy_for_ref (full_sdk_ref, cancellable, error); if (sdk_deploy == NULL) return FALSE; 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 && !copy_extensions (sdk_deploy, branch, opt_sdk_extensions, usr_dir, cancellable, error)) return FALSE; } if (opt_var) { var_ref = flatpak_build_runtime_ref (opt_var, 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 && !copy_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 ("[Application]\n"); g_string_append_printf (metadata_contents, "name=%s\n" "runtime=%s\n" "sdk=%s\n", app_id, runtime_ref, sdk_ref); 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 (!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_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; 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"); if (opt_sdk_dir) usr_dir = g_file_get_child (base, opt_sdk_dir); else usr_dir = g_file_get_child (base, "usr"); 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); if (opt_writable_sdk || is_runtime) { g_autoptr(GFile) sdk_deploy_files = NULL; g_autoptr(FlatpakDeploy) sdk_deploy = NULL; sdk_deploy = flatpak_dir_load_deployed (sdk_dir, sdk_ref, NULL, cancellable, error); if (sdk_deploy == NULL) return FALSE; 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 && !copy_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 && !copy_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; }