From c33db03b4c1516de8fbbb1e510f3dd71c45f5ab7 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 16 Nov 2011 22:43:26 -0500 Subject: [PATCH] core: Flesh out diff a bit more Now correctly notices changes to directory metadata (not just contents). --- src/libostree/ostree-core.c | 47 +++++++++++ src/libostree/ostree-core.h | 5 ++ src/libostree/ostree-repo-file.c | 36 +++++---- src/libostree/ostree-repo-file.h | 5 +- src/libostree/ostree-repo.c | 130 +++++++++++++++---------------- src/ostree/ot-builtin-diff.c | 7 +- 6 files changed, 141 insertions(+), 89 deletions(-) diff --git a/src/libostree/ostree-core.c b/src/libostree/ostree-core.c index 0d7c6d87..6ce51ca4 100644 --- a/src/libostree/ostree-core.c +++ b/src/libostree/ostree-core.c @@ -300,6 +300,53 @@ ostree_stat_and_checksum_file (int dir_fd, const char *path, return ret; } +gboolean +ostree_get_directory_metadata (GFile *dir, + GVariant **out_metadata, + GCancellable *cancellable, + GError **error) +{ + gboolean ret = FALSE; + struct stat stbuf; + GVariant *xattrs = NULL; + GVariant *ret_metadata = NULL; + + if (lstat (ot_gfile_get_path_cached (dir), &stbuf) < 0) + { + ot_util_set_error_from_errno (error, errno); + goto out; + } + + if (!S_ISDIR(stbuf.st_mode)) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Not a directory: '%s'", ot_gfile_get_path_cached (dir)); + goto out; + } + + xattrs = ostree_get_xattrs_for_path (ot_gfile_get_path_cached (dir), error); + if (!xattrs) + goto out; + + ret_metadata = g_variant_new ("(uuuu@a(ayay))", + OSTREE_DIR_META_VERSION, + GUINT32_TO_BE ((guint32)stbuf.st_uid), + GUINT32_TO_BE ((guint32)stbuf.st_gid), + GUINT32_TO_BE ((guint32)stbuf.st_mode), + xattrs); + g_variant_ref_sink (ret_metadata); + + ret = TRUE; + *out_metadata = ret_metadata; + ret_metadata = NULL; + out: + if (ret_metadata) + g_variant_unref (ret_metadata); + if (xattrs) + g_variant_unref (xattrs); + return ret; +} + gboolean ostree_set_xattrs (const char *path, GVariant *xattrs, GCancellable *cancellable, GError **error) { diff --git a/src/libostree/ostree-core.h b/src/libostree/ostree-core.h index d67f42f9..69ec769b 100644 --- a/src/libostree/ostree-core.h +++ b/src/libostree/ostree-core.h @@ -113,6 +113,11 @@ gboolean ostree_stat_and_checksum_file (int dirfd, const char *path, struct stat *out_stbuf, GError **error); +gboolean ostree_get_directory_metadata (GFile *dir, + GVariant **out_metadata, + GCancellable *cancellable, + GError **error); + /* Packed files: * * guint32 metadata_length [metadata gvariant] [content] diff --git a/src/libostree/ostree-repo-file.c b/src/libostree/ostree-repo-file.c index a3d5e79c..016bbb3c 100644 --- a/src/libostree/ostree-repo-file.c +++ b/src/libostree/ostree-repo-file.c @@ -392,7 +392,7 @@ _ostree_repo_file_nontree_get_local (OstreeRepoFile *self) g_assert (!ostree_repo_is_archive (self->repo)); - checksum = _ostree_repo_file_nontree_get_checksum (self); + checksum = _ostree_repo_file_get_checksum (self); path = ostree_repo_get_object_path (self->repo, checksum, OSTREE_OBJECT_TYPE_FILE); ret = ot_util_new_file_for_path (path); g_free (path); @@ -417,33 +417,35 @@ _ostree_repo_file_get_root (OstreeRepoFile *self) } const char * -_ostree_repo_file_nontree_get_checksum (OstreeRepoFile *self) +_ostree_repo_file_get_checksum (OstreeRepoFile *self) { int n; gboolean is_dir; + GVariant *files_variant; + GVariant *dirs_variant; + const char *checksum; g_assert (self->parent); n = _ostree_repo_file_tree_find_child (self->parent, self->name, &is_dir, NULL); - g_assert (n >= 0 && !is_dir); - - return _ostree_repo_file_tree_get_child_checksum (self->parent, n); -} + g_assert (n >= 0); -const char * -_ostree_repo_file_tree_get_child_checksum (OstreeRepoFile *self, - int n) -{ - GVariant *files_variant; - const char *checksum; + files_variant = g_variant_get_child_value (self->parent->tree_contents, 2); + dirs_variant = g_variant_get_child_value (self->parent->tree_contents, 3); - g_assert (self->tree_contents); - - files_variant = g_variant_get_child_value (self->tree_contents, 2); - - g_variant_get_child (files_variant, n, "(@s&s)", NULL, &checksum); + if (is_dir) + { + g_variant_get_child (dirs_variant, n, + "(@s@s&s)", NULL, NULL, &checksum); + } + else + { + g_variant_get_child (files_variant, n, + "(@s&s)", NULL, &checksum); + } g_variant_unref (files_variant); + g_variant_unref (dirs_variant); return checksum; } diff --git a/src/libostree/ostree-repo-file.h b/src/libostree/ostree-repo-file.h index 904a80a5..cccfc34d 100644 --- a/src/libostree/ostree-repo-file.h +++ b/src/libostree/ostree-repo-file.h @@ -75,7 +75,7 @@ const char *_ostree_repo_file_tree_get_content_checksum (OstreeRepoFile *self); gboolean _ostree_repo_file_is_tree (OstreeRepoFile *self); -const char * _ostree_repo_file_nontree_get_checksum (OstreeRepoFile *self); +const char * _ostree_repo_file_get_checksum (OstreeRepoFile *self); GFile *_ostree_repo_file_nontree_get_local (OstreeRepoFile *self); @@ -96,9 +96,6 @@ int _ostree_repo_file_tree_find_child (OstreeRepoFile *self, gboolean *is_dir, GVariant **out_container); -const char *_ostree_repo_file_tree_get_child_checksum (OstreeRepoFile *self, - int n); - gboolean _ostree_repo_file_tree_query_child (OstreeRepoFile *self, int n, const char *attributes, diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 0548eb43..f23f0dad 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -534,10 +534,18 @@ ostree_repo_is_archive (OstreeRepo *self) return priv->archive; } +static GVariant * +pack_metadata_variant (OstreeSerializedVariantType type, + GVariant *variant) +{ + return g_variant_new ("(uv)", GUINT32_TO_BE ((guint32)type), variant); +} + static gboolean write_gvariant_to_tmp (OstreeRepo *self, OstreeSerializedVariantType type, GVariant *variant, + GFile **out_tmpname, GChecksum **out_checksum, GError **error) { @@ -551,7 +559,7 @@ write_gvariant_to_tmp (OstreeRepo *self, GUnixOutputStream *stream = NULL; GChecksum *checksum = NULL; - serialized = g_variant_new ("(uv)", GUINT32_TO_BE ((guint32)type), variant); + serialized = pack_metadata_variant (type, variant); tmp_name = g_build_filename (ot_gfile_get_path_cached (priv->tmp_dir), "variant-tmp-XXXXXX", NULL); fd = g_mkstemp (tmp_name); @@ -586,6 +594,7 @@ write_gvariant_to_tmp (OstreeRepo *self, } ret = TRUE; + *out_tmpname = ot_util_new_file_for_path (dest_name); *out_checksum = checksum; checksum = NULL; out: @@ -611,18 +620,14 @@ import_gvariant_object (OstreeRepo *self, GError **error) { gboolean ret = FALSE; - OstreeRepoPrivate *priv = GET_PRIVATE (self); - char *tmp_name = NULL; + GFile *tmp_path = NULL; GChecksum *ret_checksum = NULL; gboolean did_exist; - if (!write_gvariant_to_tmp (self, type, variant, &ret_checksum, error)) + if (!write_gvariant_to_tmp (self, type, variant, &tmp_path, &ret_checksum, error)) goto out; - tmp_name = g_build_filename (ot_gfile_get_path_cached (priv->tmp_dir), - g_checksum_get_string (ret_checksum), NULL); - - if (!ostree_repo_store_object_trusted (self, tmp_name, + if (!ostree_repo_store_object_trusted (self, ot_gfile_get_path_cached (tmp_path), g_checksum_get_string (ret_checksum), OSTREE_OBJECT_TYPE_META, TRUE, FALSE, &did_exist, error)) @@ -632,8 +637,8 @@ import_gvariant_object (OstreeRepo *self, *out_checksum = ret_checksum; ret_checksum = NULL; out: - (void) unlink (tmp_name); - g_free (tmp_name); + (void) g_file_delete (tmp_path, NULL, NULL); + g_clear_object (&tmp_path); if (ret_checksum) g_checksum_free (ret_checksum); return ret; @@ -678,56 +683,30 @@ import_directory_meta (OstreeRepo *self, GError **error) { gboolean ret = FALSE; - struct stat stbuf; GChecksum *ret_checksum = NULL; GVariant *dirmeta = NULL; - GVariant *xattrs = NULL; + GFile *f = NULL; - if (lstat (path, &stbuf) < 0) - { - ot_util_set_error_from_errno (error, errno); - goto out; - } - - if (!S_ISDIR(stbuf.st_mode)) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Not a directory: '%s'", path); - goto out; - } + f = ot_util_new_file_for_path (path); - xattrs = ostree_get_xattrs_for_path (path, error); - if (!xattrs) + if (!ostree_get_directory_metadata (f, &dirmeta, NULL, error)) goto out; - - dirmeta = g_variant_new ("(uuuu@a(ayay))", - OSTREE_DIR_META_VERSION, - GUINT32_TO_BE ((guint32)stbuf.st_uid), - GUINT32_TO_BE ((guint32)stbuf.st_gid), - GUINT32_TO_BE ((guint32)stbuf.st_mode), - xattrs); - g_variant_ref_sink (dirmeta); - + if (!import_gvariant_object (self, OSTREE_SERIALIZED_DIRMETA_VARIANT, dirmeta, &ret_checksum, error)) - goto out; + goto out; ret = TRUE; + *out_variant = dirmeta; + dirmeta = NULL; + *out_checksum = ret_checksum; + ret_checksum = NULL; out: - if (!ret) - { - if (ret_checksum) - g_checksum_free (ret_checksum); - if (dirmeta != NULL) - g_variant_unref (dirmeta); - } - else - { - *out_checksum = ret_checksum; - *out_variant = dirmeta; - } - if (xattrs) - g_variant_unref (xattrs); + g_clear_object (&f); + if (ret_checksum) + g_checksum_free (ret_checksum); + if (dirmeta != NULL) + g_variant_unref (dirmeta); return ret; } @@ -1760,7 +1739,7 @@ checkout_tree (OstreeRepo *self, } else { - const char *checksum = _ostree_repo_file_nontree_get_checksum ((OstreeRepoFile*)child); + const char *checksum = _ostree_repo_file_get_checksum ((OstreeRepoFile*)child); dest_path = g_build_filename (destination, name, NULL); object_path = ostree_repo_get_object_path (self, checksum, OSTREE_OBJECT_TYPE_FILE); @@ -1849,26 +1828,42 @@ ostree_repo_checkout (OstreeRepo *self, static gboolean get_file_checksum (GFile *f, + GFileInfo *f_info, char **out_checksum, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; GChecksum *tmp_checksum = NULL; + GVariant *dirmeta = NULL; + GVariant *packed_dirmeta = NULL; char *ret_checksum = NULL; struct stat stbuf; if (OSTREE_IS_REPO_FILE (f)) { - ret_checksum = g_strdup (_ostree_repo_file_nontree_get_checksum ((OstreeRepoFile*)f)); + ret_checksum = g_strdup (_ostree_repo_file_get_checksum ((OstreeRepoFile*)f)); } else { - if (!ostree_stat_and_checksum_file (-1, ot_gfile_get_path_cached (f), - OSTREE_OBJECT_TYPE_FILE, - &tmp_checksum, &stbuf, error)) - goto out; - ret_checksum = g_strdup (g_checksum_get_string (tmp_checksum)); + if (g_file_info_get_file_type (f_info) == G_FILE_TYPE_DIRECTORY) + { + tmp_checksum = g_checksum_new (G_CHECKSUM_SHA256); + if (!ostree_get_directory_metadata (f, &dirmeta, cancellable, error)) + goto out; + packed_dirmeta = pack_metadata_variant (OSTREE_SERIALIZED_DIRMETA_VARIANT, dirmeta); + g_checksum_update (tmp_checksum, g_variant_get_data (packed_dirmeta), + g_variant_get_size (packed_dirmeta)); + ret_checksum = g_strdup (g_checksum_get_string (tmp_checksum)); + } + else + { + if (!ostree_stat_and_checksum_file (-1, ot_gfile_get_path_cached (f), + OSTREE_OBJECT_TYPE_FILE, + &tmp_checksum, &stbuf, error)) + goto out; + ret_checksum = g_strdup (g_checksum_get_string (tmp_checksum)); + } } ret = TRUE; @@ -1878,6 +1873,10 @@ get_file_checksum (GFile *f, g_free (ret_checksum); if (tmp_checksum) g_checksum_free (tmp_checksum); + if (dirmeta) + g_variant_unref (dirmeta); + if (packed_dirmeta) + g_variant_unref (packed_dirmeta); return ret; } @@ -1937,9 +1936,9 @@ diff_files (GFile *a, char *checksum_b = NULL; OstreeRepoDiffItem *ret_item = NULL; - if (!get_file_checksum (a, &checksum_a, cancellable, error)) + if (!get_file_checksum (a, a_info, &checksum_a, cancellable, error)) goto out; - if (!get_file_checksum (b, &checksum_b, cancellable, error)) + if (!get_file_checksum (b, b_info, &checksum_b, cancellable, error)) goto out; if (strcmp (checksum_a, checksum_b) != 0) @@ -2075,12 +2074,6 @@ diff_dirs (GFile *a, { g_ptr_array_add (modified, g_object_ref (child_a)); } - else if (child_a_type == G_FILE_TYPE_DIRECTORY) - { - if (!diff_dirs (child_a, child_b, modified, - removed, added, cancellable, error)) - goto out; - } else { OstreeRepoDiffItem *diff_item = NULL; @@ -2090,6 +2083,13 @@ diff_dirs (GFile *a, if (diff_item) g_ptr_array_add (modified, diff_item); /* Transfer ownership */ + + if (child_a_type == G_FILE_TYPE_DIRECTORY) + { + if (!diff_dirs (child_a, child_b, modified, + removed, added, cancellable, error)) + goto out; + } } } diff --git a/src/ostree/ot-builtin-diff.c b/src/ostree/ot-builtin-diff.c index 7c21ae2f..b1982abf 100644 --- a/src/ostree/ot-builtin-diff.c +++ b/src/ostree/ot-builtin-diff.c @@ -42,13 +42,14 @@ parse_file_or_commit (OstreeRepo *repo, GFile *ret_file = NULL; if (g_str_has_prefix (arg, "/") - || g_str_has_prefix (arg, "./")) + || g_str_has_prefix (arg, "./") + ) { ret_file = ot_util_new_file_for_path (arg); } else { - if (!ostree_repo_read_commit (repo, arg, &ret_file, cancellable, NULL)) + if (!ostree_repo_read_commit (repo, arg, &ret_file, cancellable, error)) goto out; } @@ -125,7 +126,7 @@ ostree_builtin_diff (int argc, char **argv, const char *repo_path, GError **erro { char *relpath = g_file_get_relative_path (cwd, added_f); g_assert (relpath != NULL); - g_print ("A %s\n", relpath); + g_print ("A /%s\n", relpath); g_free (relpath); } else