@@ -29,16 +29,27 @@ class Depfile {
29
29
30
30
/// Checks whether the inputs mentioned in the depfile are fresh.
31
31
///
32
- /// It is fresh if it has not changed and none of its inputs have changed.
33
- FreshnessResult checkFreshness () {
32
+ /// They are fresh if the output exists, the depfile exists, the digest file
33
+ /// exists and none of the input files has changed.
34
+ ///
35
+ /// Set [digestsAreFresh] if digests were very recently updated. Then, they
36
+ /// will be re-used from disk if possible instead of recomputed.
37
+ FreshnessResult checkFreshness ({required bool digestsAreFresh}) {
34
38
final outputFile = File (outputPath);
35
39
if (! outputFile.existsSync ()) return FreshnessResult (outputIsFresh: false );
36
40
final depsFile = File (depfilePath);
37
41
if (! depsFile.existsSync ()) return FreshnessResult (outputIsFresh: false );
38
42
final digestFile = File (digestPath);
39
43
if (! digestFile.existsSync ()) return FreshnessResult (outputIsFresh: false );
40
44
final digests = digestFile.readAsStringSync ();
41
- final expectedDigests = _computeDigest ();
45
+
46
+ if (digestsAreFresh) {
47
+ _depfilePaths ?? = _readPaths ();
48
+ return FreshnessResult (outputIsFresh: true , digest: digests);
49
+ }
50
+
51
+ _depfilePaths = _readPaths ();
52
+ final expectedDigests = _digestPaths ();
42
53
return digests == expectedDigests
43
54
? FreshnessResult (outputIsFresh: true , digest: digests)
44
55
: FreshnessResult (outputIsFresh: false );
@@ -53,18 +64,18 @@ class Depfile {
53
64
/// Writes a digest of all input files mentioned in [depfilePath] to
54
65
/// [digestPath] .
55
66
void writeDigest () {
56
- File (digestPath).writeAsStringSync (_computeDigest ());
67
+ _depfilePaths = _readPaths ();
68
+ File (digestPath).writeAsStringSync (_digestPaths ());
57
69
}
58
70
59
- String _computeDigest () {
71
+ /// Reads input paths from the depfile.
72
+ Set <String > _readPaths () {
60
73
final depsFile = File (depfilePath).readAsStringSync ();
61
- final paths = parse (depsFile);
62
- _depfilePaths = paths.toSet ();
63
- return _digestPaths (paths);
74
+ return parse (depsFile);
64
75
}
65
76
66
77
@visibleForTesting
67
- static List <String > parse (String deps) {
78
+ static Set <String > parse (String deps) {
68
79
// The depfile has the output path followed by a colon then a
69
80
// space-separated list of input paths. Backslashes and spaces in paths are
70
81
// backslash escaped.
@@ -75,19 +86,25 @@ class Depfile {
75
86
.replaceAll (r'\ ' , '\u 0000' )
76
87
// And unescape backslashes.
77
88
.replaceAll (r'\\' , r'\' )
78
- .split (' ' )
79
- .map ((item) => item.replaceAll ('\u 0000' , ' ' ));
80
-
81
- final result = items.skip (1 ).toList ();
82
- // File ends in a newline.
83
- result.last = result.last.substring (0 , result.last.length - 1 );
89
+ .split (' ' );
90
+
91
+ final result = < String > {};
92
+ // The first item is the output path, skip it.
93
+ for (var i = 1 ; i != items.length; ++ i) {
94
+ final item = items[i];
95
+ final path = item.replaceAll ('\u 0000' , ' ' );
96
+ // File ends in a newline.
97
+ result.add (
98
+ i == items.length - 1 ? path.substring (0 , path.length - 1 ) : path,
99
+ );
100
+ }
84
101
return result;
85
102
}
86
103
87
- String _digestPaths (Iterable < String > deps ) {
104
+ String _digestPaths () {
88
105
final digestSink = AccumulatorSink <Digest >();
89
106
final result = md5.startChunkedConversion (digestSink);
90
- for (final dep in deps ) {
107
+ for (final dep in _depfilePaths ! ) {
91
108
final file = File (dep);
92
109
if (file.existsSync ()) {
93
110
result.add ([1 ]);
0 commit comments