Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Move CommandConfigs and LifecycleHooks to their own directories #652

Merged
merged 3 commits into from
Mar 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 3 additions & 7 deletions packages/melos/lib/melos.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export 'src/command_configs/command_configs.dart'
show BootstrapCommandConfigs, CleanCommandConfigs, VersionCommandConfigs;
export 'src/commands/runner.dart'
show
BootstrapException,
Expand Down Expand Up @@ -29,10 +31,4 @@ export 'src/package.dart'
export 'src/scripts.dart' show ExecOptions, Script, Scripts;
export 'src/workspace.dart' show IdeWorkspace, MelosWorkspace;
export 'src/workspace_configs.dart'
show
BootstrapCommandConfigs,
CommandConfigs,
IDEConfigs,
IntelliJConfig,
MelosWorkspaceConfig,
VersionCommandConfigs;
show IDEConfigs, IntelliJConfig, MelosWorkspaceConfig;
222 changes: 222 additions & 0 deletions packages/melos/lib/src/command_configs/bootstrap.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
import 'package:collection/collection.dart';
import 'package:glob/glob.dart';
import 'package:meta/meta.dart';
import 'package:pubspec/pubspec.dart';

import '../common/glob.dart';
import '../common/glob_equality.dart';
import '../common/utils.dart';
import '../common/validation.dart';
import '../lifecycle_hooks/lifecycle_hooks.dart';

/// Configurations for `melos bootstrap`.
@immutable
class BootstrapCommandConfigs {
const BootstrapCommandConfigs({
this.runPubGetInParallel = true,
this.runPubGetOffline = false,
this.enforceLockfile = false,
this.environment,
this.dependencies,
this.devDependencies,
this.dependencyOverridePaths = const [],
this.hooks = LifecycleHooks.empty,
});

factory BootstrapCommandConfigs.fromYaml(
Map<Object?, Object?> yaml, {
required String workspacePath,
}) {
final runPubGetInParallel = assertKeyIsA<bool?>(
key: 'runPubGetInParallel',
map: yaml,
path: 'command/bootstrap',
) ??
true;

final runPubGetOffline = assertKeyIsA<bool?>(
key: 'runPubGetOffline',
map: yaml,
path: 'command/bootstrap',
) ??
false;

final enforceLockfile = assertKeyIsA<bool?>(
key: 'enforceLockfile',
map: yaml,
path: 'command/bootstrap',
) ??
false;

final environment = assertKeyIsA<Map<Object?, Object?>?>(
key: 'environment',
map: yaml,
).let(Environment.fromJson);

final dependencies = assertKeyIsA<Map<Object?, Object?>?>(
key: 'dependencies',
map: yaml,
)?.map(
(key, value) => MapEntry(
key.toString(),
DependencyReference.fromJson(value),
),
);

final devDependencies = assertKeyIsA<Map<Object?, Object?>?>(
key: 'dev_dependencies',
map: yaml,
)?.map(
(key, value) => MapEntry(
key.toString(),
DependencyReference.fromJson(value),
),
);

final dependencyOverridePaths = assertListIsA<String>(
key: 'dependencyOverridePaths',
map: yaml,
isRequired: false,
assertItemIsA: (index, value) => assertIsA<String>(
value: value,
index: index,
path: 'dependencyOverridePaths',
),
);

final hooksMap = assertKeyIsA<Map<Object?, Object?>?>(
key: 'hooks',
map: yaml,
path: 'command/bootstrap',
);
final hooks = hooksMap != null
? LifecycleHooks.fromYaml(hooksMap, workspacePath: workspacePath)
: LifecycleHooks.empty;

return BootstrapCommandConfigs(
runPubGetInParallel: runPubGetInParallel,
runPubGetOffline: runPubGetOffline,
enforceLockfile: enforceLockfile,
environment: environment,
dependencies: dependencies,
devDependencies: devDependencies,
dependencyOverridePaths: dependencyOverridePaths
.map(
(override) =>
createGlob(override, currentDirectoryPath: workspacePath),
)
.toList(),
hooks: hooks,
);
}

static const BootstrapCommandConfigs empty = BootstrapCommandConfigs();

/// Whether to run `pub get` in parallel during bootstrapping.
///
/// The default is `true`.
final bool runPubGetInParallel;

/// Whether to attempt to run `pub get` in offline mode during bootstrapping.
/// Useful in closed network environments with pre-populated pubcaches.
///
/// The default is `false`.
final bool runPubGetOffline;

/// Whether `pubspec.lock` is enforced when running `pub get` or not.
/// Useful when you want to ensure the same versions of dependencies are used
/// across different environments/machines.
///
/// The default is `false`.
final bool enforceLockfile;

/// Environment configuration to be synced between all packages.
final Environment? environment;

/// Dependencies to be synced between all packages.
final Map<String, DependencyReference>? dependencies;

/// Dev dependencies to be synced between all packages.
final Map<String, DependencyReference>? devDependencies;

/// A list of [Glob]s for paths that contain packages to be used as dependency
/// overrides for all packages managed in the Melos workspace.
final List<Glob> dependencyOverridePaths;

/// Lifecycle hooks for this command.
final LifecycleHooks hooks;

Map<String, Object?> toJson() {
return {
'runPubGetInParallel': runPubGetInParallel,
'runPubGetOffline': runPubGetOffline,
'enforceLockfile': enforceLockfile,
if (environment != null) 'environment': environment!.toJson(),
if (dependencies != null)
'dependencies': dependencies!.map(
(key, value) => MapEntry(key, value.toJson()),
),
if (devDependencies != null)
'dev_dependencies': devDependencies!.map(
(key, value) => MapEntry(key, value.toJson()),
),
if (dependencyOverridePaths.isNotEmpty)
'dependencyOverridePaths':
dependencyOverridePaths.map((path) => path.toString()).toList(),
'hooks': hooks.toJson(),
};
}

@override
bool operator ==(Object other) =>
other is BootstrapCommandConfigs &&
runtimeType == other.runtimeType &&
other.runPubGetInParallel == runPubGetInParallel &&
other.runPubGetOffline == runPubGetOffline &&
other.enforceLockfile == enforceLockfile &&
// Extracting equality from environment here as it does not implement ==
other.environment?.sdkConstraint == environment?.sdkConstraint &&
const DeepCollectionEquality().equals(
other.environment?.unParsedYaml,
environment?.unParsedYaml,
) &&
const DeepCollectionEquality().equals(other.dependencies, dependencies) &&
const DeepCollectionEquality()
.equals(other.devDependencies, devDependencies) &&
const DeepCollectionEquality(GlobEquality())
.equals(other.dependencyOverridePaths, dependencyOverridePaths) &&
other.hooks == hooks;

@override
int get hashCode =>
runtimeType.hashCode ^
runPubGetInParallel.hashCode ^
runPubGetOffline.hashCode ^
enforceLockfile.hashCode ^
// Extracting hashCode from environment here as it does not implement
// hashCode
(environment?.sdkConstraint).hashCode ^
const DeepCollectionEquality().hash(
environment?.unParsedYaml,
) ^
const DeepCollectionEquality().hash(dependencies) ^
const DeepCollectionEquality().hash(devDependencies) ^
const DeepCollectionEquality(GlobEquality())
.hash(dependencyOverridePaths) ^
hooks.hashCode;

@override
String toString() {
return '''
BootstrapCommandConfigs(
runPubGetInParallel: $runPubGetInParallel,
runPubGetOffline: $runPubGetOffline,
enforceLockfile: $enforceLockfile,
environment: $environment,
dependencies: $dependencies,
devDependencies: $devDependencies,
dependencyOverridePaths: $dependencyOverridePaths,
hooks: $hooks,
)''';
}
}
57 changes: 57 additions & 0 deletions packages/melos/lib/src/command_configs/clean.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import 'package:meta/meta.dart';

import '../common/validation.dart';
import '../lifecycle_hooks/lifecycle_hooks.dart';

/// Configurations for `melos clean`.
@immutable
class CleanCommandConfigs {
const CleanCommandConfigs({
this.hooks = LifecycleHooks.empty,
});

factory CleanCommandConfigs.fromYaml(
Map<Object?, Object?> yaml, {
required String workspacePath,
}) {
final hooksMap = assertKeyIsA<Map<Object?, Object?>?>(
key: 'hooks',
map: yaml,
path: 'command/clean',
);
final hooks = hooksMap != null
? LifecycleHooks.fromYaml(hooksMap, workspacePath: workspacePath)
: LifecycleHooks.empty;

return CleanCommandConfigs(
hooks: hooks,
);
}

static const CleanCommandConfigs empty = CleanCommandConfigs();

final LifecycleHooks hooks;

Map<String, Object?> toJson() {
return {
'hooks': hooks.toJson(),
};
}

@override
bool operator ==(Object other) =>
other is CleanCommandConfigs &&
runtimeType == other.runtimeType &&
other.hooks == hooks;

@override
int get hashCode => runtimeType.hashCode ^ hooks.hashCode;

@override
String toString() {
return '''
CleanCommandConfigs(
hooks: $hooks,
)''';
}
}
Loading
Loading