| Index: tools/migration/lib/src/editable_status_file.dart
|
| diff --git a/tools/migration/lib/src/editable_status_file.dart b/tools/migration/lib/src/editable_status_file.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..7a3795266da73de500e6aa935e8105b866912f84
|
| --- /dev/null
|
| +++ b/tools/migration/lib/src/editable_status_file.dart
|
| @@ -0,0 +1,109 @@
|
| +// Copyright (c) 2017, 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.
|
| +
|
| +import 'dart:io';
|
| +
|
| +import 'package:status_file/status_file.dart';
|
| +
|
| +import 'io.dart';
|
| +import 'log.dart';
|
| +
|
| +// TODO(rnystrom): This file is kind of a hack. The problem is that a parsed
|
| +// StatusFile doesn't contain all of the original information in the source
|
| +// text. Comments and whitespace are lost. That means a StatusFile itself
|
| +// couldn't be modified and saved back to disc.
|
| +//
|
| +// Instead, this wraps a StatusFile and also lets you modify entire lines in
|
| +// it, including their comments. Ideally, StatusFile would include parsed
|
| +// comments and we would canonicalize other whitespace so that you could
|
| +// modify a StatusFile object then save it back to disc.
|
| +class EditableStatusFile {
|
| + final String path;
|
| +
|
| + StatusFile _statusFile;
|
| + StatusFile get statusFile {
|
| + if (_statusFile == null) {
|
| + _statusFile = new StatusFile.read(path);
|
| + }
|
| +
|
| + return _statusFile;
|
| + }
|
| +
|
| + List<String> _lines;
|
| +
|
| + EditableStatusFile(this.path);
|
| +
|
| + /// Gets the line at the given one-based index.
|
| + String lineAt(int line) {
|
| + _ensureLines();
|
| + return _lines[line - 1];
|
| + }
|
| +
|
| + /// Delete the numbered [lines] from the file.
|
| + void delete(List<int> lines) {
|
| + if (lines.isEmpty) return;
|
| +
|
| + if (dryRun) {
|
| + print("Delete lines ${lines.join(', ')} from $path.");
|
| + return;
|
| + }
|
| +
|
| + _ensureLines();
|
| +
|
| + var deleted = 0;
|
| + for (var line in lines) {
|
| + // Adjust index because previous lines have already been removed, shifting
|
| + // the subsequent line numbers.
|
| + _lines.removeAt(line - deleted);
|
| + deleted++;
|
| + }
|
| +
|
| + _save();
|
| + }
|
| +
|
| + /// Insert [entries] at [line] in the file.
|
| + void insert(int line, List<String> entries) {
|
| + if (dryRun) {
|
| + print("Insert ${bold(path)}, insert at line $line:");
|
| + entries.forEach(print);
|
| + return;
|
| + }
|
| +
|
| + _ensureLines();
|
| + _lines.insertAll(line, entries);
|
| + _save();
|
| + }
|
| +
|
| + /// Adds [header] followed by [entries] to the end of the file.
|
| + void append(String header, List<String> entries) {
|
| + if (dryRun) {
|
| + print("To ${bold(path)}, append:");
|
| + print(header);
|
| + entries.forEach(print);
|
| + return;
|
| + }
|
| +
|
| + _ensureLines();
|
| + _lines.add("");
|
| +
|
| + _lines.add(header);
|
| + _lines.addAll(entries);
|
| + _save();
|
| + }
|
| +
|
| + void _ensureLines() {
|
| + if (_lines == null) {
|
| + _lines = new File(path).readAsLinesSync();
|
| + }
|
| + }
|
| +
|
| + void _save() {
|
| + new File(path).writeAsStringSync(_lines.join("\n") + "\n");
|
| +
|
| + // It needs to be reparsed now since the lines have changed.
|
| + // TODO(rnystrom): This is kind of hacky and slow, but it gets the job done.
|
| + _statusFile = null;
|
| + _lines = null;
|
| + }
|
| +}
|
|
|