Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(943)

Side by Side Diff: pkg/analysis_server/lib/src/package_map_provider.dart

Issue 365443002: Handle a failure in "pub list-package-dirs". (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 package.map.provider; 5 library 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:analysis_server/src/analysis_server.dart'; 10 import 'package:analysis_server/src/analysis_server.dart';
11 import 'package:analysis_server/src/resource.dart'; 11 import 'package:analysis_server/src/resource.dart';
12 import 'package:analyzer/src/generated/engine.dart'; 12 import 'package:analyzer/src/generated/engine.dart';
13 import 'package:path/path.dart';
13 14
14 /** 15 /**
15 * A PackageMapProvider is an entity capable of determining the mapping from 16 * A PackageMapProvider is an entity capable of determining the mapping from
16 * package name to source directory for a given folder. 17 * package name to source directory for a given folder.
17 */ 18 */
18 abstract class PackageMapProvider { 19 abstract class PackageMapProvider {
19 /** 20 /**
20 * Compute a package map for the given folder, if possible. 21 * Compute a package map for the given folder, if possible.
21 * 22 *
22 * If a package map can't be computed, return null. 23 * If a package map can't be computed (e.g. because an error occurred), a
24 * [PackageMapInfo] will still be returned, but its packageMap will be null.
23 */ 25 */
24 PackageMapInfo computePackageMap(Folder folder); 26 PackageMapInfo computePackageMap(Folder folder);
25 } 27 }
26 28
27 /** 29 /**
28 * Data structure output by PackageMapProvider. This contains both the package 30 * Data structure output by PackageMapProvider. This contains both the package
29 * map and dependency information. 31 * map and dependency information.
30 */ 32 */
31 class PackageMapInfo { 33 class PackageMapInfo {
32 /** 34 /**
33 * The package map itself. This is a map from package name to a list of 35 * The package map itself. This is a map from package name to a list of
34 * the folders containing source code for the package. 36 * the folders containing source code for the package.
37 *
38 * `null` if an error occurred.
35 */ 39 */
36 Map<String, List<Folder>> packageMap; 40 Map<String, List<Folder>> packageMap;
37 41
38 /** 42 /**
39 * Dependency information. This is a set of the paths which were consulted 43 * Dependency information. This is a set of the paths which were consulted
40 * in order to generate the package map. If any of these files is 44 * in order to generate the package map. If any of these files is
41 * modified, the package map will need to be regenerated. 45 * modified, the package map will need to be regenerated.
42 */ 46 */
43 Set<String> dependencies; 47 Set<String> dependencies;
44 48
45 PackageMapInfo(this.packageMap, this.dependencies); 49 PackageMapInfo(this.packageMap, this.dependencies);
46 } 50 }
47 51
48 /** 52 /**
49 * Implementation of PackageMapProvider that operates by executing pub. 53 * Implementation of PackageMapProvider that operates by executing pub.
50 */ 54 */
51 class PubPackageMapProvider implements PackageMapProvider { 55 class PubPackageMapProvider implements PackageMapProvider {
52 static const String PUB_LIST_COMMAND = 'list-package-dirs'; 56 static const String PUB_LIST_COMMAND = 'list-package-dirs';
53 57
54 /** 58 /**
59 * The name of the 'pubspec.lock' file, which we assume is the dependency
60 * in the event that [PUB_LIST_COMMAND] fails.
61 */
62 static const String PUBSPEC_LOCK_NAME = 'pubspec.lock';
63
64 /**
55 * [ResourceProvider] that is used to create the [Folder]s that populate the 65 * [ResourceProvider] that is used to create the [Folder]s that populate the
56 * package map. 66 * package map.
57 */ 67 */
58 final ResourceProvider resourceProvider; 68 final ResourceProvider resourceProvider;
59 69
60 PubPackageMapProvider(this.resourceProvider); 70 PubPackageMapProvider(this.resourceProvider);
61 71
62 @override 72 @override
63 PackageMapInfo computePackageMap(Folder folder) { 73 PackageMapInfo computePackageMap(Folder folder) {
64 // TODO(paulberry) make this asynchronous so that we can (a) do other 74 // TODO(paulberry) make this asynchronous so that we can (a) do other
65 // analysis while it's in progress, and (b) time out if it takes too long 75 // analysis while it's in progress, and (b) time out if it takes too long
66 // to respond. 76 // to respond.
67 String executable = SHARED_SDK.pubExecutable.getAbsolutePath(); 77 String executable = SHARED_SDK.pubExecutable.getAbsolutePath();
68 io.ProcessResult result; 78 io.ProcessResult result;
69 try { 79 try {
70 result = io.Process.runSync( 80 result = io.Process.runSync(
71 executable, [PUB_LIST_COMMAND], workingDirectory: folder.path); 81 executable, [PUB_LIST_COMMAND], workingDirectory: folder.path);
72 } on io.ProcessException catch (exception, stackTrace) { 82 } on io.ProcessException catch (exception, stackTrace) {
73 AnalysisEngine.instance.logger.logInformation( 83 AnalysisEngine.instance.logger.logInformation(
74 "Error running pub $PUB_LIST_COMMAND\n${exception}\n${stackTrace}"); 84 "Error running pub $PUB_LIST_COMMAND\n${exception}\n${stackTrace}");
75 } 85 }
76 if (result.exitCode != 0) { 86 if (result.exitCode != 0) {
77 AnalysisEngine.instance.logger.logInformation( 87 AnalysisEngine.instance.logger.logInformation(
78 "pub $PUB_LIST_COMMAND failed: exit code ${result.exitCode}"); 88 "pub $PUB_LIST_COMMAND failed: exit code ${result.exitCode}");
79 return null; 89 return _error(folder);
80 } 90 }
81 try { 91 try {
82 return parsePackageMap(result.stdout); 92 return parsePackageMap(result.stdout);
83 } catch (exception, stackTrace) { 93 } catch (exception, stackTrace) {
84 AnalysisEngine.instance.logger.logError( 94 AnalysisEngine.instance.logger.logError(
85 "Malformed output from pub $PUB_LIST_COMMAND\n${exception}\n${stackTra ce}"); 95 "Malformed output from pub $PUB_LIST_COMMAND\n${exception}\n${stackTra ce}");
86 } 96 }
87 97
88 return null; 98 return _error(folder);
89 } 99 }
90 100
91 /** 101 /**
102 * Create a PackageMapInfo object representing an error condition.
103 */
104 PackageMapInfo _error(Folder folder) {
105 // Even if an error occurs, we still need to know the dependencies, so that
106 // we'll know when to try running "pub list-package-dirs" again.
107 // Unfortunately, "pub list-package-dirs" doesn't tell us dependencies when
108 // an error occurs, so just assume there is one dependency, "pubspec.lock".
109 List<String> dependencies = <String>[join(folder.path, PUBSPEC_LOCK_NAME)];
110 return new PackageMapInfo(null, dependencies.toSet());
111 }
112
113 /**
92 * Decode the JSON output from pub into a package map. 114 * Decode the JSON output from pub into a package map.
93 */ 115 */
94 PackageMapInfo parsePackageMap(String jsonText) { 116 PackageMapInfo parsePackageMap(String jsonText) {
95 // The output of pub looks like this: 117 // The output of pub looks like this:
96 // { 118 // {
97 // "packages": { 119 // "packages": {
98 // "foo": "path/to/foo", 120 // "foo": "path/to/foo",
99 // "bar": ["path/to/bar1", "path/to/bar2"], 121 // "bar": ["path/to/bar1", "path/to/bar2"],
100 // "myapp": "path/to/myapp", // self link is included 122 // "myapp": "path/to/myapp", // self link is included
101 // }, 123 // },
(...skipping 30 matching lines...) Expand all
132 if (inputFiles != null) { 154 if (inputFiles != null) {
133 for (var path in inputFiles) { 155 for (var path in inputFiles) {
134 if (path is String) { 156 if (path is String) {
135 dependencies.add(path); 157 dependencies.add(path);
136 } 158 }
137 } 159 }
138 } 160 }
139 return new PackageMapInfo(packageMap, dependencies); 161 return new PackageMapInfo(packageMap, dependencies);
140 } 162 }
141 } 163 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698