diff --git a/src/libostree/ostree-repo-checkout.c b/src/libostree/ostree-repo-checkout.c index 51dbedab..6c91f38c 100644 --- a/src/libostree/ostree-repo-checkout.c +++ b/src/libostree/ostree-repo-checkout.c @@ -186,7 +186,7 @@ find_loose_for_checkout (OstreeRepo *self, switch (self->mode) { case OSTREE_REPO_MODE_BARE: - path = ostree_repo_get_object_path (self, checksum, OSTREE_OBJECT_TYPE_FILE); + path = _ostree_repo_get_object_path (self, checksum, OSTREE_OBJECT_TYPE_FILE); break; case OSTREE_REPO_MODE_ARCHIVE: path = _ostree_repo_get_archive_content_path (self, checksum); diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index 30a6b01d..b382021d 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -73,6 +73,11 @@ GFile * _ostree_repo_get_file_object_path (OstreeRepo *self, const char *checksum); +GFile * +_ostree_repo_get_object_path (OstreeRepo *self, + const char *checksum, + OstreeObjectType type); + gboolean _ostree_repo_stage_directory_meta (OstreeRepo *self, GFileInfo *file_info, diff --git a/src/libostree/ostree-repo-prune.c b/src/libostree/ostree-repo-prune.c index 19651026..6492e6e8 100644 --- a/src/libostree/ostree-repo-prune.c +++ b/src/libostree/ostree-repo-prune.c @@ -22,7 +22,7 @@ #include "config.h" -#include "ostree.h" +#include "ostree-repo-private.h" #include "otutil.h" typedef struct { @@ -49,7 +49,7 @@ maybe_prune_loose_object (OtPruneData *data, key = ostree_object_name_serialize (checksum, objtype); - objf = ostree_repo_get_object_path (data->repo, checksum, objtype); + objf = _ostree_repo_get_object_path (data->repo, checksum, objtype); if (!g_hash_table_lookup_extended (data->reachable, key, NULL, NULL)) { diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 9e403739..226678ee 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -426,7 +426,7 @@ GFile * _ostree_repo_get_file_object_path (OstreeRepo *self, const char *checksum) { - return ostree_repo_get_object_path (self, checksum, OSTREE_OBJECT_TYPE_FILE); + return _ostree_repo_get_object_path (self, checksum, OSTREE_OBJECT_TYPE_FILE); } GFile * @@ -493,7 +493,7 @@ commit_loose_object_trusted (OstreeRepo *self, gboolean ret = FALSE; gs_unref_object GFile *dest_file = NULL; - dest_file = ostree_repo_get_object_path (self, checksum, objtype); + dest_file = _ostree_repo_get_object_path (self, checksum, objtype); if (!commit_loose_object_impl (self, tempfile_path, dest_file, is_regular, cancellable, error)) @@ -1276,22 +1276,10 @@ _ostree_repo_stage_directory_meta (OstreeRepo *self, dirmeta, out_csum, cancellable, error); } -/** - * ostree_repo_get_object_path: - * @self: - * @checksum: SHA256 checksum string - * @type: Object type - * - * This function directly retrieves the path of loose objects; it is a - * low level API as one cannot assume that all objects are loose. Use - * higher level API such as ostree_repo_load_file() if possible. - * - * Returns: (transfer full): A new file containing the direct path to a loose object - */ GFile * -ostree_repo_get_object_path (OstreeRepo *self, - const char *checksum, - OstreeObjectType type) +_ostree_repo_get_object_path (OstreeRepo *self, + const char *checksum, + OstreeObjectType type) { char *relpath; GFile *ret; @@ -2198,7 +2186,7 @@ repo_find_object (OstreeRepo *self, gs_unref_object GFile *object_path = NULL; gs_unref_object GFile *ret_stored_path = NULL; - object_path = ostree_repo_get_object_path (self, checksum, objtype); + object_path = _ostree_repo_get_object_path (self, checksum, objtype); if (lstat (gs_file_get_path_cached (object_path), &stbuf) == 0) { @@ -2249,6 +2237,63 @@ ostree_repo_has_object (OstreeRepo *self, return ret; } +/** + * ostree_repo_delete_object: + * @self: + * @objtype: Object type + * @sha256: Checksum + * @cancellable: + * @error: + * + * Remove the object of type @objtype with checksum @sha256 + * from the repository. An error of type %G_IO_ERROR_NOT_FOUND + * is thrown if the object does not exist. + */ +gboolean +ostree_repo_delete_object (OstreeRepo *self, + OstreeObjectType objtype, + const char *sha256, + GCancellable *cancellable, + GError **error) +{ + gs_unref_object GFile *objpath = _ostree_repo_get_object_path (self, sha256, objtype); + return gs_file_unlink (objpath, cancellable, error); +} + +/** + * ostree_repo_query_object_storage_size: + * @self: + * @objtype: Object type + * @sha256: Checksum + * @out_size: (out): Size in bytes object occupies physically + * @cancellable: + * @error: + * + * Return the size in bytes of object with checksum @sha256, after any + * compression has been applied. + */ +gboolean +ostree_repo_query_object_storage_size (OstreeRepo *self, + OstreeObjectType objtype, + const char *sha256, + gsize *out_size, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = FALSE; + gs_unref_object GFile *objpath = _ostree_repo_get_object_path (self, sha256, objtype); + gs_unref_object GFileInfo *finfo = g_file_query_info (objpath, OSTREE_GIO_FAST_QUERYINFO, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, + cancellable, error); + if (!finfo) + goto out; + + *out_size = g_file_info_get_size (finfo); + ret = TRUE; + out: + return ret; +} + gboolean ostree_repo_load_variant_c (OstreeRepo *self, OstreeObjectType objtype, diff --git a/src/libostree/ostree-repo.h b/src/libostree/ostree-repo.h index a8fb6cb2..8179f684 100644 --- a/src/libostree/ostree-repo.h +++ b/src/libostree/ostree-repo.h @@ -65,10 +65,6 @@ gboolean ostree_repo_write_config (OstreeRepo *self, GKeyFile *new_config, GError **error); -GFile * ostree_repo_get_object_path (OstreeRepo *self, - const char *checksum, - OstreeObjectType type); - gboolean ostree_repo_prepare_transaction (OstreeRepo *self, gboolean enable_commit_hardlink_scan, gboolean *out_transaction_resume, @@ -204,6 +200,19 @@ gboolean ostree_repo_load_file (OstreeRepo *self, GCancellable *cancellable, GError **error); +gboolean ostree_repo_query_object_storage_size (OstreeRepo *self, + OstreeObjectType objtype, + const char *sha256, + gsize *out_size, + GCancellable *cancellable, + GError **error); + +gboolean ostree_repo_delete_object (OstreeRepo *self, + OstreeObjectType objtype, + const char *sha256, + GCancellable *cancellable, + GError **error); + typedef enum { OSTREE_REPO_COMMIT_FILTER_ALLOW, OSTREE_REPO_COMMIT_FILTER_SKIP diff --git a/src/ostree/ot-builtin-diff.c b/src/ostree/ot-builtin-diff.c index e335194c..7abe071f 100644 --- a/src/ostree/ot-builtin-diff.c +++ b/src/ostree/ot-builtin-diff.c @@ -100,17 +100,13 @@ object_set_total_size (OstreeRepo *repo, GVariant *v = key; const char *csum; OstreeObjectType objtype; - gs_unref_object GFile *objpath = NULL; - gs_unref_object GFileInfo *finfo = NULL; + guint64 size; ostree_object_name_deserialize (v, &csum, &objtype); - objpath = ostree_repo_get_object_path (repo, csum, objtype); - finfo = g_file_query_info (objpath, OSTREE_GIO_FAST_QUERYINFO, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - cancellable, error); - if (!finfo) + if (!ostree_repo_query_object_storage_size (repo, objtype, csum, &size, + cancellable, error)) goto out; - - *out_total += g_file_info_get_size (finfo); + *out_total += size; } ret = TRUE; diff --git a/src/ostree/ot-builtin-fsck.c b/src/ostree/ot-builtin-fsck.c index e267415b..f7c7b332 100644 --- a/src/ostree/ot-builtin-fsck.c +++ b/src/ostree/ot-builtin-fsck.c @@ -155,9 +155,8 @@ load_and_fsck_one_object (OstreeRepo *repo, tmp_checksum); if (opt_delete) { - gs_unref_object GFile *object_path = ostree_repo_get_object_path (repo, checksum, objtype); g_printerr ("%s\n", msg); - (void) gs_file_unlink (object_path, cancellable, NULL); + (void) ostree_repo_delete_object (repo, objtype, checksum, cancellable, NULL); *out_found_corruption = TRUE; } else diff --git a/src/ostree/ot-builtin-show.c b/src/ostree/ot-builtin-show.c index cbdce34c..82a8e019 100644 --- a/src/ostree/ot-builtin-show.c +++ b/src/ostree/ot-builtin-show.c @@ -76,89 +76,6 @@ do_print_variant_generic (const GVariantType *type, return ret; } -static gboolean -show_repo_meta (OstreeRepo *repo, - const char *rev, - const char *resolved_rev, - GCancellable *cancellable, - GError **error) -{ - gboolean ret = FALSE; - OstreeObjectType objtype; - gs_unref_variant GVariant *variant = NULL; - gs_unref_object GFile *object_path = NULL; - gs_unref_object GInputStream *in = NULL; - - for (objtype = OSTREE_OBJECT_TYPE_FILE; objtype <= OSTREE_OBJECT_TYPE_COMMIT; objtype++) - { - g_clear_object (&object_path); - - object_path = ostree_repo_get_object_path (repo, resolved_rev, objtype); - - if (!g_file_query_exists (object_path, NULL)) - continue; - - g_print ("Object: %s\nType: %s\n", resolved_rev, ostree_object_type_to_string (objtype)); - - if (OSTREE_OBJECT_TYPE_IS_META (objtype)) - { - if (!ostree_repo_load_variant (repo, objtype, resolved_rev, &variant, error)) - continue; - - print_variant (variant); - break; - } - else if (objtype == OSTREE_OBJECT_TYPE_FILE) - { - gs_unref_object GFileInfo *finfo = NULL; - gs_unref_variant GVariant *xattrs = NULL; - GFileType filetype; - - if (!ostree_repo_load_file (repo, resolved_rev, NULL, &finfo, &xattrs, - cancellable, error)) - goto out; - - filetype = g_file_info_get_file_type (finfo); - g_print ("File Type: "); - switch (filetype) - { - case G_FILE_TYPE_REGULAR: - g_print ("regular\n"); - g_print ("Size: %" G_GUINT64_FORMAT "\n", g_file_info_get_size (finfo)); - break; - case G_FILE_TYPE_SYMBOLIC_LINK: - g_print ("symlink\n"); - g_print ("Target: %s\n", g_file_info_get_symlink_target (finfo)); - break; - default: - g_printerr ("(unknown type %u)\n", (guint)filetype); - } - - g_print ("Mode: 0%04o\n", g_file_info_get_attribute_uint32 (finfo, "unix::mode")); - g_print ("Uid: %u\n", g_file_info_get_attribute_uint32 (finfo, "unix::uid")); - g_print ("Gid: %u\n", g_file_info_get_attribute_uint32 (finfo, "unix::gid")); - - g_print ("Extended Attributes: "); - if (xattrs) - { - gs_free char *xattr_string = g_variant_print (xattrs, TRUE); - g_print ("{ %s }\n", xattr_string); - } - else - { - g_print ("(none)\n"); - } - } - else - g_assert_not_reached (); - } - - - ret = TRUE; - out: - return ret; -} - static gboolean do_print_related (OstreeRepo *repo, const char *rev, @@ -223,6 +140,39 @@ do_print_metadata_key (OstreeRepo *repo, return ret; } +static gboolean +print_if_found (OstreeRepo *repo, + OstreeObjectType objtype, + const char *rev, + gboolean *inout_was_found, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = FALSE; + gboolean have_object = FALSE; + + if (*inout_was_found) + return TRUE; + + if (!ostree_repo_has_object (repo, objtype, rev, &have_object, + cancellable, error)) + goto out; + if (have_object) + { + gs_unref_variant GVariant *variant = NULL; + if (!ostree_repo_load_variant (repo, objtype, rev, + &variant, error)) + goto out; + *inout_was_found = TRUE; + g_print ("Object: %s\nType: %s\n", rev, ostree_object_type_to_string (objtype)); + print_variant (variant); + } + + ret = TRUE; + out: + return ret; +} + gboolean ostree_builtin_show (int argc, char **argv, GFile *repo_path, GCancellable *cancellable, GError **error) { @@ -272,11 +222,71 @@ ostree_builtin_show (int argc, char **argv, GFile *repo_path, GCancellable *canc } else { - if (!ostree_repo_resolve_rev (repo, rev, FALSE, &resolved_rev, error)) - goto out; + gboolean found = FALSE; + if (!ostree_validate_rev (rev, NULL)) + { + gs_unref_variant GVariant *variant = NULL; + if (!ostree_repo_resolve_rev (repo, rev, FALSE, &resolved_rev, error)) + goto out; + if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT, resolved_rev, + &variant, error)) + goto out; + print_variant (variant); + } + else + { + if (!print_if_found (repo, OSTREE_OBJECT_TYPE_COMMIT, rev, + &found, cancellable, error)) + goto out; + if (!print_if_found (repo, OSTREE_OBJECT_TYPE_DIR_META, rev, + &found, cancellable, error)) + goto out; + if (!print_if_found (repo, OSTREE_OBJECT_TYPE_DIR_TREE, rev, + &found, cancellable, error)) + goto out; + if (!found) + { + gs_unref_object GFileInfo *finfo = NULL; + gs_unref_variant GVariant *xattrs = NULL; + GFileType filetype; + + if (!ostree_repo_load_file (repo, resolved_rev, NULL, &finfo, &xattrs, + cancellable, error)) + goto out; - if (!show_repo_meta (repo, rev, resolved_rev, cancellable, error)) - goto out; + g_print ("Object: %s\nType: %s\n", rev, ostree_object_type_to_string (OSTREE_OBJECT_TYPE_FILE)); + filetype = g_file_info_get_file_type (finfo); + g_print ("File Type: "); + switch (filetype) + { + case G_FILE_TYPE_REGULAR: + g_print ("regular\n"); + g_print ("Size: %" G_GUINT64_FORMAT "\n", g_file_info_get_size (finfo)); + break; + case G_FILE_TYPE_SYMBOLIC_LINK: + g_print ("symlink\n"); + g_print ("Target: %s\n", g_file_info_get_symlink_target (finfo)); + break; + default: + g_printerr ("(unknown type %u)\n", (guint)filetype); + } + + g_print ("Mode: 0%04o\n", g_file_info_get_attribute_uint32 (finfo, "unix::mode")); + g_print ("Uid: %u\n", g_file_info_get_attribute_uint32 (finfo, "unix::uid")); + g_print ("Gid: %u\n", g_file_info_get_attribute_uint32 (finfo, "unix::gid")); + + g_print ("Extended Attributes: "); + if (xattrs) + { + gs_free char *xattr_string = g_variant_print (xattrs, TRUE); + g_print ("{ %s }\n", xattr_string); + } + else + { + g_print ("(none)\n"); + } + } + } } ret = TRUE;