2014-03-22 23:05:41 +04:00
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright ( C ) 2014 Colin Walters < walters @ verbum . org >
*
* 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 <gio/gio.h>
# include <errno.h>
2014-11-24 20:34:45 +03:00
# include <stdlib.h>
2014-03-22 23:05:41 +04:00
# include <string.h>
# include <unistd.h>
# include <locale.h>
# include "rpmostree-builtins.h"
# include "libgsystem.h"
static RpmOstreeCommand commands [ ] = {
2014-09-17 05:45:30 +04:00
# ifdef HAVE_COMPOSE_TOOLING
2014-05-26 23:05:08 +04:00
{ " compose " , rpmostree_builtin_compose , 0 } ,
2014-09-17 05:45:30 +04:00
# endif
2014-03-25 02:11:21 +04:00
{ " upgrade " , rpmostree_builtin_upgrade , 0 } ,
2014-05-30 02:00:11 +04:00
{ " rebase " , rpmostree_builtin_rebase , 0 } ,
2014-03-29 03:48:06 +04:00
{ " rollback " , rpmostree_builtin_rollback , 0 } ,
2014-06-11 21:47:10 +04:00
{ " status " , rpmostree_builtin_status , 0 } ,
2014-07-03 11:32:21 +04:00
{ " rpm " , rpmostree_builtin_rpm , 0 } ,
2014-03-22 23:05:41 +04:00
{ NULL }
} ;
2014-11-24 20:34:45 +03:00
static gboolean opt_version ;
static GOptionEntry global_entries [ ] = {
{ " version " , 0 , 0 , G_OPTION_ARG_NONE , & opt_version , " Print version information and exit " , NULL } ,
{ NULL }
} ;
static GOptionContext *
option_context_new_with_commands ( void )
2014-03-22 23:05:41 +04:00
{
RpmOstreeCommand * command = commands ;
2014-11-24 20:34:45 +03:00
GOptionContext * context ;
GString * summary ;
2014-03-22 23:05:41 +04:00
2014-11-24 20:34:45 +03:00
context = g_option_context_new ( " COMMAND " ) ;
2014-03-22 23:05:41 +04:00
2014-11-24 20:34:45 +03:00
summary = g_string_new ( " Builtin Commands: " ) ;
2014-03-22 23:05:41 +04:00
2014-11-24 20:34:45 +03:00
while ( command - > name ! = NULL )
2014-03-22 23:05:41 +04:00
{
2014-11-24 20:34:45 +03:00
g_string_append_printf ( summary , " \n %s " , command - > name ) ;
2014-03-22 23:05:41 +04:00
command + + ;
}
2014-11-24 20:34:45 +03:00
g_option_context_set_summary ( context , summary - > str ) ;
g_string_free ( summary , TRUE ) ;
return context ;
}
gboolean
rpmostree_option_context_parse ( GOptionContext * context ,
const GOptionEntry * main_entries ,
int * argc ,
char * * * argv ,
GError * * error )
{
if ( main_entries ! = NULL )
g_option_context_add_main_entries ( context , main_entries , NULL ) ;
g_option_context_add_main_entries ( context , global_entries , NULL ) ;
if ( ! g_option_context_parse ( context , argc , argv , error ) )
return FALSE ;
if ( opt_version )
{
g_print ( " %s \n %s \n " , PACKAGE_NAME , RPM_OSTREE_FEATURES ) ;
exit ( EXIT_SUCCESS ) ;
}
return TRUE ;
2014-03-22 23:05:41 +04:00
}
int
main ( int argc ,
char * * argv )
{
GError * error = NULL ;
GCancellable * cancellable = NULL ;
RpmOstreeCommand * command ;
2014-11-24 20:34:45 +03:00
int in , out ;
const char * command_name = NULL ;
gs_free char * prgname = NULL ;
2014-03-22 23:05:41 +04:00
/* 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 ] ! = ' - ' )
{
2014-11-24 20:34:45 +03:00
if ( command_name = = NULL )
2014-03-22 23:05:41 +04:00
{
2014-11-24 20:34:45 +03:00
command_name = argv [ in ] ;
out - - ;
continue ;
2014-03-22 23:05:41 +04:00
}
}
2014-11-24 20:34:45 +03:00
else if ( g_str_equal ( argv [ in ] , " -- " ) )
2014-03-22 23:05:41 +04:00
{
2014-11-24 20:34:45 +03:00
break ;
2014-03-22 23:05:41 +04:00
}
2014-11-24 20:34:45 +03:00
argv [ out ] = argv [ in ] ;
2014-03-22 23:05:41 +04:00
}
argc = out ;
command = commands ;
while ( command - > name )
{
2014-11-24 20:34:45 +03:00
if ( g_strcmp0 ( command_name , command - > name ) = = 0 )
2014-03-22 23:05:41 +04:00
break ;
command + + ;
}
if ( ! command - > fn )
{
2014-11-24 20:34:45 +03:00
GOptionContext * context ;
gs_free char * help ;
context = option_context_new_with_commands ( ) ;
/* This will not return for some options (e.g. --version). */
if ( rpmostree_option_context_parse ( context , NULL , & argc , & argv , & error ) )
{
if ( command_name = = NULL )
{
g_set_error_literal ( & error , G_IO_ERROR , G_IO_ERROR_FAILED ,
" No command specified " ) ;
}
else
{
g_set_error ( & error , G_IO_ERROR , G_IO_ERROR_FAILED ,
" Unknown command '%s' " , command_name ) ;
}
}
help = g_option_context_get_help ( context , FALSE , NULL ) ;
g_printerr ( " %s " , help ) ;
g_option_context_free ( context ) ;
2014-03-22 23:05:41 +04:00
goto out ;
}
2014-11-24 20:34:45 +03:00
prgname = g_strdup_printf ( " %s %s " , g_get_prgname ( ) , command_name ) ;
g_set_prgname ( prgname ) ;
2014-03-22 23:05:41 +04:00
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 ;
}