summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2016-01-21 17:00:27 +0100
committerRichard Hughes <richard@hughsie.com>2016-01-22 11:56:15 +0000
commit688ce88229a1aaf9d285e6d8859e006fe4dfde2a (patch)
treec8ffdbee46312aae75da1c95ed56f87dc2640a9f
parent8f4e1688529b1bdc364937004e68b165103302a0 (diff)
downloadappstream-glib-688ce88229a1aaf9d285e6d8859e006fe4dfde2a.tar.gz
Add appstream-compose
This is a simple app that takes a prefix (default /usr) and a set of app names. It looks for appdata, desktop and icon files with that basename in $prefix/share/[appdata|applications|icons] and generates appstream xml files + icons in (by default) $prefix/share/app-info.
-rw-r--r--client/Makefile.am13
-rw-r--r--client/as-compose.c490
-rw-r--r--contrib/libappstream-glib.spec.in2
-rw-r--r--data/Makefile.am6
-rw-r--r--data/appstream-compose.xml58
-rw-r--r--libappstream-glib/as-utils.c2
-rw-r--r--po/POTFILES.in1
7 files changed, 570 insertions, 2 deletions
diff --git a/client/Makefile.am b/client/Makefile.am
index dc04134..8777c11 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -21,6 +21,7 @@ AS_BUILDER_LIBS = \
$(top_builddir)/libappstream-builder/libappstream-builder.la
bin_PROGRAMS = \
+ appstream-compose \
appstream-util
if HAVE_BUILDER
@@ -57,4 +58,16 @@ appstream_builder_CFLAGS = \
$(WARNINGFLAGS_C)
endif
+appstream_compose_SOURCES = \
+ as-compose.c
+appstream_compose_LDADD = \
+ $(AS_GLIB_LIBS) \
+ $(GLIB_LIBS) \
+ $(SOUP_LIBS) \
+ $(LIBARCHIVE_LIBS)
+appstream_compose_LDFLAGS = \
+ $(PIE_LDFLAGS)
+appstream_compose_CFLAGS = \
+ $(WARNINGFLAGS_C)
+
-include $(top_srcdir)/git.mk
diff --git a/client/as-compose.c b/client/as-compose.c
new file mode 100644
index 0000000..6bca881
--- /dev/null
+++ b/client/as-compose.c
@@ -0,0 +1,490 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2014-2015 Richard Hughes <richard@hughsie.com>
+ * Copyright (C) 2016 Alexander Larsson <alexl@redhat.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+
+#include <appstream-glib.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <stdlib.h>
+#include <locale.h>
+#include <errno.h>
+
+/**
+ * as_util_app_log:
+ **/
+G_GNUC_PRINTF (2, 3)
+static void
+as_compose_app_log (AsApp *app, const gchar *fmt, ...)
+{
+ const gchar *id;
+ guint i;
+ va_list args;
+ g_autofree gchar *tmp = NULL;
+
+ va_start (args, fmt);
+ tmp = g_strdup_vprintf (fmt, args);
+ va_end (args);
+
+ /* print status */
+ id = as_app_get_id (app);
+ g_print ("%s: ", id);
+ for (i = strlen (id) + 2; i < 35; i++)
+ g_print (" ");
+ g_print ("%s\n", tmp);
+}
+
+static gboolean
+add_icons (AsApp *app,
+ const gchar *icons_dir,
+ guint min_icon_size,
+ const gchar *prefix,
+ const gchar *key,
+ GError **error)
+{
+ g_autofree gchar *fn_hidpi = NULL;
+ g_autofree gchar *fn = NULL;
+ g_autofree gchar *name_hidpi = NULL;
+ g_autofree gchar *name = NULL;
+ g_autofree gchar *icon_path = NULL;
+ g_autofree gchar *icon_subdir = NULL;
+ g_autofree gchar *icon_path_hidpi = NULL;
+ g_autofree gchar *icon_subdir_hidpi = NULL;
+ g_autoptr(AsIcon) icon_hidpi = NULL;
+ g_autoptr(AsIcon) icon = NULL;
+ g_autoptr(AsImage) im = NULL;
+ g_autoptr(GdkPixbuf) pixbuf_hidpi = NULL;
+ g_autoptr(GdkPixbuf) pixbuf = NULL;
+
+ /* find 64x64 icon */
+ fn = as_utils_find_icon_filename_full (prefix, key,
+ AS_UTILS_FIND_ICON_NONE,
+ error);
+ if (fn == NULL) {
+ g_prefix_error (error, "Failed to find icon: ");
+ return FALSE;
+ }
+
+ /* load the icon */
+ im = as_image_new ();
+ if (!as_image_load_filename_full (im, fn,
+ 64, min_icon_size,
+ AS_IMAGE_LOAD_FLAG_SHARPEN,
+ error)) {
+ g_prefix_error (error, "Failed to load icon: ");
+ return FALSE;
+ }
+ pixbuf = g_object_ref (as_image_get_pixbuf (im));
+
+ /* save in target directory */
+ name = g_strdup_printf ("%ix%i/%s.png",
+ 64, 64,
+ as_app_get_id_filename (AS_APP (app)));
+
+ icon = as_icon_new ();
+ as_icon_set_pixbuf (icon, pixbuf);
+ as_icon_set_name (icon, name);
+ as_icon_set_kind (icon, AS_ICON_KIND_CACHED);
+ as_icon_set_prefix (icon, as_app_get_icon_path (AS_APP (app)));
+ as_app_add_icon (AS_APP (app), icon);
+
+ icon_path = g_build_filename (icons_dir, name, NULL);
+
+ icon_subdir = g_path_get_dirname (icon_path);
+ if (g_mkdir_with_parents (icon_subdir, 0755)) {
+ int errsv = errno;
+ g_set_error (error,
+ AS_APP_ERROR,
+ AS_APP_ERROR_FAILED,
+ "failed to create %s: %s",
+ icon_subdir,
+ strerror (errsv));
+ return FALSE;
+ }
+
+ /* TRANSLATORS: we've saving the icon file to disk */
+ g_print ("%s %s\n", _("Saving icon"), icon_path);
+ if (!gdk_pixbuf_save (pixbuf, icon_path, "png", error, NULL))
+ return FALSE;
+
+ /* try to get a HiDPI icon */
+ fn_hidpi = as_utils_find_icon_filename_full (prefix, key,
+ AS_UTILS_FIND_ICON_HI_DPI,
+ NULL);
+ if (fn_hidpi == NULL)
+ return TRUE;
+
+ /* load the HiDPI icon */
+ if (!as_image_load_filename_full (im, fn,
+ 128, 128,
+ AS_IMAGE_LOAD_FLAG_SHARPEN,
+ NULL)) {
+ return TRUE;
+ }
+ pixbuf_hidpi = g_object_ref (as_image_get_pixbuf (im));
+ if (gdk_pixbuf_get_width (pixbuf_hidpi) <= gdk_pixbuf_get_width (pixbuf) ||
+ gdk_pixbuf_get_height (pixbuf_hidpi) <= gdk_pixbuf_get_height (pixbuf))
+ return TRUE;
+ as_app_add_kudo_kind (AS_APP (app), AS_KUDO_KIND_HI_DPI_ICON);
+
+ /* save icon */
+ name_hidpi = g_strdup_printf ("%ix%i/%s.png",
+ 128, 128,
+ as_app_get_id_filename (AS_APP (app)));
+ icon_hidpi = as_icon_new ();
+ as_icon_set_pixbuf (icon_hidpi, pixbuf_hidpi);
+ as_icon_set_name (icon_hidpi, name_hidpi);
+ as_icon_set_kind (icon_hidpi, AS_ICON_KIND_CACHED);
+ as_icon_set_prefix (icon_hidpi, as_app_get_icon_path (AS_APP (app)));
+ as_app_add_icon (AS_APP (app), icon_hidpi);
+
+ icon_path_hidpi = g_build_filename (icons_dir, name_hidpi, NULL);
+ icon_subdir_hidpi = g_path_get_dirname (icon_path_hidpi);
+ if (g_mkdir_with_parents (icon_subdir_hidpi, 0755)) {
+ int errsv = errno;
+ g_set_error (error,
+ AS_APP_ERROR,
+ AS_APP_ERROR_FAILED,
+ "failed to create %s: %s",
+ icon_subdir_hidpi,
+ strerror (errsv));
+ return FALSE;
+ }
+
+ /* TRANSLATORS: we've saving the icon file to disk */
+ g_print ("%s %s\n", _("Saving icon"), icon_path_hidpi);
+ if (!gdk_pixbuf_save (pixbuf_hidpi, icon_path_hidpi, "png", error, NULL))
+ return FALSE;
+ return TRUE;
+}
+
+static AsApp *
+load_desktop (const gchar *prefix,
+ const gchar *icons_dir,
+ guint min_icon_size,
+ const gchar *app_name,
+ const gchar *appdata_id,
+ GError **error)
+{
+ AsIcon *icon;
+ g_autofree gchar *desktop_basename = NULL;
+ g_autofree gchar *desktop_path = NULL;
+ g_autoptr(AsApp) app = NULL;
+
+ if (appdata_id != NULL)
+ desktop_basename = g_strdup (appdata_id);
+ else
+ desktop_basename = g_strconcat (app_name, ".desktop", NULL);
+ desktop_path = g_build_filename (prefix, "share/applications", desktop_basename, NULL);
+
+ app = as_app_new ();
+ if (!as_app_parse_file (app, desktop_path,
+ AS_APP_PARSE_FLAG_USE_HEURISTICS |
+ AS_APP_PARSE_FLAG_ALLOW_VETO,
+ error))
+ return NULL;
+ if (as_app_get_id_kind (app) == AS_ID_KIND_UNKNOWN) {
+ g_set_error (error,
+ AS_APP_ERROR,
+ AS_APP_ERROR_FAILED,
+ "%s has no recognised type",
+ as_app_get_id (AS_APP (app)));
+ return NULL;
+ }
+
+ icon = as_app_get_icon_default (AS_APP (app));
+ if (icon != NULL) {
+ g_autofree gchar *key = NULL;
+ key = g_strdup (as_icon_get_name (icon));
+ if (as_icon_get_kind (icon) == AS_ICON_KIND_STOCK) {
+ as_compose_app_log (app,
+ "using stock icon %s", key);
+ } else {
+ g_autoptr(GError) error_local = NULL;
+ gboolean ret;
+
+ g_ptr_array_set_size (as_app_get_icons (AS_APP (app)), 0);
+ ret = add_icons (app,
+ icons_dir,
+ min_icon_size,
+ prefix,
+ key,
+ error);
+ if (!ret)
+ return NULL;
+ }
+ }
+
+ return g_steal_pointer (&app);
+}
+
+static AsApp *
+load_appdata (const gchar *prefix, const gchar *app_name, GError **error)
+{
+ g_autofree gchar *appdata_basename = NULL;
+ g_autofree gchar *appdata_path = NULL;
+ g_autoptr(AsApp) app = NULL;
+ g_autoptr(GPtrArray) problems = NULL;
+ AsProblemKind problem_kind;
+ AsProblem *problem;
+ guint i;
+
+ appdata_basename = g_strconcat (app_name,
+ ".appdata.xml",
+ NULL);
+ appdata_path = g_build_filename (prefix,
+ "share",
+ "appdata",
+ appdata_basename,
+ NULL);
+ g_debug ("Looking for %s", appdata_path);
+
+ app = as_app_new ();
+ if (!as_app_parse_file (app, appdata_path,
+ AS_APP_PARSE_FLAG_NONE,
+ error))
+ return NULL;
+ if (as_app_get_id_kind (app) == AS_ID_KIND_UNKNOWN) {
+ g_set_error (error,
+ AS_APP_ERROR,
+ AS_APP_ERROR_FAILED,
+ "%s has no recognised type",
+ as_app_get_id (AS_APP (app)));
+ return NULL;
+ }
+
+ problems = as_app_validate (app,
+ AS_APP_VALIDATE_FLAG_NO_NETWORK |
+ AS_APP_VALIDATE_FLAG_RELAX,
+ error);
+ if (problems == NULL)
+ return NULL;
+ for (i = 0; i < problems->len; i++) {
+ problem = g_ptr_array_index (problems, i);
+ problem_kind = as_problem_get_kind (problem);
+ as_compose_app_log (app,
+ "AppData problem: %s : %s",
+ as_problem_kind_to_string (problem_kind),
+ as_problem_get_message (problem));
+ }
+ if (problems->len > 0) {
+ g_set_error (error,
+ AS_APP_ERROR,
+ AS_APP_ERROR_FAILED,
+ "AppData file %s was not valid",
+ appdata_path);
+ return NULL;
+ }
+
+ return g_steal_pointer (&app);
+}
+
+/**
+ * main:
+ **/
+int
+main (int argc, char **argv)
+{
+ g_autoptr(GOptionContext) option_context = NULL;
+ gboolean ret;
+ gboolean verbose = FALSE;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *basename = NULL;
+ g_autofree gchar *icons_dir = NULL;
+ g_autofree gchar *origin = NULL;
+ g_autofree gchar *xml_basename = NULL;
+ g_autofree gchar *output_dir = NULL;
+ g_autofree gchar *prefix = NULL;
+ g_autoptr(AsStore) store = NULL;
+ g_autoptr(GFile) xml_dir = NULL;
+ g_autoptr(GFile) xml_file = NULL;
+ gint min_icon_size = 32;
+ gdouble api_version = 0.0f;
+ guint i;
+ const GOptionEntry options[] = {
+ { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
+ /* TRANSLATORS: command line option */
+ _("Show extra debugging information"), NULL },
+ { "prefix", '\0', 0, G_OPTION_ARG_FILENAME, &prefix,
+ /* TRANSLATORS: command line option */
+ _("Set the prefix"), "DIR" },
+ { "output-dir", '\0', 0, G_OPTION_ARG_FILENAME, &output_dir,
+ /* TRANSLATORS: command line option */
+ _("Set the output directory"), "DIR" },
+ { "icons-dir", '\0', 0, G_OPTION_ARG_FILENAME, &icons_dir,
+ /* TRANSLATORS: command line option */
+ _("Set the icons directory"), "DIR" },
+ { "origin", '\0', 0, G_OPTION_ARG_STRING, &origin,
+ /* TRANSLATORS: command line option */
+ _("Set the origin name"), "NAME" },
+ { "min-icon-size", '\0', 0, G_OPTION_ARG_INT, &min_icon_size,
+ /* TRANSLATORS: command line option */
+ _("Set the minimum icon size in pixels"), "ICON_SIZE" },
+ { "basename", '\0', 0, G_OPTION_ARG_STRING, &basename,
+ /* TRANSLATORS: command line option */
+ _("Set the basenames of the output files"), "NAME" },
+ { "api-version", '\0', 0, G_OPTION_ARG_DOUBLE, &api_version,
+ /* TRANSLATORS: command line option */
+ _("Set the AppStream version"), "API_VERSION" },
+ { NULL}
+ };
+
+ setlocale (LC_ALL, "");
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+ textdomain (GETTEXT_PACKAGE);
+ option_context = g_option_context_new (" - APP-IDS");
+
+ g_option_context_add_main_entries (option_context, options, NULL);
+ ret = g_option_context_parse (option_context, &argc, &argv, &error);
+ if (!ret) {
+ /* TRANSLATORS: error message */
+ g_print ("%s: %s\n", _("Failed to parse arguments"), error->message);
+ return EXIT_FAILURE;
+ }
+
+ if (verbose)
+ g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
+
+ /* set defaults */
+ if (api_version < 0.01)
+ api_version = 0.8;
+ if (prefix == NULL)
+ prefix = g_strdup ("/usr");
+ if (output_dir == NULL)
+ output_dir = g_build_filename (prefix, "share/app-info/xmls", NULL);
+ if (icons_dir == NULL)
+ icons_dir = g_build_filename (prefix, "share/app-info/icons", origin, NULL);
+ if (origin == NULL) {
+ g_print ("WARNING: Metadata origin not set, using 'example'\n");
+ origin = g_strdup ("example");
+ }
+ if (basename == NULL)
+ basename = g_strdup (origin);
+
+ if (argc == 1) {
+ g_autofree gchar *tmp = NULL;
+ tmp = g_option_context_get_help (option_context, TRUE, NULL);
+ g_print ("%s", tmp);
+ return EXIT_FAILURE;
+ }
+
+ store = as_store_new ();
+ as_store_set_api_version (store, api_version);
+ as_store_set_origin (store, origin);
+
+ /* load each application specified */
+ for (i = 1; i < (guint) argc; i++) {
+ const gchar *app_name = argv[i];
+ const gchar *gettext_domain;
+ g_auto(GStrv) intl_domains = NULL;
+ g_autofree gchar *locale_path = NULL;
+ g_autoptr(AsApp) app_appdata = NULL;
+ g_autoptr(AsApp) app_desktop = NULL;
+
+ /* TRANSLATORS: we're generating the AppStream data */
+ g_print ("%s %s\n", _("Processing application"), app_name);
+
+ app_appdata = load_appdata (prefix, app_name, &error);
+ if (app_appdata == NULL) {
+ /* TRANSLATORS: the .appdata.xml file could not
+ * be loaded */
+ g_print ("%s: %s\n", _("Error loading AppData file"),
+ error->message);
+ return EXIT_FAILURE;
+ }
+
+ /* set translations: FIXME add to specification */
+ gettext_domain = as_app_get_metadata_item (app_appdata,
+ "X-Gettext-Domain");
+ if (gettext_domain != NULL) {
+ locale_path = g_build_filename (prefix,
+ "share",
+ "locale",
+ NULL);
+ intl_domains = g_strsplit (gettext_domain, ",", -1);
+ if (!as_app_gettext_search_path (app_appdata,
+ locale_path,
+ intl_domains,
+ 25,
+ NULL,
+ &error)) {
+ /* TRANSLATORS: the .mo files could not be parsed */
+ g_print ("%s: %s\n", _("Error parsing translations"),
+ error->message);
+ return EXIT_FAILURE;
+ }
+ }
+
+ as_store_add_app (store, app_appdata);
+
+ app_desktop = load_desktop (prefix,
+ icons_dir,
+ min_icon_size,
+ app_name,
+ as_app_get_id (app_appdata),
+ &error);
+ if (app_desktop == NULL) {
+ /* TRANSLATORS: the .desktop file could not
+ * be loaded */
+ g_print ("%s: %s\n", _("Error loading desktop file"),
+ error->message);
+ return EXIT_FAILURE;
+ }
+ as_store_add_app (store, app_desktop);
+ }
+
+ /* create output directory */
+ if (g_mkdir_with_parents (output_dir, 0755)) {
+ int errsv = errno;
+ g_print ("%s: %s\n",
+ /* TRANSLATORS: this is when the folder could
+ * not be created */
+ _("Error creating output directory"),
+ strerror (errsv));
+ return EXIT_FAILURE;
+ }
+
+ xml_dir = g_file_new_for_path (output_dir);
+ xml_basename = g_strconcat (basename, ".xml.gz", NULL);
+ xml_file = g_file_get_child (xml_dir, xml_basename);
+ /* TRANSLATORS: we've saving the XML file to disk */
+ g_print ("%s %s\n", _("Saving AppStream"),
+ g_file_get_path (xml_file));
+ if (!as_store_to_file (store,
+ xml_file,
+ AS_NODE_TO_XML_FLAG_FORMAT_MULTILINE |
+ AS_NODE_TO_XML_FLAG_FORMAT_INDENT |
+ AS_NODE_TO_XML_FLAG_ADD_HEADER,
+ NULL, &error)) {
+ /* TRANSLATORS: this is when the destination file
+ * cannot be saved for some reason */
+ g_print ("%s: %s\n", _("Error saving AppStream file"),
+ error->message);
+ return EXIT_FAILURE;
+ }
+
+ /* TRANSLATORS: information message */
+ g_print ("%s\n", _("Done!"));
+
+ return EXIT_SUCCESS;
+}
diff --git a/contrib/libappstream-glib.spec.in b/contrib/libappstream-glib.spec.in
index 4fd82b5..cc1a7b8 100644
--- a/contrib/libappstream-glib.spec.in
+++ b/contrib/libappstream-glib.spec.in
@@ -104,9 +104,11 @@ make install DESTDIR=$RPM_BUILD_ROOT
%{_libdir}/libappstream-glib.so.8*
%{_libdir}/girepository-1.0/*.typelib
%{_bindir}/appstream-util
+%{_bindir}/appstream-compose
%dir %{_datadir}/bash-completion/completions/
%{_datadir}/bash-completion/completions/appstream-util
%{_mandir}/man1/appstream-util.1.gz
+%{_mandir}/man1/appstream-compose.1.gz
%files devel
%{_libdir}/libappstream-glib.so
diff --git a/data/Makefile.am b/data/Makefile.am
index b902cba..5325046 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -13,7 +13,8 @@ dist_m4data_DATA += \
man_MANS =
if ENABLE_MAN
man_MANS += \
- appstream-util.1
+ appstream-util.1 \
+ appstream-compose.1
if HAVE_BUILDER
man_MANS += \
appstream-builder.1
@@ -33,6 +34,8 @@ XSLTPROC_FLAGS = \
appstream-util.1: appstream-util.xml
$(AM_V_GEN) xsltproc $(XSLTPROC_FLAGS) http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
+appstream-compose.1: appstream-compose.xml
+ $(AM_V_GEN) xsltproc $(XSLTPROC_FLAGS) http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
if HAVE_BUILDER
appstream-builder.1: appstream-builder.xml
$(AM_V_GEN) xsltproc $(XSLTPROC_FLAGS) http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $<
@@ -44,6 +47,7 @@ dist_bashcompletion_DATA += appstream-builder
endif
EXTRA_DIST = \
+ appstream-compose.xml \
appstream-util.xml \
appstream-builder.xml
diff --git a/data/appstream-compose.xml b/data/appstream-compose.xml
new file mode 100644
index 0000000..ec8a39f
--- /dev/null
+++ b/data/appstream-compose.xml
@@ -0,0 +1,58 @@
+<?xml version='1.0'?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
+
+<refentry id="appstream-compose">
+
+ <refentryinfo>
+ <title>appstream-compose</title>
+ <author>
+ <contrib>Maintainer</contrib>
+ <firstname>Richard</firstname>
+ <surname>Hughes</surname>
+ <email>richard@hughsie.com</email>
+ </author>
+ <copyright>
+ <year>2013-2014</year>
+ <holder>Richard Hughes</holder>
+ </copyright>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>appstream-compose</refentrytitle>
+ <manvolnum>1</manvolnum>
+ <refmiscinfo class="manual">User Commands</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+ <refname>appstream-compose</refname>
+ <refpurpose>Generate AppStream metadata</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>appstream-compose</command>
+ <arg choice="opt" rep="repeat">OPTION</arg>
+ </cmdsynopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+ <title>Description</title>
+ <para>
+ This manual page documents briefly the <command>appstream-compose</command> command.
+ </para>
+ <para>
+ <command>appstream-compose</command> is a simple app that takes a
+ prefix (default /usr) and a set of application names.
+ It looks for appdata, desktop and icon files with that
+ basename in $prefix/share/[appdata|applications|icons] and generates
+ appstream xml files and icons in (by default) $prefix/share/app-info.
+ </para>
+ </refsect1>
+
+ <refsect1>
+ <title>Author</title>
+ <para>This manual page was written by Richard Hughes <email>richard@hughsie.com</email>.
+ </para>
+ </refsect1>
+</refentry>
diff --git a/libappstream-glib/as-utils.c b/libappstream-glib/as-utils.c
index 45a5b5f..92213db 100644
--- a/libappstream-glib/as-utils.c
+++ b/libappstream-glib/as-utils.c
@@ -1178,7 +1178,7 @@ as_utils_find_icon_filename_full (const gchar *destdir,
prefix = g_strdup_printf ("%s/usr", destdir);
if (!g_file_test (prefix, G_FILE_TEST_EXISTS)) {
g_free (prefix);
- prefix = g_strdup_printf ("%s/files", destdir);
+ prefix = g_strdup (destdir);
}
if (!g_file_test (prefix, G_FILE_TEST_EXISTS)) {
g_set_error (error,
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 86ec69b..48df45d 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -2,4 +2,5 @@
# List of source files containing translatable strings.
# Please keep this file sorted alphabetically.
client/as-builder.c
+client/as-compose.c
client/as-util.c