| // 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; |
| } |