summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <philip@tecnocode.co.uk>2015-01-31 22:48:56 +0000
committerPhilip Withnall <philip.withnall@collabora.co.uk>2015-02-16 08:49:28 +0000
commit8480bf5f108f72585016254c79d9c495e1b0a4a7 (patch)
tree2578ac864bad36ff27720fd1b931ee7776521349
parent6ff0b08ff1982ef60d077ba5e1c11ea605be606b (diff)
downloadgobject-introspection-8480bf5f108f72585016254c79d9c495e1b0a4a7.tar.gz
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
-rw-r--r--docs/reference/gi-sections.txt1
-rw-r--r--girepository/girepository.c117
-rw-r--r--girepository/girepository.h4
-rw-r--r--girepository/girwriter.c4
-rw-r--r--girepository/giversionmacros.h16
5 files changed, 132 insertions, 10 deletions
diff --git a/docs/reference/gi-sections.txt b/docs/reference/gi-sections.txt
index 59f0d50a..548a5f48 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 fb91afaa..efc3bded 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 dcc34ce2..e3ed8372 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 5b39e2de..01f5f506 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 15c88476..3c2faf47 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__ */