| Index: tools/migration/bin/migrate_batch.dart
|
| diff --git a/tools/migration/bin/migrate_batch.dart b/tools/migration/bin/migrate_batch.dart
|
| index 4b23fe0a30c9723af30f12f861169f027b5c8d03..67952664b7ba525e324ceb9ae59a77060b8c67af 100644
|
| --- a/tools/migration/bin/migrate_batch.dart
|
| +++ b/tools/migration/bin/migrate_batch.dart
|
| @@ -11,20 +11,14 @@
|
| import 'dart:io';
|
|
|
| import 'package:path/path.dart' as p;
|
| +import 'package:status_file/status_file.dart';
|
|
|
| +import 'package:migration/src/fork.dart';
|
| +import 'package:migration/src/io.dart';
|
| import 'package:migration/src/log.dart';
|
| -import 'package:migration/src/validate.dart';
|
| -import 'package:status_file/status_file.dart';
|
|
|
| const simpleDirs = const ["corelib", "language", "lib"];
|
|
|
| -final String sdkRoot =
|
| - p.normalize(p.join(p.dirname(p.fromUri(Platform.script)), '../../../'));
|
| -
|
| -final String testRoot = p.join(sdkRoot, "tests");
|
| -
|
| -bool dryRun = false;
|
| -
|
| void main(List<String> arguments) {
|
| if (arguments.contains("--dry-run")) {
|
| dryRun = true;
|
| @@ -42,29 +36,20 @@ void main(List<String> arguments) {
|
| exit(1);
|
| }
|
|
|
| - var first = toTwoPath(arguments[0]);
|
| - var last = toTwoPath(arguments[1]);
|
| -
|
| var tests = scanTests();
|
|
|
| - // Find the range of files in the chunk. We use comparisons here instead of
|
| - // equality to try to compensate for files that may only appear in one fork
|
| - // and should be part of the chunk but aren't officially listed as the begin
|
| - // or end point.
|
| - var startIndex = -1;
|
| - var endIndex = 0;
|
| - for (var i = 0; i < tests.length; i++) {
|
| - if (startIndex == -1 && tests[i].twoPath.compareTo(first) >= 0) {
|
| - startIndex = i;
|
| - }
|
| + var startIndex = findFork(tests, arguments[0]);
|
| + var endIndex = findFork(tests, arguments[1]);
|
|
|
| - if (tests[i].twoPath.compareTo(last) > 0) {
|
| - endIndex = i;
|
| - break;
|
| - }
|
| - }
|
| + if (startIndex == null || endIndex == null) exit(1);
|
| +
|
| + var first = tests[startIndex].twoPath;
|
| + var last = tests[endIndex].twoPath;
|
|
|
| - if ((endIndex - startIndex) == 0) {
|
| + // Make the range half-inclusive to simplify the math below.
|
| + endIndex++;
|
| +
|
| + if (endIndex - startIndex == 0) {
|
| print(bold("No tests in range."));
|
| return;
|
| }
|
| @@ -152,34 +137,27 @@ void printStatusFileEntries(
|
| }
|
| }
|
|
|
| -String toTwoPath(String path) {
|
| - // Allow eliding "_test" and/or ".dart" to make things more command-line
|
| - // friendly.
|
| - if (!path.endsWith(".dart") && !path.endsWith("_test.dart")) {
|
| - path += "_test.dart";
|
| - }
|
| - if (!path.endsWith(".dart")) path += ".dart";
|
| -
|
| - for (var dir in simpleDirs) {
|
| - if (p.isWithin(dir, path)) {
|
| - return p.join("${dir}_2", p.relative(path, from: dir));
|
| - }
|
| +int findFork(List<Fork> forks, String description) {
|
| + var matches = <int>[];
|
|
|
| - if (p.isWithin("${dir}_strong", path)) {
|
| - return p.join("${dir}_2", p.relative(path, from: dir));
|
| - }
|
| + for (var i = 0; i < forks.length; i++) {
|
| + if (forks[i].twoPath.contains(description)) matches.add(i);
|
| }
|
|
|
| - if (p.isWithin("html", path)) {
|
| - return p.join("lib_2/html", p.relative(path, from: "html"));
|
| - }
|
| + if (matches.isEmpty) {
|
| + print('Could not find a test matching "${bold(description)}".');
|
| + return null;
|
| + } else if (matches.length == 1) {
|
| + return matches.first;
|
| + } else {
|
| + print('Description "${bold(description)}" is ambiguous. Could be any of:');
|
| + for (var i in matches) {
|
| + print("- ${forks[i].twoPath.replaceAll(description, bold(description))}");
|
| + }
|
|
|
| - if (p.isWithin("isolate", path)) {
|
| - return p.join("lib_2/isolate", p.relative(path, from: "isolate"));
|
| + print("Please use a more precise description.");
|
| + return null;
|
| }
|
| -
|
| - // Guess it's already a two path.
|
| - return path;
|
| }
|
|
|
| /// Loads all of the unforked test files.
|
| @@ -189,12 +167,9 @@ String toTwoPath(String path) {
|
| List<Fork> scanTests() {
|
| var tests = <String, Fork>{};
|
|
|
| - addTestDirectory(String fromDir, String twoDir) {
|
| - for (var entry
|
| - in new Directory(p.join(testRoot, fromDir)).listSync(recursive: true)) {
|
| - if (!entry.path.endsWith(".dart")) continue;
|
| -
|
| - var fromPath = p.relative(entry.path, from: testRoot);
|
| + addFromDirectory(String fromDir, String twoDir) {
|
| + for (var path in listFiles(fromDir)) {
|
| + var fromPath = p.relative(path, from: testRoot);
|
| var twoPath = p.join(twoDir, p.relative(fromPath, from: fromDir));
|
|
|
| var fork = tests.putIfAbsent(twoPath, () => new Fork(twoPath));
|
| @@ -206,14 +181,29 @@ List<Fork> scanTests() {
|
| }
|
| }
|
|
|
| - addTestDirectory("corelib", "corelib_2");
|
| - addTestDirectory("corelib_strong", "corelib_2");
|
| - addTestDirectory("html", "lib_2/html");
|
| - addTestDirectory("isolate", "lib_2/isolate");
|
| - addTestDirectory("language", "language_2");
|
| - addTestDirectory("language_strong", "language_2");
|
| - addTestDirectory("lib", "lib_2");
|
| - addTestDirectory("lib_strong", "lib_2");
|
| + addFromDirectory("corelib", "corelib_2");
|
| + addFromDirectory("corelib_strong", "corelib_2");
|
| + addFromDirectory("html", "lib_2/html");
|
| + addFromDirectory("isolate", "lib_2/isolate");
|
| + addFromDirectory("language", "language_2");
|
| + addFromDirectory("language_strong", "language_2");
|
| + addFromDirectory("lib", "lib_2");
|
| + addFromDirectory("lib_strong", "lib_2");
|
| +
|
| + // Include tests that have already been migrated too so we can show what
|
| + // works remains to be done in them.
|
| + const twoDirs = const [
|
| + "corelib_2",
|
| + "lib_2",
|
| + "language_2",
|
| + ];
|
| +
|
| + for (var dir in twoDirs) {
|
| + for (var path in listFiles(dir)) {
|
| + var twoPath = p.relative(path, from: testRoot);
|
| + tests.putIfAbsent(twoPath, () => new Fork(twoPath));
|
| + }
|
| + }
|
|
|
| var sorted = tests.values.toList();
|
| sorted.sort((a, b) => a.twoPath.compareTo(b.twoPath));
|
| @@ -224,11 +214,8 @@ List<StatusFile> loadStatusFiles() {
|
| var statusFiles = <StatusFile>[];
|
|
|
| addStatusFile(String fromDir) {
|
| - for (var entry
|
| - in new Directory(p.join(testRoot, fromDir)).listSync(recursive: true)) {
|
| - if (!entry.path.endsWith(".status")) continue;
|
| -
|
| - statusFiles.add(new StatusFile.read(entry.path));
|
| + for (var path in listFiles(fromDir, extension: ".status")) {
|
| + statusFiles.add(new StatusFile.read(path));
|
| }
|
| }
|
|
|
| @@ -242,126 +229,3 @@ List<StatusFile> loadStatusFiles() {
|
| addStatusFile("lib_strong");
|
| return statusFiles;
|
| }
|
| -
|
| -/// Moves the file from [from] to [to], which are both assumed to be relative
|
| -/// paths inside "tests".
|
| -void moveFile(String from, String to) {
|
| - if (dryRun) {
|
| - print(" Dry run: move $from to $to");
|
| - return;
|
| - }
|
| -
|
| - // Create the directory if needed.
|
| - new Directory(p.dirname(p.join(testRoot, to))).createSync(recursive: true);
|
| -
|
| - new File(p.join(testRoot, from)).renameSync(p.join(testRoot, to));
|
| -}
|
| -
|
| -/// Reads the contents of the file at [path], which is assumed to be relative
|
| -/// within "tests".
|
| -String readFile(String path) {
|
| - return new File(p.join(testRoot, path)).readAsStringSync();
|
| -}
|
| -
|
| -/// Deletes the file at [path], which is assumed to be relative within "tests".
|
| -void deleteFile(String path) {
|
| - if (dryRun) {
|
| - print(" Dry run: delete $path");
|
| - return;
|
| - }
|
| -
|
| - new File(p.join(testRoot, path)).deleteSync();
|
| -}
|
| -
|
| -class Fork {
|
| - final String twoPath;
|
| - String onePath;
|
| - String strongPath;
|
| -
|
| - String get twoSource {
|
| - if (twoPath == null) return null;
|
| - if (_twoSource == null) _twoSource = readFile(twoPath);
|
| - return _twoSource;
|
| - }
|
| -
|
| - String _twoSource;
|
| -
|
| - String get oneSource {
|
| - if (onePath == null) return null;
|
| - if (_oneSource == null) _oneSource = readFile(onePath);
|
| - return _oneSource;
|
| - }
|
| -
|
| - String _oneSource;
|
| -
|
| - String get strongSource {
|
| - if (strongPath == null) return null;
|
| - if (_strongSource == null) _strongSource = readFile(strongPath);
|
| - return _strongSource;
|
| - }
|
| -
|
| - String _strongSource;
|
| -
|
| - Fork(this.twoPath);
|
| -
|
| - List<String> migrate() {
|
| - print("- ${bold(twoPath)}:");
|
| -
|
| - var todos = <String>[];
|
| - var isMigrated = new File(p.join(testRoot, twoPath)).existsSync();
|
| -
|
| - // If there is a migrated version and it's the same as an unmigrated one,
|
| - // delete the unmigrated one.
|
| - if (isMigrated) {
|
| - if (onePath != null) {
|
| - if (oneSource == twoSource) {
|
| - deleteFile(onePath);
|
| - done("Deleted already-migrated $onePath.");
|
| - } else {
|
| - note("${bold(onePath)} does not match already-migrated "
|
| - "${bold(twoPath)}.");
|
| - todos.add("Merge from ${bold(onePath)} into this file.");
|
| - validateFile(onePath, oneSource);
|
| - }
|
| - }
|
| -
|
| - if (strongPath != null) {
|
| - if (strongSource == twoSource) {
|
| - deleteFile(strongPath);
|
| - done("Deleted already-migrated ${bold(strongPath)}.");
|
| - } else {
|
| - note("${bold(strongPath)} does not match already-migrated "
|
| - "${bold(twoPath)}.");
|
| - todos.add("Merge from ${bold(strongPath)} into this file.");
|
| - validateFile(strongPath, strongSource);
|
| - }
|
| - }
|
| - } else {
|
| - // If it only exists in one place, just move it.
|
| - if (strongPath == null) {
|
| - moveFile(onePath, twoPath);
|
| - done("Moved from ${bold(onePath)} (no strong mode fork).");
|
| - } else if (onePath == null) {
|
| - moveFile(strongPath, twoPath);
|
| - done("Moved from ${bold(strongPath)} (no 1.0 mode fork).");
|
| - } else if (oneSource == strongSource) {
|
| - // The forks are identical, pick one.
|
| - moveFile(onePath, twoPath);
|
| - deleteFile(strongPath);
|
| - done("Merged identical forks.");
|
| - validateFile(twoPath, oneSource);
|
| - } else {
|
| - // Otherwise, a manual merge is required. Start with the strong one.
|
| - print(new File(strongPath).existsSync());
|
| - moveFile(strongPath, twoPath);
|
| - done("Moved strong fork, kept 1.0 fork, manual merge required.");
|
| - todos.add("Merge from ${bold(onePath)} into this file.");
|
| - validateFile(onePath, oneSource);
|
| - }
|
| - }
|
| -
|
| - validateFile(twoPath, twoSource, todos);
|
| -
|
| - return todos;
|
| - }
|
| -}
|
|
|