[ostree] core: Allow specifying a previous commit tree as a basis for a new commit
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ostree] core: Allow specifying a previous commit tree as a basis for a new commit
- Date: Thu, 22 Dec 2011 01:11:50 +0000 (UTC)
commit add55849abf4f9f18442beebe0067aa50b55aa7f
Author: Colin Walters <walters verbum org>
Date: Wed Dec 21 20:10:10 2011 -0500
core: Allow specifying a previous commit tree as a basis for a new commit
It's pretty trivial to map a previously existing commit tree into a
mutable tree too. While we're here change the command line arguments
for commit so that we can now properly overlay any combination of
directory, commit, or tarfile.
src/libostree/ostree-mutable-tree.c | 16 +++++
src/libostree/ostree-mutable-tree.h | 5 ++
src/libostree/ostree-repo.c | 119 +++++++++++++++++++++-------------
src/ostree/ot-builtin-commit.c | 50 ++++++++++++---
tests/t0000-basic.sh | 5 +-
tests/t0006-libarchive.sh | 6 +-
6 files changed, 143 insertions(+), 58 deletions(-)
---
diff --git a/src/libostree/ostree-mutable-tree.c b/src/libostree/ostree-mutable-tree.c
index 943ef31..1c698b9 100644
--- a/src/libostree/ostree-mutable-tree.c
+++ b/src/libostree/ostree-mutable-tree.c
@@ -28,6 +28,7 @@ struct _OstreeMutableTree
{
GObject parent_instance;
+ char *contents_checksum;
char *metadata_checksum;
GHashTable *files;
@@ -43,6 +44,7 @@ ostree_mutable_tree_finalize (GObject *object)
self = OSTREE_MUTABLE_TREE (object);
+ g_free (self->contents_checksum);
g_free (self->metadata_checksum);
g_hash_table_destroy (self->files);
@@ -82,6 +84,20 @@ ostree_mutable_tree_get_metadata_checksum (OstreeMutableTree *self)
return self->metadata_checksum;
}
+void
+ostree_mutable_tree_set_contents_checksum (OstreeMutableTree *self,
+ const char *checksum)
+{
+ g_free (self->contents_checksum);
+ self->contents_checksum = g_strdup (checksum);
+}
+
+const char *
+ostree_mutable_tree_get_contents_checksum (OstreeMutableTree *self)
+{
+ return self->contents_checksum;
+}
+
static gboolean
set_error_noent (GError **error, const char *path)
{
diff --git a/src/libostree/ostree-mutable-tree.h b/src/libostree/ostree-mutable-tree.h
index 42e9e77..413da02 100644
--- a/src/libostree/ostree-mutable-tree.h
+++ b/src/libostree/ostree-mutable-tree.h
@@ -56,6 +56,11 @@ void ostree_mutable_tree_set_metadata_checksum (OstreeMutableTree *self,
const char *ostree_mutable_tree_get_metadata_checksum (OstreeMutableTree *self);
+void ostree_mutable_tree_set_contents_checksum (OstreeMutableTree *self,
+ const char *checksum);
+
+const char *ostree_mutable_tree_get_contents_checksum (OstreeMutableTree *self);
+
gboolean ostree_mutable_tree_replace_file (OstreeMutableTree *self,
const char *name,
const char *checksum,
diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c
index 9070cd0..493c7bc 100644
--- a/src/libostree/ostree-repo.c
+++ b/src/libostree/ostree-repo.c
@@ -1370,6 +1370,7 @@ ostree_repo_stage_directory_to_mtree (OstreeRepo *self,
GError **error)
{
gboolean ret = FALSE;
+ OstreeRepoFile *repo_dir = NULL;
GError *temp_error = NULL;
GFileInfo *child_info = NULL;
OstreeMutableTree *child_mtree = NULL;
@@ -1380,26 +1381,38 @@ ostree_repo_stage_directory_to_mtree (OstreeRepo *self,
GVariant *xattrs = NULL;
GInputStream *file_input = NULL;
- child_info = g_file_query_info (dir, OSTREE_GIO_FAST_QUERYINFO,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- cancellable, error);
- if (!child_info)
- goto out;
-
- modified_info = create_modified_file_info (child_info, modifier);
-
- xattrs = ostree_get_xattrs_for_file (dir, error);
- if (!xattrs)
- goto out;
+ /* We can only reuse checksums directly if there's no modifier */
+ if (OSTREE_IS_REPO_FILE (dir) && modifier == NULL)
+ repo_dir = (OstreeRepoFile*)dir;
- if (!stage_directory_meta (self, modified_info, xattrs, &child_file_checksum,
- cancellable, error))
- goto out;
+ if (repo_dir)
+ {
+ ostree_mutable_tree_set_metadata_checksum (mtree, ostree_repo_file_get_checksum (repo_dir));
+ ostree_mutable_tree_set_contents_checksum (mtree, ostree_repo_file_tree_get_content_checksum (repo_dir));
+ }
+ else
+ {
+ child_info = g_file_query_info (dir, OSTREE_GIO_FAST_QUERYINFO,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ cancellable, error);
+ if (!child_info)
+ goto out;
+
+ modified_info = create_modified_file_info (child_info, modifier);
+
+ xattrs = ostree_get_xattrs_for_file (dir, error);
+ if (!xattrs)
+ goto out;
+
+ if (!stage_directory_meta (self, modified_info, xattrs, &child_file_checksum,
+ cancellable, error))
+ goto out;
+
+ ostree_mutable_tree_set_metadata_checksum (mtree, g_checksum_get_string (child_file_checksum));
- ostree_mutable_tree_set_metadata_checksum (mtree, g_checksum_get_string (child_file_checksum));
-
- g_clear_object (&child_info);
- g_clear_object (&modified_info);
+ g_clear_object (&child_info);
+ g_clear_object (&modified_info);
+ }
dir_enum = g_file_enumerate_children ((GFile*)dir, OSTREE_GIO_FAST_QUERYINFO,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
@@ -1428,6 +1441,13 @@ ostree_repo_stage_directory_to_mtree (OstreeRepo *self,
modifier, cancellable, error))
goto out;
}
+ else if (repo_dir)
+ {
+ if (!ostree_mutable_tree_replace_file (mtree, name,
+ ostree_repo_file_get_checksum ((OstreeRepoFile*) child),
+ error))
+ goto out;
+ }
else
{
ot_clear_checksum (&child_file_checksum);
@@ -1568,43 +1588,50 @@ ostree_repo_stage_mtree (OstreeRepo *self,
gboolean ret = FALSE;
GChecksum *ret_contents_checksum_obj = NULL;
char *ret_contents_checksum = NULL;
- GHashTable *dir_metadata_checksums;
- GHashTable *dir_contents_checksums;
+ GHashTable *dir_metadata_checksums = NULL;
+ GHashTable *dir_contents_checksums = NULL;
GVariant *serialized_tree = NULL;
GHashTableIter hash_iter;
gpointer key, value;
- dir_contents_checksums = g_hash_table_new_full (g_str_hash, g_str_equal,
- (GDestroyNotify)g_free, (GDestroyNotify)g_free);
- 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, ostree_mutable_tree_get_subdirs (mtree));
- while (g_hash_table_iter_next (&hash_iter, &key, &value))
+ if (ostree_mutable_tree_get_contents_checksum (mtree))
{
- const char *name = key;
- OstreeMutableTree *child_dir = value;
- char *child_dir_contents_checksum;
+ ret_contents_checksum = g_strdup (ostree_mutable_tree_get_contents_checksum (mtree));
+ }
+ else
+ {
+ dir_contents_checksums = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify)g_free, (GDestroyNotify)g_free);
+ 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, ostree_mutable_tree_get_subdirs (mtree));
+ while (g_hash_table_iter_next (&hash_iter, &key, &value))
+ {
+ const char *name = key;
+ OstreeMutableTree *child_dir = value;
+ char *child_dir_contents_checksum;
- if (!ostree_repo_stage_mtree (self, child_dir, &child_dir_contents_checksum,
- cancellable, error))
- goto out;
+ if (!ostree_repo_stage_mtree (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); /* Transfer ownership */
- g_hash_table_replace (dir_metadata_checksums, g_strdup (name),
- g_strdup (ostree_mutable_tree_get_metadata_checksum (child_dir)));
- }
+ g_hash_table_replace (dir_contents_checksums, g_strdup (name),
+ child_dir_contents_checksum); /* Transfer ownership */
+ g_hash_table_replace (dir_metadata_checksums, g_strdup (name),
+ g_strdup (ostree_mutable_tree_get_metadata_checksum (child_dir)));
+ }
- serialized_tree = create_tree_variant_from_hashes (ostree_mutable_tree_get_files (mtree),
- dir_contents_checksums,
- dir_metadata_checksums);
+ serialized_tree = create_tree_variant_from_hashes (ostree_mutable_tree_get_files (mtree),
+ dir_contents_checksums,
+ dir_metadata_checksums);
- if (!stage_gvariant_object (self, OSTREE_OBJECT_TYPE_DIR_TREE,
- serialized_tree, &ret_contents_checksum_obj,
- cancellable, error))
- goto out;
- ret_contents_checksum = g_strdup (g_checksum_get_string (ret_contents_checksum_obj));
+ if (!stage_gvariant_object (self, OSTREE_OBJECT_TYPE_DIR_TREE,
+ serialized_tree, &ret_contents_checksum_obj,
+ cancellable, error))
+ goto out;
+ ret_contents_checksum = g_strdup (g_checksum_get_string (ret_contents_checksum_obj));
+ }
ret = TRUE;
ot_transfer_out_value(out_contents_checksum, &ret_contents_checksum);
diff --git a/src/ostree/ot-builtin-commit.c b/src/ostree/ot-builtin-commit.c
index cdaf10b..d84a77a 100644
--- a/src/ostree/ot-builtin-commit.c
+++ b/src/ostree/ot-builtin-commit.c
@@ -35,7 +35,7 @@ static char *subject;
static char *body;
static char *parent;
static char *branch;
-static gboolean tar;
+static char **trees;
static gint owner_uid = -1;
static gint owner_gid = -1;
@@ -46,7 +46,7 @@ static GOptionEntry options[] = {
{ "metadata-variant", 0, 0, G_OPTION_ARG_FILENAME, &metadata_bin_path, "File containing serialized variant, in host endianness", "path" },
{ "branch", 'b', 0, G_OPTION_ARG_STRING, &branch, "Branch", "branch" },
{ "parent", 'p', 0, G_OPTION_ARG_STRING, &parent, "Parent commit", "commit" },
- { "tar", 0, 0, G_OPTION_ARG_NONE, &tar, "Given arguments are tar files", NULL },
+ { "tree", 0, 0, G_OPTION_ARG_STRING_ARRAY, &trees, "Overlay the given argument as a tree", "NAME" },
{ "owner-uid", 0, 0, G_OPTION_ARG_INT, &owner_uid, "Set file ownership user id", "UID" },
{ "owner-gid", 0, 0, G_OPTION_ARG_INT, &owner_gid, "Set file ownership group id", "GID" },
{ NULL }
@@ -68,7 +68,7 @@ ostree_builtin_commit (int argc, char **argv, const char *repo_path, GError **er
char *contents_checksum = NULL;
GCancellable *cancellable = NULL;
OstreeMutableTree *mtree = NULL;
- int i;
+ char *tree_type = NULL;
context = g_option_context_new ("[ARG] - Commit a new revision");
g_option_context_add_main_entries (context, options, NULL);
@@ -133,7 +133,7 @@ ostree_builtin_commit (int argc, char **argv, const char *repo_path, GError **er
mtree = ostree_mutable_tree_new ();
- if (argc == 1)
+ if (argc == 1 && (trees == NULL || trees[0] == NULL))
{
char *current_dir = g_get_current_dir ();
arg = ot_gfile_new_for_path (current_dir);
@@ -145,22 +145,55 @@ ostree_builtin_commit (int argc, char **argv, const char *repo_path, GError **er
}
else
{
- for (i = 1; i < argc; i++)
+ const char *const*tree_iter;
+ const char *tree;
+ const char *eq;
+
+ for (tree_iter = (const char *const*)trees; *tree_iter; tree_iter++)
{
+ tree = *tree_iter;
+
+ eq = strchr (tree, '=');
+ if (!eq)
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Missing type in tree specification '%s'", tree);
+ goto out;
+ }
+ g_free (tree_type);
+ tree_type = g_strndup (tree, eq - tree);
+ tree = eq + 1;
+
g_clear_object (&arg);
- arg = ot_gfile_new_for_path (argv[i]);
- if (tar)
+ if (strcmp (tree_type, "dir") == 0)
+ {
+ arg = ot_gfile_new_for_path (tree);
+ if (!ostree_repo_stage_directory_to_mtree (repo, arg, mtree, modifier,
+ cancellable, error))
+ goto out;
+ }
+ else if (strcmp (tree_type, "tar") == 0)
{
+ arg = ot_gfile_new_for_path (tree);
if (!ostree_repo_stage_archive_to_mtree (repo, arg, mtree, modifier,
cancellable, error))
goto out;
}
- else
+ else if (strcmp (tree_type, "ref") == 0)
{
+ if (!ostree_repo_read_commit (repo, tree, &arg, cancellable, error))
+ goto out;
+
if (!ostree_repo_stage_directory_to_mtree (repo, arg, mtree, modifier,
cancellable, error))
goto out;
}
+ else
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Invalid tree type specification '%s'", tree_type);
+ goto out;
+ }
}
}
@@ -185,6 +218,7 @@ ostree_builtin_commit (int argc, char **argv, const char *repo_path, GError **er
g_clear_object (&mtree);
g_free (contents_checksum);
g_free (parent);
+ g_free (tree_type);
if (metadata_mappedf)
g_mapped_file_unref (metadata_mappedf);
if (context)
diff --git a/tests/t0000-basic.sh b/tests/t0000-basic.sh
index e73631b..3ef89d2 100755
--- a/tests/t0000-basic.sh
+++ b/tests/t0000-basic.sh
@@ -19,7 +19,7 @@
set -e
-echo "1..18"
+echo "1..19"
. libtest.sh
@@ -151,3 +151,6 @@ echo "ok local clone checkout"
$OSTREE checkout -U test2 checkout-user-test2
echo "ok user checkout"
+
+$OSTREE commit -b test2 -s "Another commit" --tree=ref=test2
+echo "ok commit from ref"
diff --git a/tests/t0006-libarchive.sh b/tests/t0006-libarchive.sh
index 7094c22..4173c97 100755
--- a/tests/t0006-libarchive.sh
+++ b/tests/t0006-libarchive.sh
@@ -39,7 +39,7 @@ echo not > subdir/2/notempty
tar -c -z -f ../foo.tar.gz .
cd ..
-$OSTREE commit -s "from tar" -b test-tar --tar foo.tar.gz
+$OSTREE commit -s "from tar" -b test-tar --tree=tar=foo.tar.gz
echo "ok tar commit"
cd ${test_tmpdir}
@@ -62,7 +62,7 @@ echo foo1 > foo
ln foo bar
tar czf ${test_tmpdir}/hardlinktest.tar.gz .
cd ${test_tmpdir}
-$OSTREE commit -s 'hardlinks' -b test-hardlinks --tar hardlinktest.tar.gz
+$OSTREE commit -s 'hardlinks' -b test-hardlinks --tree=tar=hardlinktest.tar.gz
rm -rf hardlinktest
echo "ok hardlink commit"
@@ -89,7 +89,7 @@ echo "new" > files2/subdir/new
tar -c -C files1 -z -f files1.tar.gz .
tar -c -C files2 -z -f files2.tar.gz .
-$OSTREE commit -s 'multi tar' -b multicommit --tar files1.tar.gz files2.tar.gz
+$OSTREE commit -s 'multi tar' -b multicommit --tree=tar=files1.tar.gz --tree=tar=files2.tar.gz
echo "ok tar multicommit"
cd ${test_tmpdir}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]