From c0409773d99d3a8c8cf2d70d2c163dfde46ba388 Mon Sep 17 00:00:00 2001 From: bspinner <4580497+bspinner@users.noreply.github.com> Date: Tue, 29 Oct 2024 14:10:11 +0100 Subject: [PATCH 1/2] Executes scripts with same dart/melos combination as currently running --- packages/melos/lib/src/scripts.dart | 45 ++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/packages/melos/lib/src/scripts.dart b/packages/melos/lib/src/scripts.dart index 8d172b29..20221df6 100644 --- a/packages/melos/lib/src/scripts.dart +++ b/packages/melos/lib/src/scripts.dart @@ -3,6 +3,7 @@ import 'dart:collection'; import 'package:collection/collection.dart'; import 'package:meta/meta.dart'; +import 'common/platform.dart'; import 'common/utils.dart'; import 'common/validation.dart'; import 'package.dart'; @@ -318,7 +319,8 @@ class Script { if (exec == null) { return scriptCommand; } else { - final execCommand = ['melos', 'exec']; + /// `dart melos.dart exec` or `melos exec` with absolute paths + final execCommand = [..._determineMelosExecutablePaths(), 'exec']; if (exec.concurrency != null) { execCommand.addAll(['--concurrency', '${exec.concurrency}']); @@ -338,6 +340,47 @@ class Script { } } + /// Identifies path of currently running melos and reuses it for nested script execution. + /// + /// Starting melos by just calling `melos` via shell + /// would use the first found binary found in `$PATH`, + /// i.e. usually the globally activated version. If there is one. + /// + /// This can cause issues when melos is started with `dart run melos`, + /// which will prefer the melos version specified via (dev_)dependencies. + /// So the initially started melos binary/script and the one used for melos script execution + /// could differ. + /// + /// Besides ensuring starting the same melos as currently running, + /// this furthermore enables use of melos in environments + /// where `.pub-cache/bin` should/must not be put in `$PATH`. + List _determineMelosExecutablePaths() { + final currentExecutablePathString = currentPlatform.resolvedExecutable; + final currentExecutablePathUri = Uri.file(currentExecutablePathString); + if (!currentExecutablePathUri.isAbsolute) { + throw 'Got invalid, unsupported or relative path to running executable. Expected absolute path.'; + } + + final currentScriptPathUri = currentPlatform.script; + final currentScriptPathString = currentScriptPathUri.toFilePath(); + if (!currentScriptPathString.isEmpty && !currentScriptPathUri.isAbsolute) { + throw 'Got invalid, unsupported or relative path to melos. Expected absolute path.'; + } + + // Determine if melos is running as script or compiled binary + final isScriptPathAvailable = !currentScriptPathString.isEmpty; + final isCompiledMelosRunning = + currentExecutablePathUri == currentScriptPathUri; + + if (!isScriptPathAvailable || isCompiledMelosRunning) { + return [currentExecutablePathString]; + } + + // currentExecutablePathString => path to dart binary + // currentScriptPathUri => path to melos.dart + return [currentExecutablePathString, currentScriptPathString]; + } + /// Validates the script. Throws a [MelosConfigException] if the script is /// invalid. void validate() { From c1f5d002e054ad9eb0a1c63ef0d5e593dfbfa0e6 Mon Sep 17 00:00:00 2001 From: bspinner <4580497+bspinner@users.noreply.github.com> Date: Tue, 29 Oct 2024 14:15:37 +0100 Subject: [PATCH 2/2] Fixes analysis issues --- packages/melos/lib/src/scripts.dart | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/melos/lib/src/scripts.dart b/packages/melos/lib/src/scripts.dart index 20221df6..80205a8b 100644 --- a/packages/melos/lib/src/scripts.dart +++ b/packages/melos/lib/src/scripts.dart @@ -340,7 +340,8 @@ class Script { } } - /// Identifies path of currently running melos and reuses it for nested script execution. + /// Identifies path of currently running melos and reuses it + /// for nested script execution. /// /// Starting melos by just calling `melos` via shell /// would use the first found binary found in `$PATH`, @@ -352,23 +353,28 @@ class Script { /// could differ. /// /// Besides ensuring starting the same melos as currently running, - /// this furthermore enables use of melos in environments - /// where `.pub-cache/bin` should/must not be put in `$PATH`. + /// this furthermore enables use of melos in environments where + /// `.pub-cache/bin` should/must not be put in `$PATH`. List _determineMelosExecutablePaths() { final currentExecutablePathString = currentPlatform.resolvedExecutable; final currentExecutablePathUri = Uri.file(currentExecutablePathString); if (!currentExecutablePathUri.isAbsolute) { - throw 'Got invalid, unsupported or relative path to running executable. Expected absolute path.'; + throw FormatException( + 'Got invalid, unsupported or relative path to running executable.' + 'Expected absolute path.'); } final currentScriptPathUri = currentPlatform.script; final currentScriptPathString = currentScriptPathUri.toFilePath(); - if (!currentScriptPathString.isEmpty && !currentScriptPathUri.isAbsolute) { - throw 'Got invalid, unsupported or relative path to melos. Expected absolute path.'; + if (currentScriptPathString.isNotEmpty && + !currentScriptPathUri.isAbsolute) { + throw FormatException( + 'Got invalid, unsupported or relative path to melos.' + 'Expected absolute path.'); } // Determine if melos is running as script or compiled binary - final isScriptPathAvailable = !currentScriptPathString.isEmpty; + final isScriptPathAvailable = currentScriptPathString.isNotEmpty; final isCompiledMelosRunning = currentExecutablePathUri == currentScriptPathUri;