Fix package name when refreshing binstubs (#4205)
diff --git a/lib/src/global_packages.dart b/lib/src/global_packages.dart index ab80d24..9ce849c 100644 --- a/lib/src/global_packages.dart +++ b/lib/src/global_packages.dart
@@ -371,7 +371,7 @@ /// Returns an [Entrypoint] loaded with the active package if found. Future<Entrypoint> find(String name) async { var lockFilePath = _getLockFilePath(name); - late LockFile lockFile; + late final LockFile lockFile; try { lockFile = LockFile.load(lockFilePath, cache.sources); } on IOException { @@ -379,11 +379,7 @@ dataError('No active package ${log.bold(name)}.'); } - // Remove the package itself from the lockfile. We put it in there so we - // could find and load the [Package] object, but normally an entrypoint - // doesn't expect to be in its own lockfile. - var id = lockFile.packages[name]!; - lockFile = lockFile.removePackage(name); + final id = lockFile.packages[name]!; Entrypoint entrypoint; if (id.source is CachedSource) { @@ -624,7 +620,7 @@ log.fine('Replacing old binstub $file'); deleteEntry(file); _createBinStub( - entrypoint.workspaceRoot, + activatedPackage(entrypoint), p.basenameWithoutExtension(file), binStubScript, overwrite: true, @@ -947,3 +943,17 @@ return match == null ? null : match[1]; } } + +/// The package that was activated. +/// +/// * For path packages this is [Entrypoint.workspaceRoot]. +/// * For cached packages this is the sole dependency of +/// [Entrypoint.workspaceRoot]. +Package activatedPackage(Entrypoint entrypoint) { + if (entrypoint.isCachedGlobal) { + final dep = entrypoint.workspaceRoot.dependencies.keys.single; + return entrypoint.cache.load(entrypoint.lockFile.packages[dep]!); + } else { + return entrypoint.workspaceRoot; + } +}
diff --git a/test/global/binstubs/binstub_runs_global_run_if_no_snapshot_test.dart b/test/global/binstubs/binstub_runs_global_run_if_no_snapshot_test.dart index b3a804a..8888c8f 100644 --- a/test/global/binstubs/binstub_runs_global_run_if_no_snapshot_test.dart +++ b/test/global/binstubs/binstub_runs_global_run_if_no_snapshot_test.dart
@@ -2,6 +2,9 @@ // 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:path/path.dart' as p; import 'package:test/test.dart'; import '../../descriptor.dart' as d; @@ -32,4 +35,60 @@ ]), ]).validate(); }); + + test( + 'the binstubs of hosted package runs pub global run if there is no snapshot', + () async { + final server = await servePackages(); + server.serve( + 'foo', + '1.0.0', + contents: [ + d.dir('bin', [d.file('script.dart', "main() => print('ok');")]), + ], + pubspec: { + 'name': 'foo', + 'executables': {'foo-script': 'script'}, + }, + ); + + await runPub( + args: ['global', 'activate', 'foo'], + output: contains('Installed executable foo-script.'), + ); + + await d.dir(cachePath, [ + d.dir('bin', [ + d.file( + binStubName('foo-script'), + contains('global run foo:script'), + ), + ]), + ]).validate(); + + // Force refresh of snapshot/binstub + Directory( + p.join(d.sandbox, cachePath, 'global_packages', 'foo', 'bin'), + ).deleteSync(recursive: true); + final binstub = p.join( + d.sandbox, + cachePath, + 'bin', + 'foo-script${Platform.isWindows ? '.bat' : ''}', + ); + final result = + await Process.run(binstub, [], environment: getPubTestEnvironment()); + expect(result.stderr, ''); + expect(result.exitCode, 0); + expect(result.stdout, contains('ok')); + + await d.dir(cachePath, [ + d.dir('bin', [ + d.file( + binStubName('foo-script'), + contains('global run foo:script'), + ), + ]), + ]).validate(); + }); }