| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library source.caching_pub_package_map_provider; | 5 library source.caching_pub_package_map_provider; |
| 6 | 6 |
| 7 import 'dart:convert'; | 7 import 'dart:convert'; |
| 8 import 'dart:io' as io; | 8 import 'dart:io' as io; |
| 9 | 9 |
| 10 import 'package:analyzer/file_system/file_system.dart'; | 10 import 'package:analyzer/file_system/file_system.dart'; |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 68 | 68 |
| 69 /** | 69 /** |
| 70 * The function used to write the cache file. | 70 * The function used to write the cache file. |
| 71 */ | 71 */ |
| 72 WriteFile _writeFile; | 72 WriteFile _writeFile; |
| 73 | 73 |
| 74 /** | 74 /** |
| 75 * Construct a new instance. | 75 * Construct a new instance. |
| 76 * [RunPubList] and [WriteFile] implementations may be injected for testing | 76 * [RunPubList] and [WriteFile] implementations may be injected for testing |
| 77 */ | 77 */ |
| 78 CachingPubPackageMapProvider(ResourceProvider resourceProvider, | 78 CachingPubPackageMapProvider( |
| 79 DirectoryBasedDartSdk sdk, [RunPubList runPubList, this._writeFile]) | 79 ResourceProvider resourceProvider, DirectoryBasedDartSdk sdk, |
| 80 [RunPubList runPubList, this._writeFile]) |
| 80 : super(resourceProvider, sdk, runPubList) { | 81 : super(resourceProvider, sdk, runPubList) { |
| 81 if (_writeFile == null) { | 82 if (_writeFile == null) { |
| 82 _writeFile = _writeFileDefault; | 83 _writeFile = _writeFileDefault; |
| 83 } | 84 } |
| 84 } | 85 } |
| 85 | 86 |
| 86 File get cacheFile => _cacheDir.getChild('cache'); | 87 File get cacheFile => _cacheDir.getChild('cache'); |
| 87 Folder get _cacheDir => resourceProvider.getStateLocation('.pub-list'); | 88 Folder get _cacheDir => resourceProvider.getStateLocation('.pub-list'); |
| 88 File get _touchFile => _cacheDir.getChild('touch'); | 89 File get _touchFile => _cacheDir.getChild('touch'); |
| 89 | 90 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 130 } | 131 } |
| 131 // computePackageMap calls parsePackageMap which caches the result | 132 // computePackageMap calls parsePackageMap which caches the result |
| 132 info = super.computePackageMap(folder); | 133 info = super.computePackageMap(folder); |
| 133 ++runCount; | 134 ++runCount; |
| 134 if (!_haveDependenciesChangedSince(info, startStamp)) { | 135 if (!_haveDependenciesChangedSince(info, startStamp)) { |
| 135 // If no dependencies have changed while running pub then finished | 136 // If no dependencies have changed while running pub then finished |
| 136 break; | 137 break; |
| 137 } | 138 } |
| 138 if (runCount == 4) { | 139 if (runCount == 4) { |
| 139 // Don't run forever | 140 // Don't run forever |
| 140 AnalysisEngine.instance.logger.logInformation( | 141 AnalysisEngine.instance.logger |
| 141 'pub list called $runCount times: $folder'); | 142 .logInformation('pub list called $runCount times: $folder'); |
| 142 break; | 143 break; |
| 143 } | 144 } |
| 144 } | 145 } |
| 145 _writeCache(); | 146 _writeCache(); |
| 146 return info; | 147 return info; |
| 147 } | 148 } |
| 148 | 149 |
| 149 @override | 150 @override |
| 150 PackageMapInfo parsePackageMap(Map obj, Folder folder) { | 151 PackageMapInfo parsePackageMap(Map obj, Folder folder) { |
| 151 PackageMapInfo info = super.parsePackageMap(obj, folder); | 152 PackageMapInfo info = super.parsePackageMap(obj, folder); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 } | 200 } |
| 200 | 201 |
| 201 /** | 202 /** |
| 202 * Read the cache from disk if it has not been read before. | 203 * Read the cache from disk if it has not been read before. |
| 203 */ | 204 */ |
| 204 void _readCache() { | 205 void _readCache() { |
| 205 // TODO(danrubel) This implementation assumes that | 206 // TODO(danrubel) This implementation assumes that |
| 206 // two separate processes are not accessing the cache file at the same time | 207 // two separate processes are not accessing the cache file at the same time |
| 207 Source source = cacheFile.createSource(); | 208 Source source = cacheFile.createSource(); |
| 208 if (source.exists() && | 209 if (source.exists() && |
| 209 (_cache == null || _cacheModificationTime != source.modificationStamp))
{ | 210 (_cache == null || |
| 211 _cacheModificationTime != source.modificationStamp)) { |
| 210 try { | 212 try { |
| 211 TimestampedData<String> data = source.contents; | 213 TimestampedData<String> data = source.contents; |
| 212 Map map = JSON.decode(data.data); | 214 Map map = JSON.decode(data.data); |
| 213 if (map[cacheVersionKey] == cacheVersion) { | 215 if (map[cacheVersionKey] == cacheVersion) { |
| 214 _cache = map[cacheKey]; | 216 _cache = map[cacheKey]; |
| 215 _cacheModificationTime = data.modificationTime; | 217 _cacheModificationTime = data.modificationTime; |
| 216 } | 218 } |
| 217 } catch (exception, stackTrace) { | 219 } catch (exception, stackTrace) { |
| 218 AnalysisEngine.instance.logger.logInformation( | 220 AnalysisEngine.instance.logger.logInformation( |
| 219 'Exception reading $cacheFile\n$exception\n$stackTrace'); | 221 'Exception reading $cacheFile\n$exception\n$stackTrace'); |
| 220 } | 222 } |
| 221 } | 223 } |
| 222 if (_cache == null) { | 224 if (_cache == null) { |
| 223 _cache = new Map<String, Map>(); | 225 _cache = new Map<String, Map>(); |
| 224 } | 226 } |
| 225 } | 227 } |
| 226 | 228 |
| 227 /** | 229 /** |
| 228 * Write the cache to disk. | 230 * Write the cache to disk. |
| 229 */ | 231 */ |
| 230 void _writeCache() { | 232 void _writeCache() { |
| 231 try { | 233 try { |
| 232 _cacheModificationTime = _writeFile(cacheFile, JSON.encode({ | 234 _cacheModificationTime = _writeFile(cacheFile, |
| 233 cacheVersionKey: cacheVersion, | 235 JSON.encode({cacheVersionKey: cacheVersion, cacheKey: _cache})); |
| 234 cacheKey: _cache | |
| 235 })); | |
| 236 } catch (exception, stackTrace) { | 236 } catch (exception, stackTrace) { |
| 237 AnalysisEngine.instance.logger.logInformation( | 237 AnalysisEngine.instance.logger.logInformation( |
| 238 'Exception writing $cacheFile\n$exception\n$stackTrace'); | 238 'Exception writing $cacheFile\n$exception\n$stackTrace'); |
| 239 } | 239 } |
| 240 } | 240 } |
| 241 | 241 |
| 242 /** | 242 /** |
| 243 * Update the given file with the specified content. | 243 * Update the given file with the specified content. |
| 244 */ | 244 */ |
| 245 int _writeFileDefault(File cacheFile, String content) { | 245 int _writeFileDefault(File cacheFile, String content) { |
| 246 // TODO(danrubel) This implementation assumes that | 246 // TODO(danrubel) This implementation assumes that |
| 247 // two separate processes are not accessing the cache file at the same time | 247 // two separate processes are not accessing the cache file at the same time |
| 248 io.File file = new io.File(cacheFile.path); | 248 io.File file = new io.File(cacheFile.path); |
| 249 if (!file.parent.existsSync()) { | 249 if (!file.parent.existsSync()) { |
| 250 file.parent.createSync(recursive: true); | 250 file.parent.createSync(recursive: true); |
| 251 } | 251 } |
| 252 file.writeAsStringSync(content, flush: true); | 252 file.writeAsStringSync(content, flush: true); |
| 253 return file.lastModifiedSync().millisecondsSinceEpoch; | 253 return file.lastModifiedSync().millisecondsSinceEpoch; |
| 254 } | 254 } |
| 255 } | 255 } |
| OLD | NEW |