[glib/gsettings] full support for non-cached schema reading



commit 97bb280adba6d1c7151b109189bcaca1b4082064
Author: Ryan Lortie <desrt desrt ca>
Date:   Mon Oct 5 13:10:42 2009 -0400

    full support for non-cached schema reading

 gio/Makefile.am                     |    4 +-
 gio/gsettings-update-schema-cache.c |   77 +++++++++++++++++++++++++++++++++--
 gio/gsettingsschema.c               |   66 +++++++++++++++++++++++++++--
 3 files changed, 137 insertions(+), 10 deletions(-)
---
diff --git a/gio/Makefile.am b/gio/Makefile.am
index 5ec46b4..6bb2947 100644
--- a/gio/Makefile.am
+++ b/gio/Makefile.am
@@ -41,6 +41,8 @@ TESTS = abicheck.sh pltcheck.sh
 endif
 endif
 
+GSETTINGS_SCHEMA_COMPILER = $(libexecdir)/gsettings-update-schema-cache
+
 AM_CPPFLAGS = \
 	-DG_LOG_DOMAIN=\"GLib-GIO\"			\
 	-I$(top_builddir)				\
@@ -51,7 +53,7 @@ AM_CPPFLAGS = \
 	-DG_DISABLE_DEPRECATED				\
 	-DGIO_COMPILATION				\
 	-DGIO_MODULE_DIR=\"$(GIO_MODULE_DIR)\"		\
-	-DGSETTINGS_SCHEMAS_DIR=\"$(datadir)/gsettings/schemas\"
+	-DGSETTINGS_SCHEMA_COMPILER=\"$(GSETTINGS_SCHEMA_COMPILER)\"
 
 lib_LTLIBRARIES = libgio-2.0.la
 
diff --git a/gio/gsettings-update-schema-cache.c b/gio/gsettings-update-schema-cache.c
index 4c23fe8..c376cbd 100644
--- a/gio/gsettings-update-schema-cache.c
+++ b/gio/gsettings-update-schema-cache.c
@@ -889,14 +889,83 @@ compile_directory (const gchar *dirname)
   write_cache (cache);
 }
 
+static void
+single_schema_to_stdout (const gchar *schema_name,
+                         const gchar *filename)
+{
+  TokenStream stream = {  };
+  GError *error = NULL;
+  gconstpointer data;
+  GVariant *variant;
+  gchar *contents;
+  Schema *schema;
+  gsize length;
+  Cache *cache;
+  gsize i;
+
+  cache = cache_new ();
+
+  if (!g_file_get_contents (filename, &contents, &length, &error))
+    g_error ("%s: %s\n", filename, error->message);
+
+  stream.stream = contents;
+  stream.start = contents;
+  stream.end = contents + length;
+
+  if (!read_file (&stream, cache))
+    {
+      show_error_message (&stream, filename);
+      g_assert_not_reached ();
+    }
+
+  schema = g_hash_table_lookup (cache->schemas, schema_name);
+
+  if (schema == NULL)
+    g_error ("schema `%s' not found in `%s'", schema_name, filename);
+
+  variant = g_variant_ref_sink (serialise_schema (schema));
+  length = g_variant_get_size (variant);
+  data = g_variant_get_data (variant);
+
+  for (i = 0; i < length;)
+    {
+      gssize count = fwrite (data + i, 1, length - i, stdout);
+      if (count <= 0)
+        g_error ("error on write to stdout: %s\n", g_strerror (errno));
+      i += count;
+    }
+
+  g_variant_unref (variant);
+}
+
 int
 main (int argc, char **argv)
 {
-  if (argc == 1)
-    g_warning ("nothing to do");
+  argv++;
+
+  if (g_strcmp0 (*argv, "--compile-one-schema") == 0)
+    {
+      const gchar *schema_name;
+      const gchar *filename;
 
-  while (*++argv)
-    compile_directory (*argv);
+      argv++;
+
+      if ((schema_name = *argv++) == NULL)
+        g_error ("missing argument to `--compile-one-schema'");
+
+      if ((filename = *argv++) == NULL || *argv != NULL)
+        g_error ("expected one filename to follow schema name");
+
+      single_schema_to_stdout (schema_name, filename);
+    }
+  else
+    {
+      if (!*argv)
+        g_warning ("nothing to do");
+
+      while (*argv)
+        compile_directory (*argv++);
+    }
 
   return 0;
 }
diff --git a/gio/gsettingsschema.c b/gio/gsettingsschema.c
index 5131fdd..03714a6 100644
--- a/gio/gsettingsschema.c
+++ b/gio/gsettingsschema.c
@@ -10,8 +10,11 @@
 
 #include "gsettingsschema.h"
 
+#include <sys/wait.h>
 #include <sys/stat.h>
+#include <unistd.h>
 #include <string.h>
+#include <errno.h>
 
 #include "gioalias.h"
 
@@ -110,10 +113,63 @@ g_settings_schema_initialise_directories (void)
 }
 
 static GVariant *
-g_settings_schema_compile (const gchar *filename)
+g_settings_schema_compile (const gchar *filename,
+                           const gchar *schema_name)
 {
-  g_print ("compiling %s\n", filename);
-  return NULL;
+ const gchar *argv[] = { GSETTINGS_SCHEMA_COMPILER,
+                          "--compile-one-schema",
+                          schema_name, filename, NULL };
+  GError *error = NULL;
+  gint out_fd, status;
+  gint data_size;
+  gint allocated;
+  gssize count;
+  gchar *data;
+  GPid pid;
+
+  /* can't use g_spawn_sync because it uses nul-terminated strings */
+  if (!g_spawn_async_with_pipes (/* working directory */ NULL,
+                                 (gchar **) argv,
+                                 /* environment */ NULL,
+                                 G_SPAWN_DO_NOT_REAP_CHILD,
+                                 /* child setup */ NULL,
+                                 /* child setup user_data */ NULL,
+                                 &pid,
+                                 /* stdin pipe */ NULL,
+                                 &out_fd,
+                                 /* stderr pipe */ NULL,
+                                 &error))
+    g_error ("%s", error->message);
+
+  count = allocated = data_size = 0;
+  data = NULL;
+
+  /* read the stdout until EOF */
+  do
+    if ((data_size += count) + 1024 > allocated)
+      data = g_realloc (data, allocated = (data_size + 1024) * 2);
+  while ((count = read (out_fd, data + data_size, 1024)) > 0);
+
+  data = g_realloc (data, data_size);
+  close (out_fd);
+
+  if (count < 0)
+    g_error ("GSettings: reading from schema compiler: %s\n",
+             g_strerror (errno));
+
+  while ((pid = waitpid (pid, &status, 0)) < 0 && errno == EINTR);
+
+  if (pid < 0)
+    g_error ("GSettings: waitpid() on schema compiler: %s\n",
+             g_strerror (errno));
+
+  g_spawn_close_pid (pid);
+
+  if (status != 0)
+    g_error ("GSettings schema compiler: exit code %d\n", status);
+
+  return g_variant_from_data (G_VARIANT_TYPE ("(asmsa{s(sv)}a{ss})"),
+                              data, data_size, 0, g_free, data);
 }
 
 static GVariant *
@@ -127,7 +183,7 @@ g_settings_schema_scan_dir (const gchar *directory,
   gint end;
 
   directory_length = strlen (directory);
-  name_length = strlen (schema_name);
+  name_length = strcspn (schema_name, "/");
 
   path = g_malloc (directory_length + 1 + name_length + 1  +  7  +  1);
                  /*       directory   /   schema_name   .  schemas  \0 */
@@ -146,7 +202,7 @@ g_settings_schema_scan_dir (const gchar *directory,
       if (path[end] != '.')
         break;
 
-      value = g_settings_schema_compile (path);
+      value = g_settings_schema_compile (path, schema_name);
     }
 
   g_free (path);



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