From af49603d6fba85e6d45bbd27ba9c3fac78295bc0 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sat, 22 Mar 2014 15:05:41 -0400 Subject: [PATCH] core: Use generic "builtin" infrastructure for command handling I want to have more options than just "create". --- Makefile-rpm-ostree.am | 4 +- src/main.c | 201 ++++++++++++++++++ ...pm-ostree.c => rpmostree-builtin-create.c} | 44 +--- src/rpmostree-builtins.h | 40 ++++ 4 files changed, 255 insertions(+), 34 deletions(-) create mode 100644 src/main.c rename src/{rpm-ostree.c => rpmostree-builtin-create.c} (96%) create mode 100644 src/rpmostree-builtins.h diff --git a/Makefile-rpm-ostree.am b/Makefile-rpm-ostree.am index ba93aa0e..459c4e55 100644 --- a/Makefile-rpm-ostree.am +++ b/Makefile-rpm-ostree.am @@ -19,9 +19,11 @@ privlib_SCRIPTS = src/repoquery-sorted bin_PROGRAMS += rpm-ostree -rpm_ostree_SOURCES = src/rpm-ostree.c \ +rpm_ostree_SOURCES = src/main.c \ src/rpmostree-postprocess.h \ src/rpmostree-postprocess.c \ + src/rpmostree-builtins.h \ + src/rpmostree-builtin-create.c \ $(NULL) rpm_ostree_CFLAGS = $(AM_CFLAGS) -I$(srcdir)/src -DPKGLIBDIR=\"$(pkglibdir)\" $(PKGDEP_RPMOSTREE_CFLAGS) rpm_ostree_LDADD = $(AM_LDFLAGS) $(PKGDEP_RPMOSTREE_LIBS) diff --git a/src/main.c b/src/main.c new file mode 100644 index 00000000..c4e258b8 --- /dev/null +++ b/src/main.c @@ -0,0 +1,201 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2014 Colin Walters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "config.h" + +#include + +#include +#include +#include +#include + +#include "rpmostree-builtins.h" + +#include "libgsystem.h" + +static RpmOstreeCommand commands[] = { + { "create", rpmostree_builtin_create, 0 }, + { NULL } +}; + +static int +usage (char **argv, + gboolean is_error) +{ + RpmOstreeCommand *command = commands; + void (*print_func) (const gchar *format, ...); + + if (is_error) + print_func = g_printerr; + else + print_func = g_print; + + print_func ("usage: %s COMMAND [options]\n", + argv[0]); + print_func ("Builtin commands:\n"); + + while (command->name) + { + print_func (" %s\n", command->name); + command++; + } + return (is_error ? 1 : 0); +} + +int +main (int argc, + char **argv) +{ + GError *error = NULL; + GCancellable *cancellable = NULL; + RpmOstreeCommand *command; + int i, in, out; + gboolean skip; + gboolean want_help = FALSE; + const char *cmd = NULL; + + /* avoid gvfs (http://bugzilla.gnome.org/show_bug.cgi?id=526454) */ + g_setenv ("GIO_USE_VFS", "local", TRUE); + g_set_prgname (argv[0]); + + setlocale (LC_ALL, ""); + + /* + * Parse the global options. We rearrange the options as + * necessary, in order to pass relevant options through + * to the commands, but also have them take effect globally. + */ + for (in = 1, out = 1; in < argc; in++, out++) + { + /* The non-option is the command, take it out of the arguments */ + if (argv[in][0] != '-') + { + skip = (cmd == NULL); + if (cmd == NULL) + cmd = argv[in]; + } + + /* The global long options */ + else if (argv[in][1] == '-') + { + skip = FALSE; + + if (g_str_equal (argv[in], "--")) + { + break; + } + else if (g_str_equal (argv[in], "--help")) + { + want_help = TRUE; + } + else if (cmd == NULL && g_str_equal (argv[in], "--version")) + { + g_print ("%s\n %s\n", PACKAGE_STRING, ""); + return 0; + } + else if (cmd == NULL) + { + g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Unknown or invalid global option: %s", argv[in]); + goto out; + } + } + + /* The global short options */ + else + { + skip = FALSE; + for (i = 1; argv[in][i] != '\0'; i++) + { + switch (argv[in][i]) + { + case 'h': + want_help = TRUE; + break; + default: + if (cmd == NULL) + { + g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Unknown or invalid global option: %s", argv[in]); + goto out; + } + break; + } + } + } + + /* Skipping this argument? */ + if (skip) + out--; + else + argv[out] = argv[in]; + } + + argc = out; + + if (cmd == NULL) + { + if (!want_help) + { + g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, + "No command specified"); + } + usage (argv, TRUE); + goto out; + } + + command = commands; + while (command->name) + { + if (g_strcmp0 (cmd, command->name) == 0) + break; + command++; + } + + if (!command->fn) + { + gs_free char *msg = g_strdup_printf ("Unknown command '%s'", cmd); + g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, msg); + goto out; + } + + g_set_prgname (g_strdup_printf (PACKAGE_STRING " %s", cmd)); + + if (!command->fn (argc, argv, cancellable, &error)) + goto out; + + out: + if (error != NULL) + { + int is_tty = isatty (1); + const char *prefix = ""; + const char *suffix = ""; + if (is_tty) + { + prefix = "\x1b[31m\x1b[1m"; /* red, bold */ + suffix = "\x1b[22m\x1b[0m"; /* bold off, color reset */ + } + g_printerr ("%serror: %s%s\n", prefix, suffix, error->message); + g_error_free (error); + return 1; + } + return 0; +} diff --git a/src/rpm-ostree.c b/src/rpmostree-builtin-create.c similarity index 96% rename from src/rpm-ostree.c rename to src/rpmostree-builtin-create.c index 5741217f..a9e72ae9 100644 --- a/src/rpm-ostree.c +++ b/src/rpmostree-builtin-create.c @@ -24,6 +24,7 @@ #include #include +#include "rpmostree-builtins.h" #include "rpmostree-postprocess.h" #include "libgsystem.h" @@ -537,15 +538,14 @@ yuminstall (JsonObject *treedata, return ret; } -int -main (int argc, - char **argv) +gboolean +rpmostree_builtin_create (int argc, + char **argv, + GCancellable *cancellable, + GError **error) { - GError *local_error = NULL; - GError **error = &local_error; - GCancellable *cancellable = NULL; + gboolean ret = FALSE; GOptionContext *context = g_option_context_new ("- Run yum and commit the result to an OSTree repository"); - const char *cmd; const char *ref; JsonNode *treefile_root = NULL; JsonObject *treefile = NULL; @@ -568,22 +568,15 @@ main (int argc, if (!g_option_context_parse (context, &argc, &argv, error)) goto out; - if (argc < 3) + if (argc < 2) { - g_printerr ("usage: %s create treefile.json\n", argv[0]); + g_printerr ("usage: " PACKAGE_STRING " create TREEFILE\n"); g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Option processing failed"); goto out; } - cmd = argv[1]; - if (strcmp (cmd, "create") != 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Unknown command '%s'", cmd); - goto out; - } - treefile_path = g_file_new_for_path (argv[2]); + treefile_path = g_file_new_for_path (argv[1]); if (opt_workdir && chdir (opt_workdir) != 0) { @@ -892,20 +885,5 @@ main (int argc, g_print ("Complete\n"); out: - if (local_error != NULL) - { - int is_tty = isatty (1); - const char *prefix = ""; - const char *suffix = ""; - if (is_tty) - { - prefix = "\x1b[31m\x1b[1m"; /* red, bold */ - suffix = "\x1b[22m\x1b[0m"; /* bold off, color reset */ - } - g_printerr ("%serror: %s%s\n", prefix, suffix, local_error->message); - g_error_free (local_error); - return 2; - } - else - return 0; + return ret; } diff --git a/src/rpmostree-builtins.h b/src/rpmostree-builtins.h new file mode 100644 index 00000000..d3eb7389 --- /dev/null +++ b/src/rpmostree-builtins.h @@ -0,0 +1,40 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- + * + * Copyright (C) 2014 Colin Walters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#pragma once + +#include "ostree.h" + +G_BEGIN_DECLS + +typedef struct { + const char *name; + gboolean (*fn) (int argc, char **argv, GCancellable *cancellable, GError **error); + int flags; +} RpmOstreeCommand; + +#define BUILTINPROTO(name) gboolean rpmostree_builtin_ ## name (int argc, char **argv, GCancellable *cancellable, GError **error) + +BUILTINPROTO(create); + +#undef BUILTINPROTO + +G_END_DECLS +