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

Side by Side Diff: tools/migration/lib/src/migrate_statuses.dart

Issue 2994573002: Handle migration status entries into split up status files. (Closed)
Patch Set: Created 3 years, 4 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
OLDNEW
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, 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 import 'package:path/path.dart' as p; 5 import 'package:path/path.dart' as p;
6 6
7 import 'editable_status_file.dart'; 7 import 'editable_status_file.dart';
8 import 'fork.dart'; 8 import 'fork.dart';
9 import 'io.dart'; 9 import 'io.dart';
10 import 'log.dart';
10 import 'test_directories.dart'; 11 import 'test_directories.dart';
11 12
12 /// Migrates the status file entries that match [files]. 13 /// Migrates the status file entries that match [files].
13 void migrateStatusEntries(List<Fork> files) { 14 void migrateStatusEntries(List<Fork> files, Map<String, List<String>> todos) {
14 var entriesToMove = new EntrySet(); 15 var entriesToMove = new EntrySet();
15 16
16 _collectEntries(files, entriesToMove, isOne: true); 17 _collectEntries(files, entriesToMove, isOne: true);
17 _collectEntries(files, entriesToMove, isOne: false); 18 _collectEntries(files, entriesToMove, isOne: false);
18 19
19 for (var statusFile in entriesToMove.statusFiles) { 20 for (var statusFile in entriesToMove.statusFiles) {
20 var sections = entriesToMove.sections(statusFile); 21 var sections = entriesToMove.sections(statusFile);
21 _addEntries(statusFile, sections); 22 _addEntries(statusFile, sections);
22 } 23 }
23 24
24 // TODO(rnystrom): Should this log any output? 25 // If any entries need manual splitting, let the user know.
26 for (var dir in entriesToMove._todoHeaders.keys) {
27 var destination = "$dir.status";
28 var headers = entriesToMove._todoHeaders[dir];
29 var splits = headers.map((header) {
30 var files =
31 filesForHeader(header).map((file) => bold("${dir}_$file")).join(", ");
32 return "Need to manually split status file section in ${bold(destination)} "
33 " across files $files:\n $header";
34 }).toList();
35
36 if (splits.isNotEmpty) todos[destination] = splits;
37 }
38 }
39
40 /// Given the header for a status file section, looks at the condition
41 /// expression to determine which status files it should go in.
42 Set<String> filesForHeader(String header) {
43 // Figure out which status file it goes into.
44 var result = new Set<String>();
45
46 // The various compilers are roughly separate products.
47 const compilers = const {
48 r"$compiler == dart2analyzer": "analyzer",
49 r"$compiler == dart2js": "dart2js",
50 r"$compiler == dartdevc": "dartdevc",
51 // This deliberately matches both dartk and dartkp.
52 r"$compiler == dartk": "kernel",
53 r"$compiler == precompiler": "precompiled"
54 };
55
56 // TODO(rnystrom): This is obviously very sensitive to the formatting of
57 // the expression. Hacky, but hopefully good enough for now.
58 compilers.forEach((compiler, file) {
59 if (header.contains(compiler)) result.add(file);
60 });
61
62 // If we couldn't figure out where to put it based on the compiler, look at
63 // the runtime.
64 if (result.isEmpty) {
65 const runtimes = const {
66 r"$runtime == vm": "vm",
67 r"$runtime == flutter": "flutter",
68 r"$runtime == dart_precompiled": "precompiled",
69 };
70
71 runtimes.forEach((runtime, file) {
72 if (header.contains(runtime)) result.add(file);
73 });
74 }
75
76 return result;
25 } 77 }
26 78
27 /// Tracks a set of entries to add to a set of Dart 2.0 status files. 79 /// Tracks a set of entries to add to a set of Dart 2.0 status files.
28 class EntrySet { 80 class EntrySet {
29 /// Keys are the names of the Dart 2.0 status file that will receive the 81 /// Keys are the names of the Dart 2.0 status file that will receive the
30 /// entries. The value for each key is a map of section headers to the list 82 /// entries. The value for each key is a map of section headers to the list
31 /// of entries to add under that section. 83 /// of entries to add under that section.
32 final Map<String, Map<String, List<String>>> _files = {}; 84 final Map<String, Map<String, List<String>>> _files = {};
33 85
86 final _todoHeaders = <String, Set<String>>{};
87
34 Iterable<String> get statusFiles => _files.keys; 88 Iterable<String> get statusFiles => _files.keys;
35 89
36 void add(String fromDir, String header, String entry) { 90 bool add(String fromDir, String header, String entry) {
jcollins 2017/08/04 16:55:56 might be nice to have a comment: /// Returns true
Bob Nystrom 2017/08/04 17:33:02 Done.
37 var toDir = toTwoDirectory(fromDir); 91 var toDir = toTwoDirectory(fromDir);
38 var sections = _files.putIfAbsent(p.join(toDir, "$toDir.status"), () => {}); 92
93 // Figure out which status file it goes into.
94 var possibleFiles = filesForHeader(header);
95 var destination = "$toDir.status";
96
97 if (possibleFiles.length > 1) {
98 // The condition matches multiple files, so the user is going to have to
99 // manually split it up into multiple sections first.
100 // TODO(rnystrom): Would be good to automate this, though it requires
101 // being able to work with condition expressions directly.
102 _todoHeaders.putIfAbsent(toDir, () => new Set()).add(header);
103 return false;
104 }
105
106 // If the condition places it directly into one file, put it there.
107 if (possibleFiles.length == 1) {
108 destination = "${toDir}_${possibleFiles.single}.status";
109 }
110
111 var sections = _files.putIfAbsent(p.join(toDir, destination), () => {});
112
39 var entries = sections.putIfAbsent(header, () => []); 113 var entries = sections.putIfAbsent(header, () => []);
40 entries.add(entry); 114 entries.add(entry);
115 return true;
41 } 116 }
42 117
43 Map<String, List<String>> sections(String file) => _files[file]; 118 Map<String, List<String>> sections(String file) => _files[file];
44 } 119 }
45 120
46 /// Removes entries from the 1.0 and strong status files that correspond to 121 /// Removes entries from the 1.0 and strong status files that correspond to
47 /// the list of [files] being migrated. 122 /// the list of [files] being migrated.
48 /// 123 ///
49 /// Adds moved entries to [entriesToMove]. 124 /// Adds moved entries to [entriesToMove].
50 void _collectEntries(List<Fork> files, EntrySet entriesToMove, {bool isOne}) { 125 void _collectEntries(List<Fork> files, EntrySet entriesToMove, {bool isOne}) {
51 // Map the files to the way they will appear in the status file. 126 // Map the files to the way they will appear in the status file.
52 var filePaths = files 127 var filePaths = files
53 .map((fork) => p.withoutExtension(isOne ? fork.onePath : fork.strongPath)) 128 .map((fork) => p.withoutExtension(isOne ? fork.onePath : fork.strongPath))
54 .toList(); 129 .toList();
55 130
56 for (var fromDir in isOne ? oneRootDirs : strongRootDirs) { 131 for (var fromDir in isOne ? oneRootDirs : strongRootDirs) {
57 for (var path in listFiles(fromDir, extension: ".status")) { 132 for (var path in listFiles(fromDir, extension: ".statustemp")) {
jcollins 2017/08/04 16:55:56 was this a temporary change?
Bob Nystrom 2017/08/04 17:33:01 Oops, yes! Fixed.
58 var editable = new EditableStatusFile(path); 133 var editable = new EditableStatusFile(path);
59 134
60 var deleteLines = <int>[]; 135 var deleteLines = <int>[];
61 for (var section in editable.statusFile.sections) { 136 for (var section in editable.statusFile.sections) {
62 // TODO(rnystrom): For now, we don't support entries in the initial 137 // TODO(rnystrom): For now, we don't support entries in the initial
63 // implicit section at the top of the file. Do we need to? 138 // implicit section at the top of the file. Do we need to?
64 if (section.condition == null) continue; 139 if (section.condition == null) continue;
65 140
66 for (var entry in section.entries) { 141 for (var entry in section.entries) {
67 var entryPath = p.join(fromDir, entry.path); 142 var entryPath = p.join(fromDir, entry.path);
68 143
69 for (var filePath in filePaths) { 144 for (var filePath in filePaths) {
70 // We only support entries that precisely match the file being 145 // We only support entries that precisely match the file being
71 // migrated, or a multitest within that. In both cases, the entry 146 // migrated, or a multitest within that. In both cases, the entry
72 // path will begin with the full path of the file. We don't migrate 147 // path will begin with the full path of the file. We don't migrate
73 // directory or glob patterns because those may also match other 148 // directory or glob patterns because those may also match other
74 // files that have not been migrated yet. 149 // files that have not been migrated yet.
75 // TODO(rnystrom): It would be good to detect when a glob matches 150 // TODO(rnystrom): It would be good to detect when a glob matches
76 // a migrated file and let the user know that they may need to 151 // a migrated file and let the user know that they may need to
77 // manually handle it. 152 // manually handle it.
78 if (!entryPath.startsWith(filePath)) continue; 153 if (!entryPath.startsWith(filePath)) continue;
79 154
80 // Remove it from this status file. 155 // Add it to the 2.0 one.
81 deleteLines.add(entry.lineNumber - 1); 156 if (entriesToMove.add(fromDir, editable.lineAt(section.lineNumber),
82 157 editable.lineAt(entry.lineNumber))) {
83 // And add it to the 2.0 one. 158 // Remove it from the original status file.
84 entriesToMove.add(fromDir, editable.lineAt(section.lineNumber), 159 deleteLines.add(entry.lineNumber - 1);
85 editable.lineAt(entry.lineNumber)); 160 }
86 } 161 }
87 } 162 }
88 } 163 }
89 164
90 // TODO(rnystrom): If all of the entries are deleted from a section, it 165 // TODO(rnystrom): If all of the entries are deleted from a section, it
91 // would be nice to delete the section header too. 166 // would be nice to delete the section header too.
92 editable.delete(deleteLines); 167 editable.delete(deleteLines);
93 } 168 }
94 } 169 }
95 } 170 }
(...skipping 23 matching lines...) Expand all
119 break; 194 break;
120 } 195 }
121 } 196 }
122 197
123 if (!found) { 198 if (!found) {
124 // This section doesn't exist in the status file, so add it. 199 // This section doesn't exist in the status file, so add it.
125 editable.append(header, entries[header]); 200 editable.append(header, entries[header]);
126 } 201 }
127 } 202 }
128 } 203 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698