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();
+  });
 }