Commit 6ef31828 authored by Christoph Reiter's avatar Christoph Reiter 🐍

windows: rework loaders cache relocation support

Relocation works by recognizing paths in the loaders cache
which start with the built time prefix and extract the relative
path from that.

This leads to the following problem when updating the cache:

In case the package is build on another machine one has to
either match the build directory layout or adjust the
cache by hand for the resulting cache to stay relocatable.

This commonly occurs with msys2 where mostly pre-build packages
are used which are built on another machine and the cache gets
generated at install time. Another case is updating the cache
in a separate deployment environment.

This patch takes the package installation directory as a base
and writes relative paths into the cache when relocation
is enabled. When loading the cache a relative path is made
absolute by prepending the package base again.

https://bugzilla.gnome.org/show_bug.cgi?id=776081
parent 12aa6f92
......@@ -347,34 +347,24 @@ get_libdir (void)
#undef GDK_PIXBUF_LIBDIR
#define GDK_PIXBUF_LIBDIR get_libdir()
static void
correct_prefix (gchar **path)
#endif /* GDK_PIXBUF_RELOCATABLE */
/* In case we have a relative module path in the loaders cache
* prepend the toplevel dir */
static gchar *
build_module_path (const gchar *path)
{
if (strncmp (*path, GDK_PIXBUF_PREFIX "/", strlen (GDK_PIXBUF_PREFIX "/")) == 0 ||
strncmp (*path, GDK_PIXBUF_PREFIX "\\", strlen (GDK_PIXBUF_PREFIX "\\")) == 0)
{
gchar *tem = NULL;
if (g_str_has_suffix (*path, ".libs"))
{
/* We are being run from inside the build tree, and shouldn't mess about. */
return;
#ifdef GDK_PIXBUF_RELOCATABLE
if (g_path_is_absolute (path)) {
return g_strdup (path);
} else {
return g_build_filename (gdk_pixbuf_get_toplevel (), path, NULL);
}
/* This is an entry put there by gdk-pixbuf-query-loaders on the
* packager's system. On Windows a prebuilt gdk-pixbuf package can be
* installed in a random location. The loaders.cache file
* distributed in such a package contains paths from the package
* builder's machine. Replace the build-time prefix with the
* installation prefix on this machine.
*/
tem = *path;
*path = g_strconcat (gdk_pixbuf_get_toplevel (), tem + strlen (GDK_PIXBUF_PREFIX), NULL);
g_free (tem);
}
#else
return g_strdup (path);
#endif
}
#endif /* GDK_PIXBUF_RELOCATABLE */
static gchar *
gdk_pixbuf_get_module_file (void)
{
......@@ -512,9 +502,6 @@ gdk_pixbuf_io_init (void)
/* Blank line marking the end of a module
*/
if (module && *p != '#') {
#ifdef GDK_PIXBUF_RELOCATABLE
correct_prefix (&module->module_path);
#endif
file_formats = g_slist_prepend (file_formats, module);
module = NULL;
}
......@@ -536,7 +523,7 @@ gdk_pixbuf_io_init (void)
filename, line_buf);
have_error = TRUE;
}
module->module_path = g_strdup (tmp_buf->str);
module->module_path = build_module_path (tmp_buf->str);
}
else if (!module->module_name) {
module->info = g_new0 (GdkPixbufFormat, 1);
......
......@@ -116,14 +116,80 @@ loader_sanity_check (const char *path, GdkPixbufFormat *info, GdkPixbufModule *v
return 0;
}
#ifdef GDK_PIXBUF_RELOCATABLE
/* Based on gdk_pixbuf_get_toplevel () */
static gchar *
get_toplevel (void)
{
static gchar *toplevel = NULL;
if (toplevel == NULL) {
#if defined (G_OS_WIN32)
toplevel = g_win32_get_package_installation_directory_of_module (NULL);
#elif defined(OS_DARWIN)
char pathbuf[PATH_MAX + 1];
uint32_t bufsize = sizeof (pathbuf);
gchar *bin_dir;
_NSGetExecutablePath (pathbuf, &bufsize);
bin_dir = g_dirname (pathbuf);
toplevel = g_build_path (G_DIR_SEPARATOR_S, bin_dir, "..", NULL);
g_free (bin_dir);
#elif defined (OS_LINUX) || defined (__MINGW32__)
gchar *exe_path, *bin_dir;
exe_path = g_file_read_link ("/proc/self/exe", NULL);
bin_dir = g_dirname (exe_path);
toplevel = g_build_path (G_DIR_SEPARATOR_S, bin_dir, "..", NULL);
g_free (exe_path);
g_free (bin_dir);
#else
#error "Relocations not supported for this platform"
#endif
}
return toplevel;
}
/* Returns the relative path or NULL; transfer full */
static gchar *
get_relative_path (const gchar *parent, const gchar *descendant)
{
GFile *parent_file, *descendant_file;
char *relative_path;
parent_file = g_file_new_for_path (parent);
descendant_file = g_file_new_for_path (descendant);
relative_path = g_file_get_relative_path (parent_file, descendant_file);
g_object_unref (parent_file);
g_object_unref (descendant_file);
return relative_path;
}
#endif /* GDK_PIXBUF_RELOCATABLE */
static void
write_loader_info (GString *contents, const char *path, GdkPixbufFormat *info)
{
const GdkPixbufModulePattern *pattern;
char **mime;
char **ext;
gchar *module_path = NULL, *escaped_path;
#ifdef GDK_PIXBUF_RELOCATABLE
module_path = get_relative_path (get_toplevel (), path);
#endif
if (module_path == NULL) {
module_path = g_strdup (path);
}
escaped_path = g_strescape (module_path, "");
g_string_append_printf (contents, "\"%s\"\n", escaped_path);
g_free (module_path);
g_free (escaped_path);
g_string_append_printf (contents, "\"%s\"\n", path);
g_string_append_printf (contents, "\"%s\" %u \"%s\" \"%s\" \"%s\"\n",
info->name,
info->flags,
......@@ -212,17 +278,6 @@ query_module (GString *contents, const char *dir, const char *file)
#ifdef G_OS_WIN32
static char *
get_toplevel (void)
{
static char *toplevel = NULL;
if (toplevel == NULL)
toplevel = g_win32_get_package_installation_directory_of_module (NULL);
return toplevel;
}
static char *
get_libdir (void)
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment