| Index: pkg/analysis_server/lib/src/source/caching_pub_package_map_provider.dart
|
| diff --git a/pkg/analysis_server/lib/src/source/caching_pub_package_map_provider.dart b/pkg/analysis_server/lib/src/source/caching_pub_package_map_provider.dart
|
| deleted file mode 100644
|
| index 964e7dec57871bac973570ad62e4869d9b13ec1f..0000000000000000000000000000000000000000
|
| --- a/pkg/analysis_server/lib/src/source/caching_pub_package_map_provider.dart
|
| +++ /dev/null
|
| @@ -1,260 +0,0 @@
|
| -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
|
| -// 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.
|
| -
|
| -library source.caching_pub_package_map_provider;
|
| -
|
| -import 'dart:convert';
|
| -import 'dart:core';
|
| -import 'dart:io' as io;
|
| -
|
| -import 'package:analyzer/file_system/file_system.dart';
|
| -import 'package:analyzer/source/package_map_provider.dart';
|
| -import 'package:analyzer/source/pub_package_map_provider.dart';
|
| -import 'package:analyzer/src/dart/sdk/sdk.dart';
|
| -import 'package:analyzer/src/generated/engine.dart';
|
| -import 'package:analyzer/src/generated/source.dart';
|
| -
|
| -/**
|
| - * The function used to write the cache file.
|
| - * Returns the modification stamp for the newly written file.
|
| - */
|
| -typedef int WriteFile(File file, String content);
|
| -
|
| -/**
|
| - * [PubPackageMapProvider] extension which caches pub list results.
|
| - * These results are cached in memory and in a single place on disk that is
|
| - * shared cross session and between different simultaneous sessions.
|
| - *
|
| - * TODO(paulberry): before this class is used again, it should be ported over
|
| - * to extend OptimizingPubPackageMapProvider instead of PubPackageMapProvider.
|
| - */
|
| -class CachingPubPackageMapProvider extends PubPackageMapProvider {
|
| - static const cacheKey = 'pub_list_cache';
|
| - static const cacheVersion = 1;
|
| - static const cacheVersionKey = 'pub_list_cache_version';
|
| - static const pubListResultKey = 'pub_list_result';
|
| - static const modificationStampsKey = 'modification_stamps';
|
| -
|
| - /**
|
| - * A cache of folder path to pub list information as shown below
|
| - * or `null` if the cache has not yet been initialized.
|
| - *
|
| - * {
|
| - * "path/to/folder": {
|
| - * "pub_list_result": {
|
| - * "packages": {
|
| - * "foo": "path/to/foo",
|
| - * "bar": ["path/to/bar1", "path/to/bar2"],
|
| - * "myapp": "path/to/myapp", // self link is included
|
| - * },
|
| - * "input_files": [
|
| - * "path/to/myapp/pubspec.lock"
|
| - * ]
|
| - * },
|
| - * "modification_stamps": {
|
| - * "path/to/myapp/pubspec.lock": 1424305309
|
| - * }
|
| - * }
|
| - * "path/to/another/folder": {
|
| - * ...
|
| - * }
|
| - * ...
|
| - * }
|
| - */
|
| - Map<String, Map> _cache;
|
| -
|
| - /**
|
| - * The modification time of the cache file
|
| - * or `null` if it has not yet been read.
|
| - */
|
| - int _cacheModificationTime;
|
| -
|
| - /**
|
| - * The function used to write the cache file.
|
| - */
|
| - WriteFile _writeFile;
|
| -
|
| - /**
|
| - * Construct a new instance.
|
| - * [RunPubList] and [WriteFile] implementations may be injected for testing
|
| - */
|
| - CachingPubPackageMapProvider(
|
| - ResourceProvider resourceProvider, FolderBasedDartSdk sdk,
|
| - [RunPubList runPubList, this._writeFile])
|
| - : super(resourceProvider, sdk, runPubList) {
|
| - if (_writeFile == null) {
|
| - _writeFile = _writeFileDefault;
|
| - }
|
| - }
|
| -
|
| - File get cacheFile => _cacheDir.getChild('cache');
|
| - Folder get _cacheDir => resourceProvider.getStateLocation('.pub-list');
|
| - File get _touchFile => _cacheDir.getChild('touch');
|
| -
|
| - @override
|
| - PackageMapInfo computePackageMap(Folder folder) {
|
| - //
|
| - // Return error if folder does not exist, but don't remove previously
|
| - // cached result because folder may be only temporarily inaccessible
|
| - //
|
| - if (!folder.exists) {
|
| - return computePackageMapError(folder);
|
| - }
|
| - // Ensure cache is up to date
|
| - _readCache();
|
| - // Check for cached entry
|
| - Map entry = _cache[folder.path];
|
| - if (entry != null) {
|
| - Map<String, int> modificationStamps =
|
| - entry[modificationStampsKey] as Map<String, int>;
|
| - if (modificationStamps != null) {
|
| - //
|
| - // Check to see if any dependencies have changed
|
| - // before returning cached result
|
| - //
|
| - if (!_haveDependenciesChanged(modificationStamps)) {
|
| - return parsePackageMap(entry[pubListResultKey], folder);
|
| - }
|
| - }
|
| - }
|
| - int runCount = 0;
|
| - PackageMapInfo info;
|
| - while (true) {
|
| - // Capture the current time so that we can tell if an input file
|
| - // has changed while running pub list. This is done
|
| - // by writing to a file rather than getting millisecondsSinceEpoch
|
| - // because file modification time has different granularity
|
| - // on diferent systems.
|
| - int startStamp;
|
| - try {
|
| - startStamp = _writeFile(_touchFile, 'touch');
|
| - } catch (exception, stackTrace) {
|
| - AnalysisEngine.instance.logger.logInformation(
|
| - 'Exception writing $_touchFile\n$exception\n$stackTrace');
|
| - startStamp = new DateTime.now().millisecondsSinceEpoch;
|
| - }
|
| - // computePackageMap calls parsePackageMap which caches the result
|
| - info = super.computePackageMap(folder);
|
| - ++runCount;
|
| - if (!_haveDependenciesChangedSince(info, startStamp)) {
|
| - // If no dependencies have changed while running pub then finished
|
| - break;
|
| - }
|
| - if (runCount == 4) {
|
| - // Don't run forever
|
| - AnalysisEngine.instance.logger
|
| - .logInformation('pub list called $runCount times: $folder');
|
| - break;
|
| - }
|
| - }
|
| - _writeCache();
|
| - return info;
|
| - }
|
| -
|
| - @override
|
| - PackageMapInfo parsePackageMap(Map obj, Folder folder) {
|
| - PackageMapInfo info = super.parsePackageMap(obj, folder);
|
| - Map<String, int> modificationStamps = new Map<String, int>();
|
| - for (String path in info.dependencies) {
|
| - Resource res = resourceProvider.getResource(path);
|
| - if (res is File && res.exists) {
|
| - modificationStamps[path] = res.createSource().modificationStamp;
|
| - }
|
| - }
|
| - // Assumes entry has been initialized by computePackageMap
|
| - _cache[folder.path] = <String, Map>{
|
| - pubListResultKey: obj,
|
| - modificationStampsKey: modificationStamps
|
| - };
|
| - return info;
|
| - }
|
| -
|
| - /**
|
| - * Determine if any of the dependencies have changed.
|
| - */
|
| - bool _haveDependenciesChanged(Map<String, int> modificationStamps) {
|
| - for (String path in modificationStamps.keys) {
|
| - Resource res = resourceProvider.getResource(path);
|
| - if (res is File) {
|
| - if (!res.exists ||
|
| - res.createSource().modificationStamp != modificationStamps[path]) {
|
| - return true;
|
| - }
|
| - } else {
|
| - return true;
|
| - }
|
| - }
|
| - return false;
|
| - }
|
| -
|
| - /**
|
| - * Determine if any of the dependencies have changed since the given time.
|
| - */
|
| - bool _haveDependenciesChangedSince(PackageMapInfo info, int startStamp) {
|
| - for (String path in info.dependencies) {
|
| - Resource res = resourceProvider.getResource(path);
|
| - if (res is File) {
|
| - int modStamp = res.createSource().modificationStamp;
|
| - if (modStamp != null && modStamp >= startStamp) {
|
| - return true;
|
| - }
|
| - }
|
| - }
|
| - return false;
|
| - }
|
| -
|
| - /**
|
| - * Read the cache from disk if it has not been read before.
|
| - */
|
| - void _readCache() {
|
| - // TODO(danrubel) This implementation assumes that
|
| - // two separate processes are not accessing the cache file at the same time
|
| - Source source = cacheFile.createSource();
|
| - if (source.exists() &&
|
| - (_cache == null ||
|
| - _cacheModificationTime != source.modificationStamp)) {
|
| - try {
|
| - TimestampedData<String> data = source.contents;
|
| - Map map = JSON.decode(data.data);
|
| - if (map[cacheVersionKey] == cacheVersion) {
|
| - _cache = map[cacheKey] as Map<String, Map>;
|
| - _cacheModificationTime = data.modificationTime;
|
| - }
|
| - } catch (exception, stackTrace) {
|
| - AnalysisEngine.instance.logger.logInformation(
|
| - 'Exception reading $cacheFile\n$exception\n$stackTrace');
|
| - }
|
| - }
|
| - if (_cache == null) {
|
| - _cache = new Map<String, Map>();
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Write the cache to disk.
|
| - */
|
| - void _writeCache() {
|
| - try {
|
| - _cacheModificationTime = _writeFile(cacheFile,
|
| - JSON.encode({cacheVersionKey: cacheVersion, cacheKey: _cache}));
|
| - } catch (exception, stackTrace) {
|
| - AnalysisEngine.instance.logger.logInformation(
|
| - 'Exception writing $cacheFile\n$exception\n$stackTrace');
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Update the given file with the specified content.
|
| - */
|
| - int _writeFileDefault(File cacheFile, String content) {
|
| - // TODO(danrubel) This implementation assumes that
|
| - // two separate processes are not accessing the cache file at the same time
|
| - io.File file = new io.File(cacheFile.path);
|
| - if (!file.parent.existsSync()) {
|
| - file.parent.createSync(recursive: true);
|
| - }
|
| - file.writeAsStringSync(content, flush: true);
|
| - return file.lastModifiedSync().millisecondsSinceEpoch;
|
| - }
|
| -}
|
|
|