Index: sdk/lib/_internal/pub_generated/lib/src/entrypoint.dart |
diff --git a/sdk/lib/_internal/pub_generated/lib/src/entrypoint.dart b/sdk/lib/_internal/pub_generated/lib/src/entrypoint.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b36827b6bff8b5b869dffae778bb2aa8372c1e22 |
--- /dev/null |
+++ b/sdk/lib/_internal/pub_generated/lib/src/entrypoint.dart |
@@ -0,0 +1,281 @@ |
+library pub.entrypoint; |
+import 'dart:async'; |
+import 'package:path/path.dart' as path; |
+import 'package:barback/barback.dart'; |
+import 'barback/asset_environment.dart'; |
+import 'io.dart'; |
+import 'lock_file.dart'; |
+import 'log.dart' as log; |
+import 'package.dart'; |
+import 'package_graph.dart'; |
+import 'sdk.dart' as sdk; |
+import 'solver/version_solver.dart'; |
+import 'source/cached.dart'; |
+import 'system_cache.dart'; |
+import 'utils.dart'; |
+class Entrypoint { |
+ final Package root; |
+ final SystemCache cache; |
+ final bool _packageSymlinks; |
+ LockFile _lockFile; |
+ PackageGraph _packageGraph; |
+ Entrypoint(String rootDir, SystemCache cache, {bool packageSymlinks: true}) |
+ : root = new Package.load(null, rootDir, cache.sources), |
+ cache = cache, |
+ _packageSymlinks = packageSymlinks; |
+ Entrypoint.inMemory(this.root, this._lockFile, this.cache) |
+ : _packageSymlinks = false; |
+ String get packagesDir => path.join(root.dir, 'packages'); |
+ bool get lockFileExists => _lockFile != null || entryExists(lockFilePath); |
+ LockFile get lockFile { |
+ if (_lockFile != null) return _lockFile; |
+ if (!lockFileExists) { |
+ _lockFile = new LockFile.empty(); |
+ } else { |
+ _lockFile = new LockFile.load(lockFilePath, cache.sources); |
+ } |
+ return _lockFile; |
+ } |
+ String get pubspecPath => path.join(root.dir, 'pubspec.yaml'); |
+ String get lockFilePath => path.join(root.dir, 'pubspec.lock'); |
+ Future acquireDependencies(SolveType type, {List<String> useLatest, |
+ bool dryRun: false}) { |
+ return syncFuture(() { |
+ return resolveVersions( |
+ type, |
+ cache.sources, |
+ root, |
+ lockFile: lockFile, |
+ useLatest: useLatest); |
+ }).then((result) { |
+ if (!result.succeeded) throw result.error; |
+ result.showReport(type); |
+ if (dryRun) { |
+ result.summarizeChanges(type, dryRun: dryRun); |
+ return null; |
+ } |
+ if (_packageSymlinks) { |
+ cleanDir(packagesDir); |
+ } else { |
+ deleteEntry(packagesDir); |
+ } |
+ return Future.wait(result.packages.map(_get)).then((ids) { |
+ _saveLockFile(ids); |
+ if (_packageSymlinks) _linkSelf(); |
+ _linkOrDeleteSecondaryPackageDirs(); |
+ result.summarizeChanges(type, dryRun: dryRun); |
+ return loadPackageGraph(result); |
+ }).then((packageGraph) { |
+ return precompileExecutables( |
+ changed: result.changedPackages).catchError((error, stackTrace) { |
+ log.exception(error, stackTrace); |
+ }); |
+ }); |
+ }); |
+ } |
+ Future precompileExecutables({Iterable<String> changed}) { |
+ if (changed != null) changed = changed.toSet(); |
+ var binDir = path.join('.pub', 'bin'); |
+ var sdkVersionPath = path.join(binDir, 'sdk-version'); |
+ var sdkMatches = |
+ fileExists(sdkVersionPath) && |
+ readTextFile(sdkVersionPath) == "${sdk.version}\n"; |
+ if (!sdkMatches) changed = null; |
+ return loadPackageGraph().then((graph) { |
+ var executables = new Map.fromIterable( |
+ root.immediateDependencies, |
+ key: (dep) => dep.name, |
+ value: (dep) => _executablesForPackage(graph, dep.name, changed)); |
+ for (var package in executables.keys.toList()) { |
+ if (executables[package].isEmpty) executables.remove(package); |
+ } |
+ if (!sdkMatches) deleteEntry(binDir); |
+ if (executables.isEmpty) return null; |
+ return log.progress("Precompiling executables", () { |
+ ensureDir(binDir); |
+ writeTextFile(sdkVersionPath, "${sdk.version}\n"); |
+ var packagesToLoad = unionAll( |
+ executables.keys.map( |
+ graph.transitiveDependencies)).map((package) => package.name).toSet(); |
+ return AssetEnvironment.create( |
+ this, |
+ BarbackMode.RELEASE, |
+ packages: packagesToLoad, |
+ useDart2JS: false).then((environment) { |
+ environment.barback.errors.listen((error) { |
+ log.error(log.red("Build error:\n$error")); |
+ }); |
+ return waitAndPrintErrors(executables.keys.map((package) { |
+ var dir = path.join(binDir, package); |
+ cleanDir(dir); |
+ return environment.precompileExecutables( |
+ package, |
+ dir, |
+ executableIds: executables[package]); |
+ })); |
+ }); |
+ }); |
+ }); |
+ } |
+ List<AssetId> _executablesForPackage(PackageGraph graph, String packageName, |
+ Set<String> changed) { |
+ var package = graph.packages[packageName]; |
+ var binDir = path.join(package.dir, 'bin'); |
+ if (!dirExists(binDir)) return []; |
+ var deps = graph.transitiveDependencies(packageName); |
+ var hasUncachedDependency = deps.any((package) { |
+ var source = cache.sources[graph.lockFile.packages[package.name].source]; |
+ return source is! CachedSource; |
+ }); |
+ if (hasUncachedDependency) return []; |
+ var executables = package.executableIds; |
+ if (changed == null) return executables; |
+ if (deps.any((package) => changed.contains(package.name))) { |
+ return executables; |
+ } |
+ var executablesExist = executables.every( |
+ (executable) => |
+ fileExists( |
+ path.join( |
+ '.pub', |
+ 'bin', |
+ packageName, |
+ "${path.url.basename(executable.path)}.snapshot"))); |
+ if (!executablesExist) return executables; |
+ return []; |
+ } |
+ Future<PackageId> _get(PackageId id) { |
+ if (id.isRoot) return new Future.value(id); |
+ var source = cache.sources[id.source]; |
+ return syncFuture(() { |
+ if (!_packageSymlinks) { |
+ if (source is! CachedSource) return null; |
+ return source.downloadToSystemCache(id); |
+ } |
+ var packageDir = path.join(packagesDir, id.name); |
+ if (entryExists(packageDir)) deleteEntry(packageDir); |
+ return source.get(id, packageDir); |
+ }).then((_) => source.resolveId(id)); |
+ } |
+ bool _isLockFileUpToDate(LockFile lockFile) { |
+ return root.immediateDependencies.every((package) { |
+ var locked = lockFile.packages[package.name]; |
+ if (locked == null) return false; |
+ if (package.source != locked.source) return false; |
+ if (!package.constraint.allows(locked.version)) return false; |
+ var source = cache.sources[package.source]; |
+ if (source == null) return false; |
+ return source.descriptionsEqual(package.description, locked.description); |
+ }); |
+ } |
+ Future<bool> _arePackagesAvailable(LockFile lockFile) { |
+ return Future.wait(lockFile.packages.values.map((package) { |
+ var source = cache.sources[package.source]; |
+ assert(source != null); |
+ if (source is! CachedSource) return new Future.value(true); |
+ return source.getDirectory(package).then((dir) { |
+ return dirExists(dir) || fileExists(path.join(dir, "pubspec.yaml")); |
+ }); |
+ })).then((results) { |
+ return results.every((result) => result); |
+ }); |
+ } |
+ Future ensureLockFileIsUpToDate() { |
+ return syncFuture(() { |
+ if (!_isLockFileUpToDate(lockFile)) { |
+ if (lockFileExists) { |
+ log.message( |
+ "Your pubspec has changed, so we need to update your lockfile:"); |
+ } else { |
+ log.message( |
+ "You don't have a lockfile, so we need to generate that:"); |
+ } |
+ return false; |
+ } |
+ return _arePackagesAvailable(lockFile).then((available) { |
+ if (!available) { |
+ log.message( |
+ "You are missing some dependencies, so we need to install them " "first:"); |
+ } |
+ return available; |
+ }); |
+ }).then((upToDate) { |
+ if (upToDate) return null; |
+ return acquireDependencies(SolveType.GET); |
+ }); |
+ } |
+ Future<PackageGraph> loadPackageGraph([SolveResult result]) { |
+ if (_packageGraph != null) return new Future.value(_packageGraph); |
+ return syncFuture(() { |
+ if (result != null) { |
+ return Future.wait(result.packages.map((id) { |
+ return cache.sources[id.source].getDirectory( |
+ id).then((dir) => new Package(result.pubspecs[id.name], dir)); |
+ })).then((packages) { |
+ return new PackageGraph( |
+ this, |
+ new LockFile(result.packages), |
+ new Map.fromIterable(packages, key: (package) => package.name)); |
+ }); |
+ } else { |
+ return ensureLockFileIsUpToDate().then((_) { |
+ return Future.wait(lockFile.packages.values.map((id) { |
+ var source = cache.sources[id.source]; |
+ return source.getDirectory( |
+ id).then((dir) => new Package.load(id.name, dir, cache.sources)); |
+ })).then((packages) { |
+ var packageMap = new Map.fromIterable(packages, key: (p) => p.name); |
+ packageMap[root.name] = root; |
+ return new PackageGraph(this, lockFile, packageMap); |
+ }); |
+ }); |
+ } |
+ }).then((graph) { |
+ _packageGraph = graph; |
+ return graph; |
+ }); |
+ } |
+ void _saveLockFile(List<PackageId> packageIds) { |
+ _lockFile = new LockFile(packageIds); |
+ var lockFilePath = path.join(root.dir, 'pubspec.lock'); |
+ writeTextFile(lockFilePath, _lockFile.serialize(root.dir, cache.sources)); |
+ } |
+ void _linkSelf() { |
+ var linkPath = path.join(packagesDir, root.name); |
+ if (entryExists(linkPath)) return; |
+ ensureDir(packagesDir); |
+ createPackageSymlink( |
+ root.name, |
+ root.dir, |
+ linkPath, |
+ isSelfLink: true, |
+ relative: true); |
+ } |
+ void _linkOrDeleteSecondaryPackageDirs() { |
+ var binDir = path.join(root.dir, 'bin'); |
+ if (dirExists(binDir)) _linkOrDeleteSecondaryPackageDir(binDir); |
+ for (var dir in ['benchmark', 'example', 'test', 'tool', 'web']) { |
+ _linkOrDeleteSecondaryPackageDirsRecursively(path.join(root.dir, dir)); |
+ } |
+ } |
+ void _linkOrDeleteSecondaryPackageDirsRecursively(String dir) { |
+ if (!dirExists(dir)) return; |
+ _linkOrDeleteSecondaryPackageDir(dir); |
+ _listDirWithoutPackages( |
+ dir).where(dirExists).forEach(_linkOrDeleteSecondaryPackageDir); |
+ } |
+ List<String> _listDirWithoutPackages(dir) { |
+ return flatten(listDir(dir).map((file) { |
+ if (path.basename(file) == 'packages') return []; |
+ if (!dirExists(file)) return []; |
+ var fileAndSubfiles = [file]; |
+ fileAndSubfiles.addAll(_listDirWithoutPackages(file)); |
+ return fileAndSubfiles; |
+ })); |
+ } |
+ void _linkOrDeleteSecondaryPackageDir(String dir) { |
+ var symlink = path.join(dir, 'packages'); |
+ if (entryExists(symlink)) deleteEntry(symlink); |
+ if (_packageSymlinks) createSymlink(packagesDir, symlink, relative: true); |
+ } |
+} |