core: Use at-relative lookups for archive-z2 content

We can't quite do it for bare repositories yet because we need to have
a way to go from struct stat -> GFileInfo, and that's buried in gio's
private GLocalFile class.
This commit is contained in:
Colin Walters 2013-09-07 10:10:21 -04:00
parent d2c6e19278
commit 5a685ff989
1 changed files with 105 additions and 71 deletions

View File

@ -767,6 +767,32 @@ list_loose_objects (OstreeRepo *self,
return ret; return ret;
} }
static gboolean
openat_allow_noent (int dfd,
const char *path,
int *fd,
GCancellable *cancellable,
GError **error)
{
GError *temp_error = NULL;
if (!gs_file_openat_noatime (dfd, path, fd,
cancellable, &temp_error))
{
if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
*fd = -1;
g_clear_error (&temp_error);
}
else
{
g_propagate_error (error, temp_error);
return FALSE;
}
}
return TRUE;
}
static gboolean static gboolean
load_metadata_internal (OstreeRepo *self, load_metadata_internal (OstreeRepo *self,
OstreeObjectType objtype, OstreeObjectType objtype,
@ -779,11 +805,8 @@ load_metadata_internal (OstreeRepo *self,
GError **error) GError **error)
{ {
gboolean ret = FALSE; gboolean ret = FALSE;
GError *temp_error = NULL;
char loose_path_buf[_OSTREE_LOOSE_PATH_MAX]; char loose_path_buf[_OSTREE_LOOSE_PATH_MAX];
int fd = -1; int fd = -1;
gboolean have_loose_object = FALSE;
gs_unref_object GFile *object_path = NULL;
gs_unref_object GInputStream *ret_stream = NULL; gs_unref_object GInputStream *ret_stream = NULL;
gs_unref_variant GVariant *ret_variant = NULL; gs_unref_variant GVariant *ret_variant = NULL;
@ -791,24 +814,11 @@ load_metadata_internal (OstreeRepo *self,
_ostree_loose_path (loose_path_buf, sha256, objtype, self->mode); _ostree_loose_path (loose_path_buf, sha256, objtype, self->mode);
if (!gs_file_openat_noatime (self->objects_dir_fd, loose_path_buf, &fd, if (!openat_allow_noent (self->objects_dir_fd, loose_path_buf, &fd,
cancellable, &temp_error)) cancellable, error))
{
if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
{
have_loose_object = FALSE;
g_clear_error (&temp_error);
}
else
{
g_propagate_error (error, temp_error);
goto out; goto out;
}
}
else
have_loose_object = TRUE;
if (have_loose_object) if (fd != -1)
{ {
if (out_variant) if (out_variant)
{ {
@ -852,7 +862,7 @@ load_metadata_internal (OstreeRepo *self,
} }
else if (error_if_not_found) else if (error_if_not_found)
{ {
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
"No such metadata object %s.%s", "No such metadata object %s.%s",
sha256, ostree_object_type_to_string (objtype)); sha256, ostree_object_type_to_string (objtype));
goto out; goto out;
@ -890,39 +900,59 @@ ostree_repo_load_file (OstreeRepo *self,
GError **error) GError **error)
{ {
gboolean ret = FALSE; gboolean ret = FALSE;
gboolean found = FALSE;
OstreeRepoMode repo_mode; OstreeRepoMode repo_mode;
gs_unref_object GFile *loose_path = NULL;
gs_unref_object GInputStream *ret_input = NULL; gs_unref_object GInputStream *ret_input = NULL;
gs_unref_object GFileInfo *ret_file_info = NULL; gs_unref_object GFileInfo *ret_file_info = NULL;
gs_unref_variant GVariant *ret_xattrs = NULL; gs_unref_variant GVariant *ret_xattrs = NULL;
if (!_ostree_repo_find_object (self, OSTREE_OBJECT_TYPE_FILE, checksum, &loose_path, repo_mode = ostree_repo_get_mode (self);
if (repo_mode == OSTREE_REPO_MODE_ARCHIVE_Z2)
{
char loose_path_buf[_OSTREE_LOOSE_PATH_MAX];
int fd = -1;
struct stat stbuf;
gs_unref_object GInputStream *tmp_stream = NULL;
_ostree_loose_path (loose_path_buf, checksum, OSTREE_OBJECT_TYPE_FILE, self->mode);
if (!openat_allow_noent (self->objects_dir_fd, loose_path_buf, &fd,
cancellable, error)) cancellable, error))
goto out; goto out;
repo_mode = ostree_repo_get_mode (self); if (fd != -1)
{
tmp_stream = g_unix_input_stream_new (fd, TRUE);
fd = -1; /* Transfer ownership */
if (loose_path) if (!gs_stream_fstat ((GFileDescriptorBased*) tmp_stream, &stbuf,
{ cancellable, error))
switch (repo_mode) goto out;
{
case OSTREE_REPO_MODE_ARCHIVE_Z2: if (!ostree_content_stream_parse (TRUE, tmp_stream, stbuf.st_size, TRUE,
{
if (!ostree_content_file_parse (TRUE, loose_path, TRUE,
out_input ? &ret_input : NULL, out_input ? &ret_input : NULL,
&ret_file_info, &ret_xattrs, &ret_file_info, &ret_xattrs,
cancellable, error)) cancellable, error))
goto out; goto out;
found = TRUE;
} }
break; }
case OSTREE_REPO_MODE_BARE: else
{ {
ret_file_info = g_file_query_info (loose_path, OSTREE_GIO_FAST_QUERYINFO, gs_unref_object GFile *loose_path = NULL;
loose_path = _ostree_repo_get_object_path (self, checksum, OSTREE_OBJECT_TYPE_FILE);
if (!ot_gfile_query_info_allow_noent (loose_path, OSTREE_GIO_FAST_QUERYINFO,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
cancellable, error); &ret_file_info,
if (!ret_file_info) cancellable, error))
goto out; goto out;
if (ret_file_info)
{
if (out_xattrs) if (out_xattrs)
{ {
if (!ostree_get_xattrs_for_file (loose_path, &ret_xattrs, if (!ostree_get_xattrs_for_file (loose_path, &ret_xattrs,
@ -939,11 +969,14 @@ ostree_repo_load_file (OstreeRepo *self,
goto out; goto out;
} }
} }
}
break; found = TRUE;
} }
} }
else if (self->parent_repo)
if (!found)
{
if (self->parent_repo)
{ {
if (!ostree_repo_load_file (self->parent_repo, checksum, if (!ostree_repo_load_file (self->parent_repo, checksum,
out_input ? &ret_input : NULL, out_input ? &ret_input : NULL,
@ -958,6 +991,7 @@ ostree_repo_load_file (OstreeRepo *self,
"Couldn't find file object '%s'", checksum); "Couldn't find file object '%s'", checksum);
goto out; goto out;
} }
}
ret = TRUE; ret = TRUE;
ot_transfer_out_value (out_input, &ret_input); ot_transfer_out_value (out_input, &ret_input);