mirror of
https://github.com/ostreedev/ostree.git
synced 2024-10-26 17:25:36 +03:00
core: Use linkat() for hardlink checkouts too
Clean up how we deal with the uncompressed object cache; we now use openat()/linkat() and such just like we do for the main objects/. Use linkat() between the objects and the destination, if possible. https://bugzilla.gnome.org/show_bug.cgi?id=707733
This commit is contained in:
parent
db148cc9ba
commit
9846fb27fd
@ -74,6 +74,12 @@ gboolean _ostree_write_variant_with_size (GOutputStream *output,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
gboolean
|
||||
_ostree_set_xattrs_fd (int fd,
|
||||
GVariant *xattrs,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
/* XX + / + checksum-2 + . + extension, but let's just use 256 for a
|
||||
* bit of overkill.
|
||||
*/
|
||||
|
@ -1036,6 +1036,43 @@ ostree_create_directory_metadata (GFileInfo *dir_info,
|
||||
return ret_metadata;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_ostree_set_xattrs_fd (int fd,
|
||||
GVariant *xattrs,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
int i, n;
|
||||
|
||||
n = g_variant_n_children (xattrs);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
const guint8* name;
|
||||
gs_unref_variant GVariant *value = NULL;
|
||||
const guint8* value_data;
|
||||
gsize value_len;
|
||||
int res;
|
||||
|
||||
g_variant_get_child (xattrs, i, "(^&ay@ay)",
|
||||
&name, &value);
|
||||
value_data = g_variant_get_fixed_array (value, &value_len, 1);
|
||||
|
||||
do
|
||||
res = fsetxattr (fd, (char*)name, (char*)value_data, value_len, 0);
|
||||
while (G_UNLIKELY (res == -1 && errno == EINTR));
|
||||
if (G_UNLIKELY (res == -1))
|
||||
{
|
||||
ot_util_set_error_from_errno (error, errno);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_set_xattrs:
|
||||
* @f: a file
|
||||
|
@ -23,11 +23,81 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <glib-unix.h>
|
||||
#include <attr/xattr.h>
|
||||
#include <gio/gfiledescriptorbased.h>
|
||||
#include "otutil.h"
|
||||
|
||||
#include "ostree-repo-file.h"
|
||||
#include "ostree-core-private.h"
|
||||
#include "ostree-repo-private.h"
|
||||
|
||||
static gboolean
|
||||
checkout_object_for_uncompressed_cache (OstreeRepo *self,
|
||||
const char *loose_path,
|
||||
GFileInfo *src_info,
|
||||
GInputStream *content,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
gs_free char *temp_filename = NULL;
|
||||
gs_unref_object GOutputStream *temp_out = NULL;
|
||||
int fd;
|
||||
int res;
|
||||
guint32 file_mode;
|
||||
|
||||
/* Don't make setuid files in uncompressed cache */
|
||||
file_mode = g_file_info_get_attribute_uint32 (src_info, "unix::mode");
|
||||
file_mode &= ~(S_ISUID|S_ISGID);
|
||||
|
||||
if (!gs_file_open_in_tmpdir_at (self->tmp_dir_fd, file_mode,
|
||||
&temp_filename, &temp_out,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (g_output_stream_splice (temp_out, content, 0, cancellable, error) < 0)
|
||||
goto out;
|
||||
|
||||
if (!g_output_stream_flush (temp_out, cancellable, error))
|
||||
goto out;
|
||||
|
||||
fd = g_file_descriptor_based_get_fd ((GFileDescriptorBased*)temp_out);
|
||||
|
||||
do
|
||||
res = fsync (fd);
|
||||
while (G_UNLIKELY (res == -1 && errno == EINTR));
|
||||
if (G_UNLIKELY (res == -1))
|
||||
{
|
||||
ot_util_set_error_from_errno (error, errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!g_output_stream_close (temp_out, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (!_ostree_repo_ensure_loose_objdir_at (self->uncompressed_objects_dir_fd,
|
||||
loose_path,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (G_UNLIKELY (renameat (self->tmp_dir_fd, temp_filename,
|
||||
self->uncompressed_objects_dir_fd, loose_path) == -1))
|
||||
{
|
||||
if (errno != EEXIST)
|
||||
{
|
||||
ot_util_set_error_from_errno (error, errno);
|
||||
g_prefix_error (error, "Storing file '%s': ", temp_filename);
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
(void) unlinkat (self->tmp_dir_fd, temp_filename, 0);
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* create_file_from_input:
|
||||
* @dest_file: Destination; must not exist
|
||||
@ -323,21 +393,24 @@ checkout_file_from_input (GFile *file,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
checkout_file_hardlink (OstreeRepo *self,
|
||||
OstreeRepoCheckoutMode mode,
|
||||
OstreeRepoCheckoutOverwriteMode overwrite_mode,
|
||||
GFile *source,
|
||||
int dirfd,
|
||||
const char *name,
|
||||
gboolean *out_was_supported,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
checkout_file_hardlink (OstreeRepo *self,
|
||||
OstreeRepoCheckoutMode mode,
|
||||
OstreeRepoCheckoutOverwriteMode overwrite_mode,
|
||||
const char *loose_path,
|
||||
int destination_dfd,
|
||||
const char *destination_name,
|
||||
gboolean allow_noent,
|
||||
gboolean *out_was_supported,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
gboolean ret_was_supported = FALSE;
|
||||
int srcfd = self->mode == OSTREE_REPO_MODE_BARE ?
|
||||
self->objects_dir_fd : self->uncompressed_objects_dir_fd;
|
||||
|
||||
again:
|
||||
if (linkat (-1, gs_file_get_path_cached (source), dirfd, name, 0) != -1)
|
||||
if (linkat (srcfd, loose_path, destination_dfd, destination_name, 0) != -1)
|
||||
ret_was_supported = TRUE;
|
||||
else if (errno == EMLINK || errno == EXDEV || errno == EPERM)
|
||||
{
|
||||
@ -346,6 +419,10 @@ checkout_file_hardlink (OstreeRepo *self,
|
||||
*/
|
||||
ret_was_supported = FALSE;
|
||||
}
|
||||
else if (allow_noent && errno == ENOENT)
|
||||
{
|
||||
ret_was_supported = FALSE;
|
||||
}
|
||||
else if (errno == EEXIST && overwrite_mode == OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES)
|
||||
{
|
||||
/* Idiocy, from man rename(2)
|
||||
@ -356,9 +433,8 @@ checkout_file_hardlink (OstreeRepo *self,
|
||||
*
|
||||
* So we can't make this atomic.
|
||||
*/
|
||||
(void) unlinkat (dirfd, name, 0);
|
||||
(void) unlinkat (destination_dfd, destination_name, 0);
|
||||
goto again;
|
||||
ret_was_supported = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -373,72 +449,6 @@ checkout_file_hardlink (OstreeRepo *self,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
find_loose_for_checkout (OstreeRepo *self,
|
||||
const char *checksum,
|
||||
GFile **out_loose_path,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
gs_unref_object GFile *path = NULL;
|
||||
struct stat stbuf;
|
||||
|
||||
do
|
||||
{
|
||||
switch (self->mode)
|
||||
{
|
||||
case OSTREE_REPO_MODE_BARE:
|
||||
path = _ostree_repo_get_object_path (self, checksum, OSTREE_OBJECT_TYPE_FILE);
|
||||
break;
|
||||
case OSTREE_REPO_MODE_ARCHIVE_Z2:
|
||||
{
|
||||
if (self->enable_uncompressed_cache)
|
||||
path = _ostree_repo_get_uncompressed_object_cache_path (self, checksum);
|
||||
else
|
||||
path = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!path)
|
||||
{
|
||||
self = self->parent_repo;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lstat (gs_file_get_path_cached (path), &stbuf) < 0)
|
||||
{
|
||||
if (errno != ENOENT)
|
||||
{
|
||||
ot_util_set_error_from_errno (error, errno);
|
||||
goto out;
|
||||
}
|
||||
self = self->parent_repo;
|
||||
}
|
||||
else if (S_ISLNK (stbuf.st_mode))
|
||||
{
|
||||
/* Don't check out symbolic links via hardlink; it's very easy
|
||||
* to hit the maximum number of hardlinks to an inode this way,
|
||||
* especially since right now we have a lot of symbolic links to
|
||||
* busybox.
|
||||
*
|
||||
* fs/ext4/ext4.h:#define EXT4_LINK_MAX 65000
|
||||
*/
|
||||
self = self->parent_repo;
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
||||
g_clear_object (&path);
|
||||
} while (self != NULL);
|
||||
|
||||
ret = TRUE;
|
||||
ot_transfer_out_value (out_loose_path, &path);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
checkout_one_file (OstreeRepo *repo,
|
||||
GFile *source,
|
||||
@ -454,61 +464,68 @@ checkout_one_file (OstreeRepo *repo,
|
||||
gboolean ret = FALSE;
|
||||
const char *checksum;
|
||||
gboolean is_symlink;
|
||||
gboolean hardlink_supported;
|
||||
gs_unref_object GFile *loose_path = NULL;
|
||||
gboolean did_hardlink = FALSE;
|
||||
char loose_path_buf[_OSTREE_LOOSE_PATH_MAX];
|
||||
gs_unref_object GInputStream *input = NULL;
|
||||
gs_unref_variant GVariant *xattrs = NULL;
|
||||
|
||||
/* Hack to avoid trying to create device files as a user */
|
||||
if (mode == OSTREE_REPO_CHECKOUT_MODE_USER
|
||||
&& g_file_info_get_file_type (source_info) == G_FILE_TYPE_SPECIAL)
|
||||
goto out;
|
||||
|
||||
is_symlink = g_file_info_get_file_type (source_info) == G_FILE_TYPE_SYMBOLIC_LINK;
|
||||
|
||||
checksum = ostree_repo_file_get_checksum ((OstreeRepoFile*)source);
|
||||
|
||||
/* We can only do hardlinks in these scenarios */
|
||||
if (!is_symlink &&
|
||||
((repo->mode == OSTREE_REPO_MODE_BARE && mode == OSTREE_REPO_CHECKOUT_MODE_NONE)
|
||||
|| (repo->mode == OSTREE_REPO_MODE_ARCHIVE_Z2 && mode == OSTREE_REPO_CHECKOUT_MODE_USER)))
|
||||
/* Try to do a hardlink first, if it's a regular file. This also
|
||||
* traverses all parent repos.
|
||||
*/
|
||||
if (!is_symlink)
|
||||
{
|
||||
if (!find_loose_for_checkout (repo, checksum, &loose_path,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
OstreeRepo *current_repo = repo;
|
||||
|
||||
while (current_repo)
|
||||
{
|
||||
gboolean is_bare = (current_repo->mode == OSTREE_REPO_MODE_BARE
|
||||
&& mode == OSTREE_REPO_CHECKOUT_MODE_NONE);
|
||||
gboolean is_archive_z2_with_cache = (current_repo->mode == OSTREE_REPO_MODE_ARCHIVE_Z2
|
||||
&& mode == OSTREE_REPO_CHECKOUT_MODE_USER);
|
||||
|
||||
/* But only under these conditions */
|
||||
if (is_bare || is_archive_z2_with_cache)
|
||||
{
|
||||
/* Override repo mode; for archive-z2 we're looking in
|
||||
the cache, which is in "bare" form */
|
||||
_ostree_loose_path (loose_path_buf, checksum, OSTREE_OBJECT_TYPE_FILE, OSTREE_REPO_MODE_BARE);
|
||||
if (!checkout_file_hardlink (current_repo,
|
||||
mode, overwrite_mode, loose_path_buf,
|
||||
destination_dfd, destination_name,
|
||||
TRUE, &did_hardlink,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
if (did_hardlink)
|
||||
break;
|
||||
}
|
||||
current_repo = current_repo->parent_repo;
|
||||
}
|
||||
}
|
||||
/* Also, if we're archive-z and we didn't find an object, uncompress it now,
|
||||
* stick it in the cache, and then hardlink to that.
|
||||
|
||||
|
||||
/* Ok, if we're archive-z2 and we didn't find an object, uncompress
|
||||
* it now, stick it in the cache, and then hardlink to that.
|
||||
*/
|
||||
if (!is_symlink
|
||||
&& loose_path == NULL
|
||||
&& !did_hardlink
|
||||
&& repo->mode == OSTREE_REPO_MODE_ARCHIVE_Z2
|
||||
&& mode == OSTREE_REPO_CHECKOUT_MODE_USER
|
||||
&& repo->enable_uncompressed_cache)
|
||||
{
|
||||
gs_unref_object GFile *objdir = NULL;
|
||||
|
||||
loose_path = _ostree_repo_get_uncompressed_object_cache_path (repo, checksum);
|
||||
if (!ostree_repo_load_file (repo, checksum, &input, NULL, &xattrs,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
objdir = g_file_get_parent (loose_path);
|
||||
if (!gs_file_ensure_directory (objdir, TRUE, cancellable, error))
|
||||
{
|
||||
g_prefix_error (error, "Creating cache directory %s: ",
|
||||
gs_file_get_path_cached (objdir));
|
||||
goto out;
|
||||
}
|
||||
/* Overwrite any parent repo from earlier */
|
||||
_ostree_loose_path (loose_path_buf, checksum, OSTREE_OBJECT_TYPE_FILE, OSTREE_REPO_MODE_BARE);
|
||||
|
||||
/* Use UNION_FILES to make this last-one-wins thread behavior
|
||||
* for now; we lose deduplication potentially, but oh well
|
||||
*/
|
||||
if (!checkout_file_from_input (loose_path,
|
||||
OSTREE_REPO_CHECKOUT_MODE_USER,
|
||||
OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES,
|
||||
source_info, xattrs,
|
||||
input, cancellable, error))
|
||||
if (!checkout_object_for_uncompressed_cache (repo, loose_path_buf,
|
||||
source_info, input,
|
||||
cancellable, error))
|
||||
{
|
||||
g_prefix_error (error, "Unpacking loose object %s: ", checksum);
|
||||
goto out;
|
||||
@ -538,24 +555,16 @@ checkout_one_file (OstreeRepo *repo,
|
||||
g_hash_table_insert (repo->updated_uncompressed_dirs, key, key);
|
||||
}
|
||||
g_mutex_unlock (&repo->cache_lock);
|
||||
}
|
||||
|
||||
if (loose_path)
|
||||
{
|
||||
/* If we found one, try hardlinking */
|
||||
if (!checkout_file_hardlink (repo, mode,
|
||||
overwrite_mode, loose_path,
|
||||
if (!checkout_file_hardlink (repo, mode, overwrite_mode, loose_path_buf,
|
||||
destination_dfd, destination_name,
|
||||
&hardlink_supported, cancellable, error))
|
||||
{
|
||||
g_prefix_error (error, "Hardlinking loose object %s to %s: ", checksum,
|
||||
gs_file_get_path_cached (destination));
|
||||
goto out;
|
||||
}
|
||||
FALSE, &did_hardlink,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Fall back to copy if there's no loose object, or we couldn't hardlink */
|
||||
if (loose_path == NULL || !hardlink_supported)
|
||||
/* Fall back to copy if we couldn't hardlink */
|
||||
if (!did_hardlink)
|
||||
{
|
||||
if (!ostree_repo_load_file (repo, checksum, &input, NULL, &xattrs,
|
||||
cancellable, error))
|
||||
@ -708,8 +717,7 @@ ostree_repo_checkout_gc (OstreeRepo *self,
|
||||
gs_free char *objdir_name = NULL;
|
||||
|
||||
objdir_name = g_strdup_printf ("%02x", GPOINTER_TO_UINT (key));
|
||||
objdir = ot_gfile_get_child_build_path (self->uncompressed_objects_dir, "objects",
|
||||
objdir_name, NULL);
|
||||
objdir = g_file_get_child (self->uncompressed_objects_dir, objdir_name);
|
||||
|
||||
enumerator = g_file_enumerate_children (objdir, "standard::name,standard::type,unix::inode,unix::nlink",
|
||||
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||
|
@ -32,6 +32,29 @@
|
||||
#include "ostree-checksum-input-stream.h"
|
||||
#include "ostree-mutable-tree.h"
|
||||
|
||||
gboolean
|
||||
_ostree_repo_ensure_loose_objdir_at (int dfd,
|
||||
const char *loose_path,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
char loose_prefix[3];
|
||||
|
||||
loose_prefix[0] = loose_path[0];
|
||||
loose_prefix[1] = loose_path[1];
|
||||
loose_prefix[2] = '\0';
|
||||
if (mkdirat (dfd, loose_prefix, 0777) == -1)
|
||||
{
|
||||
int errsv = errno;
|
||||
if (G_UNLIKELY (errsv != EEXIST))
|
||||
{
|
||||
ot_util_set_error_from_errno (error, errsv);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
commit_loose_object_trusted (OstreeRepo *self,
|
||||
const char *loose_path,
|
||||
@ -40,20 +63,10 @@ commit_loose_object_trusted (OstreeRepo *self,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
char loose_prefix[3];
|
||||
|
||||
loose_prefix[0] = loose_path[0];
|
||||
loose_prefix[1] = loose_path[1];
|
||||
loose_prefix[2] = '\0';
|
||||
if (G_UNLIKELY (mkdirat (self->objects_dir_fd, loose_prefix, 0777) == -1))
|
||||
{
|
||||
int errsv = errno;
|
||||
if (errsv != EEXIST)
|
||||
{
|
||||
ot_util_set_error_from_errno (error, errsv);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (!_ostree_repo_ensure_loose_objdir_at (self->objects_dir_fd, loose_path,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (G_UNLIKELY (renameat (self->tmp_dir_fd, tempfile_name,
|
||||
self->objects_dir_fd, loose_path) == -1))
|
||||
@ -1000,20 +1013,6 @@ _ostree_repo_get_object_path (OstreeRepo *self,
|
||||
return ret;
|
||||
}
|
||||
|
||||
GFile *
|
||||
_ostree_repo_get_uncompressed_object_cache_path (OstreeRepo *self,
|
||||
const char *checksum)
|
||||
{
|
||||
char *relpath;
|
||||
GFile *ret;
|
||||
|
||||
relpath = ostree_get_relative_object_path (checksum, OSTREE_OBJECT_TYPE_FILE, FALSE);
|
||||
ret = g_file_resolve_relative_path (self->uncompressed_objects_dir, relpath);
|
||||
g_free (relpath);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ostree_repo_write_content_trusted:
|
||||
* @self: Repo
|
||||
|
@ -36,6 +36,7 @@ struct OstreeRepo {
|
||||
GFile *objects_dir;
|
||||
int objects_dir_fd;
|
||||
GFile *uncompressed_objects_dir;
|
||||
int uncompressed_objects_dir_fd;
|
||||
GFile *remote_cache_dir;
|
||||
GFile *config_file;
|
||||
|
||||
@ -60,9 +61,11 @@ struct OstreeRepo {
|
||||
OstreeRepo *parent_repo;
|
||||
};
|
||||
|
||||
GFile *
|
||||
_ostree_repo_get_uncompressed_object_cache_path (OstreeRepo *self,
|
||||
const char *checksum);
|
||||
gboolean
|
||||
_ostree_repo_ensure_loose_objdir_at (int dfd,
|
||||
const char *loose_path,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
GFile *
|
||||
_ostree_repo_get_file_object_path (OstreeRepo *self,
|
||||
|
@ -92,6 +92,8 @@ ostree_repo_finalize (GObject *object)
|
||||
if (self->objects_dir_fd != -1)
|
||||
(void) close (self->objects_dir_fd);
|
||||
g_clear_object (&self->uncompressed_objects_dir);
|
||||
if (self->uncompressed_objects_dir_fd != -1)
|
||||
(void) close (self->uncompressed_objects_dir_fd);
|
||||
g_clear_object (&self->remote_cache_dir);
|
||||
g_clear_object (&self->config_file);
|
||||
|
||||
@ -164,7 +166,7 @@ ostree_repo_constructed (GObject *object)
|
||||
self->remote_heads_dir = g_file_resolve_relative_path (self->repodir, "refs/remotes");
|
||||
|
||||
self->objects_dir = g_file_get_child (self->repodir, "objects");
|
||||
self->uncompressed_objects_dir = g_file_get_child (self->repodir, "uncompressed-objects-cache");
|
||||
self->uncompressed_objects_dir = g_file_resolve_relative_path (self->repodir, "uncompressed-objects-cache/objects");
|
||||
self->remote_cache_dir = g_file_get_child (self->repodir, "remote-cache");
|
||||
self->config_file = g_file_get_child (self->repodir, "config");
|
||||
|
||||
@ -196,6 +198,7 @@ ostree_repo_init (OstreeRepo *self)
|
||||
g_mutex_init (&self->cache_lock);
|
||||
g_mutex_init (&self->txn_stats_lock);
|
||||
self->objects_dir_fd = -1;
|
||||
self->uncompressed_objects_dir_fd = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -526,6 +529,16 @@ ostree_repo_open (OstreeRepo *self,
|
||||
if (!gs_file_open_dir_fd (self->tmp_dir, &self->tmp_dir_fd, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (self->mode == OSTREE_REPO_MODE_ARCHIVE_Z2)
|
||||
{
|
||||
if (!gs_file_ensure_directory (self->uncompressed_objects_dir, TRUE, cancellable, error))
|
||||
goto out;
|
||||
if (!gs_file_open_dir_fd (self->uncompressed_objects_dir,
|
||||
&self->uncompressed_objects_dir_fd,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
self->inited = TRUE;
|
||||
|
||||
ret = TRUE;
|
||||
@ -644,8 +657,7 @@ _ostree_repo_get_loose_object_dirs (OstreeRepo *self,
|
||||
|
||||
if (ostree_repo_get_mode (self) == OSTREE_REPO_MODE_ARCHIVE_Z2)
|
||||
{
|
||||
gs_unref_object GFile *cachedir = g_file_get_child (self->uncompressed_objects_dir, "objects");
|
||||
if (!append_object_dirs_from (self, cachedir, ret_object_dirs,
|
||||
if (!append_object_dirs_from (self, self->uncompressed_objects_dir, ret_object_dirs,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user