core: Add --tar-autocreate-parents option for commit

The tar files we're making of artifacts don't include parent
directories.  Now we could change the builder to make them, but we can
also just autocreate them on import.  Mode 0755 with no xattrs seems
OK here.
This commit is contained in:
Colin Walters 2011-12-23 06:49:04 -05:00
parent 4bbc99fb1d
commit 3e59cc1305
6 changed files with 119 additions and 12 deletions

View File

@ -221,6 +221,55 @@ ostree_mutable_tree_lookup (OstreeMutableTree *self,
return ret;
}
gboolean
ostree_mutable_tree_ensure_parent_dirs (OstreeMutableTree *self,
GPtrArray *split_path,
const char *metadata_checksum,
OstreeMutableTree **out_parent,
GError **error)
{
gboolean ret = FALSE;
int i;
OstreeMutableTree *ret_parent = NULL;
OstreeMutableTree *subdir = self;
g_assert (metadata_checksum != NULL);
if (!self->metadata_checksum)
ostree_mutable_tree_set_metadata_checksum (self, metadata_checksum);
for (i = 0; i+1 < split_path->len; i++)
{
OstreeMutableTree *next;
const char *name = split_path->pdata[i];
if (g_hash_table_lookup (subdir->files, name))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Can't replace file with directory: %s", name);
goto out;
}
next = g_hash_table_lookup (subdir->subdirs, name);
if (!next)
{
next = ostree_mutable_tree_new ();
ostree_mutable_tree_set_metadata_checksum (next, metadata_checksum);
g_hash_table_insert (subdir->subdirs, g_strdup (name), next);
}
subdir = next;
}
ret_parent = g_object_ref (subdir);
ret = TRUE;
ot_transfer_out_value (out_parent, &ret_parent);
out:
g_clear_object (&ret_parent);
return ret;
}
gboolean
ostree_mutable_tree_walk (OstreeMutableTree *self,
GPtrArray *split_path,

View File

@ -77,6 +77,13 @@ gboolean ostree_mutable_tree_lookup (OstreeMutableTree *self,
OstreeMutableTree **out_subdir,
GError **error);
gboolean
ostree_mutable_tree_ensure_parent_dirs (OstreeMutableTree *self,
GPtrArray *split_path,
const char *metadata_checksum,
OstreeMutableTree **out_parent,
GError **error);
gboolean ostree_mutable_tree_walk (OstreeMutableTree *self,
GPtrArray *split_path,
guint start,

View File

@ -1585,6 +1585,7 @@ ostree_repo_stage_mtree (OstreeRepo *self,
while (g_hash_table_iter_next (&hash_iter, &key, &value))
{
const char *name = key;
const char *metadata_checksum;
OstreeMutableTree *child_dir = value;
char *child_dir_contents_checksum;
@ -1592,10 +1593,13 @@ ostree_repo_stage_mtree (OstreeRepo *self,
cancellable, error))
goto out;
g_assert (child_dir_contents_checksum);
g_hash_table_replace (dir_contents_checksums, g_strdup (name),
child_dir_contents_checksum); /* Transfer ownership */
metadata_checksum = ostree_mutable_tree_get_metadata_checksum (child_dir);
g_assert (metadata_checksum);
g_hash_table_replace (dir_metadata_checksums, g_strdup (name),
g_strdup (ostree_mutable_tree_get_metadata_checksum (child_dir)));
g_strdup (metadata_checksum));
}
serialized_tree = create_tree_variant_from_hashes (ostree_mutable_tree_get_files (mtree),
@ -1709,6 +1713,7 @@ stage_libarchive_entry_to_mtree (OstreeRepo *self,
struct archive *a,
struct archive_entry *entry,
OstreeRepoCommitModifier *modifier,
const char *tmp_dir_checksum,
GCancellable *cancellable,
GError **error)
{
@ -1736,10 +1741,21 @@ stage_libarchive_entry_to_mtree (OstreeRepo *self,
parent = NULL;
basename = NULL;
}
else
{
if (tmp_dir_checksum)
{
if (!ostree_mutable_tree_ensure_parent_dirs (root, split_path,
tmp_dir_checksum,
&parent,
error))
goto out;
}
else
{
if (!ostree_mutable_tree_walk (root, split_path, 0, &parent, error))
goto out;
}
basename = (char*)split_path->pdata[split_path->len-1];
}
@ -1858,14 +1874,17 @@ ostree_repo_stage_archive_to_mtree (OstreeRepo *self,
GFile *archive_f,
OstreeMutableTree *root,
OstreeRepoCommitModifier *modifier,
gboolean autocreate_parents,
GCancellable *cancellable,
GError **error)
{
#ifdef HAVE_LIBARCHIVE
gboolean ret = FALSE;
struct archive *a;
struct archive *a = NULL;
struct archive_entry *entry;
int r;
GFileInfo *tmp_dir_info = NULL;
GChecksum *tmp_dir_checksum = NULL;
a = archive_read_new ();
archive_read_support_compression_all (a);
@ -1887,7 +1906,22 @@ ostree_repo_stage_archive_to_mtree (OstreeRepo *self,
goto out;
}
if (!stage_libarchive_entry_to_mtree (self, root, a, entry, modifier, cancellable, error))
if (autocreate_parents && !tmp_dir_checksum)
{
tmp_dir_info = g_file_info_new ();
g_file_info_set_attribute_uint32 (tmp_dir_info, "unix::uid", archive_entry_uid (entry));
g_file_info_set_attribute_uint32 (tmp_dir_info, "unix::gid", archive_entry_gid (entry));
g_file_info_set_attribute_uint32 (tmp_dir_info, "unix::mode", 0755 | S_IFDIR);
if (!stage_directory_meta (self, tmp_dir_info, NULL, &tmp_dir_checksum, cancellable, error))
goto out;
}
if (!stage_libarchive_entry_to_mtree (self, root, a,
entry, modifier,
autocreate_parents ? g_checksum_get_string (tmp_dir_checksum) : NULL,
cancellable, error))
goto out;
}
if (archive_read_close (a) != ARCHIVE_OK)
@ -1898,6 +1932,9 @@ ostree_repo_stage_archive_to_mtree (OstreeRepo *self,
ret = TRUE;
out:
g_clear_object (&tmp_dir_info);
ot_clear_checksum (&tmp_dir_checksum);
if (a)
(void)archive_read_close (a);
return ret;
#else

View File

@ -158,6 +158,7 @@ gboolean ostree_repo_stage_archive_to_mtree (OstreeRepo *self,
GFile *archive,
OstreeMutableTree *tree,
OstreeRepoCommitModifier *modifier,
gboolean autocreate_parents,
GCancellable *cancellable,
GError **error);

View File

@ -36,6 +36,7 @@ static char *body;
static char *parent;
static char *branch;
static gboolean skip_if_unchanged;
static gboolean tar_autocreate_parents;
static char **trees;
static gint owner_uid = -1;
static gint owner_gid = -1;
@ -50,6 +51,7 @@ static GOptionEntry options[] = {
{ "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" },
{ "tar-autocreate-parents", 0, 0, G_OPTION_ARG_NONE, &tar_autocreate_parents, "When loading tar archives, automatically create parent directories as needed", NULL },
{ "skip-if-unchanged", 0, 0, G_OPTION_ARG_NONE, &skip_if_unchanged, "If the contents are unchanged from previous commit, do nothing", NULL },
{ NULL }
};
@ -187,6 +189,7 @@ ostree_builtin_commit (int argc, char **argv, GFile *repo_path, GError **error)
{
arg = ot_gfile_new_for_path (tree);
if (!ostree_repo_stage_archive_to_mtree (repo, arg, mtree, modifier,
tar_autocreate_parents,
cancellable, error))
goto out;
}

View File

@ -100,3 +100,13 @@ assert_file_has_content otherfile "not overwritten"
assert_file_has_content subdir/original "original"
assert_file_has_content subdir/new "new"
echo "ok tar multicommit contents"
cd ${test_tmpdir}/multicommit-files
tar -c -C files1 -z -f partial.tar.gz subdir/original
$OSTREE commit -s 'partial' -b partial --tar-autocreate-parents --tree=tar=partial.tar.gz
echo "ok tar partial commit"
cd ${test_tmpdir}
$OSTREE checkout partial partial-checkout
cd partial-checkout
assert_file_has_content subdir/original "original"