Remove Entrypoint._configRoot (#4169)

diff --git a/lib/src/entrypoint.dart b/lib/src/entrypoint.dart
index 782c093..c122cc3 100644
--- a/lib/src/entrypoint.dart
+++ b/lib/src/entrypoint.dart
@@ -57,9 +57,11 @@
 class Entrypoint {
   /// The directory where the package is stored.
   ///
-  /// For global packages this is inside the pub cache.
+  /// For cached global packages this is `PUB_CACHE/global_packages/foo
   ///
-  /// Except for packages globally activated from path.
+  /// For path-activated global packages this is the actual package dir.
+  ///
+  /// The lock file and package configurations are to be found relative to here.
   final String rootDir;
 
   Package? _root;
@@ -74,10 +76,6 @@
         withPubspecOverrides: true,
       );
 
-  /// For a global package, this is the directory that the package is installed
-  /// in. Non-global packages have null.
-  final String? globalDir;
-
   /// The system-wide cache which caches packages that need to be fetched over
   /// the network.
   final SystemCache cache;
@@ -86,8 +84,9 @@
   bool get isCached => p.isWithin(cache.rootDir, rootDir);
 
   /// Whether this is an entrypoint for a globally-activated package.
-  // final bool isGlobal;
-  bool get isGlobal => globalDir != null;
+  ///
+  /// False for path-activated global packages.
+  final bool isCachedGlobal;
 
   /// The lockfile for the entrypoint.
   ///
@@ -171,16 +170,10 @@
 
   Future<PackageGraph>? _packageGraph;
 
-  /// Where the lock file and package configurations are to be found.
-  ///
-  /// Global packages (except those from path source)
-  /// store these in the global cache.
-  String? get _configRoot => isCached ? globalDir : rootDir;
-
   /// The path to the entrypoint's ".dart_tool/package_config.json" file
   /// relative to the current working directory .
   late String packageConfigPath = p.relative(
-    p.normalize(p.join(_configRoot!, '.dart_tool', 'package_config.json')),
+    p.normalize(p.join(rootDir, '.dart_tool', 'package_config.json')),
   );
 
   /// The path to the entrypoint package's pubspec.
@@ -191,17 +184,13 @@
       p.normalize(p.join(rootDir, 'pubspec_overrides.yaml'));
 
   /// The path to the entrypoint package's lockfile.
-  String get lockFilePath => p.normalize(p.join(_configRoot!, 'pubspec.lock'));
-
-  /// The path to the entrypoint package's `.dart_tool/pub` cache directory.
-  ///
-  /// For globally activated packages from path, this is not the same as
-  /// [configRoot], because the snapshots should be stored in the global cache,
-  /// but the configuration is stored at the package itself.
-  String get cachePath => globalDir ?? p.join(rootDir, '.dart_tool/pub');
+  String get lockFilePath => p.normalize(p.join(rootDir, 'pubspec.lock'));
 
   /// The path to the directory containing dependency executable snapshots.
-  String get _snapshotPath => p.join(cachePath, 'bin');
+  String get _snapshotPath => p.join(
+        isCachedGlobal ? rootDir : p.join(rootDir, '.dart_tool/pub'),
+        'bin',
+      );
 
   Entrypoint._(
     this.rootDir,
@@ -210,7 +199,7 @@
     this._packageGraph,
     this.cache,
     this._root,
-    this.globalDir,
+    this.isCachedGlobal,
   );
 
   /// An entrypoint representing a package at [rootDir].
@@ -221,7 +210,7 @@
   })  : _root = preloaded == null
             ? null
             : Package(preloaded.pubspec, rootDir, preloaded.workspacePackages),
-        globalDir = null {
+        isCachedGlobal = false {
     if (p.isWithin(cache.rootDir, rootDir)) {
       fail('Cannot operate on packages inside the cache.');
     }
@@ -241,19 +230,19 @@
         rootDir,
         root.workspaceChildren,
       ),
-      globalDir,
+      isCachedGlobal,
     );
   }
 
   /// Creates an entrypoint given package and lockfile objects.
   /// If a SolveResult is already created it can be passed as an optimization.
   Entrypoint.global(
-    this.globalDir,
     Package this._root,
     this._lockFile,
     this.cache, {
     SolveResult? solveResult,
-  }) : rootDir = _root.dir {
+  })  : rootDir = _root.dir,
+        isCachedGlobal = true {
     if (solveResult != null) {
       _packageGraph =
           Future.value(PackageGraph.fromSolveResult(this, solveResult));
@@ -289,7 +278,7 @@
   /// Returns the contents of the `.dart_tool/package_config` file generated
   /// from this entrypoint based on [lockFile].
   ///
-  /// If [isGlobal] no entry will be created for [root].
+  /// If [isCachedGlobal] no entry will be created for [root].
   Future<String> _packageConfigFile(
     SystemCache cache, {
     VersionConstraint? entrypointSdkConstraint,
@@ -298,7 +287,7 @@
     for (final name in ordered(lockFile.packages.keys)) {
       final id = lockFile.packages[name]!;
       final rootPath =
-          cache.getDirectory(id, relativeFrom: isGlobal ? null : rootDir);
+          cache.getDirectory(id, relativeFrom: isCachedGlobal ? null : rootDir);
       Uri rootUri;
       if (p.isRelative(rootPath)) {
         // Relative paths are relative to the root project, we want them
@@ -318,7 +307,7 @@
       );
     }
 
-    if (!isGlobal) {
+    if (!isCachedGlobal) {
       /// Run through the entire workspace transitive closure and add an entry
       /// for each package.
       for (final package in root.transitiveWorkspace) {
@@ -484,15 +473,6 @@
   /// Except globally activated packages they should precompile executables from
   /// the package itself if they are immutable.
   Future<List<Executable>> get _builtExecutables async {
-    if (isGlobal) {
-      if (isCached) {
-        return root.executablePaths
-            .map((path) => Executable(root.name, path))
-            .toList();
-      } else {
-        return <Executable>[];
-      }
-    }
     final graph = await packageGraph;
     final r = root.immediateDependencies.keys.expand((packageName) {
       final package = graph.packages[packageName]!;
@@ -509,7 +489,7 @@
     if (executables.isEmpty) return;
 
     await log.progress('Building package executables', () async {
-      if (isGlobal) {
+      if (isCachedGlobal) {
         /// Global snapshots might linger in the cache if we don't remove old
         /// snapshots when it is re-activated.
         cleanDir(_snapshotPath);
@@ -582,7 +562,7 @@
   String pathOfExecutable(Executable executable) {
     assert(p.isRelative(executable.relativePath));
     final versionSuffix = sdk.version;
-    return isGlobal
+    return isCachedGlobal
         ? p.join(
             _snapshotPath,
             '${p.basename(executable.relativePath)}-$versionSuffix.snapshot',
diff --git a/lib/src/executable.dart b/lib/src/executable.dart
index ad7df8f..d6c790a 100644
--- a/lib/src/executable.dart
+++ b/lib/src/executable.dart
@@ -78,7 +78,7 @@
   if (!fileExists(executablePath)) {
     var message =
         'Could not find ${log.bold(p.normalize(executable.relativePath))}';
-    if (entrypoint.isGlobal || package != entrypoint.root.name) {
+    if (entrypoint.isCachedGlobal || package != entrypoint.root.name) {
       message += ' in package ${log.bold(package)}';
     }
     log.error('$message.');
diff --git a/lib/src/global_packages.dart b/lib/src/global_packages.dart
index c79e95f..6d59c1c 100644
--- a/lib/src/global_packages.dart
+++ b/lib/src/global_packages.dart
@@ -125,6 +125,18 @@
     );
   }
 
+  Package packageForConstraint(PackageRange dep, String dir) {
+    return Package(
+      Pubspec(
+        'pub global activate',
+        dependencies: [dep],
+        sources: cache.sources,
+      ),
+      dir,
+      [],
+    );
+  }
+
   /// Finds the latest version of the hosted package with [name] that matches
   /// [constraint] and makes it the active global version.
   ///
@@ -211,16 +223,9 @@
     final name = dep.name;
     final originalLockFile = _describeActive(name, cache);
 
+    final tempDir = cache.createTempDir();
     // Create a dummy package with just [dep] so we can do resolution on it.
-    var root = Package(
-      Pubspec(
-        'pub global activate',
-        dependencies: [dep],
-        sources: cache.sources,
-      ),
-      _packageDir(name),
-      [],
-    );
+    var root = packageForConstraint(dep, tempDir);
 
     // Resolve it and download its dependencies.
     SolveResult result;
@@ -271,14 +276,12 @@
         ).show(summary: false);
       }
 
-      final tempDir = cache.createTempDir();
       lockFile.writeToFile(p.join(tempDir, 'pubspec.lock'), cache);
 
       // Load the package graph from [result] so we don't need to re-parse all
       // the pubspecs.
       final entrypoint = Entrypoint.global(
-        tempDir,
-        cache.loadCached(id),
+        root,
         lockFile,
         cache,
         solveResult: result,
@@ -293,8 +296,7 @@
     }
 
     final entrypoint = Entrypoint.global(
-      _packageDir(id.name),
-      cache.loadCached(id),
+      packageForConstraint(dep, _packageDir(dep.name)),
       lockFile,
       cache,
       solveResult: result,
@@ -387,8 +389,7 @@
       // For cached sources, the package itself is in the cache and the
       // lockfile is the one we just loaded.
       entrypoint = Entrypoint.global(
-        _packageDir(id.name),
-        cache.loadCached(id),
+        packageForConstraint(id.toRange(), _packageDir(id.name)),
         lockFile,
         cache,
       );
@@ -401,23 +402,6 @@
       );
     }
 
-    entrypoint.root.pubspec.sdkConstraints.forEach((sdkName, constraint) {
-      var sdk = sdks[sdkName];
-      if (sdk == null) {
-        dataError('${log.bold(name)} ${entrypoint.root.version} requires '
-            'unknown SDK "$name".');
-      } else if (sdkName == 'dart') {
-        if (constraint.effectiveConstraint.allows((sdk as DartSdk).version)) {
-          return;
-        }
-        dataError("${log.bold(name)} ${entrypoint.root.version} doesn't "
-            'support Dart ${sdk.version}.');
-      } else {
-        dataError('${log.bold(name)} ${entrypoint.root.version} requires the '
-            '${sdk.name} SDK, which is unsupported for global executables.');
-      }
-    });
-
     // Check that the SDK constraints the lockFile says we have are honored.
     lockFile.sdkConstraints.forEach((sdkName, constraint) {
       var sdk = sdks[sdkName];
@@ -571,7 +555,7 @@
           final packageExecutables = executables.remove(id.name) ?? [];
 
           if (entrypoint.isCached) {
-            deleteEntry(entrypoint.globalDir!);
+            deleteEntry(_packageDir(id.name));
             await _installInCache(
               id.toRange(),
               packageExecutables,
diff --git a/test/global/run/fails_if_sdk_constraint_is_unmet_test.dart b/test/global/run/fails_if_sdk_constraint_is_unmet_test.dart
index dcda1d2..5631fe3 100644
--- a/test/global/run/fails_if_sdk_constraint_is_unmet_test.dart
+++ b/test/global/run/fails_if_sdk_constraint_is_unmet_test.dart
@@ -21,30 +21,17 @@
       contents: [
         d.dir('bin', [d.file('script.dart', "main(args) => print('ok');")]),
       ],
+      sdk: '3.1.2+3',
     );
 
     await runPub(args: ['global', 'activate', 'foo']);
 
-    await d.hostedCache([
-      d.dir('foo-1.0.0', [d.libPubspec('foo', '1.0.0', sdk: '0.5.6')]),
-    ]).create();
-
-    // Make the snapshot out-of-date, too, so that we load the pubspec with the
-    // SDK constraint in the first place. In practice, the VM snapshot
-    // invalidation logic is based on the version anyway, so this is a safe
-    // assumption.
-    await d.dir(cachePath, [
-      d.dir('global_packages', [
-        d.dir('foo', [
-          d.dir('bin', [d.outOfDateSnapshot('script.dart.snapshot')]),
-        ]),
-      ]),
-    ]).create();
-
     await runPub(
       args: ['global', 'run', 'foo:script'],
-      error: contains("foo 1.0.0 doesn't support Dart 3.1.2+3."),
+      error:
+          contains("foo as globally activated doesn't support Dart 3.1.2+4."),
       exitCode: exit_codes.DATA,
+      environment: {'_PUB_TEST_SDK_VERSION': '3.1.2+4'},
     );
   });
 
@@ -72,7 +59,7 @@
         '_PUB_TEST_SDK_VERSION': '3.0.0',
       },
       args: ['global', 'run', 'foo:script'],
-      error: contains("foo 1.0.0 doesn't support Dart 3.0.0."),
+      error: contains("foo as globally activated doesn't support Dart 3.0.0."),
       exitCode: exit_codes.DATA,
     );
   });