blob: 7c33619877330a34854a827079d1e00c1a6faac7 [file] [log] [blame]
// Copyright (c) 2019, 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:async';
import 'dart:io';
import 'package:path/path.dart' as p;
/// Returns a port that is probably, but not definitely, not in use.
///
/// This has a built-in race condition: another process may bind this port at
/// any time after this call has returned.
Future<int> findUnusedPort() async {
int port;
ServerSocket socket;
try {
socket = await ServerSocket.bind(InternetAddress.loopbackIPv6, 0);
} on SocketException {
socket = await ServerSocket.bind(InternetAddress.loopbackIPv4, 0);
}
port = socket.port;
await socket.close();
return port;
}
/// Copy directory [from] to [to].
///
/// Updates contents of [to] if already exists.
Future<void> updatePath(String from, String to) async {
await _removeDeleted(from, to);
await _copyUpdated(from, to);
}
// Update modified files.
Future<void> _copyUpdated(String from, String to) async {
if (!Directory(from).existsSync()) return;
await Directory(to).create(recursive: true);
await for (final file in Directory(from).list()) {
final copyTo = p.join(to, p.relative(file.path, from: from));
if (file is Directory) {
await _copyUpdated(file.path, copyTo);
} else if (file is File) {
final copyToFile = File(copyTo);
if (!copyToFile.existsSync() ||
copyToFile.statSync().modified.compareTo(file.statSync().modified) <
0) {
await File(file.path).copy(copyTo);
}
} else if (file is Link) {
await Link(copyTo).create(await file.target(), recursive: true);
}
}
}
// Remove deleted files.
Future<void> _removeDeleted(String from, String to) async {
if (!Directory(from).existsSync()) {
if (Directory(to).existsSync()) {
await Directory(to).delete(recursive: true);
}
return;
}
if (!Directory(to).existsSync()) return;
await for (final file in Directory(to).list()) {
final copyFrom = p.join(from, p.relative(file.path, from: to));
if (file is File) {
final copyFromFile = File(copyFrom);
if (!copyFromFile.existsSync()) {
await File(file.path).delete();
}
} else if (file is Directory) {
final copyFromDir = Directory(copyFrom);
await _removeDeleted(copyFromDir.path, file.path);
} else if (file is Link) {
final copyFromDir = Link(copyFrom);
if (!copyFromDir.existsSync()) {
await Link(file.path).delete();
}
}
}
}
/// Returns the absolute file path of the `package_config.json` file in the `.dart_tool`
/// directory, searching recursively from the current directory hierarchy.
String? findPackageConfigFilePath() {
var candidateDir = Directory(p.current).absolute;
while (true) {
final candidatePackageConfigFile =
File(p.join(candidateDir.path, '.dart_tool', 'package_config.json'));
if (candidatePackageConfigFile.existsSync()) {
return candidatePackageConfigFile.path;
}
final parentDir = candidateDir.parent;
if (parentDir.path == candidateDir.path) {
// We've reached the root directory
return null;
}
candidateDir = parentDir;
}
}