blob: 56b3992b376db8ac65fd702bed00dd2e103856f4 [file] [log] [blame]
// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:io';
import 'package:args/args.dart';
class BaselineOptions {
final List<String> builders;
final Map<String, List<String>> configs;
final bool dryRun;
final List<String> channels;
final ConfigurationMapping mapping;
final Set<String> suites;
final String target;
BaselineOptions(this.builders, this.configs, this.dryRun, this.channels,
this.mapping, this.suites, this.target);
factory BaselineOptions.parse(List<String> arguments) {
var parser = ArgParser();
parser.addMultiOption('channel',
abbr: 'c',
allowed: ['main', 'dev', 'beta', 'stable'],
defaultsTo: ['main'],
help: 'a comma separated list of channels');
parser.addMultiOption('config-mapping',
abbr: 'm',
defaultsTo: ['*'],
help: 'a comma separated list of configuration mappings in the form:'
'<old1>:<new1>,<old2>:<new2>');
parser.addMultiOption('builders',
abbr: 'b',
help: 'a comma separated list of builders to read result data from');
parser.addMultiOption('suites',
abbr: 's', help: 'a comma separated list of test suites to include');
parser.addOption('target',
abbr: 't', help: 'a the name of the builder to baseline');
parser.addFlag('dry-run',
abbr: 'n',
defaultsTo: false,
help: 'prevents writes and only processes a single result',
negatable: false);
parser.addFlag('ignore-unmapped',
abbr: 'u',
defaultsTo: false,
help: 'ignore tests in unmapped configurations',
negatable: false);
parser.addFlag('help',
abbr: 'h', negatable: false, help: 'prints this message');
var parsed = parser.parse(arguments);
if (parsed['help'] ||
parsed['builders'] is! List<String> ||
parsed['target'] is! String) {
print(parser.usage);
exit(64);
}
var builders = (parsed['builders'] as List<String>);
final target = parsed['target'];
if (builders.isEmpty) {
builders = [target];
}
var mapping = parsed['ignore-unmapped']
? ConfigurationMapping.relaxed
: ConfigurationMapping.strict;
var configs = const <String, List<String>>{};
final configMapping = parsed['config-mapping'] as List<String>;
if (configMapping.length == 1 && configMapping.first == '*') {
mapping = ConfigurationMapping.none;
} else {
configs = {};
for (var mapping in configMapping.map((c) => c.split(':'))) {
configs.putIfAbsent(mapping.first, () => []).add(mapping.last);
}
}
final dryRun = parsed['dry-run'];
final channels = parsed['channel'];
final suites = Set.unmodifiable(parsed['suites'] as List<String>);
return BaselineOptions(
builders, configs, dryRun, channels, mapping, suites, target);
}
}
List<String>? _strict(
String configuration, Map<String, List<String>> configs) =>
configs[configuration] ??
(throw Exception("Missing configuration mapping for $configuration"));
List<String>? _relaxed(
String configuration, Map<String, List<String>> configs) =>
configs[configuration];
List<String>? _none(String configuration, Map<String, List<String>> configs) =>
[configuration];
enum ConfigurationMapping {
none(_none),
strict(_strict),
relaxed(_relaxed);
const ConfigurationMapping(this.mapping);
final List<String>? Function(
String configuration, Map<String, List<String>> configs) mapping;
List<String>? call(String configuration, Map<String, List<String>> configs) =>
mapping(configuration, configs);
}