[ostree] core: Add new "mutable tree" class, use it for tar file import
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ostree] core: Add new "mutable tree" class, use it for tar file import
- Date: Wed, 21 Dec 2011 18:38:06 +0000 (UTC)
commit 2b7a83d1cc4dc44c145fbb4dccd9b994f21256da
Author: Colin Walters <walters verbum org>
Date: Wed Dec 21 13:34:10 2011 -0500
core: Add new "mutable tree" class, use it for tar file import
The tar import code forced the resuscitation of a hackish "FileTree"
data type for representing an in-memory tree. Split this out
into an OstreeMutableTree class for future use by any other in-memory
tree construction.
Makefile-libostree.am | 2 +
src/libostree/ostree-repo.c | 358 +++++++++++++++++--------------------------
src/libostree/ostree.h | 1 +
3 files changed, 147 insertions(+), 214 deletions(-)
---
diff --git a/Makefile-libostree.am b/Makefile-libostree.am
index 2fc7d93..adcddf7 100644
--- a/Makefile-libostree.am
+++ b/Makefile-libostree.am
@@ -22,6 +22,8 @@ privlib_LTLIBRARIES += libostree.la
libostree_la_SOURCES = src/libostree/ostree.h \
src/libostree/ostree-core.c \
src/libostree/ostree-core.h \
+ src/libostree/ostree-mutable-tree.c \
+ src/libostree/ostree-mutable-tree.h \
src/libostree/ostree-repo.c \
src/libostree/ostree-repo.h \
src/libostree/ostree-repo-file.c \
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c
index dffc162..b23391f 100644
--- a/src/libostree/ostree-repo.c
+++ b/src/libostree/ostree-repo.c
@@ -1647,79 +1647,12 @@ import_libarchive_entry_file (OstreeRepo *self,
return ret;
}
-typedef struct {
- char *metadata_checksum;
- char *contents_checksum;
-
- GHashTable *file_checksums;
- GHashTable *subdirs;
-} FileTree;
-
-static void
-file_tree_free (FileTree *tree)
-{
- g_free (tree->metadata_checksum);
- g_free (tree->contents_checksum);
-
- g_hash_table_destroy (tree->file_checksums);
- g_hash_table_destroy (tree->subdirs);
-
- g_free (tree);
-}
-
-static FileTree *
-file_tree_new (void)
-{
- FileTree *ret = g_new0 (FileTree, 1);
-
- ret->file_checksums = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, g_free);
- ret->subdirs = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, (GDestroyNotify)file_tree_free);
- return ret;
-}
-
static gboolean
-file_tree_walk (FileTree *dir,
- GPtrArray *split_path,
- guint start,
- FileTree **out_parent,
- GError **error)
-{
- if (start >= split_path->len)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
- "No such file or directory: %s",
- (char*)split_path->pdata[start]);
- return FALSE;
- }
- else if (start == split_path->len - 1)
- {
- *out_parent = dir;
- return TRUE;
- }
- else
- {
- FileTree *subdir = g_hash_table_lookup (dir->subdirs, split_path->pdata[start]);
-
- if (!subdir)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
- "No such file or directory: %s",
- (char*)split_path->pdata[start]);
- return FALSE;
- }
-
- return file_tree_walk (subdir, split_path, start + 1, out_parent, error);
- }
-}
-
-static gboolean
-file_tree_import_recurse (OstreeRepo *self,
- FileTree *tree,
- char **out_contents_checksum,
- GCancellable *cancellable,
- GError **error)
+stage_mutable_tree_recurse (OstreeRepo *self,
+ OstreeMutableTree *tree,
+ char **out_contents_checksum,
+ GCancellable *cancellable,
+ GError **error)
{
gboolean ret = FALSE;
GChecksum *ret_contents_checksum_obj = NULL;
@@ -1735,22 +1668,22 @@ file_tree_import_recurse (OstreeRepo *self,
dir_metadata_checksums = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify)g_free, (GDestroyNotify)g_free);
- g_hash_table_iter_init (&hash_iter, tree->subdirs);
+ g_hash_table_iter_init (&hash_iter, ostree_mutable_tree_get_subdirs (tree));
while (g_hash_table_iter_next (&hash_iter, &key, &value))
{
const char *name = key;
- FileTree *child_dir = value;
+ OstreeMutableTree *child_dir = value;
char *child_dir_contents_checksum;
- if (!file_tree_import_recurse (self, child_dir, &child_dir_contents_checksum, cancellable, error))
+ if (!stage_mutable_tree_recurse (self, child_dir, &child_dir_contents_checksum, cancellable, error))
goto out;
g_hash_table_replace (dir_contents_checksums, g_strdup (name), child_dir_contents_checksum);
g_hash_table_replace (dir_metadata_checksums, g_strdup (name),
- g_strdup (child_dir->metadata_checksum));
+ g_strdup (ostree_mutable_tree_get_metadata_checksum (child_dir)));
}
- serialized_tree = create_tree_variant_from_hashes (tree->file_checksums,
+ serialized_tree = create_tree_variant_from_hashes (ostree_mutable_tree_get_files (tree),
dir_contents_checksums,
dir_metadata_checksums);
@@ -1772,124 +1705,94 @@ file_tree_import_recurse (OstreeRepo *self,
ot_clear_gvariant (&serialized_tree);
return ret;
}
-
+
static gboolean
-stage_libarchive_into_root (OstreeRepo *self,
- FileTree *root,
- GFile *archive_f,
- OstreeRepoCommitModifier *modifier,
- GCancellable *cancellable,
- GError **error)
+stage_libarchive_entry_into_root (OstreeRepo *self,
+ OstreeMutableTree *root,
+ struct archive *a,
+ struct archive_entry *entry,
+ OstreeRepoCommitModifier *modifier,
+ GCancellable *cancellable,
+ GError **error)
{
gboolean ret = FALSE;
- int r;
- struct archive *a;
- struct archive_entry *entry;
+ const char *pathname;
+ const char *hardlink;
+ const char *basename;
GFileInfo *file_info = NULL;
GChecksum *tmp_checksum = NULL;
GPtrArray *split_path = NULL;
GPtrArray *hardlink_split_path = NULL;
+ OstreeMutableTree *subdir = NULL;
+ OstreeMutableTree *parent = NULL;
+ OstreeMutableTree *hardlink_source_parent = NULL;
+ char *hardlink_source_checksum = NULL;
+ OstreeMutableTree *hardlink_source_subdir = NULL;
- a = archive_read_new ();
- archive_read_support_compression_all (a);
- archive_read_support_format_all (a);
- if (archive_read_open_filename (a, ot_gfile_get_path_cached (archive_f), 8192) != ARCHIVE_OK)
+ pathname = archive_entry_pathname (entry);
+
+ if (!ot_util_path_split_validate (pathname, &split_path, error))
+ goto out;
+
+ if (split_path->len == 0)
{
- propagate_libarchive_error (error, a);
- goto out;
+ parent = NULL;
+ basename = NULL;
+ }
+ else
+ {
+ if (!ostree_mutable_tree_walk (root, split_path, 0, &parent, error))
+ goto out;
+ basename = (char*)split_path->pdata[split_path->len-1];
}
- while (TRUE)
+ hardlink = archive_entry_hardlink (entry);
+ if (hardlink)
{
- const char *pathname;
- const char *hardlink;
- const char *basename;
- FileTree *parent;
+ const char *hardlink_basename;
+
+ g_assert (parent != NULL);
- r = archive_read_next_header (a, &entry);
- if (r == ARCHIVE_EOF)
- break;
- else if (r != ARCHIVE_OK)
+ if (!ot_util_path_split_validate (hardlink, &hardlink_split_path, error))
+ goto out;
+ if (hardlink_split_path->len == 0)
{
- propagate_libarchive_error (error, a);
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Invalid hardlink path %s", hardlink);
goto out;
}
-
- pathname = archive_entry_pathname (entry);
- if (split_path)
- g_ptr_array_unref (split_path);
- if (!ot_util_path_split_validate (pathname, &split_path, error))
+ hardlink_basename = hardlink_split_path->pdata[hardlink_split_path->len - 1];
+
+ if (!ostree_mutable_tree_walk (root, hardlink_split_path, 0, &hardlink_source_parent, error))
goto out;
-
- if (split_path->len == 0)
- {
- parent = NULL;
- basename = NULL;
- }
- else
- {
- if (!file_tree_walk (root, split_path, 0, &parent, error))
- goto out;
- basename = (char*)split_path->pdata[split_path->len-1];
- }
-
- if (parent)
+
+ if (!ostree_mutable_tree_lookup (hardlink_source_parent, hardlink_basename,
+ &hardlink_source_checksum,
+ &hardlink_source_subdir,
+ error))
{
- if (!parent->metadata_checksum)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_EXISTS,
- "No such file or directory: %s", pathname);
+ g_prefix_error (error, "While resolving hardlink target: ");
goto out;
- }
}
-
- hardlink = archive_entry_hardlink (entry);
- if (hardlink)
+
+ if (hardlink_source_subdir)
{
- FileTree *hardlink_parent;
- const char *hardlink_basename;
- const char *hardlink_source_checksum;
-
- if (!ot_util_path_split_validate (hardlink, &hardlink_split_path, error))
- goto out;
- if (hardlink_split_path->len == 0)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Invalid hardlink path %s", hardlink);
- goto out;
- }
-
- if (!file_tree_walk (root, hardlink_split_path, 0, &hardlink_parent, error))
- goto out;
-
-
- hardlink_basename = hardlink_split_path->pdata[hardlink_split_path->len - 1];
-
- g_assert (parent);
- hardlink_source_checksum = g_hash_table_lookup (hardlink_parent->file_checksums, hardlink_basename);
- if (!hardlink_source_checksum)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Hardlink %s refers to nonexistent path %s",
- pathname, hardlink);
- goto out;
- }
-
- if (g_hash_table_lookup (parent->subdirs, basename))
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Directory exists: %s", hardlink);
- goto out;
- }
-
- g_hash_table_replace (parent->file_checksums,
- g_strdup (basename),
- g_strdup (hardlink_source_checksum));
- continue;
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Hardlink %s refers to directory %s",
+ pathname, hardlink);
+ goto out;
}
-
- g_clear_object (&file_info);
+ g_assert (hardlink_source_checksum);
+
+ if (!ostree_mutable_tree_replace_file (parent,
+ basename,
+ hardlink_source_checksum,
+ error))
+ goto out;
+ }
+ else
+ {
file_info = file_info_from_archive_entry_and_modifier (entry, modifier);
if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_UNKNOWN)
@@ -1899,65 +1802,94 @@ stage_libarchive_into_root (OstreeRepo *self,
goto out;
}
- ot_clear_checksum (&tmp_checksum);
-
if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
{
- FileTree *dir;
-
- if (parent)
- {
- }
if (!stage_directory_meta (self, file_info, NULL, &tmp_checksum, cancellable, error))
goto out;
if (parent == NULL)
{
- dir = root;
+ subdir = g_object_ref (root);
}
else
{
- if (g_hash_table_lookup (parent->file_checksums, basename))
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Can't replace file with directory: %s", pathname);
- goto out;
- }
- /* Allow duplicate directories */
- if (!g_hash_table_lookup (parent->subdirs, basename))
- {
- dir = file_tree_new ();
- g_assert (basename);
- g_hash_table_replace (parent->subdirs, g_strdup (basename), dir);
- }
+ if (!ostree_mutable_tree_ensure_dir (parent, basename, &subdir, error))
+ goto out;
}
- g_free (dir->metadata_checksum);
- dir->metadata_checksum = g_strdup (g_checksum_get_string (tmp_checksum));
+
+ ostree_mutable_tree_set_metadata_checksum (subdir, g_checksum_get_string (tmp_checksum));
}
else
{
- if (g_hash_table_lookup (parent->subdirs, basename))
+ if (parent == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Can't replace directory with file: %s", pathname);
+ "Can't import file as root");
goto out;
}
if (!import_libarchive_entry_file (self, a, entry, file_info, &tmp_checksum, cancellable, error))
goto out;
+
+ if (!ostree_mutable_tree_replace_file (parent, basename,
+ g_checksum_get_string (tmp_checksum),
+ error))
+ goto out;
+ }
+ }
- if (parent == NULL)
- {
- g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
- "Can't import file as root");
- goto out;
- }
+ ret = TRUE;
+ out:
+ g_clear_object (&file_info);
+ ot_clear_checksum (&tmp_checksum);
+ g_clear_object (&parent);
+ g_clear_object (&subdir);
+ g_clear_object (&hardlink_source_parent);
+ g_free (hardlink_source_checksum);
+ g_clear_object (&hardlink_source_subdir);
+ if (hardlink_split_path)
+ g_ptr_array_unref (hardlink_split_path);
+ if (split_path)
+ g_ptr_array_unref (split_path);
+ return ret;
+}
+
+static gboolean
+stage_libarchive_into_root (OstreeRepo *self,
+ OstreeMutableTree *root,
+ GFile *archive_f,
+ OstreeRepoCommitModifier *modifier,
+ GCancellable *cancellable,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ struct archive *a;
+ struct archive_entry *entry;
+ int r;
- g_hash_table_replace (parent->file_checksums,
- g_strdup (basename),
- g_strdup (g_checksum_get_string (tmp_checksum)));
+ a = archive_read_new ();
+ archive_read_support_compression_all (a);
+ archive_read_support_format_all (a);
+ if (archive_read_open_filename (a, ot_gfile_get_path_cached (archive_f), 8192) != ARCHIVE_OK)
+ {
+ propagate_libarchive_error (error, a);
+ goto out;
+ }
+
+ while (TRUE)
+ {
+ r = archive_read_next_header (a, &entry);
+ if (r == ARCHIVE_EOF)
+ break;
+ else if (r != ARCHIVE_OK)
+ {
+ propagate_libarchive_error (error, a);
+ goto out;
}
+
+ if (!stage_libarchive_entry_into_root (self, root, a, entry, modifier, cancellable, error))
+ goto out;
}
if (archive_read_close (a) != ARCHIVE_OK)
{
@@ -1967,8 +1899,7 @@ stage_libarchive_into_root (OstreeRepo *self,
ret = TRUE;
out:
- g_clear_object (&file_info);
- ot_clear_checksum (&tmp_checksum);
+ (void)archive_read_close (a);
return ret;
}
#endif
@@ -1990,7 +1921,7 @@ ostree_repo_commit_tarfiles (OstreeRepo *self,
OstreeRepoPrivate *priv = GET_PRIVATE (self);
gboolean ret = FALSE;
GChecksum *ret_commit_checksum = NULL;
- FileTree *root = NULL;
+ OstreeMutableTree *root = NULL;
char *root_contents_checksum = NULL;
char *current_head = NULL;
int i;
@@ -2010,7 +1941,7 @@ ostree_repo_commit_tarfiles (OstreeRepo *self,
if (!ostree_repo_resolve_rev (self, parent, TRUE, ¤t_head, error))
goto out;
- root = file_tree_new ();
+ root = ostree_mutable_tree_new ();
for (i = 0; i < tarfiles->len; i++)
{
@@ -2020,11 +1951,11 @@ ostree_repo_commit_tarfiles (OstreeRepo *self,
goto out;
}
- if (!file_tree_import_recurse (self, root, &root_contents_checksum, cancellable, error))
+ if (!stage_mutable_tree_recurse (self, root, &root_contents_checksum, cancellable, error))
goto out;
if (!do_commit_write_ref (self, branch, current_head, subject, body, metadata,
- root_contents_checksum, root->metadata_checksum, &ret_commit_checksum,
+ root_contents_checksum, ostree_mutable_tree_get_metadata_checksum (root), &ret_commit_checksum,
cancellable, error))
goto out;
@@ -2035,8 +1966,7 @@ ostree_repo_commit_tarfiles (OstreeRepo *self,
ot_clear_checksum (&ret_commit_checksum);
g_free (current_head);
g_free (root_contents_checksum);
- if (root)
- file_tree_free (root);
+ g_clear_object (&root);
return ret;
#else
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
diff --git a/src/libostree/ostree.h b/src/libostree/ostree.h
index d683080..da42981 100644
--- a/src/libostree/ostree.h
+++ b/src/libostree/ostree.h
@@ -25,5 +25,6 @@
#include <ostree-core.h>
#include <ostree-repo.h>
#include <ostree-checkout.h>
+#include <ostree-mutable-tree.h>
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]