-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutils.dart
245 lines (201 loc) · 6.6 KB
/
utils.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
/// This file is part of dart-qtbindings
///
/// SPDX-FileCopyrightText: 2022 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
/// SPDX-License-Identifier: MIT
import 'dart:io' show Platform;
import 'dart:io';
import 'dart:convert';
/// Path list separator (for PATH env var)
final String s_listSeparator = Platform.isWindows ? ";" : ":";
/// The name of the env var for runtime library path
final String s_libraryPathEnvVariable = Platform.isWindows
? "PATH"
: Platform.isLinux
? "LD_LIBRARY_PATH"
: Platform.isMacOS
? "DYLD_LIBRARY_PATH"
: "";
final String s_qtIncludePath = qtIncludePath();
final String s_qtLibraryPath = qtLibPath();
/**
* Returns the library filename according to the operating system.
*/
String normalizedLibName(String name) {
if (Platform.isWindows) return "${name}.dll";
if (Platform.isMacOS) return "lib${name}.dylib";
return "lib${name}.so";
}
/**
* Runs the specified command. Pipes its output to this script's stdout/err.
*/
Future<int> runCommand(String command, List<String> args,
{String? workingDirectory,
Map<String, String>? env,
bool printOnly = false,
bool silent = false,
bool useGDB = false,
bool forwardStdOut = true,
bool forwardStdErr = true}) async {
if (workingDirectory != null && !silent)
print("Running: cd ${workingDirectory}");
if (useGDB) {
args.insertAll(0, ["-ex=run", "--args", command]);
command = "gdb";
}
if (!silent) print("Running: ${command} ${args.join(" ")}");
if (printOnly) return 0;
Process process = await Process.start(command, args,
workingDirectory: workingDirectory, environment: env)
.then((process) {
if (forwardStdErr) stderr.addStream(process.stderr);
if (forwardStdOut) stdout.addStream(process.stdout);
if (useGDB) process.stdin.addStream(stdin);
return process;
});
return await process.exitCode;
}
Future<int> runDartFormat(String folder, {bool printOnly = false}) async {
if (Platform.isWindows) {
return runCommand('cmd', ["/C", 'dart', 'format', '--fix', folder],
printOnly: printOnly);
} else {
return runCommand("dart", ['format', '--fix', folder],
printOnly: printOnly);
}
}
Future<int> runClangFormat(String folder) async {
final String clangFormat =
Platform.environment['DARTAGNAN_CLANG_FORMAT'] ?? "clang-format";
var dir = Directory(folder);
final fileEntries = dir.listSync().where((element) =>
element.path.endsWith('.h') || element.path.endsWith('.cpp'));
final List<String> files = fileEntries.map((e) => e.path.toString()).toList();
final List<String> arguments = ["-i"] + files;
print("Running ${clangFormat}...");
return runCommand(clangFormat, arguments, silent: true);
}
/**
* Runs "dart pub get"
*/
Future<int> getPackages(
{required String workingDirectory, bool printOnly = false}) async {
if (File("${workingDirectory}/.packages").existsSync()) {
// No need to get packages
return 0;
}
return runCommand(dartBinary(), ["pub", "get"],
workingDirectory: workingDirectory, printOnly: printOnly);
}
/**
* Runs qmake -query
*/
String qmakeQuery(String key) {
ProcessResult result = Process.runSync('qmake', ['-query']);
for (String line in result.stdout.toString().split("\n")) {
if (line.startsWith('${key}:')) {
line = line.replaceAll('${key}:', '');
line = line.trim();
return line;
}
}
return "";
}
String qtIncludePath() {
return qmakeQuery('QT_INSTALL_HEADERS');
}
String qtLibPath() {
return qmakeQuery('QT_INSTALL_LIBS');
}
List<String> includeArguments() {
if (Platform.isMacOS) {
return [
"-I${s_qtLibraryPath}/QtCore.framework/Headers",
"-I${s_qtLibraryPath}/QtGui.framework/Headers",
"-I${s_qtLibraryPath}/QtWidgets.framework/Headers",
"-F${s_qtLibraryPath}"
];
} else {
return [
"-I${s_qtIncludePath}",
"-I${s_qtIncludePath}/QtCore",
"-I${s_qtIncludePath}/QtGui",
"-I${s_qtIncludePath}/QtWidgets"
];
}
}
enum DartBinaryType {
Normal, // Usually /usr/bin/dart or so
ASAN // Something you compiled without tcmalloc, otherwise it's not asan compatible
}
String dartBinary([DartBinaryType type = DartBinaryType.Normal]) {
switch (type) {
case DartBinaryType.Normal:
return "dart";
case DartBinaryType.ASAN:
final path = Platform.environment['DART_FOR_ASAN'] ?? "";
if (path.isEmpty) {
print(
"If you want to use ASAN, you'll need to point the DART_FOR_ASAN env variable to your dart binary which you compiled without tcmalloc support");
}
return path;
}
}
class TimeStamp {
final String filename;
final String _originalContents;
final String originalTimeStamp;
static Future<TimeStamp> create(String filename) async {
final String timestamp = await getTimeStamp(filename);
return TimeStamp._ctor(filename, timestamp);
}
TimeStamp._ctor(this.filename, this.originalTimeStamp)
: _originalContents = File(filename).readAsStringSync() {}
/// @brief Returns whether this file has a different contents now
bool wasModified() {
return File(filename).readAsStringSync() != _originalContents;
}
static Future<String> getTimeStamp(String filename) async {
Process process = await Process.start("stat", ['-c', '%y', filename]);
String result = "";
await for (var line in process.stdout.transform(utf8.decoder)) {
result += line;
}
await process.exitCode;
return result.trim();
}
Future<bool> restoreTimeStamp() async {
return await runCommand("touch", ['-d', '${originalTimeStamp}', filename],
silent: true) ==
0;
}
}
class TimeStamps {
final String path;
var _timestamps = <TimeStamp>[];
TimeStamps(this.path) {}
void create() async {
final dir = Directory(path);
dir.list(recursive: true).forEach((entry) async {
if (entry.path.endsWith('.cpp') || entry.path.endsWith('.h')) {
_timestamps.add(await TimeStamp.create(entry.path));
}
});
}
/// @brief Returns the list of files which have a different contents now
List<TimeStamp> modifiedFiles() {
return _timestamps.where((t) => t.wasModified()).toList();
}
/// @brief Returns the list of files which still have the same contents
List<TimeStamp> unmodifiedFiles() {
return _timestamps.where((t) => !t.wasModified()).toList();
}
/// @brief restores the timestams of all files which weren't modified
Future<bool> restoreTimeStamps() async {
for (final file in unmodifiedFiles()) {
if (!await file.restoreTimeStamp()) {
return false;
}
}
return true;
}
}