forked from Mirrors/flatpak-builder
Add appdata-license field
This lets you modify the project_license field in the appdata file. This is useful because appdata files from upstream generally only contain license information for the app itself, whereas the bundled app may contain other code with additional licenses. Closes: #41 Approved by: alexlarssontingping/wmclass
parent
14df2dfc9a
commit
9f3e786c29
|
@ -93,7 +93,7 @@ AC_CHECK_FUNCS(fdwalk)
|
|||
AC_CHECK_HEADER([sys/xattr.h], [], [AC_MSG_ERROR([You must have sys/xattr.h from glibc])])
|
||||
AC_CHECK_HEADER([sys/capability.h], have_caps=yes, [AC_MSG_ERROR([sys/capability.h header not found])])
|
||||
|
||||
PKG_CHECK_MODULES(BASE, [glib-2.0 >= $GLIB_REQS gio-2.0 gio-unix-2.0 libsoup-2.4 ostree-1 >= $OSTREE_REQS json-glib-1.0])
|
||||
PKG_CHECK_MODULES(BASE, [glib-2.0 >= $GLIB_REQS gio-2.0 gio-unix-2.0 libsoup-2.4 ostree-1 >= $OSTREE_REQS json-glib-1.0 libxml-2.0 >= 2.4])
|
||||
|
||||
dnl ************************
|
||||
dnl *** check for libelf ***
|
||||
|
|
|
@ -207,6 +207,15 @@
|
|||
<term><option>rename-icon</option> (string)</term>
|
||||
<listitem><para>Any icon with this name will be renamed to a name based on id during the cleanup phase. Note that this is the icon name, not the full filenames, so it should not include a filename extension. </para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>appdata-license</option> (string)</term>
|
||||
<listitem><para>Replace the appdata
|
||||
project_license field with this string. This is
|
||||
useful as the upstream license is typically only
|
||||
about the application itself, whereas the bundled
|
||||
app can contain other licenses
|
||||
too. </para></listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>copy-icon</option> (boolean)</term>
|
||||
<listitem><para>If rename-icon is set, keep a copy of the old icon file.</para></listitem>
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
#include "builder-post-process.h"
|
||||
#include "builder-extension.h"
|
||||
|
||||
#include <libxml/parser.h>
|
||||
|
||||
#include "libglnx/libglnx.h"
|
||||
|
||||
#define LOCALES_SEPARATE_DIR "share/runtime/locale"
|
||||
|
@ -83,6 +85,7 @@ struct BuilderManifest
|
|||
char **tags;
|
||||
char *rename_desktop_file;
|
||||
char *rename_appdata_file;
|
||||
char *appdata_license;
|
||||
char *rename_icon;
|
||||
gboolean copy_icon;
|
||||
char *desktop_file_name_prefix;
|
||||
|
@ -147,6 +150,7 @@ enum {
|
|||
PROP_TAGS,
|
||||
PROP_RENAME_DESKTOP_FILE,
|
||||
PROP_RENAME_APPDATA_FILE,
|
||||
PROP_APPDATA_LICENSE,
|
||||
PROP_RENAME_ICON,
|
||||
PROP_COPY_ICON,
|
||||
PROP_DESKTOP_FILE_NAME_PREFIX,
|
||||
|
@ -189,6 +193,7 @@ builder_manifest_finalize (GObject *object)
|
|||
g_strfreev (self->tags);
|
||||
g_free (self->rename_desktop_file);
|
||||
g_free (self->rename_appdata_file);
|
||||
g_free (self->appdata_license);
|
||||
g_free (self->rename_icon);
|
||||
g_free (self->desktop_file_name_prefix);
|
||||
g_free (self->desktop_file_name_suffix);
|
||||
|
@ -399,6 +404,10 @@ builder_manifest_get_property (GObject *object,
|
|||
g_value_set_string (value, self->rename_appdata_file);
|
||||
break;
|
||||
|
||||
case PROP_APPDATA_LICENSE:
|
||||
g_value_set_string (value, self->appdata_license);
|
||||
break;
|
||||
|
||||
case PROP_RENAME_ICON:
|
||||
g_value_set_string (value, self->rename_icon);
|
||||
break;
|
||||
|
@ -621,6 +630,11 @@ builder_manifest_set_property (GObject *object,
|
|||
self->rename_appdata_file = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_APPDATA_LICENSE:
|
||||
g_free (self->appdata_license);
|
||||
self->appdata_license = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_RENAME_ICON:
|
||||
g_free (self->rename_icon);
|
||||
self->rename_icon = g_value_dup_string (value);
|
||||
|
@ -905,6 +919,13 @@ builder_manifest_class_init (BuilderManifestClass *klass)
|
|||
"",
|
||||
NULL,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_APPDATA_LICENSE,
|
||||
g_param_spec_string ("appdata-license",
|
||||
"",
|
||||
"",
|
||||
NULL,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_RENAME_ICON,
|
||||
g_param_spec_string ("rename-icon",
|
||||
|
@ -1543,6 +1564,7 @@ builder_manifest_checksum_for_cleanup (BuilderManifest *self,
|
|||
builder_cache_checksum_strv (cache, self->cleanup_commands);
|
||||
builder_cache_checksum_str (cache, self->rename_desktop_file);
|
||||
builder_cache_checksum_str (cache, self->rename_appdata_file);
|
||||
builder_cache_checksum_compat_str (cache, self->appdata_license);
|
||||
builder_cache_checksum_str (cache, self->rename_icon);
|
||||
builder_cache_checksum_boolean (cache, self->copy_icon);
|
||||
builder_cache_checksum_str (cache, self->desktop_file_name_prefix);
|
||||
|
@ -2028,6 +2050,62 @@ strcatv (char **strv1,
|
|||
return retval;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
rewrite_appdata (GFile *file,
|
||||
const char *license,
|
||||
GError **error)
|
||||
{
|
||||
g_autofree gchar *data = NULL;
|
||||
gsize data_len;
|
||||
g_autoptr(xmlDoc) doc = NULL;
|
||||
xml_autofree xmlChar *xmlbuff = NULL;
|
||||
int buffersize;
|
||||
xmlNode *root_element, *component_node;
|
||||
|
||||
if (!g_file_load_contents (file, NULL, &data, &data_len, NULL, error))
|
||||
return FALSE;
|
||||
|
||||
doc = xmlReadMemory (data, data_len, NULL, NULL, 0);
|
||||
if (doc == NULL)
|
||||
return flatpak_fail (error, _("Error parsing appstream"));
|
||||
|
||||
root_element = xmlDocGetRootElement (doc);
|
||||
|
||||
for (component_node = root_element; component_node; component_node = component_node->next)
|
||||
{
|
||||
xmlNode *sub_node = NULL;
|
||||
xmlNode *license_node = NULL;
|
||||
|
||||
if (component_node->type != XML_ELEMENT_NODE ||
|
||||
strcmp ((char *)component_node->name, "component") != 0)
|
||||
continue;
|
||||
|
||||
for (sub_node = component_node->children; sub_node; sub_node = sub_node->next)
|
||||
{
|
||||
if (sub_node->type != XML_ELEMENT_NODE ||
|
||||
strcmp ((char *)sub_node->name, "project_license") != 0)
|
||||
continue;
|
||||
|
||||
license_node = sub_node;
|
||||
break;
|
||||
}
|
||||
|
||||
if (license_node)
|
||||
xmlNodeSetContent(license_node, (xmlChar *)license);
|
||||
else
|
||||
xmlNewChild(component_node, NULL, (xmlChar *)"project_license", (xmlChar *)license);
|
||||
}
|
||||
|
||||
xmlDocDumpFormatMemory (doc, &xmlbuff, &buffersize, 1);
|
||||
|
||||
if (!g_file_set_contents (flatpak_file_get_path_cached (file),
|
||||
(gchar *)xmlbuff, buffersize,
|
||||
error))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
builder_manifest_cleanup (BuilderManifest *self,
|
||||
BuilderCache *cache,
|
||||
|
@ -2120,6 +2198,12 @@ builder_manifest_cleanup (BuilderManifest *self,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (self->appdata_license != NULL && self->appdata_license[0] != 0)
|
||||
{
|
||||
if (!rewrite_appdata (appdata_file, self->appdata_license, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (self->rename_desktop_file != NULL)
|
||||
{
|
||||
g_autoptr(GFile) applications_dir = g_file_resolve_relative_path (app_root, "share/applications");
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include <libsoup/soup.h>
|
||||
#include <json-glib/json-glib.h>
|
||||
|
||||
#include <libxml/tree.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct BuilderUtils BuilderUtils;
|
||||
|
@ -75,6 +77,18 @@ GParamSpec * builder_serializable_find_property_with_error (JsonSerializable *se
|
|||
void builder_set_term_title (const gchar *format,
|
||||
...) G_GNUC_PRINTF (1, 2);
|
||||
|
||||
static inline void
|
||||
xml_autoptr_cleanup_generic_free (void *p)
|
||||
{
|
||||
void **pp = (void**)p;
|
||||
if (*pp)
|
||||
xmlFree (*pp);
|
||||
}
|
||||
|
||||
#define xml_autofree _GLIB_CLEANUP(xml_autoptr_cleanup_generic_free)
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (xmlDoc, xmlFreeDoc)
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __BUILDER_UTILS_H__ */
|
||||
|
|
Loading…
Reference in New Issue