Skip to content

Commit af2bd50

Browse files
committed
fix: merge conflicts
2 parents f7b735f + a4505cf commit af2bd50

13 files changed

Lines changed: 1113 additions & 96 deletions

File tree

lib/src/commands/create/commands/create_subcommand.dart

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -169,20 +169,13 @@ abstract class CreateSubCommand extends Command<int> {
169169
return name;
170170
}
171171

172-
/// Resolves the value for the argument named [name] against the matching
173-
/// `very_good.yaml` [configValue].
174-
///
175-
/// A command line argument that was explicitly parsed always wins. Otherwise
176-
/// the [configValue] is used when present, falling back to the argument's
177-
/// default value.
178-
T? resolveArg<T>(String name, T? configValue) {
179-
if (argResults.wasParsed(name)) return argResults[name] as T?;
180-
return configValue ?? argResults[name] as T?;
181-
}
182-
183172
/// Gets the description for the project.
184-
String get projectDescription =>
185-
resolveArg<String>('description', createConfig.description) ?? '';
173+
String get projectDescription => resolveArg<String>(
174+
argResults,
175+
'description',
176+
createConfig.description,
177+
fallbackValue: '',
178+
);
186179

187180
/// Should return the desired template to be created during a command run.
188181
///
@@ -292,7 +285,12 @@ mixin OrgName on CreateSubCommand {
292285
/// Gets the organization name.
293286
String get orgName {
294287
final orgName =
295-
resolveArg<String>('org-name', createConfig.orgName) ?? _defaultOrgName;
288+
resolveArg<String>(
289+
argResults,
290+
'org-name',
291+
createConfig.orgName,
292+
fallbackValue: _defaultOrgName,
293+
);
296294
_validateOrgName(orgName);
297295
return orgName;
298296
}
@@ -337,8 +335,12 @@ mixin MultiTemplates on CreateSubCommand {
337335
@override
338336
Template get template {
339337
final templateName =
340-
resolveArg<String>('template', createConfig.template) ??
341-
defaultTemplateName;
338+
resolveArg<String>(
339+
argResults,
340+
'template',
341+
createConfig.template,
342+
fallbackValue: defaultTemplateName,
343+
);
342344

343345
return templates.firstWhere(
344346
(template) => template.name == templateName,
@@ -357,5 +359,10 @@ mixin MultiTemplates on CreateSubCommand {
357359
mixin Publishable on CreateSubCommand {
358360
/// Gets the publishable flag.
359361
bool get publishable =>
360-
resolveArg<bool>('publishable', createConfig.publishable) ?? false;
362+
resolveArg<bool>(
363+
argResults,
364+
'publishable',
365+
createConfig.publishable,
366+
fallbackValue: false,
367+
);
361368
}

lib/src/commands/create/commands/docs_site.dart

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'package:very_good_cli/src/commands/commands.dart';
22
import 'package:very_good_cli/src/commands/create/templates/templates.dart';
3+
import 'package:very_good_cli/src/very_good_config/very_good_config.dart';
34

45
/// {@template very_good_create_docs_site}
56
/// A [CreateSubCommand] for creating Dart command line interfaces.
@@ -30,9 +31,12 @@ class CreateDocsSite extends CreateSubCommand with Publishable {
3031
Map<String, dynamic> getTemplateVars() {
3132
return <String, dynamic>{
3233
...super.getTemplateVars(),
33-
'org_name':
34-
resolveArg<String>('org-name', createConfig.orgName) ??
35-
_defaultOrgName,
34+
'org_name': resolveArg<String>(
35+
argResults,
36+
'org-name',
37+
createConfig.orgName,
38+
fallbackValue: _defaultOrgName,
39+
),
3640
};
3741
}
3842

lib/src/commands/packages/commands/check/commands/licenses.dart

Lines changed: 118 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import 'package:pana/src/license_detection/license_detector.dart' as detector;
2121
import 'package:path/path.dart' as path;
2222
import 'package:very_good_cli/src/pub_license/spdx_license.gen.dart';
2323
import 'package:very_good_cli/src/pubspec_lock/pubspec_lock.dart';
24+
import 'package:very_good_cli/src/very_good_config/very_good_config.dart';
2425

2526
/// Overrides the [package_config.findPackageConfig] function for testing.
2627
@visibleForTesting
@@ -65,6 +66,87 @@ typedef _DependencyLicenseMap = Map<String, Set<String>?>;
6566
/// as values.
6667
typedef _BannedDependencyLicenseMap = Map<String, Set<String>>;
6768

69+
/// Options for configuring the `very_good packages check licenses` command.
70+
class PackagesCheckLicensesOptions {
71+
PackagesCheckLicensesOptions._({
72+
required this.ignoreRetrievalFailures,
73+
required this.dependencyTypes,
74+
required this.allowedLicenses,
75+
required this.forbiddenLicenses,
76+
required this.skippedPackages,
77+
required this.reporterOutputFormat,
78+
});
79+
80+
/// Parses [ArgResults] into a [PackagesCheckLicensesOptions] instance.
81+
///
82+
/// When [config] is provided, its values are used as defaults for any
83+
/// option that was not explicitly parsed on the command line.
84+
factory PackagesCheckLicensesOptions.parse(
85+
ArgResults argResults, {
86+
VeryGoodConfig config = VeryGoodConfig.empty,
87+
}) {
88+
final licensesConfig = config.packages.check.licenses;
89+
90+
final ignoreRetrievalFailures = resolveArg(
91+
argResults,
92+
'ignore-retrieval-failures',
93+
licensesConfig.ignoreRetrievalFailures,
94+
);
95+
final dependencyTypes = resolveArg<List<String>>(
96+
argResults,
97+
'dependency-type',
98+
licensesConfig.dependencyType,
99+
);
100+
final allowedLicenses = resolveArg<List<String>>(
101+
argResults,
102+
'allowed',
103+
licensesConfig.allowed,
104+
);
105+
final forbiddenLicenses = resolveArg<List<String>>(
106+
argResults,
107+
'forbidden',
108+
licensesConfig.forbidden,
109+
);
110+
final skippedPackages = resolveArg<List<String>>(
111+
argResults,
112+
'skip-packages',
113+
licensesConfig.skipPackages,
114+
);
115+
final reporter = resolveArg<String?>(
116+
argResults,
117+
'reporter',
118+
licensesConfig.reporter,
119+
);
120+
121+
return PackagesCheckLicensesOptions._(
122+
ignoreRetrievalFailures: ignoreRetrievalFailures,
123+
dependencyTypes: dependencyTypes.toSet(),
124+
allowedLicenses: allowedLicenses.withoutBlanks,
125+
forbiddenLicenses: forbiddenLicenses.withoutBlanks,
126+
skippedPackages: skippedPackages.toSet(),
127+
reporterOutputFormat: ReporterOutputFormat.fromString(reporter),
128+
);
129+
}
130+
131+
/// Whether to disregard licenses that failed to be retrieved.
132+
final bool ignoreRetrievalFailures;
133+
134+
/// The type of dependencies to check licenses for.
135+
final Set<String> dependencyTypes;
136+
137+
/// The only licenses allowed to be used.
138+
final List<String> allowedLicenses;
139+
140+
/// The licenses denied from being used.
141+
final List<String> forbiddenLicenses;
142+
143+
/// Packages skipped from having their licenses checked.
144+
final Set<String> skippedPackages;
145+
146+
/// The format used to list all licenses.
147+
final ReporterOutputFormat? reporterOutputFormat;
148+
}
149+
68150
/// {@template packages_check_licenses_command}
69151
/// `very_good packages check licenses` command for checking packages licenses.
70152
/// {@endtemplate}
@@ -132,19 +214,27 @@ class PackagesCheckLicensesCommand extends Command<int> {
132214
usageException('Too many arguments');
133215
}
134216

135-
final ignoreFailures = _argResults['ignore-retrieval-failures'] as bool;
136-
final dependencyTypes = _argResults['dependency-type'] as List<String>;
137-
final allowedLicenses = _argResults['allowed'] as List<String>;
138-
final forbiddenLicenses = _argResults['forbidden'] as List<String>;
139-
final skippedPackages = _argResults['skip-packages'] as List<String>;
140-
final reporterOutput = _argResults['reporter'] as String?;
217+
final target = _argResults.rest.length == 1 ? _argResults.rest[0] : '.';
218+
final targetPath = path.normalize(Directory(target).absolute.path);
141219

142-
final reporterOutputFormat = ReporterOutputFormat.fromString(
143-
reporterOutput,
220+
final VeryGoodConfig config;
221+
try {
222+
config = VeryGoodConfig.loadFromClosestAncestor(Directory(targetPath));
223+
} on VeryGoodConfigParseException catch (e) {
224+
_logger.err(
225+
'Could not read `$veryGoodConfigFileName`.\n'
226+
'${e.message}',
227+
);
228+
return ExitCode.config.code;
229+
}
230+
231+
final options = PackagesCheckLicensesOptions.parse(
232+
_argResults,
233+
config: config,
144234
);
145235

146-
allowedLicenses.removeWhere((license) => license.trim().isEmpty);
147-
forbiddenLicenses.removeWhere((license) => license.trim().isEmpty);
236+
final allowedLicenses = options.allowedLicenses;
237+
final forbiddenLicenses = options.forbiddenLicenses;
148238

149239
if (allowedLicenses.isNotEmpty && forbiddenLicenses.isNotEmpty) {
150240
usageException(
@@ -166,8 +256,6 @@ class PackagesCheckLicensesCommand extends Command<int> {
166256
);
167257
}
168258

169-
final target = _argResults.rest.length == 1 ? _argResults.rest[0] : '.';
170-
final targetPath = path.normalize(Directory(target).absolute.path);
171259
final targetDirectory = Directory(targetPath);
172260
if (!targetDirectory.existsSync()) {
173261
_logger.err(
@@ -195,24 +283,24 @@ class PackagesCheckLicensesCommand extends Command<int> {
195283
final filteredDependencies = pubspecLock.packages.where((dependency) {
196284
if (!dependency.isPubHosted) return false;
197285

198-
if (skippedPackages.contains(dependency.name)) return false;
286+
if (options.skippedPackages.contains(dependency.name)) return false;
199287

200288
final dependencyType = dependency.type;
201-
return (dependencyTypes.contains('direct-main') &&
289+
return (options.dependencyTypes.contains('direct-main') &&
202290
dependencyType == PubspecLockPackageDependencyType.directMain) ||
203-
(dependencyTypes.contains('direct-dev') &&
291+
(options.dependencyTypes.contains('direct-dev') &&
204292
dependencyType == PubspecLockPackageDependencyType.directDev) ||
205-
(dependencyTypes.contains('transitive') &&
293+
(options.dependencyTypes.contains('transitive') &&
206294
dependencyType == PubspecLockPackageDependencyType.transitive) ||
207-
(dependencyTypes.contains('direct-overridden') &&
295+
(options.dependencyTypes.contains('direct-overridden') &&
208296
dependencyType ==
209297
PubspecLockPackageDependencyType.directOverridden);
210298
});
211299

212300
if (filteredDependencies.isEmpty) {
213301
progress.cancel();
214302
_logger.info(
215-
'''No hosted dependencies found in $targetPath of type: ${dependencyTypes.stringify()}.''',
303+
'''No hosted dependencies found in $targetPath of type: ${options.dependencyTypes.stringify()}.''',
216304
);
217305
return ExitCode.success.code;
218306
}
@@ -240,7 +328,7 @@ class PackagesCheckLicensesCommand extends Command<int> {
240328
if (cachePackageEntry == null) {
241329
final errorMessage =
242330
'''[$dependencyName] Could not find cached package path. Consider running `dart pub get` or `flutter pub get` to generate a new `package_config.json`.''';
243-
if (!ignoreFailures) {
331+
if (!options.ignoreRetrievalFailures) {
244332
progress.cancel();
245333
_logger.err(errorMessage);
246334
return ExitCode.noInput.code;
@@ -256,7 +344,7 @@ class PackagesCheckLicensesCommand extends Command<int> {
256344
if (!packageDirectory.existsSync()) {
257345
final errorMessage =
258346
'''[$dependencyName] Could not find package directory at $packagePath.''';
259-
if (!ignoreFailures) {
347+
if (!options.ignoreRetrievalFailures) {
260348
progress.cancel();
261349
_logger.err(errorMessage);
262350
return ExitCode.noInput.code;
@@ -284,7 +372,7 @@ class PackagesCheckLicensesCommand extends Command<int> {
284372
} on Exception catch (e) {
285373
final errorMessage =
286374
'''[$dependencyName] Failed to detect license from $packagePath: $e''';
287-
if (!ignoreFailures) {
375+
if (!options.ignoreRetrievalFailures) {
288376
progress.cancel();
289377
_logger.err(errorMessage);
290378
return ExitCode.software.code;
@@ -326,7 +414,7 @@ class PackagesCheckLicensesCommand extends Command<int> {
326414
_composeReport(
327415
licenses: licenses,
328416
bannedDependencies: bannedDependencies,
329-
reporterOutputFormat: reporterOutputFormat,
417+
reporterOutputFormat: options.reporterOutputFormat,
330418
),
331419
);
332420

@@ -522,15 +610,20 @@ String _composeBannedReport(_BannedDependencyLicenseMap bannedDependencies) {
522610
return '''${bannedDependencies.length} $prefix $suffix: ${bannedDependenciesList.stringify()}.''';
523611
}
524612

525-
extension on List<Object> {
613+
extension on Iterable<Object> {
526614
String stringify() {
527615
if (isEmpty) return '';
528616
if (length == 1) return first.toString();
529-
final last = removeLast();
530-
return '${join(', ')} and $last';
617+
return '${take(length - 1).join(', ')} and $last';
531618
}
532619
}
533620

621+
extension on List<String> {
622+
/// The licenses that are not blank.
623+
List<String> get withoutBlanks =>
624+
where((license) => license.trim().isNotEmpty).toList();
625+
}
626+
534627
/// Format type for listing all licenses via --reporter option.
535628
enum ReporterOutputFormat {
536629
/// List all licenses separated by a dash.

0 commit comments

Comments
 (0)