Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move dependencyOverridePaths to command/bootstrap
Browse files Browse the repository at this point in the history
blaugold committed Dec 20, 2022
1 parent 5c8d47c commit da2c275
Showing 7 changed files with 111 additions and 77 deletions.
37 changes: 19 additions & 18 deletions docs/configuration/overview.mdx
Original file line number Diff line number Diff line change
@@ -8,8 +8,9 @@ description: Configure Melos using the `melos.yaml` file.
Every project requires a `melos.yaml` project in the root. The below outlines
all the configurable fields and their purpose.

Additionally, projects may include a `melos_overrides.yaml` file to override any `melos.yaml` field. This is useful for
making untracked customizations to a project.
Additionally, projects may include a `melos_overrides.yaml` file to override any
`melos.yaml` field. This is useful for making untracked customizations to a
project.

## `name`

@@ -112,22 +113,6 @@ ignore:
> You can also expand the scope of ignored packages on a per-command basis via
> the [`--scope` filter](/filters#scope) flag.

## `dependencyOverrides`

> optional

A list of extra packages in the workspace directory that should be added to each workspace package's dependency
overrides. Each entry can be a specific path or a [glob] pattern.

Note that this option has a camelCase key, unlike the snake_case key used in `pubspec.yaml`.

Tip: External local packages can be symlinked into the workspace directory.

```yaml
dependencyOverrides:
- 'external_dependencies/**'
```

## `ide`

> optional
@@ -174,6 +159,22 @@ Configuration relating to specific Melos commands such as versioning.

Configuration for the `bootstrap` command.

### `command/bootstrap/dependencyOverridePaths`

> optional

A list of paths to local packages realtive to the workspace directory that
should be added to each workspace package's dependency overrides. Each entry can
be a specific path or a [glob] pattern.

**Tip:** External local packages can be referenced using paths relative to the
workspace root.

```yaml
dependencyOverridePaths:
- '../external_project/packages/**'
```

### `command/bootstrap/runPubGetInParallel`

Whether to run `pub get` in parallel during bootstrapping.
3 changes: 2 additions & 1 deletion packages/melos/lib/src/commands/bootstrap.dart
Original file line number Diff line number Diff line change
@@ -113,7 +113,8 @@ mixin _BootstrapMixin on _CleanMixin {
}

// Add custom workspace overrides.
for (final dependencyOverride in workspace.dependencyOverrides.values) {
for (final dependencyOverride
in workspace.dependencyOverridePackages.values) {
melosDependencyOverrides[dependencyOverride.name] = PathReference(
utils.relativePath(dependencyOverride.path, package.path),
);
11 changes: 0 additions & 11 deletions packages/melos/lib/src/package.dart
Original file line number Diff line number Diff line change
@@ -615,17 +615,6 @@ The packages that caused the problem are:
_logger,
);
}

/// Creates a new [PackageMap] containing the contents of the [overlay]
/// [PackageMap] combined with this [PackageMap]. Any entries in the original
/// with duplicate keys existing in the [overlay] will be overwritten.
///
/// The [MelosLogger] from this [PackageMap] will be used in the resultant
/// [PackageMap].
PackageMap operator +(PackageMap overlay) => PackageMap(
{..._map, ...overlay._map},
_logger,
);
}

extension on Iterable<Package> {
21 changes: 13 additions & 8 deletions packages/melos/lib/src/workspace.dart
Original file line number Diff line number Diff line change
@@ -48,7 +48,7 @@ class MelosWorkspace {
required this.config,
required this.allPackages,
required this.filteredPackages,
required this.dependencyOverrides,
required this.dependencyOverridePackages,
required this.sdkPath,
required this.logger,
});
@@ -66,9 +66,9 @@ class MelosWorkspace {
ignore: workspaceConfig.ignore,
logger: logger,
);
final dependencyOverrides = await PackageMap.resolvePackages(
final dependencyOverridePackages = await PackageMap.resolvePackages(
workspacePath: workspaceConfig.path,
packages: workspaceConfig.dependencyOverrides,
packages: workspaceConfig.commands.bootstrap.dependencyOverridePaths,
ignore: const [],
logger: logger,
);
@@ -82,7 +82,7 @@ class MelosWorkspace {
allPackages: allPackages,
logger: logger,
filteredPackages: filteredPackages,
dependencyOverrides: dependencyOverrides,
dependencyOverridePackages: dependencyOverridePackages,
sdkPath: resolveSdkPath(
configSdkPath: workspaceConfig.sdkPath,
envSdkPath: currentPlatform.environment[utils.envKeyMelosSdkPath],
@@ -104,15 +104,20 @@ class MelosWorkspace {
/// Configuration as defined in the "melos.yaml" file if it exists.
final MelosWorkspaceConfig config;

/// All packages according to [MelosWorkspaceConfig].
/// All packages managed in this Melos workspace.
///
/// Packages filtered by [MelosWorkspaceConfig.ignore] are not included.
/// Packages specified in [MelosWorkspaceConfig.packages] are included,
/// except for those specified in [MelosWorkspaceConfig.ignore].
final PackageMap allPackages;

/// The packages in this Melos workspace after applying filters.
///
/// Filters are typically specified on the command line.
final PackageMap filteredPackages;

/// Packages to use as dependency overrides.
final PackageMap dependencyOverrides;
/// The packages specified in
/// [BootstrapCommandConfigs.dependencyOverridePaths].
final PackageMap dependencyOverridePackages;

late final IdeWorkspace ide = IdeWorkspace._(this);

93 changes: 60 additions & 33 deletions packages/melos/lib/src/workspace_configs.dart
Original file line number Diff line number Diff line change
@@ -168,7 +168,10 @@ class CommandConfigs {
);

return CommandConfigs(
bootstrap: BootstrapCommandConfigs.fromYaml(bootstrapMap ?? const {}),
bootstrap: BootstrapCommandConfigs.fromYaml(
bootstrapMap ?? const {},
workspacePath: workspacePath,
),
version: VersionCommandConfigs.fromYaml(
versionMap ?? const {},
workspacePath: workspacePath,
@@ -216,9 +219,13 @@ class BootstrapCommandConfigs {
const BootstrapCommandConfigs({
this.runPubGetInParallel = true,
this.runPubGetOffline = false,
this.dependencyOverridePaths = const [],
});

factory BootstrapCommandConfigs.fromYaml(Map<Object?, Object?> yaml) {
factory BootstrapCommandConfigs.fromYaml(
Map<Object?, Object?> yaml, {
required String workspacePath,
}) {
final runPubGetInParallel = assertKeyIsA<bool?>(
key: 'runPubGetInParallel',
map: yaml,
@@ -233,9 +240,26 @@ class BootstrapCommandConfigs {
) ??
false;

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

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

@@ -252,10 +276,17 @@ class BootstrapCommandConfigs {
/// The default is `false`.
final bool runPubGetOffline;

/// 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;

Map<String, Object?> toJson() {
return {
'runPubGetInParallel': runPubGetInParallel,
'runPubGetOffline': runPubGetOffline,
if (dependencyOverridePaths.isNotEmpty)
'dependencyOverridePaths':
dependencyOverridePaths.map((path) => path.toString()).toList(),
};
}

@@ -264,20 +295,25 @@ class BootstrapCommandConfigs {
other is BootstrapCommandConfigs &&
runtimeType == other.runtimeType &&
other.runPubGetInParallel == runPubGetInParallel &&
other.runPubGetOffline == runPubGetOffline;
other.runPubGetOffline == runPubGetOffline &&
const DeepCollectionEquality(_GlobEquality())
.equals(other.dependencyOverridePaths, dependencyOverridePaths);

@override
int get hashCode =>
runtimeType.hashCode ^
runPubGetInParallel.hashCode ^
runPubGetOffline.hashCode;
runPubGetOffline.hashCode ^
const DeepCollectionEquality(_GlobEquality())
.hash(dependencyOverridePaths);

@override
String toString() {
return '''
BootstrapCommandConfigs(
runPubGetInParallel: $runPubGetInParallel,
runPubGetOffline: $runPubGetOffline,
dependencyOverridePaths: $dependencyOverridePaths,
)''';
}
}
@@ -556,7 +592,6 @@ class MelosWorkspaceConfig {
this.repository,
required this.packages,
this.ignore = const [],
this.dependencyOverrides = const [],
this.scripts = Scripts.empty,
this.ide = IDEConfigs.empty,
this.commands = CommandConfigs.empty,
@@ -650,16 +685,6 @@ class MelosWorkspaceConfig {
path: 'ignore',
),
);
final dependencyOverrides = assertListIsA<String>(
key: 'dependencyOverrides',
map: yaml,
isRequired: false,
assertItemIsA: (index, value) => assertIsA<String>(
value: value,
index: index,
path: 'dependencyOverrides',
),
);

final scriptsMap = assertKeyIsA<Map<Object?, Object?>?>(
key: 'scripts',
@@ -692,9 +717,6 @@ class MelosWorkspaceConfig {
ignore: ignore
.map((ignore) => createGlob(ignore, currentDirectoryPath: path))
.toList(),
dependencyOverrides: dependencyOverrides
.map((override) => createGlob(override, currentDirectoryPath: path))
.toList(),
scripts: scriptsMap == null
? Scripts.empty
: Scripts.fromYaml(scriptsMap, workspacePath: path),
@@ -806,10 +828,6 @@ You must have one of the following to be a valid Melos workspace:
/// packages.
final List<Glob> ignore;

/// A list of [Glob]s for paths that contain packages to be used as dependency
/// overrides.
final List<Glob> dependencyOverrides;

/// A list of scripts that can be executed with `melos run` or will be
/// executed before/after some specific melos commands.
final Scripts scripts;
@@ -860,10 +878,10 @@ You must have one of the following to be a valid Melos workspace:
other.path == path &&
other.name == name &&
other.repository == repository &&
const DeepCollectionEquality().equals(other.packages, packages) &&
const DeepCollectionEquality().equals(other.ignore, ignore) &&
const DeepCollectionEquality()
.equals(other.dependencyOverrides, dependencyOverrides) &&
const DeepCollectionEquality(_GlobEquality())
.equals(other.packages, packages) &&
const DeepCollectionEquality(_GlobEquality())
.equals(other.ignore, ignore) &&
other.scripts == scripts &&
other.ide == ide &&
other.commands == commands;
@@ -874,9 +892,8 @@ You must have one of the following to be a valid Melos workspace:
path.hashCode ^
name.hashCode ^
repository.hashCode ^
const DeepCollectionEquality().hash(packages) &
const DeepCollectionEquality().hash(ignore) ^
const DeepCollectionEquality().hash(dependencyOverrides) ^
const DeepCollectionEquality(_GlobEquality()).hash(packages) &
const DeepCollectionEquality(_GlobEquality()).hash(ignore) ^
scripts.hashCode ^
ide.hashCode ^
commands.hashCode;
@@ -888,9 +905,6 @@ You must have one of the following to be a valid Melos workspace:
if (repository != null) 'repository': repository!,
'packages': packages.map((p) => p.toString()).toList(),
if (ignore.isNotEmpty) 'ignore': ignore.map((p) => p.toString()).toList(),
if (dependencyOverrides.isNotEmpty)
'dependencyOverrides':
dependencyOverrides.map((p) => p.toString()).toList(),
if (scripts.isNotEmpty) 'scripts': scripts.toJson(),
'ide': ide.toJson(),
'command': commands.toJson(),
@@ -906,10 +920,23 @@ MelosWorkspaceConfig(
repository: $repository,
packages: $packages,
ignore: $ignore,
dependencyOverrides: $dependencyOverrides,
scripts: ${scripts.toString().indent(' ')},
ide: ${ide.toString().indent(' ')},
commands: ${commands.toString().indent(' ')},
)''';
}
}

class _GlobEquality implements Equality<Glob> {
const _GlobEquality();

@override
bool equals(Glob e1, Glob e2) =>
e1.pattern == e2.pattern && e1.context.current == e2.context.current;

@override
int hash(Glob e) => e.pattern.hashCode ^ e.context.current.hashCode;

@override
bool isValidKey(Object? o) => true;
}
2 changes: 1 addition & 1 deletion packages/melos/test/utils.dart
Original file line number Diff line number Diff line change
@@ -294,7 +294,7 @@ class VirtualWorkspaceBuilder {
config: config,
allPackages: packageMap,
filteredPackages: packageMap,
dependencyOverrides: _buildVirtualPackageMap(const [], logger),
dependencyOverridePackages: _buildVirtualPackageMap(const [], logger),
logger: logger,
sdkPath: sdkPath,
);
21 changes: 16 additions & 5 deletions packages/melos/test/workspace_config_test.dart
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@

import 'package:melos/melos.dart';
import 'package:melos/src/common/git_repository.dart';
import 'package:melos/src/common/glob.dart';
import 'package:melos/src/common/platform.dart';
import 'package:melos/src/scripts.dart';
import 'package:melos/src/workspace_configs.dart';
@@ -35,16 +36,19 @@ void main() {
group('fromYaml', () {
test('accepts empty object', () {
expect(
BootstrapCommandConfigs.fromYaml(const {}),
BootstrapCommandConfigs.fromYaml(const {}, workspacePath: '.'),
BootstrapCommandConfigs.empty,
);
});

test('throws if runPubGetInParallel is not a bool', () {
expect(
() => BootstrapCommandConfigs.fromYaml(const {
'runPubGetInParallel': 42,
}),
() => BootstrapCommandConfigs.fromYaml(
const {
'runPubGetInParallel': 42,
},
workspacePath: '.',
),
throwsMelosConfigException(),
);
});
@@ -54,10 +58,17 @@ void main() {
BootstrapCommandConfigs.fromYaml(
const {
'runPubGetInParallel': false,
'runPubGetOffline': true,
'dependencyOverridePaths': ['a'],
},
workspacePath: '.',
),
const BootstrapCommandConfigs(
BootstrapCommandConfigs(
runPubGetInParallel: false,
runPubGetOffline: true,
dependencyOverridePaths: [
createGlob('a', currentDirectoryPath: '.')
],
),
);
});

0 comments on commit da2c275

Please sign in to comment.