mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-23 10:42:11 +01:00
Merge branch 'backport-4033-girepository-typelib-determinicity-glib-2-80' into 'glib-2-80'
Backport !4033 “girepository: Keep an ordered list of the loaded typelibs” to glib-2-80 See merge request GNOME/glib!4080
This commit is contained in:
commit
14a26f969f
@ -65,6 +65,23 @@
|
|||||||
* The environment variable takes precedence over the default search path
|
* The environment variable takes precedence over the default search path
|
||||||
* and the [method@GIRepository.Repository.prepend_search_path] calls.
|
* and the [method@GIRepository.Repository.prepend_search_path] calls.
|
||||||
*
|
*
|
||||||
|
* ### Namespace ordering
|
||||||
|
*
|
||||||
|
* In situations where namespaces may be searched in order, or returned in a
|
||||||
|
* list, the namespaces will be returned in alphabetical order, with all fully
|
||||||
|
* loaded namespaces being returned before any lazily loaded ones (those loaded
|
||||||
|
* with `GI_REPOSITORY_LOAD_FLAG_LAZY`). This allows for deterministic and
|
||||||
|
* reproducible results.
|
||||||
|
*
|
||||||
|
* Similarly, if a symbol (such as a `GType` or error domain) is being searched
|
||||||
|
* for in the set of loaded namespaces, the namespaces will be searched in that
|
||||||
|
* order. In particular, this means that a symbol which exists in two namespaces
|
||||||
|
* will always be returned from the alphabetically-higher namespace. This should
|
||||||
|
* only happen in the case of `Gio` and `GioUnix`/`GioWin32`, which all refer to
|
||||||
|
* the same `.so` file and expose overlapping sets of symbols. Symbols should
|
||||||
|
* always end up being resolved to `GioUnix` or `GioWin32` if they are platform
|
||||||
|
* dependent, rather than `Gio` itself.
|
||||||
|
*
|
||||||
* Since: 2.80
|
* Since: 2.80
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -98,8 +115,14 @@ struct _GIRepository
|
|||||||
GPtrArray *typelib_search_path; /* (element-type filename) (owned) */
|
GPtrArray *typelib_search_path; /* (element-type filename) (owned) */
|
||||||
GPtrArray *library_paths; /* (element-type filename) (owned) */
|
GPtrArray *library_paths; /* (element-type filename) (owned) */
|
||||||
|
|
||||||
|
/* Certain operations require iterating over the typelibs and the iteration
|
||||||
|
* order may affect the results. So keep an ordered list of the typelibs,
|
||||||
|
* alongside the hash table which keep the canonical strong reference to them. */
|
||||||
GHashTable *typelibs; /* (string) namespace -> GITypelib */
|
GHashTable *typelibs; /* (string) namespace -> GITypelib */
|
||||||
|
GPtrArray *ordered_typelibs; /* (element-type unowned GITypelib) (owned) (not nullable) */
|
||||||
GHashTable *lazy_typelibs; /* (string) namespace-version -> GITypelib */
|
GHashTable *lazy_typelibs; /* (string) namespace-version -> GITypelib */
|
||||||
|
GPtrArray *ordered_lazy_typelibs; /* (element-type unowned GITypelib) (owned) (not nullable) */
|
||||||
|
|
||||||
GHashTable *info_by_gtype; /* GType -> GIBaseInfo */
|
GHashTable *info_by_gtype; /* GType -> GIBaseInfo */
|
||||||
GHashTable *info_by_error_domain; /* GQuark -> GIBaseInfo */
|
GHashTable *info_by_error_domain; /* GQuark -> GIBaseInfo */
|
||||||
GHashTable *interfaces_for_gtype; /* GType -> GTypeInterfaceCache */
|
GHashTable *interfaces_for_gtype; /* GType -> GTypeInterfaceCache */
|
||||||
@ -187,10 +210,13 @@ gi_repository_init (GIRepository *repository)
|
|||||||
= g_hash_table_new_full (g_str_hash, g_str_equal,
|
= g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
(GDestroyNotify) g_free,
|
(GDestroyNotify) g_free,
|
||||||
(GDestroyNotify) gi_typelib_unref);
|
(GDestroyNotify) gi_typelib_unref);
|
||||||
|
repository->ordered_typelibs = g_ptr_array_new_with_free_func (NULL);
|
||||||
repository->lazy_typelibs
|
repository->lazy_typelibs
|
||||||
= g_hash_table_new_full (g_str_hash, g_str_equal,
|
= g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
(GDestroyNotify) g_free,
|
(GDestroyNotify) g_free,
|
||||||
(GDestroyNotify) gi_typelib_unref);
|
(GDestroyNotify) gi_typelib_unref);
|
||||||
|
repository->ordered_lazy_typelibs = g_ptr_array_new_with_free_func (NULL);
|
||||||
|
|
||||||
repository->info_by_gtype
|
repository->info_by_gtype
|
||||||
= g_hash_table_new_full (g_direct_hash, g_direct_equal,
|
= g_hash_table_new_full (g_direct_hash, g_direct_equal,
|
||||||
(GDestroyNotify) NULL,
|
(GDestroyNotify) NULL,
|
||||||
@ -212,7 +238,10 @@ gi_repository_finalize (GObject *object)
|
|||||||
GIRepository *repository = GI_REPOSITORY (object);
|
GIRepository *repository = GI_REPOSITORY (object);
|
||||||
|
|
||||||
g_hash_table_destroy (repository->typelibs);
|
g_hash_table_destroy (repository->typelibs);
|
||||||
|
g_ptr_array_unref (repository->ordered_typelibs);
|
||||||
g_hash_table_destroy (repository->lazy_typelibs);
|
g_hash_table_destroy (repository->lazy_typelibs);
|
||||||
|
g_ptr_array_unref (repository->ordered_lazy_typelibs);
|
||||||
|
|
||||||
g_hash_table_destroy (repository->info_by_gtype);
|
g_hash_table_destroy (repository->info_by_gtype);
|
||||||
g_hash_table_destroy (repository->info_by_error_domain);
|
g_hash_table_destroy (repository->info_by_error_domain);
|
||||||
g_hash_table_destroy (repository->interfaces_for_gtype);
|
g_hash_table_destroy (repository->interfaces_for_gtype);
|
||||||
@ -497,6 +526,29 @@ load_dependencies_recurse (GIRepository *repository,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Sort typelibs by namespace. The main requirement here is just to make iteration
|
||||||
|
* deterministic, otherwise results can change as a lot of the code here would
|
||||||
|
* just iterate over a `GHashTable`.
|
||||||
|
*
|
||||||
|
* A sub-requirement of this is that namespaces are sorted such that if a GType
|
||||||
|
* or symbol is found in multiple namespaces where one is a prefix of the other,
|
||||||
|
* the longest namespace wins. In practice, this only happens in
|
||||||
|
* Gio/GioUnix/GioWin32, as all three of those namespaces refer to the same
|
||||||
|
* `.so` file and overlapping sets of the same symbols, but we want the platform
|
||||||
|
* specific namespace to be returned in preference to anything else (even though
|
||||||
|
* either namespace is valid).
|
||||||
|
* See https://gitlab.gnome.org/GNOME/glib/-/issues/3303 */
|
||||||
|
static int
|
||||||
|
sort_typelibs_cb (const void *a,
|
||||||
|
const void *b)
|
||||||
|
{
|
||||||
|
GITypelib *typelib_a = *(GITypelib **) a;
|
||||||
|
GITypelib *typelib_b = *(GITypelib **) b;
|
||||||
|
|
||||||
|
return strcmp (gi_typelib_get_namespace (typelib_a),
|
||||||
|
gi_typelib_get_namespace (typelib_b));
|
||||||
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
register_internal (GIRepository *repository,
|
register_internal (GIRepository *repository,
|
||||||
const char *source,
|
const char *source,
|
||||||
@ -521,6 +573,8 @@ register_internal (GIRepository *repository,
|
|||||||
namespace));
|
namespace));
|
||||||
g_hash_table_insert (repository->lazy_typelibs,
|
g_hash_table_insert (repository->lazy_typelibs,
|
||||||
build_typelib_key (namespace, source), gi_typelib_ref (typelib));
|
build_typelib_key (namespace, source), gi_typelib_ref (typelib));
|
||||||
|
g_ptr_array_add (repository->ordered_lazy_typelibs, typelib);
|
||||||
|
g_ptr_array_sort (repository->ordered_lazy_typelibs, sort_typelibs_cb);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -535,13 +589,20 @@ register_internal (GIRepository *repository,
|
|||||||
if (g_hash_table_lookup_extended (repository->lazy_typelibs,
|
if (g_hash_table_lookup_extended (repository->lazy_typelibs,
|
||||||
namespace,
|
namespace,
|
||||||
(gpointer)&key, &value))
|
(gpointer)&key, &value))
|
||||||
g_hash_table_remove (repository->lazy_typelibs, key);
|
{
|
||||||
|
g_hash_table_remove (repository->lazy_typelibs, key);
|
||||||
|
g_ptr_array_remove (repository->ordered_lazy_typelibs, typelib);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
key = build_typelib_key (namespace, source);
|
{
|
||||||
|
key = build_typelib_key (namespace, source);
|
||||||
|
}
|
||||||
|
|
||||||
g_hash_table_insert (repository->typelibs,
|
g_hash_table_insert (repository->typelibs,
|
||||||
g_steal_pointer (&key),
|
g_steal_pointer (&key),
|
||||||
gi_typelib_ref (typelib));
|
gi_typelib_ref (typelib));
|
||||||
|
g_ptr_array_add (repository->ordered_typelibs, typelib);
|
||||||
|
g_ptr_array_sort (repository->ordered_typelibs, sort_typelibs_cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* These types might be resolved now, clear the cache */
|
/* These types might be resolved now, clear the cache */
|
||||||
@ -870,32 +931,29 @@ gi_repository_get_info (GIRepository *repository,
|
|||||||
NULL, typelib, entry->offset);
|
NULL, typelib, entry->offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const char *gtype_name;
|
|
||||||
GITypelib *result_typelib;
|
|
||||||
} FindByGTypeData;
|
|
||||||
|
|
||||||
static DirEntry *
|
static DirEntry *
|
||||||
find_by_gtype (GHashTable *table, FindByGTypeData *data, gboolean check_prefix)
|
find_by_gtype (GPtrArray *ordered_table,
|
||||||
|
const char *gtype_name,
|
||||||
|
gboolean check_prefix,
|
||||||
|
GITypelib **out_result_typelib)
|
||||||
{
|
{
|
||||||
GHashTableIter iter;
|
/* Search in reverse order as the longest namespaces will be listed last, and
|
||||||
gpointer key, value;
|
* those are the ones we want to search first. */
|
||||||
DirEntry *ret;
|
for (guint i = ordered_table->len; i > 0; i--)
|
||||||
|
|
||||||
g_hash_table_iter_init (&iter, table);
|
|
||||||
while (g_hash_table_iter_next (&iter, &key, &value))
|
|
||||||
{
|
{
|
||||||
GITypelib *typelib = (GITypelib*)value;
|
GITypelib *typelib = g_ptr_array_index (ordered_table, i - 1);
|
||||||
|
DirEntry *ret;
|
||||||
|
|
||||||
if (check_prefix)
|
if (check_prefix)
|
||||||
{
|
{
|
||||||
if (!gi_typelib_matches_gtype_name_prefix (typelib, data->gtype_name))
|
if (!gi_typelib_matches_gtype_name_prefix (typelib, gtype_name))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = gi_typelib_get_dir_entry_by_gtype_name (typelib, data->gtype_name);
|
ret = gi_typelib_get_dir_entry_by_gtype_name (typelib, gtype_name);
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
data->result_typelib = typelib;
|
*out_result_typelib = typelib;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -924,7 +982,8 @@ GIBaseInfo *
|
|||||||
gi_repository_find_by_gtype (GIRepository *repository,
|
gi_repository_find_by_gtype (GIRepository *repository,
|
||||||
GType gtype)
|
GType gtype)
|
||||||
{
|
{
|
||||||
FindByGTypeData data;
|
const char *gtype_name;
|
||||||
|
GITypelib *result_typelib = NULL;
|
||||||
GIBaseInfo *cached;
|
GIBaseInfo *cached;
|
||||||
DirEntry *entry;
|
DirEntry *entry;
|
||||||
|
|
||||||
@ -940,8 +999,7 @@ gi_repository_find_by_gtype (GIRepository *repository,
|
|||||||
if (g_hash_table_contains (repository->unknown_gtypes, (gpointer)gtype))
|
if (g_hash_table_contains (repository->unknown_gtypes, (gpointer)gtype))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
data.gtype_name = g_type_name (gtype);
|
gtype_name = g_type_name (gtype);
|
||||||
data.result_typelib = NULL;
|
|
||||||
|
|
||||||
/* Inside each typelib, we include the "C prefix" which acts as
|
/* Inside each typelib, we include the "C prefix" which acts as
|
||||||
* a namespace mechanism. For GtkTreeView, the C prefix is Gtk.
|
* a namespace mechanism. For GtkTreeView, the C prefix is Gtk.
|
||||||
@ -950,25 +1008,25 @@ gi_repository_find_by_gtype (GIRepository *repository,
|
|||||||
* target type does not have this typelib's C prefix. Use this
|
* target type does not have this typelib's C prefix. Use this
|
||||||
* assumption as our first attempt at locating the DirEntry.
|
* assumption as our first attempt at locating the DirEntry.
|
||||||
*/
|
*/
|
||||||
entry = find_by_gtype (repository->typelibs, &data, TRUE);
|
entry = find_by_gtype (repository->ordered_typelibs, gtype_name, TRUE, &result_typelib);
|
||||||
if (entry == NULL)
|
if (entry == NULL)
|
||||||
entry = find_by_gtype (repository->lazy_typelibs, &data, TRUE);
|
entry = find_by_gtype (repository->ordered_lazy_typelibs, gtype_name, TRUE, &result_typelib);
|
||||||
|
|
||||||
/* Not ever class library necessarily specifies a correct c_prefix,
|
/* Not every class library necessarily specifies a correct c_prefix,
|
||||||
* so take a second pass. This time we will try a global lookup,
|
* so take a second pass. This time we will try a global lookup,
|
||||||
* ignoring prefixes.
|
* ignoring prefixes.
|
||||||
* See http://bugzilla.gnome.org/show_bug.cgi?id=564016
|
* See http://bugzilla.gnome.org/show_bug.cgi?id=564016
|
||||||
*/
|
*/
|
||||||
if (entry == NULL)
|
if (entry == NULL)
|
||||||
entry = find_by_gtype (repository->typelibs, &data, FALSE);
|
entry = find_by_gtype (repository->ordered_typelibs, gtype_name, FALSE, &result_typelib);
|
||||||
if (entry == NULL)
|
if (entry == NULL)
|
||||||
entry = find_by_gtype (repository->lazy_typelibs, &data, FALSE);
|
entry = find_by_gtype (repository->ordered_lazy_typelibs, gtype_name, FALSE, &result_typelib);
|
||||||
|
|
||||||
if (entry != NULL)
|
if (entry != NULL)
|
||||||
{
|
{
|
||||||
cached = gi_info_new_full (gi_typelib_blob_type_to_info_type (entry->blob_type),
|
cached = gi_info_new_full (gi_typelib_blob_type_to_info_type (entry->blob_type),
|
||||||
repository,
|
repository,
|
||||||
NULL, data.result_typelib, entry->offset);
|
NULL, result_typelib, entry->offset);
|
||||||
|
|
||||||
g_hash_table_insert (repository->info_by_gtype,
|
g_hash_table_insert (repository->info_by_gtype,
|
||||||
(gpointer) gtype,
|
(gpointer) gtype,
|
||||||
@ -1020,28 +1078,27 @@ gi_repository_find_by_name (GIRepository *repository,
|
|||||||
NULL, typelib, entry->offset);
|
NULL, typelib, entry->offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
static DirEntry *
|
||||||
GIRepository *repository;
|
find_by_error_domain (GPtrArray *ordered_typelibs,
|
||||||
GQuark domain;
|
GQuark target_domain,
|
||||||
|
GITypelib **out_typelib)
|
||||||
GITypelib *result_typelib;
|
|
||||||
DirEntry *result;
|
|
||||||
} FindByErrorDomainData;
|
|
||||||
|
|
||||||
static void
|
|
||||||
find_by_error_domain_foreach (gpointer key,
|
|
||||||
gpointer value,
|
|
||||||
gpointer datap)
|
|
||||||
{
|
{
|
||||||
GITypelib *typelib = (GITypelib*)value;
|
/* Search in reverse order as the longest namespaces will be listed last, and
|
||||||
FindByErrorDomainData *data = datap;
|
* those are the ones we want to search first. */
|
||||||
|
for (guint i = ordered_typelibs->len; i > 0; i--)
|
||||||
|
{
|
||||||
|
GITypelib *typelib = g_ptr_array_index (ordered_typelibs, i - 1);
|
||||||
|
DirEntry *entry;
|
||||||
|
|
||||||
if (data->result != NULL)
|
entry = gi_typelib_get_dir_entry_by_error_domain (typelib, target_domain);
|
||||||
return;
|
if (entry != NULL)
|
||||||
|
{
|
||||||
|
*out_typelib = typelib;
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
data->result = gi_typelib_get_dir_entry_by_error_domain (typelib, data->domain);
|
return NULL;
|
||||||
if (data->result)
|
|
||||||
data->result_typelib = typelib;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1064,8 +1121,9 @@ GIEnumInfo *
|
|||||||
gi_repository_find_by_error_domain (GIRepository *repository,
|
gi_repository_find_by_error_domain (GIRepository *repository,
|
||||||
GQuark domain)
|
GQuark domain)
|
||||||
{
|
{
|
||||||
FindByErrorDomainData data;
|
|
||||||
GIEnumInfo *cached;
|
GIEnumInfo *cached;
|
||||||
|
DirEntry *result = NULL;
|
||||||
|
GITypelib *result_typelib = NULL;
|
||||||
|
|
||||||
g_return_val_if_fail (GI_IS_REPOSITORY (repository), NULL);
|
g_return_val_if_fail (GI_IS_REPOSITORY (repository), NULL);
|
||||||
|
|
||||||
@ -1075,20 +1133,15 @@ gi_repository_find_by_error_domain (GIRepository *repository,
|
|||||||
if (cached != NULL)
|
if (cached != NULL)
|
||||||
return (GIEnumInfo *) gi_base_info_ref ((GIBaseInfo *)cached);
|
return (GIEnumInfo *) gi_base_info_ref ((GIBaseInfo *)cached);
|
||||||
|
|
||||||
data.repository = repository;
|
result = find_by_error_domain (repository->ordered_typelibs, domain, &result_typelib);
|
||||||
data.domain = domain;
|
if (result == NULL)
|
||||||
data.result_typelib = NULL;
|
result = find_by_error_domain (repository->ordered_lazy_typelibs, domain, &result_typelib);
|
||||||
data.result = NULL;
|
|
||||||
|
|
||||||
g_hash_table_foreach (repository->typelibs, find_by_error_domain_foreach, &data);
|
if (result != NULL)
|
||||||
if (data.result == NULL)
|
|
||||||
g_hash_table_foreach (repository->lazy_typelibs, find_by_error_domain_foreach, &data);
|
|
||||||
|
|
||||||
if (data.result != NULL)
|
|
||||||
{
|
{
|
||||||
cached = (GIEnumInfo *) gi_info_new_full (gi_typelib_blob_type_to_info_type (data.result->blob_type),
|
cached = (GIEnumInfo *) gi_info_new_full (gi_typelib_blob_type_to_info_type (result->blob_type),
|
||||||
repository,
|
repository,
|
||||||
NULL, data.result_typelib, data.result->offset);
|
NULL, result_typelib, result->offset);
|
||||||
|
|
||||||
g_hash_table_insert (repository->info_by_error_domain,
|
g_hash_table_insert (repository->info_by_error_domain,
|
||||||
GUINT_TO_POINTER (domain),
|
GUINT_TO_POINTER (domain),
|
||||||
@ -1179,13 +1232,16 @@ gi_repository_get_object_gtype_interfaces (GIRepository *repository,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
collect_namespaces (gpointer key,
|
collect_namespaces (GPtrArray *ordered_typelibs,
|
||||||
gpointer value,
|
char **names,
|
||||||
gpointer data)
|
size_t *inout_i)
|
||||||
{
|
{
|
||||||
GList **list = data;
|
for (guint j = 0; j < ordered_typelibs->len; j++)
|
||||||
|
{
|
||||||
*list = g_list_append (*list, key);
|
GITypelib *typelib = g_ptr_array_index (ordered_typelibs, j);
|
||||||
|
const char *namespace = gi_typelib_get_namespace (typelib);
|
||||||
|
names[(*inout_i)++] = g_strdup (namespace);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1207,20 +1263,18 @@ char **
|
|||||||
gi_repository_get_loaded_namespaces (GIRepository *repository,
|
gi_repository_get_loaded_namespaces (GIRepository *repository,
|
||||||
size_t *n_namespaces_out)
|
size_t *n_namespaces_out)
|
||||||
{
|
{
|
||||||
GList *l, *list = NULL;
|
|
||||||
char **names;
|
char **names;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
size_t n_typelibs;
|
||||||
|
|
||||||
g_return_val_if_fail (GI_IS_REPOSITORY (repository), NULL);
|
g_return_val_if_fail (GI_IS_REPOSITORY (repository), NULL);
|
||||||
|
|
||||||
g_hash_table_foreach (repository->typelibs, collect_namespaces, &list);
|
n_typelibs = repository->ordered_typelibs->len + repository->ordered_lazy_typelibs->len;
|
||||||
g_hash_table_foreach (repository->lazy_typelibs, collect_namespaces, &list);
|
names = g_malloc0 (sizeof (char *) * (n_typelibs + 1));
|
||||||
|
|
||||||
names = g_malloc0 (sizeof (char *) * (g_list_length (list) + 1));
|
|
||||||
i = 0;
|
i = 0;
|
||||||
for (l = list; l; l = l->next)
|
|
||||||
names[i++] = g_strdup (l->data);
|
collect_namespaces (repository->ordered_typelibs, names, &i);
|
||||||
g_list_free (list);
|
collect_namespaces (repository->ordered_lazy_typelibs, names, &i);
|
||||||
|
|
||||||
if (n_namespaces_out != NULL)
|
if (n_namespaces_out != NULL)
|
||||||
*n_namespaces_out = i;
|
*n_namespaces_out = i;
|
||||||
|
@ -316,7 +316,8 @@ strsplit_iter_next (StrSplitIter *iter,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_string_overwrite_len (&iter->buf, 0, s, (gssize)len);
|
g_string_overwrite_len (&iter->buf, 0, s, (gssize)len + 1);
|
||||||
|
iter->buf.str[len] = '\0';
|
||||||
*out_val = iter->buf.str;
|
*out_val = iter->buf.str;
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -261,6 +261,7 @@ if host_system == 'windows'
|
|||||||
'--identifier-prefix=GWin32'
|
'--identifier-prefix=GWin32'
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
gio_platform_gir = gio_win32_gir
|
||||||
else
|
else
|
||||||
gio_unix_gir_c_includes = []
|
gio_unix_gir_c_includes = []
|
||||||
foreach h: gio_unix_include_headers
|
foreach h: gio_unix_include_headers
|
||||||
@ -289,6 +290,7 @@ else
|
|||||||
'--identifier-prefix=GUnix'
|
'--identifier-prefix=GUnix'
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
gio_platform_gir = gio_unix_gir
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# GIRepository
|
# GIRepository
|
||||||
|
@ -29,6 +29,11 @@ if enable_gir
|
|||||||
gio_gir,
|
gio_gir,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
gio_platform_gir_testing_dep = [
|
||||||
|
gio_gir_testing_dep,
|
||||||
|
gio_platform_gir,
|
||||||
|
]
|
||||||
|
|
||||||
girepository_gir_testing_dep = [
|
girepository_gir_testing_dep = [
|
||||||
gio_gir_testing_dep,
|
gio_gir_testing_dep,
|
||||||
girepository_gir,
|
girepository_gir,
|
||||||
@ -46,7 +51,8 @@ if enable_gir
|
|||||||
'depends': gobject_gir_testing_dep,
|
'depends': gobject_gir_testing_dep,
|
||||||
},
|
},
|
||||||
'repository' : {
|
'repository' : {
|
||||||
'depends': gio_gir_testing_dep,
|
'depends': [gio_gir_testing_dep, gio_platform_gir_testing_dep],
|
||||||
|
'dependencies': [libgio_dep],
|
||||||
},
|
},
|
||||||
'repository-search-paths' : {
|
'repository-search-paths' : {
|
||||||
'c_args': '-DGOBJECT_INTROSPECTION_LIBDIR="@0@"'.format(glib_libdir),
|
'c_args': '-DGOBJECT_INTROSPECTION_LIBDIR="@0@"'.format(glib_libdir),
|
||||||
|
@ -35,6 +35,12 @@
|
|||||||
#include "glib.h"
|
#include "glib.h"
|
||||||
#include "test-common.h"
|
#include "test-common.h"
|
||||||
|
|
||||||
|
#if defined(G_OS_UNIX)
|
||||||
|
#include "gio/gdesktopappinfo.h"
|
||||||
|
#elif defined(G_OS_WIN32)
|
||||||
|
#include "gio/gwin32inputstream.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_repository_basic (RepositoryFixture *fx,
|
test_repository_basic (RepositoryFixture *fx,
|
||||||
const void *unused)
|
const void *unused)
|
||||||
@ -507,12 +513,31 @@ test_repository_error_quark (RepositoryFixture *fx,
|
|||||||
|
|
||||||
g_test_summary ("Test finding an error quark by error domain");
|
g_test_summary ("Test finding an error quark by error domain");
|
||||||
|
|
||||||
|
/* Find a simple error domain. */
|
||||||
error_info = gi_repository_find_by_error_domain (fx->repository, G_RESOLVER_ERROR);
|
error_info = gi_repository_find_by_error_domain (fx->repository, G_RESOLVER_ERROR);
|
||||||
g_assert_nonnull (error_info);
|
g_assert_nonnull (error_info);
|
||||||
g_assert_true (GI_IS_ENUM_INFO (error_info));
|
g_assert_true (GI_IS_ENUM_INFO (error_info));
|
||||||
g_assert_cmpstr (gi_base_info_get_name (GI_BASE_INFO (error_info)), ==, "ResolverError");
|
g_assert_cmpstr (gi_base_info_get_name (GI_BASE_INFO (error_info)), ==, "ResolverError");
|
||||||
|
|
||||||
g_clear_pointer (&error_info, gi_base_info_unref);
|
g_clear_pointer (&error_info, gi_base_info_unref);
|
||||||
|
|
||||||
|
/* Find again to check the caching. */
|
||||||
|
error_info = gi_repository_find_by_error_domain (fx->repository, G_RESOLVER_ERROR);
|
||||||
|
g_assert_nonnull (error_info);
|
||||||
|
g_assert_true (GI_IS_ENUM_INFO (error_info));
|
||||||
|
g_assert_cmpstr (gi_base_info_get_name (GI_BASE_INFO (error_info)), ==, "ResolverError");
|
||||||
|
|
||||||
|
g_clear_pointer (&error_info, gi_base_info_unref);
|
||||||
|
|
||||||
|
/* Try and find an unknown error domain. */
|
||||||
|
g_assert_null (gi_repository_find_by_error_domain (fx->repository, GI_REPOSITORY_ERROR));
|
||||||
|
|
||||||
|
/* And check caching for unknown error domains. */
|
||||||
|
g_assert_null (gi_repository_find_by_error_domain (fx->repository, GI_REPOSITORY_ERROR));
|
||||||
|
|
||||||
|
/* It would be good to try and find one which will resolve in both Gio and
|
||||||
|
* GioUnix/GioWin32, but neither of the platform-specific GIRs actually define
|
||||||
|
* any error domains at the moment. */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -777,6 +802,96 @@ test_repository_vfunc_info_with_invoker_on_object (RepositoryFixture *fx,
|
|||||||
g_clear_pointer (&invoker_info, gi_base_info_unref);
|
g_clear_pointer (&invoker_info, gi_base_info_unref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_repository_find_by_gtype (RepositoryFixture *fx,
|
||||||
|
const void *unused)
|
||||||
|
{
|
||||||
|
GIObjectInfo *object_info = NULL;
|
||||||
|
|
||||||
|
g_test_summary ("Test finding a GType");
|
||||||
|
|
||||||
|
object_info = (GIObjectInfo *) gi_repository_find_by_gtype (fx->repository, G_TYPE_OBJECT);
|
||||||
|
g_assert_nonnull (object_info);
|
||||||
|
g_assert_true (GI_IS_OBJECT_INFO (object_info));
|
||||||
|
g_assert_cmpstr (gi_base_info_get_name (GI_BASE_INFO (object_info)), ==, "Object");
|
||||||
|
|
||||||
|
g_clear_pointer (&object_info, gi_base_info_unref);
|
||||||
|
|
||||||
|
/* Find it again; this time it should hit the cache. */
|
||||||
|
object_info = (GIObjectInfo *) gi_repository_find_by_gtype (fx->repository, G_TYPE_OBJECT);
|
||||||
|
g_assert_nonnull (object_info);
|
||||||
|
g_assert_true (GI_IS_OBJECT_INFO (object_info));
|
||||||
|
g_assert_cmpstr (gi_base_info_get_name (GI_BASE_INFO (object_info)), ==, "Object");
|
||||||
|
|
||||||
|
g_clear_pointer (&object_info, gi_base_info_unref);
|
||||||
|
|
||||||
|
/* Try and find an unknown GType. */
|
||||||
|
g_assert_null (gi_repository_find_by_gtype (fx->repository, GI_TYPE_BASE_INFO));
|
||||||
|
|
||||||
|
/* And check caching for unknown GTypes. */
|
||||||
|
g_assert_null (gi_repository_find_by_gtype (fx->repository, GI_TYPE_BASE_INFO));
|
||||||
|
|
||||||
|
/* Now try and find one which will resolve in both Gio and GioUnix/GioWin32.
|
||||||
|
* The longest-named typelib should be returned. */
|
||||||
|
{
|
||||||
|
GType platform_specific_type;
|
||||||
|
const char *expected_name, *expected_namespace;
|
||||||
|
|
||||||
|
#if defined(G_OS_UNIX)
|
||||||
|
platform_specific_type = G_TYPE_DESKTOP_APP_INFO;
|
||||||
|
expected_name = "DesktopAppInfo";
|
||||||
|
expected_namespace = "GioUnix";
|
||||||
|
#elif defined(G_OS_WIN32)
|
||||||
|
platform_specific_type = G_TYPE_WIN32_INPUT_STREAM;
|
||||||
|
expected_name = "InputStream";
|
||||||
|
expected_namespace = "GioWin32";
|
||||||
|
#else
|
||||||
|
platform_specific_type = G_TYPE_INVALID;
|
||||||
|
expected_name = NULL;
|
||||||
|
expected_namespace = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (expected_name != NULL)
|
||||||
|
{
|
||||||
|
object_info = (GIObjectInfo *) gi_repository_find_by_gtype (fx->repository, platform_specific_type);
|
||||||
|
g_assert_nonnull (object_info);
|
||||||
|
g_assert_true (GI_IS_OBJECT_INFO (object_info));
|
||||||
|
g_assert_cmpstr (gi_base_info_get_name (GI_BASE_INFO (object_info)), ==, expected_name);
|
||||||
|
g_assert_cmpstr (gi_base_info_get_namespace (GI_BASE_INFO (object_info)), ==, expected_namespace);
|
||||||
|
g_clear_pointer (&object_info, gi_base_info_unref);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_repository_loaded_namespaces (RepositoryFixture *fx,
|
||||||
|
const void *unused)
|
||||||
|
{
|
||||||
|
char **namespaces;
|
||||||
|
size_t n_namespaces;
|
||||||
|
|
||||||
|
/* These should be in alphabetical order */
|
||||||
|
#if defined(G_OS_UNIX)
|
||||||
|
const char *expected_namespaces[] = { "GLib", "GModule", "GObject", "Gio", "GioUnix", NULL };
|
||||||
|
#elif defined(G_OS_WIN32)
|
||||||
|
const char *expected_namespaces[] = { "GLib", "GModule", "GObject", "Gio", "GioWin32", NULL };
|
||||||
|
#else
|
||||||
|
const char *expected_namespaces[] = { "GLib", "GModule", "GObject", "Gio", NULL };
|
||||||
|
#endif
|
||||||
|
|
||||||
|
g_test_summary ("Test listing loaded namespaces");
|
||||||
|
|
||||||
|
namespaces = gi_repository_get_loaded_namespaces (fx->repository, &n_namespaces);
|
||||||
|
g_assert_cmpstrv (namespaces, expected_namespaces);
|
||||||
|
g_assert_cmpuint (n_namespaces, ==, g_strv_length ((char **) expected_namespaces));
|
||||||
|
g_strfreev (namespaces);
|
||||||
|
|
||||||
|
/* Test again but without passing `n_namespaces`. */
|
||||||
|
namespaces = gi_repository_get_loaded_namespaces (fx->repository, NULL);
|
||||||
|
g_assert_cmpstrv (namespaces, expected_namespaces);
|
||||||
|
g_strfreev (namespaces);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int argc,
|
main (int argc,
|
||||||
char *argv[])
|
char *argv[])
|
||||||
@ -794,7 +909,7 @@ main (int argc,
|
|||||||
ADD_REPOSITORY_TEST ("/repository/constructor-return-type", test_repository_constructor_return_type, &typelib_load_spec_gobject);
|
ADD_REPOSITORY_TEST ("/repository/constructor-return-type", test_repository_constructor_return_type, &typelib_load_spec_gobject);
|
||||||
ADD_REPOSITORY_TEST ("/repository/enum-info-c-identifier", test_repository_enum_info_c_identifier, &typelib_load_spec_glib);
|
ADD_REPOSITORY_TEST ("/repository/enum-info-c-identifier", test_repository_enum_info_c_identifier, &typelib_load_spec_glib);
|
||||||
ADD_REPOSITORY_TEST ("/repository/enum-info-static-methods", test_repository_enum_info_static_methods, &typelib_load_spec_glib);
|
ADD_REPOSITORY_TEST ("/repository/enum-info-static-methods", test_repository_enum_info_static_methods, &typelib_load_spec_glib);
|
||||||
ADD_REPOSITORY_TEST ("/repository/error-quark", test_repository_error_quark, &typelib_load_spec_gio);
|
ADD_REPOSITORY_TEST ("/repository/error-quark", test_repository_error_quark, &typelib_load_spec_gio_platform);
|
||||||
ADD_REPOSITORY_TEST ("/repository/flags-info-c-identifier", test_repository_flags_info_c_identifier, &typelib_load_spec_gobject);
|
ADD_REPOSITORY_TEST ("/repository/flags-info-c-identifier", test_repository_flags_info_c_identifier, &typelib_load_spec_gobject);
|
||||||
ADD_REPOSITORY_TEST ("/repository/fundamental-ref-func", test_repository_fundamental_ref_func, &typelib_load_spec_gobject);
|
ADD_REPOSITORY_TEST ("/repository/fundamental-ref-func", test_repository_fundamental_ref_func, &typelib_load_spec_gobject);
|
||||||
ADD_REPOSITORY_TEST ("/repository/instance-method-ownership-transfer", test_repository_instance_method_ownership_transfer, &typelib_load_spec_gio);
|
ADD_REPOSITORY_TEST ("/repository/instance-method-ownership-transfer", test_repository_instance_method_ownership_transfer, &typelib_load_spec_gio);
|
||||||
@ -804,6 +919,8 @@ main (int argc,
|
|||||||
ADD_REPOSITORY_TEST ("/repository/vfunc-info-with-no-invoker", test_repository_vfunc_info_with_no_invoker, &typelib_load_spec_gobject);
|
ADD_REPOSITORY_TEST ("/repository/vfunc-info-with-no-invoker", test_repository_vfunc_info_with_no_invoker, &typelib_load_spec_gobject);
|
||||||
ADD_REPOSITORY_TEST ("/repository/vfunc-info-with-invoker-on-interface", test_repository_vfunc_info_with_invoker_on_interface, &typelib_load_spec_gio);
|
ADD_REPOSITORY_TEST ("/repository/vfunc-info-with-invoker-on-interface", test_repository_vfunc_info_with_invoker_on_interface, &typelib_load_spec_gio);
|
||||||
ADD_REPOSITORY_TEST ("/repository/vfunc-info-with-invoker-on-object", test_repository_vfunc_info_with_invoker_on_object, &typelib_load_spec_gio);
|
ADD_REPOSITORY_TEST ("/repository/vfunc-info-with-invoker-on-object", test_repository_vfunc_info_with_invoker_on_object, &typelib_load_spec_gio);
|
||||||
|
ADD_REPOSITORY_TEST ("/repository/find-by-gtype", test_repository_find_by_gtype, &typelib_load_spec_gio_platform);
|
||||||
|
ADD_REPOSITORY_TEST ("/repository/loaded-namespaces", test_repository_loaded_namespaces, &typelib_load_spec_gio_platform);
|
||||||
|
|
||||||
return g_test_run ();
|
return g_test_run ();
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,11 @@ typedef struct
|
|||||||
static const TypelibLoadSpec typelib_load_spec_glib = { "GLib", "2.0" };
|
static const TypelibLoadSpec typelib_load_spec_glib = { "GLib", "2.0" };
|
||||||
static const TypelibLoadSpec typelib_load_spec_gobject = { "GObject", "2.0" };
|
static const TypelibLoadSpec typelib_load_spec_gobject = { "GObject", "2.0" };
|
||||||
static const TypelibLoadSpec typelib_load_spec_gio = { "Gio", "2.0" };
|
static const TypelibLoadSpec typelib_load_spec_gio = { "Gio", "2.0" };
|
||||||
|
#if defined(G_OS_UNIX)
|
||||||
|
static const TypelibLoadSpec typelib_load_spec_gio_platform = { "GioUnix", "2.0" };
|
||||||
|
#elif defined(G_OS_WIN32)
|
||||||
|
static const TypelibLoadSpec typelib_load_spec_gio_platform = { "GioWin32", "2.0" };
|
||||||
|
#endif
|
||||||
|
|
||||||
void repository_init (int *argc,
|
void repository_init (int *argc,
|
||||||
char **argv[]);
|
char **argv[]);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user