[ostree/wip/gio: 2/2] gio builds



commit 4980a4b0766f19f68e1588bbc0cdd4afe461f3dd
Author: Colin Walters <walters verbum org>
Date:   Tue Nov 8 09:51:11 2011 -0500

    gio builds

 libostree/ostree-core.c                 |   72 ++-
 libostree/ostree-core.h                 |    8 +-
 libostree/ostree-repo-file-enumerator.c |   46 +--
 libostree/ostree-repo-file-enumerator.h |    6 +-
 libostree/ostree-repo-file.c            |  828 ++++++++++++++++++++-----------
 libostree/ostree-repo-file.h            |   30 +-
 libostree/ostree-repo.c                 |   18 +-
 libostree/ostree-repo.h                 |    6 +-
 8 files changed, 650 insertions(+), 364 deletions(-)
---
diff --git a/libostree/ostree-core.c b/libostree/ostree-core.c
index a54f628..810ca38 100644
--- a/libostree/ostree-core.c
+++ b/libostree/ostree-core.c
@@ -627,29 +627,20 @@ unpack_meta (const char   *path,
   return ret;
 }
 
-
-static gboolean
-unpack_file (const char   *path,
-             const char   *dest_path,    
-             GChecksum   **out_checksum,
-             GError      **error)
+gboolean
+ostree_parse_packed_file (GFile            *file,
+                          GVariant    **out_metadata,
+                          GInputStream **out_content,
+                          GCancellable *cancellable,
+                          GError      **error)
 {
   gboolean ret = FALSE;
-  GFile *file = NULL;
-  GFile *dest_file = NULL;
   char *metadata_buf = NULL;
-  GVariant *metadata = NULL;
-  GVariant *xattrs = NULL;
+  GVariant *ret_metadata = NULL;
   GFileInputStream *in = NULL;
-  GFileOutputStream *out = NULL;
-  GChecksum *ret_checksum = NULL;
   guint32 metadata_len;
-  guint32 version, uid, gid, mode;
-  guint64 content_len;
   gsize bytes_read;
 
-  file = ot_util_new_file_for_path (path);
-
   in = g_file_read (file, NULL, error);
   if (!in)
     goto out;
@@ -675,9 +666,45 @@ unpack_file (const char   *path,
       goto out;
     }
 
-  metadata = g_variant_new_from_data (G_VARIANT_TYPE (OSTREE_PACK_FILE_VARIANT_FORMAT),
-                                      metadata_buf, metadata_len, FALSE, NULL, NULL);
-      
+  ret_metadata = g_variant_new_from_data (G_VARIANT_TYPE (OSTREE_PACK_FILE_VARIANT_FORMAT),
+                                          metadata_buf, metadata_len, FALSE, NULL, NULL);
+
+  ret = TRUE;
+  *out_metadata = ret_metadata;
+  ret_metadata = NULL;
+  *out_content = (GInputStream*)in;
+  in = NULL;
+ out:
+  g_free (metadata_buf);
+  g_clear_object (&in);
+  if (ret_metadata)
+   g_variant_unref (ret_metadata);
+  return ret;
+}
+
+static gboolean
+unpack_file (const char   *path,
+             const char   *dest_path,    
+             GChecksum   **out_checksum,
+             GError      **error)
+{
+  gboolean ret = FALSE;
+  GFile *file = NULL;
+  GFile *dest_file = NULL;
+  GVariant *metadata = NULL;
+  GVariant *xattrs = NULL;
+  GInputStream *in = NULL;
+  GFileOutputStream *out = NULL;
+  GChecksum *ret_checksum = NULL;
+  guint32 version, uid, gid, mode;
+  guint64 content_len;
+  gsize bytes_read;
+
+  file = ot_util_new_file_for_path (path);
+
+  if (!ostree_parse_packed_file (file, &metadata, &in, NULL, error))
+    goto out;
+
   g_variant_get (metadata, "(uuuu a(ayay)t)",
                  &version, &uid, &gid, &mode,
                  &xattrs, &content_len);
@@ -697,7 +724,7 @@ unpack_file (const char   *path,
       if (!out)
         goto out;
 
-      if (!splice_and_checksum ((GOutputStream*)out, (GInputStream*)in, ret_checksum, NULL, error))
+      if (!splice_and_checksum ((GOutputStream*)out, in, ret_checksum, NULL, error))
         goto out;
 
       if (!g_output_stream_close ((GOutputStream*)out, NULL, error))
@@ -707,7 +734,7 @@ unpack_file (const char   *path,
     {
       char target[PATH_MAX+1];
 
-      if (!g_input_stream_read_all ((GInputStream*)in, target, sizeof(target)-1, &bytes_read, NULL, error))
+      if (!g_input_stream_read_all (in, target, sizeof(target)-1, &bytes_read, NULL, error))
         goto out;
       target[bytes_read] = '\0';
       if (ret_checksum)
@@ -722,7 +749,7 @@ unpack_file (const char   *path,
     {
       guint32 dev;
 
-      if (!g_input_stream_read_all ((GInputStream*)in, &dev, 4, &bytes_read, NULL, error))
+      if (!g_input_stream_read_all (in, &dev, 4, &bytes_read, NULL, error))
         goto out;
       if (bytes_read != 4)
         {
@@ -773,7 +800,6 @@ unpack_file (const char   *path,
     (void) unlink (dest_path);
   if (ret_checksum)
     g_checksum_free (ret_checksum);
-  g_free (metadata_buf);
   g_clear_object (&file);
   g_clear_object (&dest_file);
   g_clear_object (&in);
diff --git a/libostree/ostree-core.h b/libostree/ostree-core.h
index 0ab7a16..82a864b 100644
--- a/libostree/ostree-core.h
+++ b/libostree/ostree-core.h
@@ -128,11 +128,17 @@ gboolean ostree_stat_and_checksum_file (int dirfd, const char *path,
 #define OSTREE_PACK_FILE_VARIANT_FORMAT "(uuuua(ayay)t)"
 
 gboolean  ostree_pack_object (GOutputStream     *output,
-                              GFile             *path,
+                              GFile             *file,
                               OstreeObjectType  objtype,
                               GCancellable     *cancellable,
                               GError          **error);
 
+gboolean ostree_parse_packed_file (GFile            *file,
+                                   GVariant    **out_metadata,
+                                   GInputStream **out_content,
+                                   GCancellable *cancellable,
+                                   GError      **error);
+
 gboolean ostree_unpack_object (const char   *path,
                                OstreeObjectType  objtype,
                                const char   *dest_path,    
diff --git a/libostree/ostree-repo-file-enumerator.c b/libostree/ostree-repo-file-enumerator.c
index b8f280d..ef5bb39 100644
--- a/libostree/ostree-repo-file-enumerator.c
+++ b/libostree/ostree-repo-file-enumerator.c
@@ -29,7 +29,7 @@ struct _OstreeRepoFileEnumerator
   GFileEnumerator parent;
 
   OstreeRepoFile *dir;
-  GFileAttributeMatcher *matcher;
+  char *attributes;
   GFileQueryInfoFlags flags;
 
   int index;
@@ -54,7 +54,7 @@ ostree_repo_file_enumerator_dispose (GObject *object)
   self = OSTREE_REPO_FILE_ENUMERATOR (object);
 
   g_clear_object (&self->dir);
-  g_file_attribute_matcher_unref (self->matcher);
+  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);
@@ -99,15 +99,15 @@ _ostree_repo_file_enumerator_new (OstreeRepoFile       *dir,
 {
   OstreeRepoFileEnumerator *self;
   
-  self = g_object_new (G_TYPE_LOCAL_FILE_ENUMERATOR,
+  self = g_object_new (OSTREE_TYPE_REPO_FILE_ENUMERATOR,
 		       "container", dir,
 		       NULL);
 
   self->dir = g_object_ref (dir);
-  self->matcher = g_file_attribute_matcher_new (attributes);
+  self->attributes = g_strdup (attributes);
   self->flags = flags;
   
-  return G_FILE_ENUMERATOR (local);
+  return G_FILE_ENUMERATOR (self);
 }
 
 static GFileInfo *
@@ -118,28 +118,14 @@ ostree_repo_file_enumerator_next_file (GFileEnumerator  *enumerator,
   OstreeRepoFileEnumerator *self = OSTREE_REPO_FILE_ENUMERATOR (enumerator);
   gboolean ret = FALSE;
   GFileInfo *info = NULL;
-  GFile *temp_child = NULL;
-  GVariant *tree_contents = NULL;
-  int n;
-  const char *name;
-  const char *checksum;
 
-  tree_contents = _ostree_repo_file_tree_get_contents (self->dir);
-  n = g_variant_n_children (tree_contents);
-
-  g_variant_get_child (
-
-  if (self->i >= n)
-    {
-      ret = TRUE;
-      goto out;
-    }
-
-  temp_child = g_file
-  if (
+  if (!_ostree_repo_file_tree_query_child (self->dir, self->index,
+                                           self->attributes, self->flags,
+                                           &info, cancellable, error))
+    goto out;
 
+  ret = TRUE;
  out:
- g_clear_object (&temp_child);
   if (!ret)
     g_clear_object (&info);
   return info;
@@ -150,17 +136,5 @@ ostree_repo_file_enumerator_close (GFileEnumerator  *enumerator,
 				   GCancellable     *cancellable,
 				   GError          **error)
 {
-  OstreeRepoFileEnumerator *self = OSTREE_REPO_FILE_ENUMERATOR (enumerator);
-
-  if (self->dir)
-    {
-#ifdef USE_GDIR
-      g_dir_close (self->dir);
-#else
-      closedir (self->dir);
-#endif
-      self->dir = NULL;
-    }
-
   return TRUE;
 }
diff --git a/libostree/ostree-repo-file-enumerator.h b/libostree/ostree-repo-file-enumerator.h
index c94ec36..fbba614 100644
--- a/libostree/ostree-repo-file-enumerator.h
+++ b/libostree/ostree-repo-file-enumerator.h
@@ -22,15 +22,15 @@
 #ifndef _OSTREE_REPO_FILE_ENUMERATOR
 #define _OSTREE_REPO_FILE_ENUMERATOR
 
-#include <gio/gio.h>
+#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_LOCAL_FILE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), OSTREE_TYPE_REPO_FILE_ENUMERATOR))
-#define OSTREE_IS_LOCAL_FILE_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), OSTREE_TYPE_REPO_FILE_ENUMERATOR))
+#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;
diff --git a/libostree/ostree-repo-file.c b/libostree/ostree-repo-file.c
index 5d507c4..7f473be 100644
--- a/libostree/ostree-repo-file.c
+++ b/libostree/ostree-repo-file.c
@@ -21,10 +21,9 @@
 
 #include "config.h"
 
-#include "ostree.h"
-#include "otutil.h"
+#include "ostree-repo-file-enumerator.h"
 
-static void ot_repo_file_file_iface_init (GFileIface *iface);
+static void ostree_repo_file_file_iface_init (GFileIface *iface);
 
 struct _OstreeRepoFile
 {
@@ -33,40 +32,33 @@ struct _OstreeRepoFile
   OstreeRepo *repo;
 
   char *commit;
-  char *path;
-  const char *basename;
-
-  GError *resolve_error;
+  GError *commit_resolve_error;
+  
   OstreeRepoFile *parent;
+  char *name;
 
   GVariant *tree_contents;
   GVariant *tree_metadata;
-  GFile *local_file;
-  char *file_checksum;
-
-  gboolean resolved : 1;
-  gboolean is_tree : 1;
 };
 
-#define ot_repo_file_get_type _ot_repo_file_get_type
-G_DEFINE_TYPE_WITH_CODE (OstreeRepoFile, ot_repo_file, G_TYPE_OBJECT,
+#define ostree_repo_file_get_type _ostree_repo_file_get_type
+G_DEFINE_TYPE_WITH_CODE (OstreeRepoFile, ostree_repo_file, G_TYPE_OBJECT,
 			 G_IMPLEMENT_INTERFACE (G_TYPE_FILE,
-						ot_repo_file_file_iface_init))
+						ostree_repo_file_file_iface_init))
 
 static void
 ostree_repo_file_finalize (GObject *object)
 {
   OstreeRepoFile *self;
 
-  local = OSTREE_REPO_FILE (object);
+  self = OSTREE_REPO_FILE (object);
 
-  g_clear_error (&self->resolve_error);
   if (self->tree_contents)
     g_variant_unref (self->tree_contents);
   if (self->tree_metadata)
     g_variant_unref (self->tree_metadata);
   g_free (self->commit);
-  g_free (self->path);
+  g_free (self->name);
 
   G_OBJECT_CLASS (ostree_repo_file_parent_class)->finalize (object);
 }
@@ -80,7 +72,6 @@ ostree_repo_file_dispose (GObject *object)
 
   g_clear_object (&self->repo);
   g_clear_object (&self->parent);
-  g_clear_object (&self->local_file);
 
   if (G_OBJECT_CLASS (ostree_repo_file_parent_class)->dispose)
     G_OBJECT_CLASS (ostree_repo_file_parent_class)->dispose (object);
@@ -90,7 +81,6 @@ static void
 ostree_repo_file_class_init (OstreeRepoFileClass *klass)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-  GFileAttributeInfoList *list;
 
   gobject_class->finalize = ostree_repo_file_finalize;
   gobject_class->dispose = ostree_repo_file_dispose;
@@ -102,31 +92,40 @@ ostree_repo_file_init (OstreeRepoFile *self)
 }
 
 GFile * 
-_ostree_repo_file_new (OstreeRepo  *repo,
-		       const char  *commit,
-		       const char  *path)
+_ostree_repo_file_new_root (OstreeRepo  *repo,
+                            const char  *commit)
 {
   OstreeRepoFile *self;
 
   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);
-  g_return_val_if_fail (path != NULL, NULL);
-  g_return_val_if_fail (*path == '/') != NULL, NULL);
 
   self = g_object_new (OSTREE_TYPE_REPO_FILE, NULL);
   self->repo = g_object_ref (repo);
   self->commit = g_strdup (commit);
-  self->path = g_strdup (path);
-  self->basename = strrchr (self->path, '/');
-  g_assert (self->basename);
-  self->basename += 1;
+
+  return G_FILE (self);
+}
+
+
+GFile *
+_ostree_repo_file_new_child (OstreeRepoFile *parent,
+                             const char  *name)
+{
+  OstreeRepoFile *self;
+  
+  self = g_object_new (OSTREE_TYPE_REPO_FILE, NULL);
+  self->repo = g_object_ref (parent->repo);
+  self->parent = g_object_ref (parent);
+  self->name = g_strdup (name);
 
   return G_FILE (self);
 }
 
 static gboolean
-do_resolve_commit (OstreeRepoFile  *self)
+do_resolve_commit (OstreeRepoFile  *self,
+                   GError         **error)
 {
   gboolean ret = FALSE;
   GVariant *commit = NULL;
@@ -137,22 +136,22 @@ do_resolve_commit (OstreeRepoFile  *self)
 
   g_assert (self->parent == NULL);
 
-  if (!ostree_repo_load_variant_checked (self, OSTREE_SERIALIZED_COMMIT_VARIANT,
-                                         self->commit, &commit, &self->resolve_error))
+  if (!ostree_repo_load_variant_checked (self->repo, OSTREE_SERIALIZED_COMMIT_VARIANT,
+                                         self->commit, &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);
+  g_variant_get_child (commit, 6, "&s", &tree_contents_checksum);
+  g_variant_get_child (commit, 7, "&s", &tree_meta_checksum);
 
-  if (!ostree_repo_load_variant_checked (self, OSTREE_SERIALIZED_TREE_VARIANT,
+  if (!ostree_repo_load_variant_checked (self->repo, OSTREE_SERIALIZED_TREE_VARIANT,
                                          tree_contents_checksum, &root_contents,
-					 &self->resolve_error))
+					 error))
     goto out;
 
-  if (!ostree_repo_load_variant_checked (self, OSTREE_SERIALIZED_DIRMETA_VARIANT,
+  if (!ostree_repo_load_variant_checked (self->repo, OSTREE_SERIALIZED_DIRMETA_VARIANT,
                                          tree_meta_checksum, &root_metadata,
-					 &self->resolve_error))
+					 error))
     goto out;
   
   self->tree_metadata = root_metadata;
@@ -160,8 +159,6 @@ do_resolve_commit (OstreeRepoFile  *self)
   self->tree_contents = root_contents;
   root_contents = NULL;
 
-  self->is_tree = TRUE;
-  
  out:
   if (commit)
     g_variant_unref (commit);
@@ -173,171 +170,100 @@ do_resolve_commit (OstreeRepoFile  *self)
 }
 
 static gboolean
-do_resolve_from_parent (OstreeRepoFile   *self)
+ensure_resolved (OstreeRepoFile  *self,
+                 GError         **error)
 {
-  gboolean ret = FALSE;
-  GVariant *parent_tree = NULL;
-  GVariant *files_variant = NULL;
-  GVariant *dirs_variant = NULL;
-  GVariant *tree_contents = NULL;
-  GVariant *tree_metadata = NULL;
-  int i, n;
-
-  g_assert (self->parent != NULL);
-
-  parent_tree = _ostree_repo_file_tree_get_contents (self->parent);
-
-  /* PARSE OSTREE_SERIALIZED_TREE_VARIANT */
-  files_variant = g_variant_get_child_value (parent_tree, 2);
-  dirs_variant = g_variant_get_child_value (parent_tree, 3);
-
-  n = g_variant_n_children (files_variant);
-  for (i = 0; i < n; i++)
+  if (self->parent == NULL
+      && self->commit_resolve_error == NULL
+      && self->tree_contents == NULL)
     {
-      const char *filename;
-      const char *checksum;
-
-      g_variant_get_child (files_variant, i, "(&s&s)", &filename, &checksum);
-
-      if (strcmp (filename, self->basename) == 0)
-	{
-	  char *local_path;
-	  char *relpath;
-	  
-	  relpath = ostree_get_relative_object_path (checksum, OSTREE_OBJECT_TYPE_FILE,
-						     ostree_repo_is_archive (self->repo));
-	  local_path = g_build_filename (ostree_repo_get_path (self->repo), relpath);
-	  g_free (relpath);
-	  self->local_file = ot_util_new_file_for_path (local_path);
-	  g_free (local_path);
-
-	  self->file_checksum = g_strdup (checksum);
-	  ret = TRUE;
-	  goto out;
-	}	
-    }
-
-  n = g_variant_n_children (dirs_variant);
-  for (i = 0; i < n; i++)
-    {
-      const char *dirname;
-      const char *tree_checksum;
-      const char *meta_checksum;
-
-      g_variant_get_child (dirs_variant, i, "(&s&s&s)",
-                           &dirname, &tree_checksum, &meta_checksum);
-
-      if (strcmp (dirname, self->basename) == 0)
-	{
-	  if (!ostree_repo_load_variant_checked (self, OSTREE_SERIALIZED_TREE_VARIANT,
-						 tree_contents_checksum, &tree_contents,
-						 &self->resolve_error))
-	    goto out;
-	  
-	  if (!ostree_repo_load_variant_checked (self, OSTREE_SERIALIZED_DIRMETA_VARIANT,
-						 tree_meta_checksum, &tree_metadata,
-						 &self->resolve_error))
-	    goto out;
-
-
-	  self->tree_contents = tree_contents;
-	  tree_contents = NULL;
-	  self->tree_metadata = tree_metadata;
-	  tree_metadata = NULL;
-	  ret = TRUE;
-	  goto out;
-	}
-    }
-  
-  ret = FALSE;
-  g_set_error (&self->resolve_error,
-	       G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
-	       "No such file or directory: %s",
-	       self->path);
-
- out:
-  /* parent_tree is const */
-  if (files_variant)
-    g_variant_unref (files_variant);
-  if (dirs_variant)
-    g_variant_unref (dirs_variant);
-  if (tree_metadata)
-    g_variant_unref (tree_metadata);
-  if (tree_contents)
-    g_variant_unref (tree_contents);
-  return ret;
-}
-
-gboolean
-ostree_repo_file_ensure_resolved (OstreeRepoFile  *self,
-				  GError         **error)
-{
-  gboolean ret = FALSE;
-
-  if (self->resolved)
-    {
-      ret = self->resolve_error == NULL;
-      goto out;
-    }
-
-  self->parent = g_file_get_parent (G_FILE (self));
-
-  if (self->parent == NULL)
-    {
-      if (!do_resolve_commit (self))
-	goto out;
-    }
-  else
-    {
-      if (!do_resolve_from_parent (self))
-	goto out;
+      (void)do_resolve_commit (self, &(self->commit_resolve_error));
     }
   
-  ret = TRUE;
- out:
-  self->resolved = TRUE;
-  if (self->resolve_error)
+  if (self->commit_resolve_error)
     {
       if (error)
-	*error = g_error_copy (self->resolve_error);
+	*error = g_error_copy (self->commit_resolve_error);
       return FALSE;
     }
   else
     return TRUE;
-  return ret;
 }
 
 GVariant *
 _ostree_repo_file_tree_get_contents (OstreeRepoFile  *self)
 {
-  g_assert (self->resolved);
-  g_assert (self->is_tree);
-  
   return self->tree_contents;
 }
 
 GVariant *
 _ostree_repo_file_tree_get_metadata (OstreeRepoFile  *self)
 {
-  g_assert (self->resolved);
-  g_assert (self->is_tree);
-  
   return self->tree_metadata;
 }
 
-const char *
-_ostree_repo_file_get_relpath (OstreeRepoFile  *self)
+GFile *
+_ostree_repo_file_nontree_get_local (OstreeRepoFile  *self)
+{
+  const char *checksum;
+  char *path;
+  GFile *ret;
+
+  g_assert (!ostree_repo_is_archive (self->repo));
+
+  checksum = _ostree_repo_file_nontree_get_checksum (self);
+  path = ostree_repo_get_object_path (self->repo, checksum, OSTREE_OBJECT_TYPE_FILE);
+  ret = ot_util_new_file_for_path (path);
+  g_free (path);
+  
+  return ret;
+}
+
+OstreeRepo *
+_ostree_repo_file_get_repo (OstreeRepoFile  *self)
 {
-  return self->path;
+  return self->repo;
 }
 
-GFile*
-_ostree_repo_file_nontree_get_local (OstreeRepoFile  *self)
+OstreeRepoFile *
+_ostree_repo_file_get_root (OstreeRepoFile  *self)
+{
+  OstreeRepoFile *parent = self;
+
+  while (parent->parent)
+    parent = parent->parent;
+  return parent;
+}
+
+const char *
+_ostree_repo_file_nontree_get_checksum (OstreeRepoFile  *self)
 {
-  g_assert (self->resolved);
-  g_assert (!self->is_tree);
+  int n;
+
+  g_assert (self->parent);
+
+  n = _ostree_repo_file_tree_find_child (self->parent, self->name);
+  g_assert (n >= 0);
   
-  return self->local_file;
+  return _ostree_repo_file_tree_get_child_checksum (self->parent, n);
+}
+
+const char *
+_ostree_repo_file_tree_get_child_checksum (OstreeRepoFile  *self,
+                                           int n)
+{
+  GVariant *files_variant;
+  const char *checksum;
+
+  g_assert (self->tree_contents);
+
+  files_variant = g_variant_get_child_value (self->tree_contents, 2);
+
+  g_variant_get_child (files_variant, n, "(@s&s)", NULL, &checksum);
+
+  g_variant_unref (files_variant);
+
+  return checksum;
 }
 
 static gboolean
@@ -362,24 +288,55 @@ ostree_repo_file_get_uri_scheme (GFile *file)
 static char *
 ostree_repo_file_get_basename (GFile *file)
 {
-  return g_file_get_basename (OSTREE_REPO_FILE (file)->path);
+  OstreeRepoFile *self = OSTREE_REPO_FILE (file);
+  return g_strdup (self->name);
 }
 
 static char *
 ostree_repo_file_get_path (GFile *file)
 {
-  return g_strdup (OSTREE_REPO_FILE (file)->path);
+  OstreeRepoFile *self = OSTREE_REPO_FILE (file);
+  OstreeRepoFile *parent;
+  GString *buf;
+  GSList *parents;
+  GSList *iter;
+
+  buf = g_string_new ("");
+  parents = NULL;
+
+  for (parent = self->parent; parent; parent = parent->parent)
+    parents = g_slist_prepend (parents, parent);
+
+  if (parents->next)
+    {
+      for (iter = parents->next; iter; iter = iter->next)
+        {
+          parent = iter->data;
+          g_string_append_c (buf, '/');
+          g_string_append (buf, parent->name);
+        }
+    }
+  g_string_append_c (buf, '/');
+  g_string_append (buf, self->name);
+
+  g_slist_free (parents);
+
+  return g_string_free (buf, FALSE);
 }
 
 static char *
 ostree_repo_file_get_uri (GFile *file)
 {
   OstreeRepoFile *self = OSTREE_REPO_FILE (file);
+  char *path;
   char *uri_path;
   char *ret;
 
-  uri_path = g_escape_uri_string (self->path, UNSAFE_PATH);
-  ret = g_strconcat ("ostree://", self->commit, "/", uri_path, NULL);
+  path = g_file_get_path (file);
+  uri_path = g_filename_to_uri (path, NULL, NULL);
+  g_free (path);
+  g_assert (g_str_has_prefix (uri_path, "file://"));
+  ret = g_strconcat ("ostree://", self->commit, uri_path+strlen("file://"), NULL);
   g_free (uri_path);
 
   return ret;
@@ -395,19 +352,8 @@ static GFile *
 ostree_repo_file_get_parent (GFile *file)
 {
   OstreeRepoFile *self = OSTREE_REPO_FILE (file);
-  const char *non_root;
-  char *dirname;
-  GFile *parent;
-
-  /* Check for root */
-  non_root = g_path_skip_root (self->path);
-  if (*non_root == 0)
-    return NULL;
 
-  dirname = g_path_get_dirname (self->filename);
-  parent = _ostree_repo_file_new (self->repo, self->commit, self->dirname);
-  g_free (dirname);
-  return parent;
+  return g_object_ref (self->parent);
 }
 
 static GFile *
@@ -415,7 +361,10 @@ ostree_repo_file_dup (GFile *file)
 {
   OstreeRepoFile *self = OSTREE_REPO_FILE (file);
 
-  return _ostree_repo_file_new (self->repo, self->commit, self->path);
+  if (self->parent)
+    return _ostree_repo_file_new_child (self->parent, self->name);
+  else
+    return _ostree_repo_file_new_root (self->repo, self->commit);
 }
 
 static guint
@@ -423,18 +372,30 @@ ostree_repo_file_hash (GFile *file)
 {
   OstreeRepoFile *self = OSTREE_REPO_FILE (file);
   
-  return g_str_hash (self->commit) + g_str_hash (self->path);
+  if (self->parent)
+    return g_file_hash (self->parent) + g_str_hash (self->name);
+  else
+    return g_str_hash (self->commit);
 }
 
 static gboolean
 ostree_repo_file_equal (GFile *file1,
-		    GFile *file2)
+                        GFile *file2)
 {
   OstreeRepoFile *self1 = OSTREE_REPO_FILE (file1);
   OstreeRepoFile *self2 = OSTREE_REPO_FILE (file2);
 
-  return g_str_equal (self1->commit, local2->commit)
-    && g_str_equal (self1->path, self2->path);
+  if (self1->parent && self2->parent)
+    {
+      return g_str_equal (self1->name, self2->name)
+        && g_file_equal ((GFile*)self1->parent, (GFile*)self2->parent);
+    }
+  else if (!self1->parent && !self2->parent)
+    {
+      return g_str_equal (self1->commit, self2->commit);
+    }
+  else
+    return FALSE;
 }
 
 static const char *
@@ -460,11 +421,15 @@ static gboolean
 ostree_repo_file_prefix_matches (GFile *parent,
 				 GFile *descendant)
 {
-  OstreeRepoFile *parent_self = OSTREE_REPO_FILE (parent);
-  OstreeRepoFile *descendant_self = OSTREE_REPO_FILE (descendant);
   const char *remainder;
-
-  remainder = match_prefix (descendant_self->path, parent_self->path);
+  char *parent_path;
+  char *descendant_path;
+
+  parent_path = g_file_get_path (parent);
+  descendant_path = g_file_get_path (descendant);
+  remainder = match_prefix (descendant_path, parent_path);
+  g_free (parent_path);
+  g_free (descendant_path);
   if (remainder != NULL && G_IS_DIR_SEPARATOR (*remainder))
     return TRUE;
   return FALSE;
@@ -474,11 +439,15 @@ static char *
 ostree_repo_file_get_relative_path (GFile *parent,
 				    GFile *descendant)
 {
-  OstreeRepoFile *parent_self = OSTREE_REPO_FILE (parent);
-  OstreeRepoFile *descendant_self = OSTREE_REPO_FILE (descendant);
   const char *remainder;
-
-  remainder = match_prefix (descendant_self->path, parent_self->path);
+  char *parent_path;
+  char *descendant_path;
+
+  parent_path = g_file_get_path (parent);
+  descendant_path = g_file_get_path (descendant);
+  remainder = match_prefix (descendant_path, parent_path);
+  g_free (parent_path);
+  g_free (descendant_path);
   
   if (remainder != NULL && G_IS_DIR_SEPARATOR (*remainder))
     return g_strdup (remainder + 1);
@@ -490,20 +459,29 @@ ostree_repo_file_resolve_relative_path (GFile      *file,
 					const char *relative_path)
 {
   OstreeRepoFile *self = OSTREE_REPO_FILE (file);
+  OstreeRepoFile *parent;
   char *filename;
-  GFile *child;
-
-  if (g_path_is_absolute (relative_path))
-    return _ostree_repo_file_new (self->repo, 
-				  self->commit,
-				  relative_path);
-  
-  filename = g_build_filename (self->path, relative_path, NULL);
-  child = _ostree_repo_file_new (self->repo, self->commit,
-				 filename);
+  const char *rest;
+  GFile *ret;
+
+  if (g_path_is_absolute (relative_path) && self->parent)
+    return ostree_repo_file_resolve_relative_path ((GFile*)_ostree_repo_file_get_root (self),
+                                                   relative_path+1);
+  rest = strchr (relative_path, '/');
+  if (rest)
+    rest += 1;
+  filename = g_strndup (relative_path, rest - relative_path);
+  parent = (OstreeRepoFile*)_ostree_repo_file_new_child (self, filename);
   g_free (filename);
-  
-  return child;
+    
+  if (!*rest)
+    ret = (GFile*)parent;
+  else
+    {
+      ret = ostree_repo_file_resolve_relative_path ((GFile*)parent, rest);
+      g_clear_object (&parent);
+    }
+  return ret;
 }
 
 static GFileEnumerator *
@@ -527,37 +505,41 @@ ostree_repo_file_get_child_for_display_name (GFile        *file,
   return g_file_get_child (file, display_name);
 }
 
-void
-query_info_common (OstreeRepoFile  *self,
-		   GFileInfo       *info)
+static GFile *
+get_child_local_file (OstreeRepo   *repo,
+                      const char   *checksum)
 {
-  if (*(self->basename) == '.')
-    g_file_info_set_is_hidden (info, TRUE);
+  char *path;
+  GFile *ret;
 
-  g_file_info_set_attribute_string (info, "standard::name",
-				    self->basename);
-  g_file_info_set_attribute_string (info, "standard::display-name",
-				    self->basename);
+  path = ostree_repo_get_object_path (repo, checksum, OSTREE_OBJECT_TYPE_FILE);
+  ret = ot_util_new_file_for_path (path);
+  g_free (path);
+  
+  return ret;
 }
 
 static gboolean
-query_info_file_nonarchive (OstreeRepoFile   *self,
-			    GFileInfo        *info,
-			    GCancellable     *cancellable,
-			    GError          **error)
+query_child_info_file_nonarchive (OstreeRepo       *repo,
+                                  const char       *checksum,
+                                  GFileAttributeMatcher *matcher,
+                                  GFileInfo        *info,
+                                  GCancellable     *cancellable,
+                                  GError          **error)
 {
   gboolean ret = FALSE;
   GFileInfo *local_info = NULL;
+  GFile *local_file = NULL;
   int i ;
-  const char mapped_boolean[] = {
+  const char *mapped_boolean[] = {
     "standard::is-symlink"
   };
-  const char mapped_string[] = {
+  const char *mapped_string[] = {
   };
-  const char mapped_byte_string[] = {
+  const char *mapped_byte_string[] = {
     "standard::symlink-target"
   };
-  const char mapped_uint32[] = {
+  const char *mapped_uint32[] = {
     "standard::type",
     "unix::device",
     "unix::mode",
@@ -566,13 +548,21 @@ query_info_file_nonarchive (OstreeRepoFile   *self,
     "unix::gid",
     "unix::rdev"
   };
-  const char mapped_uint64[] = {
+  const char *mapped_uint64[] = {
     "standard::size",
     "standard::allocated-size",
     "unix::inode"
   };
 
-  local_info = g_file_query_info (self->local_file,
+  if (!(g_file_attribute_matcher_matches (matcher, "unix::mode")
+        || g_file_attribute_matcher_matches (matcher, "standard::type")))
+    {
+      ret = TRUE;
+      goto out;
+    }
+
+  local_file = get_child_local_file (repo, checksum);
+  local_info = g_file_query_info (local_file,
 				  OSTREE_GIO_FAST_QUERYINFO,
 				  G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
 				  cancellable,
@@ -581,75 +571,351 @@ query_info_file_nonarchive (OstreeRepoFile   *self,
     goto out;
 
   for (i = 0; i < G_N_ELEMENTS (mapped_boolean); i++)
-    g_file_info_set_attribute_boolean (info, g_file_info_get_attribute_boolean (local_info));
+    g_file_info_set_attribute_boolean (info, mapped_boolean[i], g_file_info_get_attribute_boolean (local_info, mapped_boolean[i]));
 
   for (i = 0; i < G_N_ELEMENTS (mapped_string); i++)
-    g_file_info_set_attribute_string (info, g_file_info_get_attribute_string (local_info));
+    g_file_info_set_attribute_string (info, mapped_string[i], g_file_info_get_attribute_string (local_info, mapped_string[i]));
 
   for (i = 0; i < G_N_ELEMENTS (mapped_byte_string); i++)
-    g_file_info_set_attribute_byte_string (info, g_file_info_get_attribute_byte_string (local_info));
+    g_file_info_set_attribute_byte_string (info, mapped_byte_string[i], g_file_info_get_attribute_byte_string (local_info, mapped_byte_string[i]));
 
   for (i = 0; i < G_N_ELEMENTS (mapped_uint32); i++)
-    g_file_info_set_attribute_uint32 (info, g_file_info_get_attribute_uint32 (local_info));
+    g_file_info_set_attribute_uint32 (info, mapped_uint32[i], g_file_info_get_attribute_uint32 (local_info, mapped_uint32[i]));
 
   for (i = 0; i < G_N_ELEMENTS (mapped_uint64); i++)
-    g_file_info_set_attribute_uint64 (info, g_file_info_get_attribute_uint64 (local_info));
+    g_file_info_set_attribute_uint64 (info, mapped_uint64[i], g_file_info_get_attribute_uint64 (local_info, mapped_uint64[i]));
   
   ret = TRUE;
  out:
   g_clear_object (&local_info);
+  g_clear_object (&local_file);
   return ret;
 }
 
-static GFileInfo *
-ostree_repo_file_query_info (GFile                *file,
-			     const char           *attributes,
-			     GFileQueryInfoFlags   flags,
-			     GCancellable         *cancellable,
-			     GError              **error)
+static gboolean
+query_child_info_file_archive (OstreeRepo       *repo,
+                               const char       *checksum,
+                               GFileAttributeMatcher *matcher,
+                               GFileInfo        *info,
+                               GCancellable     *cancellable,
+                               GError          **error)
 {
-  OstreeRepoFile *self = OSTREE_REPO_FILE (file);
-  GFileInfo *info;
+  gboolean ret = FALSE;
+  GFile *local_file = NULL;
+  GVariant *metadata = NULL;
+  GInputStream *input = NULL;
+  guint32 version, uid, gid, mode;
+  guint64 content_len;
+  guint32 file_type;
+  gsize bytes_read;
+  char *buf = NULL;
+
+  local_file = get_child_local_file (repo, checksum);
+
+  if (!ostree_parse_packed_file (local_file, &metadata, &input, cancellable, error))
+    goto out;
 
-  if (!_ostree_repo_file_ensure_resolved (self, error))
-    return NULL;
+  g_variant_get (metadata, "(uuuu a(ayay)t)",
+                 &version, &uid, &gid, &mode,
+                 NULL, &content_len);
+  uid = GUINT32_FROM_BE (uid);
+  gid = GUINT32_FROM_BE (gid);
+  mode = GUINT32_FROM_BE (mode);
+  content_len = GUINT64_FROM_BE (content_len);
+
+  g_file_info_set_attribute_boolean (info, "standard::is-symlink",
+                                     S_ISLNK (mode));
+  if (S_ISLNK (mode))
+    file_type = G_FILE_TYPE_SYMBOLIC_LINK;
+  else if (S_ISREG (mode))
+    file_type = G_FILE_TYPE_REGULAR;
+  else if (S_ISBLK (mode) || S_ISCHR(mode))
+    file_type = G_FILE_TYPE_SPECIAL;
+  else
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Corrupted packfile %s: Invalid mode", checksum);
+      goto out;
+    }
+  g_file_info_set_attribute_uint32 (info, "standard::type", file_type);
+
+  g_file_info_set_attribute_uint32 (info, "unix::uid", uid);
+  g_file_info_set_attribute_uint32 (info, "unix::gid", gid);
+  g_file_info_set_attribute_uint32 (info, "unix::mode", mode);
+
+  if (file_type == G_FILE_TYPE_REGULAR)
+    {
+      g_file_info_set_attribute_uint64 (info, "standard::size", content_len);
+    }
+  else if (file_type == G_FILE_TYPE_SYMBOLIC_LINK)
+    {
+      gsize len = MIN (PATH_MAX, content_len) + 1;
+      buf = g_malloc (len);
+
+      if (!g_input_stream_read_all (input, buf, len, &bytes_read, cancellable, error))
+        goto out;
+      buf[bytes_read] = '\0';
+
+      g_file_info_set_attribute_byte_string (info, "standard::symlink-target", buf);
+    }
+  else if (file_type == G_FILE_TYPE_SPECIAL)
+    {
+      guint32 device;
+
+      if (!g_input_stream_read_all (input, &device, 4, &bytes_read, cancellable, error))
+        goto out;
+
+      device = GUINT32_FROM_BE (device);
+      g_file_info_set_attribute_uint32 (info, "unix::device", device);
+    }
+
+  ret = TRUE;
+ out:
+  g_free (buf);
+  if (metadata)
+    g_variant_unref (metadata);
+  g_clear_object (&local_file);
+  g_clear_object (&input);
+  return ret;
+}
+
+static void
+set_info_from_dirmeta (GFileInfo  *info,
+                       GVariant   *metadata)
+{
+  guint32 version, uid, gid, mode;
+
+  g_file_info_set_attribute_uint32 (info, "standard::type", G_FILE_TYPE_DIRECTORY);
+
+  /* PARSE OSTREE_SERIALIZED_DIRMETA_VARIANT */
+  g_variant_get (metadata, "(uuuu a(ayay))",
+                 &version, &uid, &gid, &mode,
+                 NULL);
+  version = GUINT32_FROM_BE (version);
+  uid = GUINT32_FROM_BE (uid);
+  gid = GUINT32_FROM_BE (gid);
+  mode = GUINT32_FROM_BE (mode);
+
+  g_file_info_set_attribute_uint32 (info, "unix::uid", uid);
+  g_file_info_set_attribute_uint32 (info, "unix::gid", gid);
+  g_file_info_set_attribute_uint32 (info, "unix::mode", mode);
+}
+
+static gboolean
+query_child_info_dir (OstreeRepo         *repo,
+                      const char         *metadata_checksum,
+                      GFileAttributeMatcher *matcher,
+                      GFileQueryInfoFlags flags,
+                      GFileInfo        *info,
+                      GCancellable    *cancellable,
+                      GError         **error)
+{
+  gboolean ret = FALSE;
+  GVariant *metadata = NULL;
+
+  if (!g_file_attribute_matcher_matches (matcher, "unix::mode"))
+    {
+      ret = TRUE;
+      goto out;
+    }
+
+  if (!ostree_repo_load_variant_checked (repo, OSTREE_SERIALIZED_DIRMETA_VARIANT,
+                                         metadata_checksum, &metadata, error))
+    goto out;
+
+  set_info_from_dirmeta (info, metadata);
+  
+  ret = TRUE;
+ out:
+  if (metadata)
+    g_variant_unref (metadata);
+  return ret;
+}
+
+
+
+static int
+bsearch_in_file_variant (GVariant  *variant,
+                         const char *name)
+{
+  int i, n;
+
+  i = 0;
+  n = g_variant_n_children (variant) - 1;
+
+  while (i <= n)
+    {
+      int m;
+      const char *cur;
+      int cmp;
+
+      m = i + ((n - i) / 2);
+
+      g_variant_get_child (variant, m, "(&s s)", &cur, NULL);
+
+      cmp = strcmp (name, cur);
+      if (cmp < 0)
+        i = m + 1;
+      else if (cmp > 0)
+        n = m - 1;
+      else
+        return m;
+    }
+  return -1;
+}
+
+int
+_ostree_repo_file_tree_find_child  (OstreeRepoFile  *self,
+                                    const char      *name)
+{
+  int i;
+  GVariant *files_variant = NULL;
+  GVariant *dirs_variant = NULL;
+
+  files_variant = g_variant_get_child_value (self->tree_contents, 2);
+  dirs_variant = g_variant_get_child_value (self->tree_contents, 3);
+
+  i = bsearch_in_file_variant (files_variant, name);
+  if (i < 0)
+    i = bsearch_in_file_variant (dirs_variant, name);
 
-  info = g_file_info_new ();
+  g_variant_unref (files_variant);
+  g_variant_unref (dirs_variant);
+  return i;
+}
+
+gboolean
+_ostree_repo_file_tree_query_child (OstreeRepoFile  *self,
+                                    int              n,
+                                    const char      *attributes,
+                                    GFileQueryInfoFlags flags,
+                                    GFileInfo      **out_info,
+                                    GCancellable    *cancellable,
+                                    GError         **error)
+{
+  const char *name;
+  gboolean ret = FALSE;
+  GFileInfo *ret_info = NULL;
+  GVariant *files_variant = NULL;
+  GVariant *dirs_variant = NULL;
+  GVariant *tree_child_metadata = NULL;
+  GFileAttributeMatcher *matcher = NULL;
+  int c;
+
+  matcher = g_file_attribute_matcher_new (attributes);
+
+  ret_info = g_file_info_new ();
 
-  query_info_common (self, info);
+  files_variant = g_variant_get_child_value (self->tree_contents, 2);
+  dirs_variant = g_variant_get_child_value (self->tree_contents, 3);
 
-  if (self->local_file)
+  c = g_variant_n_children (files_variant);
+  if (n < c)
     {
+      const char *checksum;
+
+      g_variant_get_child (files_variant, n, "(&s&s)", &name, &checksum);
+     
       if (ostree_repo_is_archive (self->repo))
 	{
+	  if (!query_child_info_file_archive (self->repo, checksum, matcher, ret_info,
+                                              cancellable, error))
+	    goto out;
 	}
       else
 	{
-	  if (!query_info_file_nonarchive (self, info, error))
+	  if (!query_child_info_file_nonarchive (self->repo, checksum, matcher, ret_info,
+                                                 cancellable, error))
 	    goto out;
 	}
     }
   else
     {
-      uint32 uid;
-      uint32 gid;
-      uint32 mode;
-
-      g_file_info_set_attribute_uint32 (info, "standard::type", G_FILE_TYPE_DIRECTORY);
+      const char *tree_checksum;
+      const char *meta_checksum;
 
-      g_variant_get_child (self->tree_metadata, 1, "u", &uid);
-      uid = GUINT32_FROM_BE (uid);
-      g_file_info_set_attribute_uint32 (info, "unix::uid", uid);
+      n -= c;
 
-      g_variant_get_child (self->tree_metadata, 2, "u", &gid);
-      gid = GUINT32_FROM_BE (gid);
-      g_file_info_set_attribute_uint32 (info, "unix::gid", gid);
+      c = g_variant_n_children (dirs_variant);
 
-      g_variant_get_child (self->tree_metadata, 3, "u", &mode);
-      mode = GUINT32_FROM_BE (mode);
-      g_file_info_set_attribute_uint32 (info, "unix::mode", mode);
+      if (n < c)
+        {
+          g_variant_get_child (dirs_variant, n, "(&s&s&s)",
+                               &name, &tree_checksum, &meta_checksum);
+          if (!query_child_info_dir (self->repo, meta_checksum,
+                                     matcher, flags, ret_info,
+                                     cancellable, error))
+            goto out;
+        }
     }
 
+  if (!name)
+    goto out;
+
+  g_file_info_set_attribute_string (ret_info, "standard::name",
+				    name);
+  g_file_info_set_attribute_string (ret_info, "standard::display-name",
+				    name);
+  if (*name == '.')
+    g_file_info_set_is_hidden (ret_info, TRUE);
+
+  ret = TRUE;
+  *out_info = ret_info;
+  ret_info = NULL;
+ out:
+  g_clear_object (&ret_info);
+  if (matcher)
+    g_file_attribute_matcher_unref (matcher);
+  if (tree_child_metadata)
+    g_variant_unref (tree_child_metadata);
+  g_variant_unref (files_variant);
+  g_variant_unref (dirs_variant);
+  return ret;
+}
+
+static GFileInfo *
+ostree_repo_file_query_info (GFile                *file,
+			     const char           *attributes,
+			     GFileQueryInfoFlags   flags,
+			     GCancellable         *cancellable,
+			     GError              **error)
+{
+  OstreeRepoFile *self = OSTREE_REPO_FILE (file);
+  gboolean ret = FALSE;
+  GFileInfo *info = NULL;
+  int i;
+
+  if (!self->parent)
+    {
+      if (!ensure_resolved (self, error))
+        goto out;
+
+      info = g_file_info_new ();
+      set_info_from_dirmeta (info, self->tree_metadata);
+    }
+  else
+    {
+      i = _ostree_repo_file_tree_find_child (self->parent, self->name);
+
+      if (i < 0)
+        {
+          char *path = g_file_get_path (file);
+          g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
+                       "No such file or directory: %s", path);
+          g_free (path);
+          goto out;
+        }
+      
+      if (!_ostree_repo_file_tree_query_child (self->parent, i, 
+                                               attributes, flags, 
+                                               &info, cancellable, error))
+        goto out;
+    }
+      
+  ret = TRUE;
+ out:
+  if (!ret)
+    g_clear_object (&info);
   return info;
 }
 
@@ -675,17 +941,15 @@ ostree_repo_file_read (GFile         *file,
 		       GError       **error)
 {
   gboolean ret = FALSE;
+  GFile *local_file = NULL;
   GFileInputStream *ret_stream = NULL;
   OstreeRepoFile *self = OSTREE_REPO_FILE (file);
 
-  if (!_ostree_repo_file_ensure_resolved (self, error))
-    goto out;
-  
-  if (self->is_tree)
+  if (self->tree_contents)
     {
       g_set_error_literal (error, G_IO_ERROR,
 			   G_IO_ERROR_IS_DIRECTORY,
-			   _("Can't open directory"));
+			   "Can't open directory");
       goto out;
     }
 
@@ -693,18 +957,20 @@ ostree_repo_file_read (GFile         *file,
     {
       g_set_error_literal (error, G_IO_ERROR,
 			   G_IO_ERROR_NOT_SUPPORTED,
-			   _("Can't open archived file (yet)"));
+			   "Can't open archived file (yet)");
       goto out;
     }
   else
     {
-      ret_stream = g_file_read (self->local_file, cancellable, error);
+      local_file = _ostree_repo_file_nontree_get_local (self);
+      ret_stream = g_file_read (local_file, cancellable, error);
       if (!ret_stream)
 	goto out;
     }
   
   ret = TRUE;
  out:
+  g_clear_object (&local_file);
   if (!ret)
     g_clear_object (&ret_stream);
   return ret_stream;
@@ -731,8 +997,8 @@ ostree_repo_file_file_iface_init (GFileIface *iface)
   iface->set_display_name = NULL;
   iface->enumerate_children = ostree_repo_file_enumerate_children;
   iface->query_info = ostree_repo_file_query_info;
-  iface->query_filesystem_info = ostree_repo_file_query_filesystem_info;
-  iface->find_enclosing_mount = ostree_repo_file_find_enclosing_mount;
+  iface->query_filesystem_info = NULL;
+  iface->find_enclosing_mount = NULL;
   iface->query_settable_attributes = ostree_repo_file_query_settable_attributes;
   iface->query_writable_namespaces = ostree_repo_file_query_writable_namespaces;
   iface->set_attribute = NULL;
@@ -755,9 +1021,3 @@ ostree_repo_file_file_iface_init (GFileIface *iface)
 
   iface->supports_thread_contexts = TRUE;
 }
-
-const char *
-_ostree_repo_file_get_checksum (OstreeRepoFile  *self)
-{
-  return self->checksum;
-}
diff --git a/libostree/ostree-repo-file.h b/libostree/ostree-repo-file.h
index 5a4d2c6..b85a575 100644
--- a/libostree/ostree-repo-file.h
+++ b/libostree/ostree-repo-file.h
@@ -22,7 +22,7 @@
 #ifndef _OSTREE_REPO_FILE
 #define _OSTREE_REPO_FILE
 
-#include <gio/gio.h>
+#include "ostree-repo.h"
 
 G_BEGIN_DECLS
 
@@ -43,18 +43,38 @@ struct _OstreeRepoFileClass
 
 GType   _ostree_repo_file_get_type (void) G_GNUC_CONST;
 
-GFile * _ostree_repo_file_new (OstreeRepo  *repo,
-                               const char  *commit,
-                               const char  *path);
+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,
                                             GError         **error);
 
-const char * _ostree_repo_file_get_relpath (OstreeRepoFile  *self);
+OstreeRepo * _ostree_repo_file_get_repo (OstreeRepoFile  *self);
+OstreeRepoFile * _ostree_repo_file_get_root (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);
+
+int     _ostree_repo_file_tree_find_child  (OstreeRepoFile  *self,
+                                            const char      *name);
+
+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);
 
diff --git a/libostree/ostree-repo.c b/libostree/ostree-repo.c
index 97c9f42..7d48edb 100644
--- a/libostree/ostree-repo.c
+++ b/libostree/ostree-repo.c
@@ -35,10 +35,6 @@ link_one_file (OstreeRepo *self, const char *path,
                gboolean ignore_exists, gboolean force,
                GChecksum **out_checksum,
                GError **error);
-static char *
-get_object_path (OstreeRepo  *self,
-                 const char    *checksum,
-                 OstreeObjectType type);
 
 enum {
   PROP_0,
@@ -683,10 +679,10 @@ import_directory_meta (OstreeRepo  *self,
   return ret;
 }
 
-static char *
-get_object_path (OstreeRepo  *self,
-                 const char    *checksum,
-                 OstreeObjectType type)
+char *
+ostree_repo_get_object_path (OstreeRepo  *self,
+                             const char    *checksum,
+                             OstreeObjectType type)
 {
   OstreeRepoPrivate *priv = GET_PRIVATE (self);
   char *ret;
@@ -708,7 +704,7 @@ prepare_dir_for_checksum_get_object_path (OstreeRepo *self,
   char *checksum_dir = NULL;
   char *object_path = NULL;
 
-  object_path = get_object_path (self, checksum, type);
+  object_path = ostree_repo_get_object_path (self, checksum, type);
   checksum_dir = g_path_get_dirname (object_path);
 
   if (!ot_util_ensure_directory (checksum_dir, FALSE, error))
@@ -2003,7 +1999,7 @@ ostree_repo_load_variant (OstreeRepo *self,
 
   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-  path = get_object_path (self, sha256, OSTREE_OBJECT_TYPE_META);
+  path = ostree_repo_get_object_path (self, sha256, OSTREE_OBJECT_TYPE_META);
   if (!ostree_parse_metadata_file (path, &ret_type, &ret_variant, error))
     goto out;
 
@@ -2086,7 +2082,7 @@ checkout_tree (OstreeRepo    *self,
       char *object_path;
       char *dest_path;
 
-      object_path = get_object_path (self, checksum, OSTREE_OBJECT_TYPE_FILE);
+      object_path = ostree_repo_get_object_path (self, checksum, OSTREE_OBJECT_TYPE_FILE);
       dest_path = g_build_filename (destination, filename, NULL);
       
       if (priv->archive)
diff --git a/libostree/ostree-repo.h b/libostree/ostree-repo.h
index 70d5eb4..dd7d102 100644
--- a/libostree/ostree-repo.h
+++ b/libostree/ostree-repo.h
@@ -22,7 +22,7 @@
 #ifndef _OSTREE_REPO
 #define _OSTREE_REPO
 
-#include <glib-object.h>
+#include "ostree-core.h"
 
 G_BEGIN_DECLS
 
@@ -64,6 +64,10 @@ gboolean      ostree_repo_write_config (OstreeRepo *self,
                                         GKeyFile   *new_config,
                                         GError    **error);
 
+char *        ostree_repo_get_object_path (OstreeRepo   *self,
+                                           const char   *object,
+                                           OstreeObjectType type);
+
 gboolean      ostree_repo_link_file (OstreeRepo *self,
                                      const char   *path,
                                      gboolean      ignore_exists,



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]