2017-01-28 04:49:09 +08:00
# include "pch.h"
2017-04-04 07:00:17 +08:00
# include "VcpkgCmdArguments.h"
2016-09-19 11:50:08 +08:00
# include "vcpkg_Commands.h"
# include "metrics.h"
# include "vcpkg_System.h"
namespace vcpkg
{
static void parse_value (
const std : : string * arg_begin ,
const std : : string * arg_end ,
const std : : string & option_name ,
std : : unique_ptr < std : : string > & option_field )
{
if ( arg_begin = = arg_end )
{
2017-04-04 07:31:00 +08:00
System : : println ( System : : Color : : error , " Error: expected value after %s " , option_name ) ;
2017-04-04 05:41:36 +08:00
Metrics : : track_property ( " error " , " error option name " ) ;
2017-01-13 14:03:57 +08:00
Commands : : Help : : print_usage ( ) ;
2017-03-23 08:46:05 +08:00
Checks : : exit_fail ( VCPKG_LINE_INFO ) ;
2016-09-19 11:50:08 +08:00
}
if ( option_field ! = nullptr )
{
2017-04-04 07:31:00 +08:00
System : : println ( System : : Color : : error , " Error: %s specified multiple times " , option_name ) ;
2017-04-04 05:41:36 +08:00
Metrics : : track_property ( " error " , " error option specified multiple times " ) ;
2017-01-13 14:03:57 +08:00
Commands : : Help : : print_usage ( ) ;
2017-03-23 08:46:05 +08:00
Checks : : exit_fail ( VCPKG_LINE_INFO ) ;
2016-09-19 11:50:08 +08:00
}
option_field = std : : make_unique < std : : string > ( * arg_begin ) ;
}
static void parse_switch (
2017-04-26 08:01:21 +08:00
OptBool new_setting ,
2016-09-19 11:50:08 +08:00
const std : : string & option_name ,
2017-04-26 08:01:21 +08:00
OptBool & option_field )
2016-09-19 11:50:08 +08:00
{
2017-04-26 08:01:21 +08:00
if ( option_field ! = OptBoolC : : UNSPECIFIED & & option_field ! = new_setting )
2016-09-19 11:50:08 +08:00
{
2017-04-04 07:31:00 +08:00
System : : println ( System : : Color : : error , " Error: conflicting values specified for --%s " , option_name ) ;
2017-04-04 05:41:36 +08:00
Metrics : : track_property ( " error " , " error conflicting switches " ) ;
2017-01-13 14:03:57 +08:00
Commands : : Help : : print_usage ( ) ;
2017-03-23 08:46:05 +08:00
Checks : : exit_fail ( VCPKG_LINE_INFO ) ;
2016-09-19 11:50:08 +08:00
}
option_field = new_setting ;
}
2017-04-04 07:00:17 +08:00
VcpkgCmdArguments VcpkgCmdArguments : : create_from_command_line ( const int argc , const wchar_t * const * const argv )
2016-09-19 11:50:08 +08:00
{
std : : vector < std : : string > v ;
for ( int i = 1 ; i < argc ; + + i )
{
v . push_back ( Strings : : utf16_to_utf8 ( argv [ i ] ) ) ;
}
2017-04-04 07:00:17 +08:00
return VcpkgCmdArguments : : create_from_arg_sequence ( v . data ( ) , v . data ( ) + v . size ( ) ) ;
2016-09-19 11:50:08 +08:00
}
2017-04-04 07:00:17 +08:00
VcpkgCmdArguments VcpkgCmdArguments : : create_from_arg_sequence ( const std : : string * arg_begin , const std : : string * arg_end )
2016-09-19 11:50:08 +08:00
{
2017-04-04 07:00:17 +08:00
VcpkgCmdArguments args ;
2016-09-19 11:50:08 +08:00
for ( ; arg_begin ! = arg_end ; + + arg_begin )
{
std : : string arg = * arg_begin ;
if ( arg . empty ( ) )
{
continue ;
}
if ( arg [ 0 ] = = ' - ' & & arg [ 1 ] ! = ' - ' )
{
2017-04-04 05:41:36 +08:00
Metrics : : track_property ( " error " , " error short options are not supported " ) ;
2017-03-23 08:06:09 +08:00
Checks : : exit_with_message ( VCPKG_LINE_INFO , " Error: short options are not supported: %s " , arg ) ;
2016-09-19 11:50:08 +08:00
}
if ( arg [ 0 ] = = ' - ' & & arg [ 1 ] = = ' - ' )
{
2017-04-27 10:21:40 +08:00
// make argument case insensitive
auto & f = std : : use_facet < std : : ctype < char > > ( std : : locale ( ) ) ;
f . tolower ( & arg [ 0 ] , & arg [ 0 ] + arg . size ( ) ) ;
2016-09-19 11:50:08 +08:00
// command switch
if ( arg = = " --vcpkg-root " )
{
+ + arg_begin ;
parse_value ( arg_begin , arg_end , " --vcpkg-root " , args . vcpkg_root_dir ) ;
continue ;
}
if ( arg = = " --triplet " )
{
+ + arg_begin ;
2017-04-11 04:01:43 +08:00
parse_value ( arg_begin , arg_end , " --triplet " , args . triplet ) ;
2016-09-19 11:50:08 +08:00
continue ;
}
if ( arg = = " --debug " )
{
2017-04-26 08:01:21 +08:00
parse_switch ( OptBoolC : : ENABLED , " debug " , args . debug ) ;
2016-09-19 11:50:08 +08:00
continue ;
}
if ( arg = = " --sendmetrics " )
{
2017-04-26 08:01:21 +08:00
parse_switch ( OptBoolC : : ENABLED , " sendmetrics " , args . sendmetrics ) ;
2016-09-19 11:50:08 +08:00
continue ;
}
if ( arg = = " --printmetrics " )
{
2017-04-26 08:01:21 +08:00
parse_switch ( OptBoolC : : ENABLED , " printmetrics " , args . printmetrics ) ;
2016-09-19 11:50:08 +08:00
continue ;
}
if ( arg = = " --no-sendmetrics " )
{
2017-04-26 08:01:21 +08:00
parse_switch ( OptBoolC : : DISABLED , " sendmetrics " , args . sendmetrics ) ;
2016-09-19 11:50:08 +08:00
continue ;
}
if ( arg = = " --no-printmetrics " )
{
2017-04-26 08:01:21 +08:00
parse_switch ( OptBoolC : : DISABLED , " printmetrics " , args . printmetrics ) ;
2016-09-19 11:50:08 +08:00
continue ;
}
args . optional_command_arguments . insert ( arg ) ;
continue ;
}
if ( args . command . empty ( ) )
{
args . command = arg ;
}
else
{
args . command_arguments . push_back ( arg ) ;
}
}
return args ;
}
2017-04-04 07:00:17 +08:00
std : : unordered_set < std : : string > VcpkgCmdArguments : : check_and_get_optional_command_arguments ( const std : : vector < std : : string > & valid_options ) const
2016-09-19 11:50:08 +08:00
{
std : : unordered_set < std : : string > output ;
auto options_copy = this - > optional_command_arguments ;
for ( const std : : string & option : valid_options )
{
auto it = options_copy . find ( option ) ;
if ( it ! = options_copy . end ( ) )
{
output . insert ( option ) ;
options_copy . erase ( it ) ;
}
}
if ( ! options_copy . empty ( ) )
{
2017-04-04 07:31:00 +08:00
System : : println ( System : : Color : : error , " Unknown option(s) for command '%s': " , this - > command ) ;
2016-09-19 11:50:08 +08:00
for ( const std : : string & option : options_copy )
{
2016-12-13 07:10:29 +08:00
System : : println ( option ) ;
2016-09-19 11:50:08 +08:00
}
2017-03-23 08:46:05 +08:00
Checks : : exit_fail ( VCPKG_LINE_INFO ) ;
2016-09-19 11:50:08 +08:00
}
return output ;
}
2017-04-04 07:00:17 +08:00
void VcpkgCmdArguments : : check_max_arg_count ( const size_t expected_arg_count ) const
2016-09-19 11:50:08 +08:00
{
2016-10-01 02:24:04 +08:00
return check_max_arg_count ( expected_arg_count , " " ) ;
}
2017-04-04 07:00:17 +08:00
void VcpkgCmdArguments : : check_min_arg_count ( const size_t expected_arg_count ) const
2016-10-01 02:24:04 +08:00
{
return check_min_arg_count ( expected_arg_count , " " ) ;
}
2017-04-04 07:00:17 +08:00
void VcpkgCmdArguments : : check_exact_arg_count ( const size_t expected_arg_count ) const
2016-10-01 02:24:04 +08:00
{
return check_exact_arg_count ( expected_arg_count , " " ) ;
}
2017-04-04 07:00:17 +08:00
void VcpkgCmdArguments : : check_max_arg_count ( const size_t expected_arg_count , const std : : string & example_text ) const
2016-10-01 02:24:04 +08:00
{
const size_t actual_arg_count = command_arguments . size ( ) ;
if ( actual_arg_count > expected_arg_count )
2016-09-19 11:50:08 +08:00
{
2017-04-04 07:31:00 +08:00
System : : println ( System : : Color : : error , " Error: `%s` requires at most %u arguments, but %u were provided " , this - > command , expected_arg_count , actual_arg_count ) ;
2016-10-01 02:24:04 +08:00
System : : print ( example_text ) ;
2017-03-23 08:46:05 +08:00
Checks : : exit_fail ( VCPKG_LINE_INFO ) ;
2016-10-01 02:24:04 +08:00
}
}
2017-04-04 07:00:17 +08:00
void VcpkgCmdArguments : : check_min_arg_count ( const size_t expected_arg_count , const std : : string & example_text ) const
2016-10-01 02:24:04 +08:00
{
const size_t actual_arg_count = command_arguments . size ( ) ;
if ( actual_arg_count < expected_arg_count )
{
2017-04-04 07:31:00 +08:00
System : : println ( System : : Color : : error , " Error: `%s` requires at least %u arguments, but %u were provided " , this - > command , expected_arg_count , actual_arg_count ) ;
2016-10-01 02:24:04 +08:00
System : : print ( example_text ) ;
2017-03-23 08:46:05 +08:00
Checks : : exit_fail ( VCPKG_LINE_INFO ) ;
2016-10-01 02:24:04 +08:00
}
}
2017-04-04 07:00:17 +08:00
void VcpkgCmdArguments : : check_exact_arg_count ( const size_t expected_arg_count , const std : : string & example_text ) const
2016-10-01 02:24:04 +08:00
{
const size_t actual_arg_count = command_arguments . size ( ) ;
if ( actual_arg_count ! = expected_arg_count )
{
2017-04-04 07:31:00 +08:00
System : : println ( System : : Color : : error , " Error: `%s` requires %u arguments, but %u were provided " , this - > command , expected_arg_count , actual_arg_count ) ;
2016-10-01 02:24:04 +08:00
System : : print ( example_text ) ;
2017-03-23 08:46:05 +08:00
Checks : : exit_fail ( VCPKG_LINE_INFO ) ;
2016-09-19 11:50:08 +08:00
}
}
}