core: Add internal GFile implementation for reading commits

The data structures we use for reading already-written commits versus
building them don't need to be the same.  It's cleaner if we can have
generic code which operates on a GFile implementation for reads,
because then we can share more generic code for walking and operating
on filesystem trees via GIO.
This commit is contained in:
Colin Walters 2011-11-07 11:25:49 -05:00
parent 3cd55cb9ab
commit 8b43c539cf
11 changed files with 1841 additions and 205 deletions

View File

@ -25,6 +25,10 @@ libostree_la_SOURCES = libostree/ostree.h \
libostree/ostree-core.h \
libostree/ostree-repo.c \
libostree/ostree-repo.h \
libostree/ostree-repo-file.c \
libostree/ostree-repo-file.h \
libostree/ostree-repo-file-enumerator.c \
libostree/ostree-repo-file-enumerator.h \
libostree/ostree-checkout.c \
libostree/ostree-checkout.h \
$(NULL)

View File

@ -296,7 +296,7 @@ ostree_stat_and_checksum_file (int dir_fd, const char *path,
}
gboolean
ostree_set_xattrs (const char *path, GVariant *xattrs, GError **error)
ostree_set_xattrs (const char *path, GVariant *xattrs, GCancellable *cancellable, GError **error)
{
gboolean ret = FALSE;
int i, n;
@ -790,7 +790,7 @@ unpack_file (const char *path,
}
}
if (!ostree_set_xattrs (dest_path, xattrs, error))
if (!ostree_set_xattrs (dest_path, xattrs, NULL, error))
goto out;
if (ret_checksum)

View File

@ -28,7 +28,7 @@ G_BEGIN_DECLS
#define OSTREE_MAX_METADATA_SIZE (1 << 26)
#define OSTREE_GIO_FAST_QUERYINFO "standard::name,standard::type,standard::is-symlink,standard::symlink-target,unix::*"
#define OSTREE_GIO_FAST_QUERYINFO "standard::name,standard::type,standard::is-symlink,standard::symlink-target,standard::is-hidden,unix::*"
#define OSTREE_EMPTY_STRING_SHA256 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
@ -98,7 +98,8 @@ char *ostree_get_relative_object_path (const char *checksum,
GVariant *ostree_get_xattrs_for_path (const char *path,
GError **error);
gboolean ostree_set_xattrs (const char *path, GVariant *xattrs, GError **error);
gboolean ostree_set_xattrs (const char *path, GVariant *xattrs,
GCancellable *cancellable, GError **error);
gboolean ostree_parse_metadata_file (const char *path,
OstreeSerializedVariantType *out_type,

View File

@ -0,0 +1,142 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2011 Colin Walters <walters@verbum.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Author: Colin Walters <walters@verbum.org>
*/
#include "config.h"
#include "ostree-repo-file-enumerator.h"
#include <string.h>
struct _OstreeRepoFileEnumerator
{
GFileEnumerator parent;
OstreeRepoFile *dir;
char *attributes;
GFileQueryInfoFlags flags;
int index;
};
#define ostree_repo_file_enumerator_get_type _ostree_repo_file_enumerator_get_type
G_DEFINE_TYPE (OstreeRepoFileEnumerator, ostree_repo_file_enumerator, G_TYPE_FILE_ENUMERATOR);
static GFileInfo *ostree_repo_file_enumerator_next_file (GFileEnumerator *enumerator,
GCancellable *cancellable,
GError **error);
static gboolean ostree_repo_file_enumerator_close (GFileEnumerator *enumerator,
GCancellable *cancellable,
GError **error);
static void
ostree_repo_file_enumerator_dispose (GObject *object)
{
OstreeRepoFileEnumerator *self;
self = OSTREE_REPO_FILE_ENUMERATOR (object);
g_clear_object (&self->dir);
g_free (self->attributes);
if (G_OBJECT_CLASS (ostree_repo_file_enumerator_parent_class)->dispose)
G_OBJECT_CLASS (ostree_repo_file_enumerator_parent_class)->dispose (object);
}
static void
ostree_repo_file_enumerator_finalize (GObject *object)
{
OstreeRepoFileEnumerator *self;
self = OSTREE_REPO_FILE_ENUMERATOR (object);
(void)self;
G_OBJECT_CLASS (ostree_repo_file_enumerator_parent_class)->finalize (object);
}
static void
ostree_repo_file_enumerator_class_init (OstreeRepoFileEnumeratorClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GFileEnumeratorClass *enumerator_class = G_FILE_ENUMERATOR_CLASS (klass);
gobject_class->finalize = ostree_repo_file_enumerator_finalize;
gobject_class->dispose = ostree_repo_file_enumerator_dispose;
enumerator_class->next_file = ostree_repo_file_enumerator_next_file;
enumerator_class->close_fn = ostree_repo_file_enumerator_close;
}
static void
ostree_repo_file_enumerator_init (OstreeRepoFileEnumerator *self)
{
}
GFileEnumerator *
_ostree_repo_file_enumerator_new (OstreeRepoFile *dir,
const char *attributes,
GFileQueryInfoFlags flags,
GCancellable *cancellable,
GError **error)
{
OstreeRepoFileEnumerator *self;
self = g_object_new (OSTREE_TYPE_REPO_FILE_ENUMERATOR,
"container", dir,
NULL);
self->dir = g_object_ref (dir);
self->attributes = g_strdup (attributes);
self->flags = flags;
return G_FILE_ENUMERATOR (self);
}
static GFileInfo *
ostree_repo_file_enumerator_next_file (GFileEnumerator *enumerator,
GCancellable *cancellable,
GError **error)
{
OstreeRepoFileEnumerator *self = OSTREE_REPO_FILE_ENUMERATOR (enumerator);
gboolean ret = FALSE;
GFileInfo *info = NULL;
if (!_ostree_repo_file_tree_query_child (self->dir, self->index,
self->attributes, self->flags,
&info, cancellable, error))
goto out;
self->index++;
ret = TRUE;
out:
if (!ret)
g_clear_object (&info);
return info;
}
static gboolean
ostree_repo_file_enumerator_close (GFileEnumerator *enumerator,
GCancellable *cancellable,
GError **error)
{
return TRUE;
}

View File

@ -0,0 +1,54 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2011 Colin Walters <walters@verbum.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Author: Colin Walters <walters@verbum.org>
*/
#ifndef _OSTREE_REPO_FILE_ENUMERATOR
#define _OSTREE_REPO_FILE_ENUMERATOR
#include "ostree-repo-file.h"
G_BEGIN_DECLS
#define OSTREE_TYPE_REPO_FILE_ENUMERATOR (_ostree_repo_file_enumerator_get_type ())
#define OSTREE_REPO_FILE_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), OSTREE_TYPE_REPO_FILE_ENUMERATOR, OstreeRepoFileEnumerator))
#define OSTREE_REPO_FILE_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), OSTREE_TYPE_REPO_FILE_ENUMERATOR, OstreeRepoFileEnumeratorClass))
#define OSTREE_IS_REPO_FILE_ENUMERATOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), OSTREE_TYPE_REPO_FILE_ENUMERATOR))
#define OSTREE_IS_REPO_FILE_ENUMERATOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), OSTREE_TYPE_REPO_FILE_ENUMERATOR))
#define OSTREE_REPO_FILE_ENUMERATOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OSTREE_TYPE_REPO_FILE_ENUMERATOR, OstreeRepoFileEnumeratorClass))
typedef struct _OstreeRepoFileEnumerator OstreeRepoFileEnumerator;
typedef struct _OstreeRepoFileEnumeratorClass OstreeRepoFileEnumeratorClass;
struct _OstreeRepoFileEnumeratorClass
{
GFileEnumeratorClass parent_class;
};
GType _ostree_repo_file_enumerator_get_type (void) G_GNUC_CONST;
GFileEnumerator * _ostree_repo_file_enumerator_new (OstreeRepoFile *dir,
const char *attributes,
GFileQueryInfoFlags flags,
GCancellable *cancellable,
GError **error);
G_END_DECLS
#endif

1427
libostree/ostree-repo-file.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,114 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2011 Colin Walters <walters@verbum.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Author: Colin Walters <walters@verbum.org>
*/
#ifndef _OSTREE_REPO_FILE
#define _OSTREE_REPO_FILE
#include "ostree-repo.h"
G_BEGIN_DECLS
#define OSTREE_TYPE_REPO_FILE (_ostree_repo_file_get_type ())
#define OSTREE_REPO_FILE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), OSTREE_TYPE_REPO_FILE, OstreeRepoFile))
#define OSTREE_REPO_FILE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), OSTREE_TYPE_REPO_FILE, OstreeRepoFileClass))
#define OSTREE_IS_LOCAL_FILE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), OSTREE_TYPE_REPO_FILE))
#define OSTREE_IS_LOCAL_FILE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), OSTREE_TYPE_REPO_FILE))
#define OSTREE_REPO_FILE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OSTREE_TYPE_REPO_FILE, OstreeRepoFileClass))
typedef struct _OstreeRepoFile OstreeRepoFile;
typedef struct _OstreeRepoFileClass OstreeRepoFileClass;
struct _OstreeRepoFileClass
{
GObjectClass parent_class;
};
GType _ostree_repo_file_get_type (void) G_GNUC_CONST;
GFile * _ostree_repo_file_new_root (OstreeRepo *repo,
const char *commit);
OstreeRepoFile * _ostree_repo_file_new_empty_tree (OstreeRepo *repo);
GFile * _ostree_repo_file_new_child (OstreeRepoFile *parent,
const char *name);
gboolean _ostree_repo_file_ensure_resolved (OstreeRepoFile *self,
GError **error);
gboolean _ostree_repo_file_get_xattrs (OstreeRepoFile *self,
GVariant **out_xattrs,
GCancellable *cancellable,
GError **error);
OstreeRepo * _ostree_repo_file_get_repo (OstreeRepoFile *self);
OstreeRepoFile * _ostree_repo_file_get_root (OstreeRepoFile *self);
void _ostree_repo_file_make_empty_tree (OstreeRepoFile *self);
void _ostree_repo_file_tree_set_metadata (OstreeRepoFile *self,
const char *checksum,
GVariant *metadata);
void _ostree_repo_file_tree_set_content_checksum (OstreeRepoFile *self,
const char *checksum);
const char *_ostree_repo_file_tree_get_content_checksum (OstreeRepoFile *self);
gboolean _ostree_repo_file_is_tree (OstreeRepoFile *self);
const char * _ostree_repo_file_nontree_get_checksum (OstreeRepoFile *self);
GFile *_ostree_repo_file_nontree_get_local (OstreeRepoFile *self);
void _ostree_repo_file_tree_remove_child (OstreeRepoFile *self,
const char *name);
void _ostree_repo_file_tree_add_file (OstreeRepoFile *self,
const char *name,
const char *checksum);
void _ostree_repo_file_tree_add_dir (OstreeRepoFile *self,
const char *name,
const char *content_checksum,
const char *metadata_checksum);
int _ostree_repo_file_tree_find_child (OstreeRepoFile *self,
const char *name,
gboolean *is_dir,
GVariant **out_container);
const char *_ostree_repo_file_tree_get_child_checksum (OstreeRepoFile *self,
int n);
gboolean _ostree_repo_file_tree_query_child (OstreeRepoFile *self,
int n,
const char *attributes,
GFileQueryInfoFlags flags,
GFileInfo **out_info,
GCancellable *cancellable,
GError **error);
GVariant *_ostree_repo_file_tree_get_contents (OstreeRepoFile *self);
GVariant *_ostree_repo_file_tree_get_metadata (OstreeRepoFile *self);
G_END_DECLS
#endif

View File

@ -25,6 +25,7 @@
#include "ostree.h"
#include "otutil.h"
#include "ostree-repo-file-enumerator.h"
#include <gio/gunixoutputstream.h>
#include <gio/gunixinputstream.h>
@ -1016,142 +1017,6 @@ parsed_tree_data_free (ParsedTreeData *pdata)
g_free (pdata);
}
static gboolean
parse_tree (OstreeRepo *self,
const char *sha256,
ParsedTreeData **out_pdata,
GError **error)
{
gboolean ret = FALSE;
ParsedTreeData *ret_pdata = NULL;
int i, n;
guint32 version;
GVariant *tree_variant = NULL;
GVariant *meta_variant = NULL;
GVariant *files_variant = NULL;
GVariant *dirs_variant = NULL;
if (!ostree_repo_load_variant_checked (self, OSTREE_SERIALIZED_TREE_VARIANT,
sha256, &tree_variant, error))
goto out;
/* PARSE OSTREE_SERIALIZED_TREE_VARIANT */
g_variant_get (tree_variant, "(u@a{sv}@a(ss)@a(sss))",
&version, &meta_variant, &files_variant, &dirs_variant);
version = GUINT32_FROM_BE (version);
ret_pdata = parsed_tree_data_new ();
n = g_variant_n_children (files_variant);
for (i = 0; i < n; i++)
{
const char *filename;
const char *checksum;
g_variant_get_child (files_variant, i, "(&s&s)", &filename, &checksum);
g_hash_table_insert (ret_pdata->files, g_strdup (filename), g_strdup (checksum));
}
n = g_variant_n_children (dirs_variant);
for (i = 0; i < n; i++)
{
const char *dirname;
const char *tree_checksum;
const char *meta_checksum;
ParsedTreeData *child_tree = NULL;
GVariant *metadata = NULL;
ParsedDirectoryData *child_dir = NULL;
g_variant_get_child (dirs_variant, i, "(&s&s&s)",
&dirname, &tree_checksum, &meta_checksum);
if (!parse_tree (self, tree_checksum, &child_tree, error))
goto out;
if (!ostree_repo_load_variant_checked (self, OSTREE_SERIALIZED_DIRMETA_VARIANT,
meta_checksum, &metadata, error))
{
parsed_tree_data_free (child_tree);
goto out;
}
child_dir = g_new0 (ParsedDirectoryData, 1);
child_dir->tree_data = child_tree;
child_dir->metadata_sha256 = g_strdup (meta_checksum);
child_dir->meta_data = metadata;
g_hash_table_insert (ret_pdata->directories, g_strdup (dirname), child_dir);
}
ret = TRUE;
out:
if (!ret)
parsed_tree_data_free (ret_pdata);
else
*out_pdata = ret_pdata;
if (tree_variant)
g_variant_unref (tree_variant);
if (meta_variant)
g_variant_unref (meta_variant);
if (files_variant)
g_variant_unref (files_variant);
if (dirs_variant)
g_variant_unref (dirs_variant);
return ret;
}
static gboolean
load_commit_and_trees (OstreeRepo *self,
const char *commit_sha256,
GVariant **out_commit,
ParsedDirectoryData **out_root_data,
GError **error)
{
GVariant *ret_commit = NULL;
ParsedDirectoryData *ret_root_data = NULL;
ParsedTreeData *tree_data = NULL;
char *ret_metadata_checksum = NULL;
GVariant *root_metadata = NULL;
gboolean ret = FALSE;
const char *tree_contents_checksum;
const char *tree_meta_checksum;
if (!ostree_repo_load_variant_checked (self, OSTREE_SERIALIZED_COMMIT_VARIANT,
commit_sha256, &ret_commit, error))
goto out;
/* PARSE OSTREE_SERIALIZED_COMMIT_VARIANT */
g_variant_get_child (ret_commit, 6, "&s", &tree_contents_checksum);
g_variant_get_child (ret_commit, 7, "&s", &tree_meta_checksum);
if (!ostree_repo_load_variant_checked (self, OSTREE_SERIALIZED_DIRMETA_VARIANT,
tree_meta_checksum, &root_metadata, error))
goto out;
if (!parse_tree (self, tree_contents_checksum, &tree_data, error))
goto out;
ret_root_data = g_new0 (ParsedDirectoryData, 1);
ret_root_data->tree_data = tree_data;
ret_root_data->metadata_sha256 = g_strdup (tree_meta_checksum);
ret_root_data->meta_data = root_metadata;
root_metadata = NULL;
ret = TRUE;
*out_commit = ret_commit;
ret_commit = NULL;
*out_root_data = ret_root_data;
ret_root_data = NULL;
out:
if (ret_commit)
g_variant_unref (ret_commit);
parsed_directory_data_free (ret_root_data);
g_free (ret_metadata_checksum);
if (root_metadata)
g_variant_unref (root_metadata);
return ret;
}
static GVariant *
create_empty_gvariant_dict (void)
{
@ -1807,106 +1672,130 @@ ostree_repo_load_variant (OstreeRepo *self,
static gboolean
checkout_tree (OstreeRepo *self,
ParsedTreeData *tree,
OstreeRepoFile *dir,
const char *destination,
GCancellable *cancellable,
GError **error);
static gboolean
checkout_one_directory (OstreeRepo *self,
const char *destination,
const char *dirname,
ParsedDirectoryData *dir,
OstreeRepoFile *dir,
GFileInfo *dir_info,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
char *dest_path = NULL;
guint32 version, uid, gid, mode;
GVariant *xattr_variant = NULL;
dest_path = g_build_filename (destination, dirname, NULL);
/* PARSE OSTREE_SERIALIZED_DIRMETA_VARIANT */
g_variant_get (dir->meta_data, "(uuuu@a(ayay))",
&version, &uid, &gid, &mode,
&xattr_variant);
version = GUINT32_FROM_BE (version);
uid = GUINT32_FROM_BE (uid);
gid = GUINT32_FROM_BE (gid);
mode = GUINT32_FROM_BE (mode);
if (mkdir (dest_path, (mode_t)mode) < 0)
if (!_ostree_repo_file_get_xattrs (dir, &xattr_variant, NULL, error))
goto out;
if (mkdir (dest_path, (mode_t)g_file_info_get_attribute_uint32 (dir_info, "unix::mode")) < 0)
{
ot_util_set_error_from_errno (error, errno);
g_prefix_error (error, "Failed to create directory '%s': ", dest_path);
goto out;
}
if (!checkout_tree (self, dir->tree_data, dest_path, error))
goto out;
if (!ostree_set_xattrs (dest_path, xattr_variant, error))
if (!ostree_set_xattrs (dest_path, xattr_variant, cancellable, error))
goto out;
if (!checkout_tree (self, dir, dest_path, cancellable, error))
goto out;
ret = TRUE;
out:
g_free (dest_path);
g_variant_unref (xattr_variant);
if (xattr_variant)
g_variant_unref (xattr_variant);
return ret;
}
static gboolean
checkout_tree (OstreeRepo *self,
ParsedTreeData *tree,
OstreeRepoFile *dir,
const char *destination,
GCancellable *cancellable,
GError **error)
{
OstreeRepoPrivate *priv = GET_PRIVATE (self);
gboolean ret = FALSE;
GHashTableIter hash_iter;
gpointer key, value;
GError *temp_error = NULL;
GFileInfo *file_info = NULL;
GFileEnumerator *dir_enum = NULL;
GFile *child = NULL;
char *object_path = NULL;
char *dest_path = NULL;
g_hash_table_iter_init (&hash_iter, tree->files);
while (g_hash_table_iter_next (&hash_iter, &key, &value))
dir_enum = g_file_enumerate_children ((GFile*)dir, OSTREE_GIO_FAST_QUERYINFO,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
cancellable,
error);
if (!dir_enum)
goto out;
while ((file_info = g_file_enumerator_next_file (dir_enum, cancellable, &temp_error)) != NULL)
{
const char *filename = key;
const char *checksum = value;
char *object_path;
char *dest_path;
const char *name;
guint32 type;
object_path = ostree_repo_get_object_path (self, checksum, OSTREE_OBJECT_TYPE_FILE);
dest_path = g_build_filename (destination, filename, NULL);
if (priv->archive)
name = g_file_info_get_attribute_byte_string (file_info, "standard::name");
type = g_file_info_get_attribute_uint32 (file_info, "standard::type");
child = g_file_get_child ((GFile*)dir, name);
if (type == G_FILE_TYPE_DIRECTORY)
{
if (!ostree_unpack_object (object_path, OSTREE_OBJECT_TYPE_FILE, dest_path, NULL, error))
if (!checkout_one_directory (self, destination, name, (OstreeRepoFile*)child, file_info, cancellable, error))
goto out;
}
else
{
if (link (object_path, dest_path) < 0)
{
ot_util_set_error_from_errno (error, errno);
g_free (object_path);
g_free (dest_path);
goto out;
}
g_free (object_path);
g_free (dest_path);
}
}
const char *checksum = _ostree_repo_file_nontree_get_checksum ((OstreeRepoFile*)child);
g_hash_table_iter_init (&hash_iter, tree->directories);
while (g_hash_table_iter_next (&hash_iter, &key, &value))
dest_path = g_build_filename (destination, name, NULL);
object_path = ostree_repo_get_object_path (self, checksum, OSTREE_OBJECT_TYPE_FILE);
if (priv->archive)
{
if (!ostree_unpack_object (object_path, OSTREE_OBJECT_TYPE_FILE, dest_path, NULL, error))
goto out;
}
else
{
if (link (object_path, dest_path) < 0)
{
ot_util_set_error_from_errno (error, errno);
goto out;
}
}
}
g_free (object_path);
object_path = NULL;
g_free (dest_path);
dest_path = NULL;
g_clear_object (&file_info);
g_clear_object (&child);
}
if (file_info == NULL && temp_error != NULL)
{
const char *dirname = key;
ParsedDirectoryData *dir = value;
if (!checkout_one_directory (self, destination, dirname, dir, error))
goto out;
g_propagate_error (error, temp_error);
goto out;
}
ret = TRUE;
out:
g_clear_object (&dir_enum);
g_clear_object (&file_info);
g_clear_object (&child);
g_free (object_path);
g_free (dest_path);
return ret;
}
@ -1914,13 +1803,13 @@ gboolean
ostree_repo_checkout (OstreeRepo *self,
const char *rev,
const char *destination,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
GVariant *commit = NULL;
char *resolved = NULL;
char *root_meta_sha = NULL;
ParsedDirectoryData *root = NULL;
OstreeRepoFile *root = NULL;
GFileInfo *root_info = NULL;
if (g_file_test (destination, G_FILE_TEST_EXISTS))
{
@ -1933,18 +1822,23 @@ ostree_repo_checkout (OstreeRepo *self,
if (!resolve_rev (self, rev, FALSE, &resolved, error))
goto out;
if (!load_commit_and_trees (self, resolved, &commit, &root, error))
root = (OstreeRepoFile*)_ostree_repo_file_new_root (self, resolved);
if (!_ostree_repo_file_ensure_resolved (root, error))
goto out;
if (!checkout_one_directory (self, destination, NULL, root, error))
root_info = g_file_query_info ((GFile*)root, OSTREE_GIO_FAST_QUERYINFO,
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
NULL, error);
if (!root_info)
goto out;
if (!checkout_one_directory (self, destination, NULL, root, root_info, cancellable, error))
goto out;
ret = TRUE;
out:
g_free (resolved);
if (commit)
g_variant_unref (commit);
parsed_directory_data_free (root);
g_free (root_meta_sha);
g_clear_object (&root);
g_clear_object (&root_info);
return ret;
}

View File

@ -18,7 +18,6 @@
*
* Author: Colin Walters <walters@verbum.org>
*/
/* ostree-repo.h */
#ifndef _OSTREE_REPO
#define _OSTREE_REPO
@ -120,9 +119,10 @@ gboolean ostree_repo_commit_from_filelist_fd (OstreeRepo *self,
GError **error);
gboolean ostree_repo_checkout (OstreeRepo *self,
const char *ref,
const char *destination,
GError **error);
const char *ref,
const char *destination,
GCancellable *cancellable,
GError **error);
typedef void (*OstreeRepoObjectIter) (OstreeRepo *self, const char *path,
GFileInfo *fileinfo, gpointer user_data);

View File

@ -64,7 +64,7 @@ ostree_builtin_checkout (int argc, char **argv, const char *repo_path, GError **
commit = argv[1];
destination = argv[2];
if (!ostree_repo_checkout (repo, commit, destination, error))
if (!ostree_repo_checkout (repo, commit, destination, NULL, error))
goto out;
ret = TRUE;

View File

@ -196,7 +196,7 @@ compose_branch_on_dir (OstreeRepo *repo,
branchf = ot_util_new_file_for_path (branchpath);
g_print ("Checking out %s (commit %s)...\n", branch, branchrev);
if (!ostree_repo_checkout (repo, branchrev, branchpath, error))
if (!ostree_repo_checkout (repo, branchrev, branchpath, NULL, error))
goto out;
g_print ("...done\n");
g_print ("Merging over destination...\n");