Now, instead of return a string, the osinfo-install-script tool writes that string in a file, that will be into a dir, passed as argument. If the prefix argument is NULL, the output files will be written as set in data/install-scripts/*.xml (in filename attribute from template element): - Linuxes: fedora.ks - Windows 2k3r2 and older: windows.sif - Windows 2k8 and newer: windows.xml Otherwise, the prefix will be prepended in the filename as: <prefix>-<filename> If the dirname argument is NULL, the output files will be written in the current directory. It will be used to create, easily, multiple scripts, as used in: http://bugzilla-attachments.gnome.org/attachment.cgi?id=214681 --- data/install-scripts/fedora.xml | 2 +- data/install-scripts/windows-sif.xml | 2 +- data/install-scripts/windows-unattend.xml | 2 +- data/schemas/libosinfo.rng | 1 + osinfo/libosinfo.syms | 4 + osinfo/osinfo_install_script.c | 246 +++++++++++++++++++++++++++++- osinfo/osinfo_install_script.h | 25 +++ osinfo/osinfo_install_scriptlist.c | 15 ++ osinfo/osinfo_install_scriptlist.h | 1 + osinfo/osinfo_loader.c | 9 ++ tools/osinfo-install-script.c | 50 +++--- 11 files changed, 324 insertions(+), 33 deletions(-) diff --git a/data/install-scripts/fedora.xml b/data/install-scripts/fedora.xml index b4ad72d..338a570 100644 --- a/data/install-scripts/fedora.xml +++ b/data/install-scripts/fedora.xml @@ -1,7 +1,7 @@ <libosinfo version="0.0.1"> <install-script id='http://fedoraproject.org/scripts/fedora/jeos'> <profile>jeos</profile> - <template> + <template filename="fedora.ks"> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> diff --git a/data/install-scripts/windows-sif.xml b/data/install-scripts/windows-sif.xml index 29a0eae..46b24ae 100644 --- a/data/install-scripts/windows-sif.xml +++ b/data/install-scripts/windows-sif.xml @@ -1,7 +1,7 @@ <libosinfo version="0.0.1"> <install-script id='http://microsoft.com/windows/sif'> <profile>jeos</profile> - <template> + <template filename="windows.sif"> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> diff --git a/data/install-scripts/windows-unattend.xml b/data/install-scripts/windows-unattend.xml index 9828b34..20e3e23 100644 --- a/data/install-scripts/windows-unattend.xml +++ b/data/install-scripts/windows-unattend.xml @@ -1,7 +1,7 @@ <libosinfo version="0.0.1"> <install-script id='http://microsoft.com/windows/unattend'> <profile>jeos</profile> - <template> + <template filename="windows.xml"> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> diff --git a/data/schemas/libosinfo.rng b/data/schemas/libosinfo.rng index a5f527d..7c8d7f7 100644 --- a/data/schemas/libosinfo.rng +++ b/data/schemas/libosinfo.rng @@ -414,6 +414,7 @@ <text/> </element> <element name='template'> + <attribute name="filename"/> <choice> <group> <attribute name="uri"/> diff --git a/osinfo/libosinfo.syms b/osinfo/libosinfo.syms index 2f90183..a6fa292 100644 --- a/osinfo/libosinfo.syms +++ b/osinfo/libosinfo.syms @@ -264,6 +264,7 @@ LIBOSINFO_0.2.0 { osinfo_install_config_set_user_administrator; osinfo_install_config_set_user_autologin; osinfo_install_config_set_hostname; + osinfo_install_script_set_output_prefix; osinfo_install_script_get_type; osinfo_install_script_new; osinfo_install_script_new_data; @@ -271,6 +272,8 @@ LIBOSINFO_0.2.0 { osinfo_install_script_generate; osinfo_install_script_generate_async; osinfo_install_script_generate_finish; + osinfo_install_script_generate_output; + osinfo_install_script_generate_output_async; osinfo_install_script_get_profile; osinfo_install_script_get_uri; osinfo_install_scriptlist_new; @@ -279,6 +282,7 @@ LIBOSINFO_0.2.0 { osinfo_install_scriptlist_new_intersection; osinfo_install_scriptlist_new_copy; osinfo_install_scriptlist_get_type; + osinfo_install_scriptlist_get_by_profile; osinfo_db_get_install_script; osinfo_db_add_install_script; osinfo_db_get_install_script_list; diff --git a/osinfo/osinfo_install_script.c b/osinfo/osinfo_install_script.c index 1f437a1..52f56da 100644 --- a/osinfo/osinfo_install_script.c +++ b/osinfo/osinfo_install_script.c @@ -56,6 +56,7 @@ enum { PROP_TEMPLATE_DATA, PROP_PROFILE, PROP_PRODUCT_KEY_FORMAT, + PROP_OUTPUT_PREFIX, }; @@ -93,6 +94,14 @@ osinfo_os_set_property(GObject *object, data); break; + case PROP_OUTPUT_PREFIX: + data = g_value_get_string(value); + if (data) + osinfo_entity_set_param(OSINFO_ENTITY(script), + OSINFO_INSTALL_SCRIPT_PROP_OUTPUT_PREFIX, + data); + break; + default: /* We don't have any other property... */ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -129,6 +138,11 @@ osinfo_os_get_property(GObject *object, osinfo_install_script_get_product_key_format(script)); break; + case PROP_OUTPUT_PREFIX: + g_value_set_string(value, + osinfo_install_script_get_output_prefix(script)); + break; + default: /* We don't have any other property... */ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -210,6 +224,19 @@ osinfo_install_script_class_init (OsinfoInstallScriptClass *klass) PROP_PROFILE, pspec); + pspec = g_param_spec_string("output-filename", + "Output Filename", + "Output filename for the script", + NULL /* default value */, + G_PARAM_READABLE | + G_PARAM_WRITABLE | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB); + g_object_class_install_property(g_klass, + PROP_OUTPUT_PREFIX, + pspec); + g_type_class_add_private (klass, sizeof (OsinfoInstallScriptPrivate)); } @@ -218,7 +245,6 @@ osinfo_install_script_init (OsinfoInstallScript *list) { OsinfoInstallScriptPrivate *priv; list->priv = priv = OSINFO_INSTALL_SCRIPT_GET_PRIVATE(list); - } @@ -291,6 +317,31 @@ const gchar *osinfo_install_script_get_product_key_format(OsinfoInstallScript *s OSINFO_INSTALL_SCRIPT_PROP_PRODUCT_KEY_FORMAT); } +void osinfo_install_script_set_output_prefix(OsinfoInstallScript *script, + const gchar *prefix) +{ + GValue value = G_VALUE_INIT; + g_value_init(&value, G_TYPE_STRING); + g_value_set_string(&value, prefix); + + osinfo_os_set_property(G_OBJECT (script), + PROP_OUTPUT_PREFIX, + &value, + NULL); +} + +const gchar *osinfo_install_script_get_output_prefix(OsinfoInstallScript *script) +{ + return osinfo_entity_get_param_value(OSINFO_ENTITY(script), + OSINFO_INSTALL_SCRIPT_PROP_OUTPUT_PREFIX); +} + +static const gchar *osinfo_install_script_get_output_filename(OsinfoInstallScript *script) +{ + return osinfo_entity_get_param_value(OSINFO_ENTITY(script), + OSINFO_INSTALL_SCRIPT_PROP_OUTPUT_FILENAME); +} + struct OsinfoInstallScriptGenerate { GSimpleAsyncResult *res; OsinfoOs *os; @@ -308,6 +359,24 @@ static void osinfo_install_script_generate_free(struct OsinfoInstallScriptGenera g_free(data); } +struct OsinfoInstallScriptGenerateOutput { + GSimpleAsyncResult *res; + GCancellable *cancellable; + GError *error; + GFile *file; + GFileOutputStream *stream; + gchar *output; + gssize output_len; + gssize output_pos; +}; + +static void osinfo_install_script_generate_output_free(struct OsinfoInstallScriptGenerateOutput *data) +{ + g_object_unref(data->stream); + g_object_unref(data->res); + g_free(data); +} + static xsltStylesheetPtr osinfo_install_script_load_template(const gchar *uri, const gchar *template, @@ -621,9 +690,9 @@ void osinfo_install_script_generate_async(OsinfoInstallScript *script, } } -gchar *osinfo_install_script_generate_finish(OsinfoInstallScript *script, - GAsyncResult *res, - GError **error) +static gpointer osinfo_install_script_generate_finish_common(OsinfoInstallScript *script, + GAsyncResult *res, + GError **error) { GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT(res); @@ -635,13 +704,61 @@ gchar *osinfo_install_script_generate_finish(OsinfoInstallScript *script, return g_simple_async_result_get_op_res_gpointer(simple); } +gchar *osinfo_install_script_generate_finish(OsinfoInstallScript *script, + GAsyncResult *res, + GError **error) +{ + return osinfo_install_script_generate_finish_common(script, + res, + error); +} + +GFile *osinfo_install_script_generate_output_finish(OsinfoInstallScript *script, + GAsyncResult *res, + GError **error) +{ + return osinfo_install_script_generate_finish_common(script, + res, + error); +} struct OsinfoInstallScriptGenerateSync { GMainLoop *loop; GError *error; gchar *output; + GFile *file; }; +static void osinfo_install_script_generate_output_done(GObject *src, + GAsyncResult *res, + gpointer user_data) +{ + struct OsinfoInstallScriptGenerateSync *data = user_data; + + data->file = + osinfo_install_script_generate_output_finish(OSINFO_INSTALL_SCRIPT(src), + res, + &data->error); + g_main_loop_quit(data->loop); +} + +static void osinfo_install_script_generate_output_close_file(GObject *src, + GAsyncResult *res, + gpointer user_data) +{ + struct OsinfoInstallScriptGenerateOutput *data = user_data; + + g_output_stream_close_finish(G_OUTPUT_STREAM(src), + res, + &data->error); + + g_simple_async_result_set_op_res_gpointer(data->res, + data->file, NULL); + g_simple_async_result_complete_in_idle(data->res); + + osinfo_install_script_generate_output_free(data); +} + static void osinfo_install_script_generate_done(GObject *src, GAsyncResult *res, gpointer user_data) @@ -655,7 +772,6 @@ static void osinfo_install_script_generate_done(GObject *src, g_main_loop_quit(data->loop); } - gchar *osinfo_install_script_generate(OsinfoInstallScript *script, OsinfoOs *os, OsinfoInstallConfig *config, @@ -665,7 +781,7 @@ gchar *osinfo_install_script_generate(OsinfoInstallScript *script, GMainLoop *loop = g_main_loop_new(g_main_context_get_thread_default(), TRUE); struct OsinfoInstallScriptGenerateSync data = { - loop, NULL, NULL + loop, NULL, NULL, NULL }; osinfo_install_script_generate_async(script, @@ -686,6 +802,124 @@ gchar *osinfo_install_script_generate(OsinfoInstallScript *script, return data.output; } +static void osinfo_install_script_generate_output_write_file(GObject *src, + GAsyncResult *res, + gpointer user_data) +{ + struct OsinfoInstallScriptGenerateOutput *data = user_data; + + if (data->stream == NULL) + data->stream = g_file_replace_finish(G_FILE (src), res, &data->error); + else + data->output_pos += g_output_stream_write_finish(G_OUTPUT_STREAM(data->stream), + res, + &data->error); + + g_assert_no_error(data->error); + + if (data->output_pos < data->output_len) { + g_output_stream_write_async(G_OUTPUT_STREAM (data->stream), + data->output + data->output_pos, + data->output_len - data->output_pos, + G_PRIORITY_DEFAULT, + data->cancellable, + osinfo_install_script_generate_output_write_file, + data); + + } else { + g_output_stream_close_async(G_OUTPUT_STREAM (data->stream), + G_PRIORITY_DEFAULT, + data->cancellable, + osinfo_install_script_generate_output_close_file, + data); + } +} + +void osinfo_install_script_generate_output_async(OsinfoInstallScript *script, + OsinfoOs *os, + OsinfoInstallConfig *config, + GFile *output_dir, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + const gchar *filename; + const gchar *prefix; + const gchar *output_filename; + struct OsinfoInstallScriptGenerateOutput *data = + g_new0(struct OsinfoInstallScriptGenerateOutput, 1); + + struct OsinfoInstallScriptGenerateSync *data_sync = user_data; + + data->res = g_simple_async_result_new(G_OBJECT(script), + callback, + user_data, + osinfo_install_script_generate_output_async); + + data->cancellable = cancellable; + data->error = data_sync->error; + data->output = osinfo_install_script_generate(script, + os, + config, + cancellable, + &data->error); + data->output_pos = 0; + data->output_len = strlen(data->output); + + prefix = + osinfo_install_script_get_output_prefix(script); + filename = + osinfo_install_script_get_output_filename(script); + + if (prefix) { + output_filename = g_strdup_printf("%s-%s", prefix, filename); + data->file = g_file_get_child(output_dir, output_filename); + g_free((gchar *)output_filename); + } else { + data->file = g_file_get_child(output_dir, filename); + } + + g_file_replace_async(data->file, + NULL, + TRUE, + G_FILE_CREATE_NONE, + G_PRIORITY_DEFAULT, + cancellable, + osinfo_install_script_generate_output_write_file, + data); +} + +const GFile *osinfo_install_script_generate_output(OsinfoInstallScript *script, + OsinfoOs *os, + OsinfoInstallConfig *config, + GFile *output_dir, + GCancellable *cancellable, + GError **error) +{ + GMainLoop *loop = g_main_loop_new(g_main_context_get_thread_default(), + TRUE); + struct OsinfoInstallScriptGenerateSync data = { + loop, NULL, NULL, NULL + }; + + osinfo_install_script_generate_output_async(script, + os, + config, + output_dir, + cancellable, + osinfo_install_script_generate_output_done, + &data); + + if (g_main_loop_is_running(loop)) + g_main_loop_run(loop); + + if (data.error) + g_propagate_error(error, data.error); + + g_main_loop_unref(loop); + + return data.file; +} /* * Local variables: diff --git a/osinfo/osinfo_install_script.h b/osinfo/osinfo_install_script.h index 00740c2..dd39114 100644 --- a/osinfo/osinfo_install_script.h +++ b/osinfo/osinfo_install_script.h @@ -49,6 +49,9 @@ typedef struct _OsinfoInstallScriptPrivate OsinfoInstallScriptPrivate; #define OSINFO_INSTALL_SCRIPT_PROP_TEMPLATE_DATA "template-data" #define OSINFO_INSTALL_SCRIPT_PROP_PROFILE "profile" #define OSINFO_INSTALL_SCRIPT_PROP_PRODUCT_KEY_FORMAT "product-key-format" +#define OSINFO_INSTALL_SCRIPT_PROP_OUTPUT_PREFIX "output-prefix" +#define OSINFO_INSTALL_SCRIPT_PROP_OUTPUT_FILENAME "output-filename" + /* object */ struct _OsinfoInstallScript @@ -85,6 +88,10 @@ const gchar *osinfo_install_script_get_profile(OsinfoInstallScript *script); const gchar *osinfo_install_script_get_product_key_format(OsinfoInstallScript *script); +void osinfo_install_script_set_output_prefix(OsinfoInstallScript *script, const gchar *prefix); + +const gchar *osinfo_install_script_get_output_prefix(OsinfoInstallScript *script); + void osinfo_install_script_generate_async(OsinfoInstallScript *script, OsinfoOs *os, OsinfoInstallConfig *config, @@ -102,6 +109,24 @@ gchar *osinfo_install_script_generate(OsinfoInstallScript *script, GCancellable *cancellable, GError **error); +void osinfo_install_script_generate_output_async(OsinfoInstallScript *script, + OsinfoOs *os, + OsinfoInstallConfig *config, + GFile *output_dir, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +GFile *osinfo_install_script_generate_output_finish(OsinfoInstallScript *script, + GAsyncResult *res, + GError **error); + +const GFile *osinfo_install_script_generate_output(OsinfoInstallScript *script, + OsinfoOs *os, + OsinfoInstallConfig *config, + GFile *output_dir, + GCancellable *cancellable, + GError **error); #endif /* __OSINFO_INSTALL_SCRIPT_H__ */ /* diff --git a/osinfo/osinfo_install_scriptlist.c b/osinfo/osinfo_install_scriptlist.c index e5309b5..dfc830b 100644 --- a/osinfo/osinfo_install_scriptlist.c +++ b/osinfo/osinfo_install_scriptlist.c @@ -160,6 +160,21 @@ OsinfoInstallScriptList *osinfo_install_scriptlist_new_union(OsinfoInstallScript return newList; } +OsinfoInstallScriptList *osinfo_install_scriptlist_get_by_profile(OsinfoInstallScriptList *source, + const gchar *profile) +{ + OsinfoInstallScriptList *newList; + OsinfoFilter *filter; + + filter = osinfo_filter_new(); + osinfo_filter_add_constraint(filter, + OSINFO_INSTALL_SCRIPT_PROP_PROFILE, + profile); + + newList = osinfo_install_scriptlist_new_filtered(source, filter); + return newList; +} + /* * Local variables: * indent-tabs-mode: nil diff --git a/osinfo/osinfo_install_scriptlist.h b/osinfo/osinfo_install_scriptlist.h index 39544d2..6407304 100644 --- a/osinfo/osinfo_install_scriptlist.h +++ b/osinfo/osinfo_install_scriptlist.h @@ -71,6 +71,7 @@ OsinfoInstallScriptList *osinfo_install_scriptlist_new_copy(OsinfoInstallScriptL OsinfoInstallScriptList *osinfo_install_scriptlist_new_filtered(OsinfoInstallScriptList *source, OsinfoFilter *filter); OsinfoInstallScriptList *osinfo_install_scriptlist_new_intersection(OsinfoInstallScriptList *sourceOne, OsinfoInstallScriptList *sourceTwo); OsinfoInstallScriptList *osinfo_install_scriptlist_new_union(OsinfoInstallScriptList *sourceOne, OsinfoInstallScriptList *sourceTwo); +OsinfoInstallScriptList *osinfo_install_scriptlist_get_by_profile(OsinfoInstallScriptList *source, const gchar *profile); #endif /* __OSINFO_INSTALL_SCRIPTLIST_H__ */ /* diff --git a/osinfo/osinfo_loader.c b/osinfo/osinfo_loader.c index f89dee0..31e442e 100644 --- a/osinfo/osinfo_loader.c +++ b/osinfo/osinfo_loader.c @@ -585,6 +585,15 @@ static void osinfo_loader_install_script(OsinfoLoader *loader, value); g_free(value); + value = osinfo_loader_string("string(./template/@filename)", ctxt, err); + if (error_is_set(err)) + goto error; + if (value) + osinfo_entity_set_param(OSINFO_ENTITY(installScript), + OSINFO_INSTALL_SCRIPT_PROP_OUTPUT_FILENAME, + value); + g_free(value); + osinfo_db_add_install_script(loader->priv->db, installScript); return; diff --git a/tools/osinfo-install-script.c b/tools/osinfo-install-script.c index c6aeae6..d75be9f 100644 --- a/tools/osinfo-install-script.c +++ b/tools/osinfo-install-script.c @@ -26,7 +26,9 @@ #include <osinfo/osinfo.h> #include <string.h> -static gchar *profile; +static const gchar *profile; +static const gchar *output_dir; +static const gchar *prefix; static OsinfoInstallConfig *config; @@ -60,6 +62,10 @@ static GOptionEntry entries[] = { { "profile", 'p', 0, G_OPTION_ARG_STRING, (void*)&profile, "Install script profile", NULL, }, + { "output-dir", 'd', 0, G_OPTION_ARG_STRING, (void*)&output_dir, + "Install script output directory", NULL, }, + { "prefix", 'P', 0, G_OPTION_ARG_STRING, (void*)&prefix, + "The output filename prefix", NULL, }, { "config", 'c', 0, G_OPTION_ARG_CALLBACK, handle_config, "Set configuration parameter", "key=value" }, @@ -103,48 +109,45 @@ static OsinfoOs *find_os(OsinfoDb *db, static gboolean generate_script(OsinfoOs *os) { OsinfoInstallScriptList *scripts = osinfo_os_get_install_script_list(os); - OsinfoInstallScriptList *jeosScripts; - OsinfoFilter *filter; + OsinfoInstallScriptList *profileScripts; OsinfoInstallScript *script; gboolean ret = FALSE; GError *error = NULL; - gchar *data; + GFile *dir = g_file_new_for_commandline_arg(output_dir ? output_dir : "."); - filter = osinfo_filter_new(); - osinfo_filter_add_constraint(filter, - OSINFO_INSTALL_SCRIPT_PROP_PROFILE, - profile ? profile : - OSINFO_INSTALL_SCRIPT_PROFILE_JEOS); + profileScripts = + osinfo_install_scriptlist_get_by_profile(scripts, + profile ? profile: + OSINFO_INSTALL_SCRIPT_PROFILE_JEOS); - jeosScripts = osinfo_install_scriptlist_new_filtered(scripts, - filter); - if (osinfo_list_get_length(OSINFO_LIST(jeosScripts)) != 1) { + if (osinfo_list_get_length(OSINFO_LIST(profileScripts)) != 1) { g_printerr("Cannot find any install script for profile '%s'\n", profile ? profile : OSINFO_INSTALL_SCRIPT_PROFILE_JEOS); goto cleanup; } - script = OSINFO_INSTALL_SCRIPT(osinfo_list_get_nth(OSINFO_LIST(jeosScripts), 0)); - if (!(data = osinfo_install_script_generate(script, - os, - config, - NULL, - &error))) { + script = OSINFO_INSTALL_SCRIPT(osinfo_list_get_nth(OSINFO_LIST(profileScripts), 0)); + + if (prefix) + osinfo_install_script_set_output_prefix(script, prefix); + + if (osinfo_install_script_generate_output(script, + os, + config, + dir, + NULL, + &error) == NULL) { g_printerr("Unable to generate install script: %s\n", error ? error->message : "unknown"); goto cleanup; } - g_print("%s\n", data); - ret = TRUE; cleanup: - g_free(data); g_object_unref(scripts); - g_object_unref(jeosScripts); - g_object_unref(filter); + g_object_unref(profileScripts); return ret; } @@ -197,7 +200,6 @@ gint main(gint argc, gchar **argv) goto EXIT; } - if (!generate_script(os)) { ret = -5; goto EXIT; -- 1.7.11.2