[ostree/wip/gio: 1/2] work on gio vfs



commit 6fc21b6dcb36d596fe20c0fcd596d189ec34d613
Author: Colin Walters <walters verbum org>
Date:   Mon Nov 7 11:25:49 2011 -0500

    work on gio vfs

 Makefile-libostree.am                   |    4 +
 libostree/ostree-core.h                 |    2 +-
 libostree/ostree-repo-file-enumerator.c |  166 +++++++
 libostree/ostree-repo-file-enumerator.h |   54 +++
 libostree/ostree-repo-file.c            |  763 +++++++++++++++++++++++++++++++
 libostree/ostree-repo-file.h            |   63 +++
 libostree/ostree-repo.h                 |    1 -
 7 files changed, 1051 insertions(+), 2 deletions(-)
---
diff --git a/Makefile-libostree.am b/Makefile-libostree.am
index 7b8790b..f1357cc 100644
--- a/Makefile-libostree.am
+++ b/Makefile-libostree.am
@@ -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)
diff --git a/libostree/ostree-core.h b/libostree/ostree-core.h
index 959a46b..0ab7a16 100644
--- a/libostree/ostree-core.h
+++ b/libostree/ostree-core.h
@@ -26,7 +26,7 @@
 
 G_BEGIN_DECLS
 
-#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";
 
diff --git a/libostree/ostree-repo-file-enumerator.c b/libostree/ostree-repo-file-enumerator.c
new file mode 100644
index 0000000..b8f280d
--- /dev/null
+++ b/libostree/ostree-repo-file-enumerator.c
@@ -0,0 +1,166 @@
+/* -*- 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;
+  GFileAttributeMatcher *matcher;
+  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, OSTREE_TYPE_REPO_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_file_attribute_matcher_unref (self->matcher);
+  
+  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 (G_TYPE_LOCAL_FILE_ENUMERATOR,
+		       "container", dir,
+		       NULL);
+
+  self->dir = g_object_ref (dir);
+  self->matcher = g_file_attribute_matcher_new (attributes);
+  self->flags = flags;
+  
+  return G_FILE_ENUMERATOR (local);
+}
+
+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;
+  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 (
+
+ out:
+ g_clear_object (&temp_child);
+  if (!ret)
+    g_clear_object (&info);
+  return info;
+}
+
+static gboolean
+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
new file mode 100644
index 0000000..c94ec36
--- /dev/null
+++ b/libostree/ostree-repo-file-enumerator.h
@@ -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 <gio/gio.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_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
+{
+  GObjectClass 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
diff --git a/libostree/ostree-repo-file.c b/libostree/ostree-repo-file.c
new file mode 100644
index 0000000..5d507c4
--- /dev/null
+++ b/libostree/ostree-repo-file.c
@@ -0,0 +1,763 @@
+/* -*- 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.h"
+#include "otutil.h"
+
+static void ot_repo_file_file_iface_init (GFileIface *iface);
+
+struct _OstreeRepoFile
+{
+  GObject parent_instance;
+
+  OstreeRepo *repo;
+
+  char *commit;
+  char *path;
+  const char *basename;
+
+  GError *resolve_error;
+  OstreeRepoFile *parent;
+
+  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,
+			 G_IMPLEMENT_INTERFACE (G_TYPE_FILE,
+						ot_repo_file_file_iface_init))
+
+static void
+ostree_repo_file_finalize (GObject *object)
+{
+  OstreeRepoFile *self;
+
+  local = 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_OBJECT_CLASS (ostree_repo_file_parent_class)->finalize (object);
+}
+
+static void
+ostree_repo_file_dispose (GObject *object)
+{
+  OstreeRepoFile *self;
+
+  self = OSTREE_REPO_FILE (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);
+}
+
+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;
+}
+
+static void
+ostree_repo_file_init (OstreeRepoFile *self)
+{
+}
+
+GFile * 
+_ostree_repo_file_new (OstreeRepo  *repo,
+		       const char  *commit,
+		       const char  *path)
+{
+  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);
+}
+
+static gboolean
+do_resolve_commit (OstreeRepoFile  *self)
+{
+  gboolean ret = FALSE;
+  GVariant *commit = NULL;
+  GVariant *root_contents = NULL;
+  GVariant *root_metadata = NULL;
+  const char *tree_contents_checksum;
+  const char *tree_meta_checksum;
+
+  g_assert (self->parent == NULL);
+
+  if (!ostree_repo_load_variant_checked (self, OSTREE_SERIALIZED_COMMIT_VARIANT,
+                                         self->commit, &commit, &self->resolve_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_TREE_VARIANT,
+                                         tree_contents_checksum, &root_contents,
+					 &self->resolve_error))
+    goto out;
+
+  if (!ostree_repo_load_variant_checked (self, OSTREE_SERIALIZED_DIRMETA_VARIANT,
+                                         tree_meta_checksum, &root_metadata,
+					 &self->resolve_error))
+    goto out;
+  
+  self->tree_metadata = root_metadata;
+  root_metadata = NULL;
+  self->tree_contents = root_contents;
+  root_contents = NULL;
+
+  self->is_tree = TRUE;
+  
+ out:
+  if (commit)
+    g_variant_unref (commit);
+  if (root_metadata)
+    g_variant_unref (root_metadata);
+  if (root_contents)
+    g_variant_unref (root_contents);
+  return ret;
+}
+
+static gboolean
+do_resolve_from_parent (OstreeRepoFile   *self)
+{
+  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++)
+    {
+      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;
+    }
+  
+  ret = TRUE;
+ out:
+  self->resolved = TRUE;
+  if (self->resolve_error)
+    {
+      if (error)
+	*error = g_error_copy (self->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)
+{
+  return self->path;
+}
+
+GFile*
+_ostree_repo_file_nontree_get_local (OstreeRepoFile  *self)
+{
+  g_assert (self->resolved);
+  g_assert (!self->is_tree);
+  
+  return self->local_file;
+}
+
+static gboolean
+ostree_repo_file_is_native (GFile *file)
+{
+  return FALSE;
+}
+
+static gboolean
+ostree_repo_file_has_uri_scheme (GFile      *file,
+				 const char *uri_scheme)
+{
+  return g_ascii_strcasecmp (uri_scheme, "ostree") == 0;
+}
+
+static char *
+ostree_repo_file_get_uri_scheme (GFile *file)
+{
+  return g_strdup ("ostree");
+}
+
+static char *
+ostree_repo_file_get_basename (GFile *file)
+{
+  return g_file_get_basename (OSTREE_REPO_FILE (file)->path);
+}
+
+static char *
+ostree_repo_file_get_path (GFile *file)
+{
+  return g_strdup (OSTREE_REPO_FILE (file)->path);
+}
+
+static char *
+ostree_repo_file_get_uri (GFile *file)
+{
+  OstreeRepoFile *self = OSTREE_REPO_FILE (file);
+  char *uri_path;
+  char *ret;
+
+  uri_path = g_escape_uri_string (self->path, UNSAFE_PATH);
+  ret = g_strconcat ("ostree://", self->commit, "/", uri_path, NULL);
+  g_free (uri_path);
+
+  return ret;
+}
+
+static char *
+ostree_repo_file_get_parse_name (GFile *file)
+{
+  return ostree_repo_file_get_uri (file);
+}
+
+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;
+}
+
+static GFile *
+ostree_repo_file_dup (GFile *file)
+{
+  OstreeRepoFile *self = OSTREE_REPO_FILE (file);
+
+  return _ostree_repo_file_new (self->repo, self->commit, self->path);
+}
+
+static guint
+ostree_repo_file_hash (GFile *file)
+{
+  OstreeRepoFile *self = OSTREE_REPO_FILE (file);
+  
+  return g_str_hash (self->commit) + g_str_hash (self->path);
+}
+
+static gboolean
+ostree_repo_file_equal (GFile *file1,
+		    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);
+}
+
+static const char *
+match_prefix (const char *path, 
+              const char *prefix)
+{
+  int prefix_len;
+
+  prefix_len = strlen (prefix);
+  if (strncmp (path, prefix, prefix_len) != 0)
+    return NULL;
+  
+  /* Handle the case where prefix is the root, so that
+   * the IS_DIR_SEPRARATOR check below works */
+  if (prefix_len > 0 &&
+      G_IS_DIR_SEPARATOR (prefix[prefix_len-1]))
+    prefix_len--;
+  
+  return path + prefix_len;
+}
+
+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);
+  if (remainder != NULL && G_IS_DIR_SEPARATOR (*remainder))
+    return TRUE;
+  return FALSE;
+}
+
+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);
+  
+  if (remainder != NULL && G_IS_DIR_SEPARATOR (*remainder))
+    return g_strdup (remainder + 1);
+  return NULL;
+}
+
+static GFile *
+ostree_repo_file_resolve_relative_path (GFile      *file,
+					const char *relative_path)
+{
+  OstreeRepoFile *self = OSTREE_REPO_FILE (file);
+  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);
+  g_free (filename);
+  
+  return child;
+}
+
+static GFileEnumerator *
+ostree_repo_file_enumerate_children (GFile                *file,
+				     const char           *attributes,
+				     GFileQueryInfoFlags   flags,
+				     GCancellable         *cancellable,
+				     GError              **error)
+{
+  OstreeRepoFile *self = OSTREE_REPO_FILE (file);
+  return _ostree_repo_file_enumerator_new (self,
+					   attributes, flags,
+					   cancellable, error);
+}
+
+static GFile *
+ostree_repo_file_get_child_for_display_name (GFile        *file,
+					 const char   *display_name,
+					 GError      **error)
+{
+  return g_file_get_child (file, display_name);
+}
+
+void
+query_info_common (OstreeRepoFile  *self,
+		   GFileInfo       *info)
+{
+  if (*(self->basename) == '.')
+    g_file_info_set_is_hidden (info, TRUE);
+
+  g_file_info_set_attribute_string (info, "standard::name",
+				    self->basename);
+  g_file_info_set_attribute_string (info, "standard::display-name",
+				    self->basename);
+}
+
+static gboolean
+query_info_file_nonarchive (OstreeRepoFile   *self,
+			    GFileInfo        *info,
+			    GCancellable     *cancellable,
+			    GError          **error)
+{
+  gboolean ret = FALSE;
+  GFileInfo *local_info = NULL;
+  int i ;
+  const char mapped_boolean[] = {
+    "standard::is-symlink"
+  };
+  const char mapped_string[] = {
+  };
+  const char mapped_byte_string[] = {
+    "standard::symlink-target"
+  };
+  const char mapped_uint32[] = {
+    "standard::type",
+    "unix::device",
+    "unix::mode",
+    "unix::nlink",
+    "unix::uid",
+    "unix::gid",
+    "unix::rdev"
+  };
+  const char mapped_uint64[] = {
+    "standard::size",
+    "standard::allocated-size",
+    "unix::inode"
+  };
+
+  local_info = g_file_query_info (self->local_file,
+				  OSTREE_GIO_FAST_QUERYINFO,
+				  G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+				  cancellable,
+				  error);
+  if (!local_info)
+    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));
+
+  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));
+
+  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));
+
+  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));
+
+  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));
+  
+  ret = TRUE;
+ out:
+  g_clear_object (&local_info);
+  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);
+  GFileInfo *info;
+
+  if (!_ostree_repo_file_ensure_resolved (self, error))
+    return NULL;
+
+  info = g_file_info_new ();
+
+  query_info_common (self, info);
+
+  if (self->local_file)
+    {
+      if (ostree_repo_is_archive (self->repo))
+	{
+	}
+      else
+	{
+	  if (!query_info_file_nonarchive (self, info, error))
+	    goto out;
+	}
+    }
+  else
+    {
+      uint32 uid;
+      uint32 gid;
+      uint32 mode;
+
+      g_file_info_set_attribute_uint32 (info, "standard::type", G_FILE_TYPE_DIRECTORY);
+
+      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);
+
+      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);
+
+      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);
+    }
+
+  return info;
+}
+
+static GFileAttributeInfoList *
+ostree_repo_file_query_settable_attributes (GFile         *file,
+					GCancellable  *cancellable,
+					GError       **error)
+{
+  return g_file_attribute_info_list_new ();
+}
+
+static GFileAttributeInfoList *
+ostree_repo_file_query_writable_namespaces (GFile         *file,
+					GCancellable  *cancellable,
+					GError       **error)
+{
+  return g_file_attribute_info_list_new ();
+}
+
+static GFileInputStream *
+ostree_repo_file_read (GFile         *file,
+		       GCancellable  *cancellable,
+		       GError       **error)
+{
+  gboolean ret = FALSE;
+  GFileInputStream *ret_stream = NULL;
+  OstreeRepoFile *self = OSTREE_REPO_FILE (file);
+
+  if (!_ostree_repo_file_ensure_resolved (self, error))
+    goto out;
+  
+  if (self->is_tree)
+    {
+      g_set_error_literal (error, G_IO_ERROR,
+			   G_IO_ERROR_IS_DIRECTORY,
+			   _("Can't open directory"));
+      goto out;
+    }
+
+  if (ostree_repo_is_archive (self->repo))
+    {
+      g_set_error_literal (error, G_IO_ERROR,
+			   G_IO_ERROR_NOT_SUPPORTED,
+			   _("Can't open archived file (yet)"));
+      goto out;
+    }
+  else
+    {
+      ret_stream = g_file_read (self->local_file, cancellable, error);
+      if (!ret_stream)
+	goto out;
+    }
+  
+  ret = TRUE;
+ out:
+  if (!ret)
+    g_clear_object (&ret_stream);
+  return ret_stream;
+}
+
+static void
+ostree_repo_file_file_iface_init (GFileIface *iface)
+{
+  iface->dup = ostree_repo_file_dup;
+  iface->hash = ostree_repo_file_hash;
+  iface->equal = ostree_repo_file_equal;
+  iface->is_native = ostree_repo_file_is_native;
+  iface->has_uri_scheme = ostree_repo_file_has_uri_scheme;
+  iface->get_uri_scheme = ostree_repo_file_get_uri_scheme;
+  iface->get_basename = ostree_repo_file_get_basename;
+  iface->get_path = ostree_repo_file_get_path;
+  iface->get_uri = ostree_repo_file_get_uri;
+  iface->get_parse_name = ostree_repo_file_get_parse_name;
+  iface->get_parent = ostree_repo_file_get_parent;
+  iface->prefix_matches = ostree_repo_file_prefix_matches;
+  iface->get_relative_path = ostree_repo_file_get_relative_path;
+  iface->resolve_relative_path = ostree_repo_file_resolve_relative_path;
+  iface->get_child_for_display_name = ostree_repo_file_get_child_for_display_name;
+  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_settable_attributes = ostree_repo_file_query_settable_attributes;
+  iface->query_writable_namespaces = ostree_repo_file_query_writable_namespaces;
+  iface->set_attribute = NULL;
+  iface->set_attributes_from_info = NULL;
+  iface->read_fn = ostree_repo_file_read;
+  iface->append_to = NULL;
+  iface->create = NULL;
+  iface->replace = NULL;
+  iface->open_readwrite = NULL;
+  iface->create_readwrite = NULL;
+  iface->replace_readwrite = NULL;
+  iface->delete_file = NULL;
+  iface->trash = NULL;
+  iface->make_directory = NULL;
+  iface->make_symbolic_link = NULL;
+  iface->copy = NULL;
+  iface->move = NULL;
+  iface->monitor_dir = NULL;
+  iface->monitor_file = NULL;
+
+  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
new file mode 100644
index 0000000..5a4d2c6
--- /dev/null
+++ b/libostree/ostree-repo-file.h
@@ -0,0 +1,63 @@
+/* -*- 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 <gio/gio.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 (OstreeRepo  *repo,
+                               const char  *commit,
+                               const char  *path);
+
+gboolean _ostree_repo_file_ensure_resolved (OstreeRepoFile  *self,
+                                            GError         **error);
+
+const char * _ostree_repo_file_get_relpath (OstreeRepoFile  *self);
+
+gboolean _ostree_repo_file_is_tree (OstreeRepoFile  *self);
+
+GFile *_ostree_repo_file_nontree_get_local (OstreeRepoFile  *self);
+GVariant *_ostree_repo_file_tree_get_contents (OstreeRepoFile  *self);
+GVariant *_ostree_repo_file_tree_get_metadata (OstreeRepoFile  *self);
+
+G_END_DECLS
+
+#endif
diff --git a/libostree/ostree-repo.h b/libostree/ostree-repo.h
index e9a690a..70d5eb4 100644
--- a/libostree/ostree-repo.h
+++ b/libostree/ostree-repo.h
@@ -18,7 +18,6 @@
  *
  * Author: Colin Walters <walters verbum org>
  */
-/* ostree-repo.h */
 
 #ifndef _OSTREE_REPO
 #define _OSTREE_REPO



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