repo-file: Base OstreeRepoFile on trees instead of commits

We want an OstreeRepoFile to be the way to represent a filesystem tree
inside an ostree repository. In order to do this, we need to drop the
commit from an OstreeRepoFile, and make that go to callers.

Switch all current users of ostree_repo_file_new_root to
ostree_repo_read_commit, and make the actual constructor private.

https://bugzilla.gnome.org/show_bug.cgi?id=707727
This commit is contained in:
Jasper St. Pierre 2013-09-06 23:27:45 -04:00
parent ac2d61dd51
commit 33db74d0ce
7 changed files with 111 additions and 119 deletions

@ -1 +1 @@
Subproject commit 7b9901e3fc8aa58cf9c0579c29340506269ebfbd Subproject commit bd2c1e436b270b39ca262765e775b4556d6bd50b

View File

@ -33,10 +33,6 @@ struct OstreeRepoFile
GObject parent_instance; GObject parent_instance;
OstreeRepo *repo; OstreeRepo *repo;
char *commit;
GError *commit_resolve_error;
OstreeRepoFile *parent; OstreeRepoFile *parent;
int index; int index;
char *name; char *name;
@ -65,8 +61,6 @@ ostree_repo_file_finalize (GObject *object)
g_free (self->cached_file_checksum); g_free (self->cached_file_checksum);
g_free (self->tree_contents_checksum); g_free (self->tree_contents_checksum);
g_free (self->tree_metadata_checksum); g_free (self->tree_metadata_checksum);
g_free (self->commit);
g_clear_error (&self->commit_resolve_error);
g_free (self->name); g_free (self->name);
G_OBJECT_CLASS (ostree_repo_file_parent_class)->finalize (object); G_OBJECT_CLASS (ostree_repo_file_parent_class)->finalize (object);
@ -110,40 +104,30 @@ set_error_noent (GFile *self, GError **error)
return FALSE; return FALSE;
} }
/** static OstreeRepoFile *
* ostree_repo_file_new_root: ostree_repo_file_new_root (OstreeRepo *repo,
* @repo: Containing repo const char *contents_checksum,
* @commit: SHA256 checksum const char *metadata_checksum)
*
* Returns: (transfer full): A new #OstreeRepoFile corresponding to commit contents
*/
GFile *
ostree_repo_file_new_root (OstreeRepo *repo,
const char *commit)
{ {
OstreeRepoFile *self; OstreeRepoFile *self;
g_return_val_if_fail (repo != NULL, NULL); g_return_val_if_fail (repo != NULL, NULL);
g_return_val_if_fail (commit != NULL, NULL); g_return_val_if_fail (contents_checksum != NULL, NULL);
g_return_val_if_fail (strlen (commit) == 64, NULL); g_return_val_if_fail (strlen (contents_checksum) == 64, NULL);
g_return_val_if_fail (metadata_checksum != NULL, NULL);
g_return_val_if_fail (strlen (metadata_checksum) == 64, NULL);
self = g_object_new (OSTREE_TYPE_REPO_FILE, NULL); self = g_object_new (OSTREE_TYPE_REPO_FILE, NULL);
self->repo = g_object_ref (repo); self->repo = g_object_ref (repo);
self->commit = g_strdup (commit); self->tree_contents_checksum = g_strdup (contents_checksum);
self->tree_metadata_checksum = g_strdup (metadata_checksum);
return G_FILE (self); return self;
} }
/** static OstreeRepoFile *
* ostree_repo_file_new_child:
* @parent:
* @name: Name for new child
*
* Returns: (transfer full): A new child file with the given name
*/
GFile *
ostree_repo_file_new_child (OstreeRepoFile *parent, ostree_repo_file_new_child (OstreeRepoFile *parent,
const char *name) const char *name)
{ {
OstreeRepoFile *self; OstreeRepoFile *self;
size_t len; size_t len;
@ -156,51 +140,66 @@ ostree_repo_file_new_child (OstreeRepoFile *parent,
if (self->name[len-1] == '/') if (self->name[len-1] == '/')
self->name[len-1] = '\0'; self->name[len-1] = '\0';
return G_FILE (self); return self;
} }
static gboolean OstreeRepoFile *
do_resolve_commit (OstreeRepoFile *self, _ostree_repo_file_new_for_commit (OstreeRepo *repo,
GError **error) const char *commit,
GError **error)
{ {
gboolean ret = FALSE; OstreeRepoFile *ret = NULL;
gs_unref_variant GVariant *commit = NULL; gs_unref_variant GVariant *commit_v = NULL;
gs_unref_variant GVariant *root_contents = NULL;
gs_unref_variant GVariant *root_metadata = NULL;
gs_unref_variant GVariant *tree_contents_csum_v = NULL; gs_unref_variant GVariant *tree_contents_csum_v = NULL;
gs_unref_variant GVariant *tree_metadata_csum_v = NULL; gs_unref_variant GVariant *tree_metadata_csum_v = NULL;
char tmp_checksum[65]; char tree_contents_csum[65];
char tree_metadata_csum[65];
g_assert (self->parent == NULL); g_return_val_if_fail (repo != NULL, NULL);
g_return_val_if_fail (commit != NULL, NULL);
g_return_val_if_fail (strlen (commit) == 64, NULL);
if (!ostree_repo_load_variant (self->repo, OSTREE_OBJECT_TYPE_COMMIT, if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT,
self->commit, &commit, error)) commit, &commit_v, error))
goto out; goto out;
/* PARSE OSTREE_OBJECT_TYPE_COMMIT */ /* PARSE OSTREE_OBJECT_TYPE_COMMIT */
g_variant_get_child (commit, 6, "@ay", &tree_contents_csum_v); g_variant_get_child (commit_v, 6, "@ay", &tree_contents_csum_v);
ostree_checksum_inplace_from_bytes (g_variant_get_data (tree_contents_csum_v),
tree_contents_csum);
ostree_checksum_inplace_from_bytes (g_variant_get_data (tree_contents_csum_v), tmp_checksum); g_variant_get_child (commit_v, 7, "@ay", &tree_metadata_csum_v);
ostree_checksum_inplace_from_bytes (g_variant_get_data (tree_metadata_csum_v),
tree_metadata_csum);
ret = ostree_repo_file_new_root (repo, tree_contents_csum, tree_metadata_csum);
out:
return ret;
}
static gboolean
do_resolve (OstreeRepoFile *self,
GError **error)
{
gboolean ret = FALSE;
gs_unref_variant GVariant *root_contents = NULL;
gs_unref_variant GVariant *root_metadata = NULL;
g_assert (self->parent == NULL);
if (!ostree_repo_load_variant (self->repo, OSTREE_OBJECT_TYPE_DIR_TREE, if (!ostree_repo_load_variant (self->repo, OSTREE_OBJECT_TYPE_DIR_TREE,
tmp_checksum, self->tree_contents_checksum, &root_contents, error))
&root_contents, error))
goto out; goto out;
g_variant_get_child (commit, 7, "@ay", &tree_metadata_csum_v);
ostree_checksum_inplace_from_bytes (g_variant_get_data (tree_metadata_csum_v), tmp_checksum);
if (!ostree_repo_load_variant (self->repo, OSTREE_OBJECT_TYPE_DIR_META, if (!ostree_repo_load_variant (self->repo, OSTREE_OBJECT_TYPE_DIR_META,
tmp_checksum, self->tree_metadata_checksum, &root_metadata, error))
&root_metadata, error))
goto out; goto out;
self->tree_metadata = root_metadata; self->tree_metadata = root_metadata;
root_metadata = NULL; root_metadata = NULL;
self->tree_contents = root_contents; self->tree_contents = root_contents;
root_contents = NULL; root_contents = NULL;
self->tree_contents_checksum = ostree_checksum_from_bytes_v (tree_contents_csum_v);
self->tree_metadata_checksum = ostree_checksum_from_bytes_v (tree_metadata_csum_v);
ret = TRUE; ret = TRUE;
out: out:
@ -217,12 +216,15 @@ do_resolve_nonroot (OstreeRepoFile *self,
gs_unref_variant GVariant *container = NULL; gs_unref_variant GVariant *container = NULL;
gs_unref_variant GVariant *tree_contents = NULL; gs_unref_variant GVariant *tree_contents = NULL;
gs_unref_variant GVariant *tree_metadata = NULL; gs_unref_variant GVariant *tree_metadata = NULL;
gs_unref_variant GVariant *content_csum_v = NULL; gs_unref_variant GVariant *contents_csum_v = NULL;
gs_unref_variant GVariant *metadata_csum_v = NULL; gs_unref_variant GVariant *metadata_csum_v = NULL;
gs_free char *tmp_checksum = NULL; gs_free char *tmp_checksum = NULL;
if (!ostree_repo_file_ensure_resolved (self->parent, error))
goto out;
i = ostree_repo_file_tree_find_child (self->parent, self->name, &is_dir, &container); i = ostree_repo_file_tree_find_child (self->parent, self->name, &is_dir, &container);
if (i < 0) if (i < 0)
{ {
set_error_noent ((GFile*)self, error); set_error_noent ((GFile*)self, error);
@ -239,15 +241,15 @@ do_resolve_nonroot (OstreeRepoFile *self,
g_clear_pointer (&files_variant, (GDestroyNotify) g_variant_unref); g_clear_pointer (&files_variant, (GDestroyNotify) g_variant_unref);
g_variant_get_child (container, i, "(&s@ay@ay)", g_variant_get_child (container, i, "(&s@ay@ay)",
&name, &content_csum_v, &metadata_csum_v); &name, &contents_csum_v, &metadata_csum_v);
g_free (tmp_checksum); g_free (tmp_checksum);
tmp_checksum = ostree_checksum_from_bytes_v (content_csum_v); tmp_checksum = ostree_checksum_from_bytes_v (contents_csum_v);
if (!ostree_repo_load_variant (self->repo, OSTREE_OBJECT_TYPE_DIR_TREE, if (!ostree_repo_load_variant (self->repo, OSTREE_OBJECT_TYPE_DIR_TREE,
tmp_checksum, &tree_contents, tmp_checksum, &tree_contents,
error)) error))
goto out; goto out;
g_free (tmp_checksum); g_free (tmp_checksum);
tmp_checksum = ostree_checksum_from_bytes_v (metadata_csum_v); tmp_checksum = ostree_checksum_from_bytes_v (metadata_csum_v);
if (!ostree_repo_load_variant (self->repo, OSTREE_OBJECT_TYPE_DIR_META, if (!ostree_repo_load_variant (self->repo, OSTREE_OBJECT_TYPE_DIR_META,
@ -259,7 +261,7 @@ do_resolve_nonroot (OstreeRepoFile *self,
tree_contents = NULL; tree_contents = NULL;
self->tree_metadata = tree_metadata; self->tree_metadata = tree_metadata;
tree_metadata = NULL; tree_metadata = NULL;
self->tree_contents_checksum = ostree_checksum_from_bytes_v (content_csum_v); self->tree_contents_checksum = ostree_checksum_from_bytes_v (contents_csum_v);
self->tree_metadata_checksum = ostree_checksum_from_bytes_v (metadata_csum_v); self->tree_metadata_checksum = ostree_checksum_from_bytes_v (metadata_csum_v);
} }
else else
@ -274,36 +276,26 @@ gboolean
ostree_repo_file_ensure_resolved (OstreeRepoFile *self, ostree_repo_file_ensure_resolved (OstreeRepoFile *self,
GError **error) GError **error)
{ {
if (self->commit_resolve_error != NULL) gboolean ret = FALSE;
goto out;
if (self->parent == NULL) if (self->parent == NULL)
{ {
if (self->tree_contents == NULL) if (self->tree_contents == NULL)
(void)do_resolve_commit (self, &(self->commit_resolve_error)); if (!do_resolve (self, error))
} goto out;
else if (self->index == -1)
{
if (!ostree_repo_file_ensure_resolved (self->parent, error))
goto out;
(void)do_resolve_nonroot (self, &(self->commit_resolve_error));
}
out:
if (self->commit_resolve_error)
{
if (error)
*error = g_error_copy (self->commit_resolve_error);
return FALSE;
} }
else else
return TRUE; {
} if (self->index == -1)
{
if (!do_resolve_nonroot (self, error))
goto out;
}
}
const char * ret = TRUE;
ostree_repo_file_get_commit (OstreeRepoFile *self) out:
{ return ret;
return ostree_repo_file_get_root (self)->commit;
} }
gboolean gboolean
@ -507,7 +499,10 @@ ostree_repo_file_get_uri (GFile *file)
path = gs_file_get_path_cached (file); path = gs_file_get_path_cached (file);
uri_path = g_filename_to_uri (path, NULL, NULL); uri_path = g_filename_to_uri (path, NULL, NULL);
g_assert (g_str_has_prefix (uri_path, "file://")); g_assert (g_str_has_prefix (uri_path, "file://"));
ret = g_strconcat ("ostree://", self->commit, uri_path+strlen("file://"), NULL); ret = g_strconcat ("ostree://",
self->tree_contents_checksum, "/", self->tree_metadata_checksum,
uri_path+strlen("file://"),
NULL);
g_free (uri_path); g_free (uri_path);
return ret; return ret;
@ -533,9 +528,9 @@ ostree_repo_file_dup (GFile *file)
OstreeRepoFile *self = OSTREE_REPO_FILE (file); OstreeRepoFile *self = OSTREE_REPO_FILE (file);
if (self->parent) if (self->parent)
return ostree_repo_file_new_child (self->parent, self->name); return G_FILE (ostree_repo_file_new_child (self->parent, self->name));
else else
return ostree_repo_file_new_root (self->repo, self->commit); return G_FILE (ostree_repo_file_new_root (self->repo, self->tree_contents_checksum, self->tree_metadata_checksum));
} }
static guint static guint
@ -546,7 +541,7 @@ ostree_repo_file_hash (GFile *file)
if (self->parent) if (self->parent)
return g_file_hash (self->parent) + g_str_hash (self->name); return g_file_hash (self->parent) + g_str_hash (self->name);
else else
return g_str_hash (self->commit); return g_str_hash (self->tree_contents_checksum) + g_str_hash (self->tree_metadata_checksum);
} }
static gboolean static gboolean
@ -558,12 +553,13 @@ ostree_repo_file_equal (GFile *file1,
if (self1->parent && self2->parent) if (self1->parent && self2->parent)
{ {
return g_str_equal (self1->name, self2->name) return (g_str_equal (self1->name, self2->name) &&
&& g_file_equal ((GFile*)self1->parent, (GFile*)self2->parent); g_file_equal ((GFile*)self1->parent, (GFile*)self2->parent));
} }
else if (!self1->parent && !self2->parent) else if (!self1->parent && !self2->parent)
{ {
return g_str_equal (self1->commit, self2->commit); return (g_str_equal (self1->tree_contents_checksum, self2->tree_contents_checksum) &&
g_str_equal (self1->tree_metadata_checksum, self2->tree_metadata_checksum));
} }
else else
return FALSE; return FALSE;
@ -654,7 +650,7 @@ ostree_repo_file_resolve_relative_path (GFile *file,
else else
filename = g_strdup (relative_path); filename = g_strdup (relative_path);
parent = (OstreeRepoFile*)ostree_repo_file_new_child (self, filename); parent = ostree_repo_file_new_child (self, filename);
g_free (filename); g_free (filename);
if (!rest) if (!rest)

View File

@ -42,12 +42,6 @@ struct _OstreeRepoFileClass
GType ostree_repo_file_get_type (void) G_GNUC_CONST; GType ostree_repo_file_get_type (void) G_GNUC_CONST;
GFile * ostree_repo_file_new_root (OstreeRepo *repo,
const char *commit);
GFile * ostree_repo_file_new_child (OstreeRepoFile *parent,
const char *name);
gboolean ostree_repo_file_ensure_resolved (OstreeRepoFile *self, gboolean ostree_repo_file_ensure_resolved (OstreeRepoFile *self,
GError **error); GError **error);
@ -68,12 +62,11 @@ void ostree_repo_file_tree_set_metadata (OstreeRepoFile *self,
const char *ostree_repo_file_tree_get_contents_checksum (OstreeRepoFile *self); const char *ostree_repo_file_tree_get_contents_checksum (OstreeRepoFile *self);
const char *ostree_repo_file_tree_get_metadata_checksum (OstreeRepoFile *self); const char *ostree_repo_file_tree_get_metadata_checksum (OstreeRepoFile *self);
gboolean ostree_repo_file_is_tree (OstreeRepoFile *self); GVariant *ostree_repo_file_tree_get_contents (OstreeRepoFile *self);
GVariant *ostree_repo_file_tree_get_metadata (OstreeRepoFile *self);
const char * ostree_repo_file_get_checksum (OstreeRepoFile *self); const char * ostree_repo_file_get_checksum (OstreeRepoFile *self);
const char * ostree_repo_file_get_commit (OstreeRepoFile *self);
int ostree_repo_file_tree_find_child (OstreeRepoFile *self, int ostree_repo_file_tree_find_child (OstreeRepoFile *self,
const char *name, const char *name,
gboolean *is_dir, gboolean *is_dir,
@ -87,8 +80,5 @@ gboolean ostree_repo_file_tree_query_child (OstreeRepoFile *self,
GCancellable *cancellable, GCancellable *cancellable,
GError **error); GError **error);
GVariant *ostree_repo_file_tree_get_contents (OstreeRepoFile *self);
GVariant *ostree_repo_file_tree_get_metadata (OstreeRepoFile *self);
G_END_DECLS G_END_DECLS

View File

@ -111,5 +111,10 @@ _ostree_repo_update_refs (OstreeRepo *self,
GCancellable *cancellable, GCancellable *cancellable,
GError **error); GError **error);
OstreeRepoFile *
_ostree_repo_file_new_for_commit (OstreeRepo *repo,
const char *commit,
GError **error);
G_END_DECLS G_END_DECLS

View File

@ -1413,18 +1413,21 @@ ostree_repo_read_commit (OstreeRepo *self,
GError **error) GError **error)
{ {
gboolean ret = FALSE; gboolean ret = FALSE;
gs_unref_object GFile *ret_root = NULL; gs_unref_object OstreeRepoFile *ret_root = NULL;
gs_free char *resolved_rev = NULL; gs_free char *resolved_rev = NULL;
if (!ostree_repo_resolve_rev (self, rev, FALSE, &resolved_rev, error)) if (!ostree_repo_resolve_rev (self, rev, FALSE, &resolved_rev, error))
goto out; goto out;
ret_root = ostree_repo_file_new_root (self, resolved_rev); ret_root = _ostree_repo_file_new_for_commit (self, resolved_rev, error);
if (!ostree_repo_file_ensure_resolved ((OstreeRepoFile*)ret_root, error)) if (!ret_root)
goto out;
if (!ostree_repo_file_ensure_resolved (ret_root, error))
goto out; goto out;
ret = TRUE; ret = TRUE;
ot_transfer_out_value(out_root, &ret_root); ot_transfer_out_value(out_root, (GFile **) &ret_root);
out: out:
return ret; return ret;
} }

View File

@ -209,18 +209,17 @@ checkout_deployment_tree (GFile *sysroot,
{ {
gboolean ret = FALSE; gboolean ret = FALSE;
const char *csum = ot_deployment_get_csum (deployment); const char *csum = ot_deployment_get_csum (deployment);
gs_unref_object OstreeRepoFile *root = NULL; gs_unref_object GFile *root = NULL;
gs_unref_object GFileInfo *file_info = NULL; gs_unref_object GFileInfo *file_info = NULL;
gs_free char *checkout_target_name = NULL; gs_free char *checkout_target_name = NULL;
gs_unref_object GFile *osdeploy_path = NULL; gs_unref_object GFile *osdeploy_path = NULL;
gs_unref_object GFile *deploy_target_path = NULL; gs_unref_object GFile *deploy_target_path = NULL;
gs_unref_object GFile *deploy_parent = NULL; gs_unref_object GFile *deploy_parent = NULL;
root = (OstreeRepoFile*)ostree_repo_file_new_root (repo, csum); if (!ostree_repo_read_commit (repo, csum, &root, cancellable, error))
if (!ostree_repo_file_ensure_resolved (root, error))
goto out; goto out;
file_info = g_file_query_info ((GFile*)root, OSTREE_GIO_FAST_QUERYINFO, file_info = g_file_query_info (root, OSTREE_GIO_FAST_QUERYINFO,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
cancellable, error); cancellable, error);
if (!file_info) if (!file_info)
@ -239,7 +238,7 @@ checkout_deployment_tree (GFile *sysroot,
g_print ("ostadmin: Creating deployment %s\n", g_print ("ostadmin: Creating deployment %s\n",
gs_file_get_path_cached (deploy_target_path)); gs_file_get_path_cached (deploy_target_path));
if (!ostree_repo_checkout_tree (repo, 0, 0, deploy_target_path, root, if (!ostree_repo_checkout_tree (repo, 0, 0, deploy_target_path, OSTREE_REPO_FILE (root),
file_info, cancellable, error)) file_info, cancellable, error))
goto out; goto out;

View File

@ -56,20 +56,19 @@ process_one_checkout (OstreeRepo *repo,
{ {
gboolean ret = FALSE; gboolean ret = FALSE;
GError *tmp_error = NULL; GError *tmp_error = NULL;
gs_unref_object OstreeRepoFile *root = NULL; gs_unref_object GFile *root = NULL;
gs_unref_object OstreeRepoFile *subtree = NULL; gs_unref_object GFile *subtree = NULL;
gs_unref_object GFileInfo *file_info = NULL; gs_unref_object GFileInfo *file_info = NULL;
root = (OstreeRepoFile*)ostree_repo_file_new_root (repo, resolved_commit); if (!ostree_repo_read_commit (repo, resolved_commit, &root, cancellable, error))
if (!ostree_repo_file_ensure_resolved (root, error))
goto out; goto out;
if (subpath) if (subpath)
subtree = (OstreeRepoFile*)g_file_resolve_relative_path ((GFile*)root, subpath); subtree = g_file_resolve_relative_path (root, subpath);
else else
subtree = g_object_ref (root); subtree = g_object_ref (root);
file_info = g_file_query_info ((GFile*)subtree, OSTREE_GIO_FAST_QUERYINFO, file_info = g_file_query_info (subtree, OSTREE_GIO_FAST_QUERYINFO,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
cancellable, &tmp_error); cancellable, &tmp_error);
if (!file_info) if (!file_info)
@ -89,7 +88,7 @@ process_one_checkout (OstreeRepo *repo,
if (!ostree_repo_checkout_tree (repo, opt_user_mode ? OSTREE_REPO_CHECKOUT_MODE_USER : 0, if (!ostree_repo_checkout_tree (repo, opt_user_mode ? OSTREE_REPO_CHECKOUT_MODE_USER : 0,
opt_union ? OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES : 0, opt_union ? OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES : 0,
target, subtree, file_info, cancellable, error)) target, OSTREE_REPO_FILE (subtree), file_info, cancellable, error))
goto out; goto out;
ret = TRUE; ret = TRUE;