blob: 35dcd6c389220c2509fb42a8a2cd0e69a9668d50 [file] [log] [blame]
// 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) {
if (new File(path).existsSync()) {
_statusFile = new StatusFile.read(path);
} else {
_statusFile = new StatusFile(path);
}
}
return _statusFile;
}
/// The lines of text in the status file, loaded lazily.
///
/// If the status file doesn't exist, creates a set of lines for a new empty
/// status file.
List<String> get _lines {
if (_linesCache == null) {
var file = new File(path);
if (file.existsSync()) {
_linesCache = file.readAsLinesSync();
} else {
_linesCache = [
"# 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."
];
}
}
return _linesCache;
}
List<String> _linesCache;
EditableStatusFile(this.path);
/// Gets the line at the given one-based index.
String lineAt(int line) {
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;
}
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;
}
_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;
}
_lines.add("");
_lines.add(header);
_lines.addAll(entries);
_save();
}
void _save() {
if (dryRun) {
print("Save ${bold(path)}");
return;
}
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;
_linesCache = null;
}
}