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:
parent
4bbc99fb1d
commit
3e59cc1305
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Reference in New Issue