[gobject-introspection] girepository: Add g_irepository_get_immediate_dependencies()



commit 8480bf5f108f72585016254c79d9c495e1b0a4a7
Author: Philip Withnall <philip tecnocode co uk>
Date:   Sat Jan 31 22:48:56 2015 +0000

    girepository: Add g_irepository_get_immediate_dependencies()
    
    g_irepository_get_dependencies() is supposed to return the transitive
    closure of all dependencies of the given namespace. However, it just
    loads the dependencies field from the typelib, which is supposed to only
    list immediate dependencies.
    
    Introduce a new g_irepository_get_immediate_dependencies() which does
    this, and rewrite g_irepository_get_dependencies() to build the
    transitive closure of all its namespace dependencies. This does not
    require loading any new typelibs, as the transitive closure of
    dependencies should already have been loaded by g_irepository_require()
    or g_irepository_load_typelib().
    
    https://bugzilla.gnome.org/show_bug.cgi?id=743782

 docs/reference/gi-sections.txt |    1 +
 girepository/girepository.c    |  117 +++++++++++++++++++++++++++++++++++++---
 girepository/girepository.h    |    4 ++
 girepository/girwriter.c       |    4 +-
 girepository/giversionmacros.h |   16 +++++-
 5 files changed, 132 insertions(+), 10 deletions(-)
---
diff --git a/docs/reference/gi-sections.txt b/docs/reference/gi-sections.txt
index 59f0d50..548a5f4 100644
--- a/docs/reference/gi-sections.txt
+++ b/docs/reference/gi-sections.txt
@@ -5,6 +5,7 @@ GIRepository
 GIRepositoryLoadFlags
 g_irepository_get_default
 g_irepository_get_dependencies
+g_irepository_get_immediate_dependencies
 g_irepository_get_loaded_namespaces
 g_irepository_get_n_infos
 g_irepository_get_info
diff --git a/girepository/girepository.c b/girepository/girepository.c
index fb91afa..efc3bde 100644
--- a/girepository/girepository.c
+++ b/girepository/girepository.c
@@ -432,6 +432,89 @@ register_internal (GIRepository *repository,
 }
 
 /**
+ * g_irepository_get_immediate_dependencies:
+ * @repository: (nullable): A #GIRepository or %NULL for the singleton
+ *   process-global default #GIRepository
+ * @namespace_: Namespace of interest
+ *
+ * Return an array of the immediate versioned dependencies for @namespace_.
+ * Returned strings are of the form <code>namespace-version</code>.
+ *
+ * Note: @namespace_ must have already been loaded using a function
+ * such as g_irepository_require() before calling this function.
+ *
+ * To get the transitive closure of dependencies for @namespace_, use
+ * g_irepository_get_dependencies().
+ *
+ * Returns: (transfer full): Zero-terminated string array of immediate versioned
+ *   dependencies
+ *
+ * Since: 1.44
+ */
+char **
+g_irepository_get_immediate_dependencies (GIRepository *repository,
+                                          const char   *namespace)
+{
+  GITypelib *typelib;
+  gchar **deps;
+
+  g_return_val_if_fail (namespace != NULL, NULL);
+
+  repository = get_repository (repository);
+
+  typelib = get_registered (repository, namespace, NULL);
+  g_return_val_if_fail (typelib != NULL, NULL);
+
+  /* Ensure we always return a non-%NULL vector. */
+  deps = get_typelib_dependencies (typelib);
+  if (deps == NULL)
+      deps = g_strsplit ("", "|", 0);
+
+  return deps;
+}
+
+/* Load the transitive closure of dependency namespace-version strings for the
+ * given @typelib. @repository must be non-%NULL. @transitive_dependencies must
+ * be a pre-existing GHashTable<owned utf8, owned utf8> set for storing the
+ * dependencies. */
+static void
+get_typelib_dependencies_transitive (GIRepository *repository,
+                                     GITypelib    *typelib,
+                                     GHashTable   *transitive_dependencies)
+{
+  gchar **immediate_dependencies;
+  guint i;
+
+  immediate_dependencies = get_typelib_dependencies (typelib);
+
+  for (i = 0; immediate_dependencies != NULL && immediate_dependencies[i]; i++)
+    {
+      gchar *dependency;
+      const gchar *last_dash;
+      gchar *dependency_namespace;
+
+      dependency = immediate_dependencies[i];
+
+      /* Steal from the strv. */
+      g_hash_table_add (transitive_dependencies, dependency);
+      immediate_dependencies[i] = NULL;
+
+      /* Recurse for this namespace. */
+      last_dash = strrchr (dependency, '-');
+      dependency_namespace = g_strndup (dependency, last_dash - dependency);
+
+      typelib = get_registered (repository, dependency_namespace, NULL);
+      g_return_if_fail (typelib != NULL);
+      get_typelib_dependencies_transitive (repository, typelib,
+                                           transitive_dependencies);
+
+      g_free (dependency_namespace);
+    }
+
+  g_free (immediate_dependencies);
+}
+
+/**
  * g_irepository_get_dependencies:
  * @repository: (allow-none): A #GIRepository or %NULL for the singleton
  *   process-global default #GIRepository
@@ -444,7 +527,10 @@ register_internal (GIRepository *repository,
  * Note: @namespace_ must have already been loaded using a function
  * such as g_irepository_require() before calling this function.
  *
- * Returns: (transfer full): Zero-terminated string array of versioned
+ * To get only the immediate dependencies for @namespace_, use
+ * g_irepository_get_immediate_dependencies().
+ *
+ * Returns: (transfer full): Zero-terminated string array of all versioned
  *   dependencies
  */
 char **
@@ -452,21 +538,38 @@ g_irepository_get_dependencies (GIRepository *repository,
                                const char *namespace)
 {
   GITypelib *typelib;
-  gchar **deps;
+  GHashTable *transitive_dependencies;  /* set of owned utf8 */
+  GHashTableIter iter;
+  gchar *dependency;
+  GPtrArray *out;  /* owned utf8 elements */
 
   g_return_val_if_fail (namespace != NULL, NULL);
 
   repository = get_repository (repository);
+  transitive_dependencies = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                                   g_free, NULL);
 
+  /* Load the dependencies. */
   typelib = get_registered (repository, namespace, NULL);
   g_return_val_if_fail (typelib != NULL, NULL);
+  get_typelib_dependencies_transitive (repository, typelib,
+                                       transitive_dependencies);
 
-  /* Ensure we always return a non-%NULL vector. */
-  deps = get_typelib_dependencies (typelib);
-  if (deps == NULL)
-      deps = g_strsplit ("", "|", 0);
+  /* Convert to a string array. */
+  out = g_ptr_array_new_full (g_hash_table_size (transitive_dependencies),
+                              g_free);
+  g_hash_table_iter_init (&iter, transitive_dependencies);
 
-  return deps;
+  while (g_hash_table_iter_next (&iter, (gpointer) &dependency, NULL))
+    {
+      g_ptr_array_add (out, dependency);
+      g_hash_table_iter_steal (&iter);
+    }
+
+  /* Add a NULL terminator. */
+  g_ptr_array_add (out, NULL);
+
+  return (gchar **) g_ptr_array_free (out, FALSE);
 }
 
 /**
diff --git a/girepository/girepository.h b/girepository/girepository.h
index dcc34ce..e3ed837 100644
--- a/girepository/girepository.h
+++ b/girepository/girepository.h
@@ -143,6 +143,10 @@ GITypelib *    g_irepository_require_private (GIRepository  *repository,
                                             GIRepositoryLoadFlags flags,
                                             GError       **error);
 
+GI_AVAILABLE_IN_1_44
+gchar      ** g_irepository_get_immediate_dependencies (GIRepository *repository,
+                                                        const gchar  *namespace_);
+
 GI_AVAILABLE_IN_ALL
 gchar      ** g_irepository_get_dependencies (GIRepository *repository,
                                              const gchar  *namespace_);
diff --git a/girepository/girwriter.c b/girepository/girwriter.c
index 5b39e2d..01f5f50 100644
--- a/girepository/girwriter.c
+++ b/girepository/girwriter.c
@@ -1307,8 +1307,8 @@ gir_writer_write (const char *filename,
              "            xmlns:c=\"http://www.gtk.org/introspection/c/1.0\"\n";
              "            xmlns:glib=\"http://www.gtk.org/introspection/glib/1.0\"";);
 
-  dependencies = g_irepository_get_dependencies (repository,
-                                                namespace);
+  dependencies = g_irepository_get_immediate_dependencies (repository,
+                                                           namespace);
   if (dependencies != NULL)
     {
       for (i = 0; dependencies[i]; i++)
diff --git a/girepository/giversionmacros.h b/girepository/giversionmacros.h
index 15c8847..3c2faf4 100644
--- a/girepository/giversionmacros.h
+++ b/girepository/giversionmacros.h
@@ -125,4 +125,18 @@
 # define GI_AVAILABLE_IN_1_42                 _GI_EXTERN
 #endif
 
-#endif /* __GIVERSIONMACROS_H__ */
\ No newline at end of file
+#if GLIB_VERSION_MIN_REQUIRED >= GLIB_VERSION_2_44
+# define GI_DEPRECATED_IN_1_44                GLIB_DEPRECATED
+# define GI_DEPRECATED_IN_1_44_FOR(f)         GLIB_DEPRECATED_FOR(f)
+#else
+# define GI_DEPRECATED_IN_1_44                _GI_EXTERN
+# define GI_DEPRECATED_IN_1_44_FOR(f)         _GI_EXTERN
+#endif
+
+#if GLIB_VERSION_MAX_ALLOWED < GLIB_VERSION_2_44
+# define GI_AVAILABLE_IN_1_44                 GLIB_UNAVAILABLE(2, 44)
+#else
+# define GI_AVAILABLE_IN_1_44                 _GI_EXTERN
+#endif
+
+#endif /* __GIVERSIONMACROS_H__ */


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