blob: 23127995c55655912e5cd1408811f6d39abc5d84 [file] [log] [blame] [edit]
// Copyright (c) 2023, 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';
/// Finds unique dills in the sdk.
///
/// Note that it reads all dills found to create and compare a checksum to
/// remove duplicates (and re-read on checksum matches).
List<File> findSdkDills() {
String? resolvedExecutable = Platform.environment['resolvedExecutable'];
File exe =
new File(resolvedExecutable ?? Platform.resolvedExecutable).absolute;
int steps = 0;
Directory parent = exe.parent.parent;
while (true) {
Set<String> foundDirs = {};
for (FileSystemEntity entry in parent.listSync(recursive: false)) {
if (entry is Directory) {
List<String> pathSegments = entry.uri.pathSegments;
String name = pathSegments[pathSegments.length - 2];
foundDirs.add(name);
}
}
if (foundDirs.contains("pkg") &&
foundDirs.contains("tools") &&
foundDirs.contains("tests")) {
break;
}
steps++;
if (parent.uri == parent.parent.uri) {
throw "Reached end without finding the root.";
}
parent = parent.parent;
}
// We had to go $steps steps to reach the "root" --- now we should go 2 steps
// shorter to be in the "compiled dir".
parent = exe.parent;
for (int i = steps - 2; i >= 0; i--) {
parent = parent.parent;
}
List<File> dills = [];
List<int> checksums = [];
for (FileSystemEntity entry in parent.listSync(recursive: false)) {
if (entry is File) {
if (entry.path.toLowerCase().endsWith(".dill")) {
_addIfNotDuplicate(entry, dills, checksums);
}
}
}
Directory sdk = new Directory.fromUri(parent.uri.resolve("dart-sdk/"));
for (FileSystemEntity entry in sdk.listSync(recursive: true)) {
if (entry is File) {
if (entry.path.toLowerCase().endsWith(".dill")) {
_addIfNotDuplicate(entry, dills, checksums);
}
}
}
return dills;
}
void _addIfNotDuplicate(File f, List<File> existingFiles, List<int> checksums) {
List<int> content = f.readAsBytesSync();
int adler = adler32(content);
for (int i = 0; i < checksums.length; i++) {
if (checksums[i] == adler) {
List<int> existingContent = existingFiles[i].readAsBytesSync();
bool duplicate = existingContent.length == content.length;
if (duplicate) {
for (int j = 0; j < existingContent.length; j++) {
if (existingContent[j] != content[j]) {
duplicate = false;
break;
}
}
}
if (duplicate) return;
}
}
checksums.add(adler);
existingFiles.add(f);
}
int adler32(List<int> data) {
int a = 1;
int b = 0;
for (int i = 0; i < data.length; i++) {
a += data[i];
b += a;
if (i & 255 == 255) {
a %= 65521;
b %= 65521;
}
}
a %= 65521;
b %= 65521;
return (b << 16) | a;
}