@@ -29,16 +29,27 @@ class Depfile {
2929
3030 /// Checks whether the inputs mentioned in the depfile are fresh.
3131 ///
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}) {
3438 final outputFile = File (outputPath);
3539 if (! outputFile.existsSync ()) return FreshnessResult (outputIsFresh: false );
3640 final depsFile = File (depfilePath);
3741 if (! depsFile.existsSync ()) return FreshnessResult (outputIsFresh: false );
3842 final digestFile = File (digestPath);
3943 if (! digestFile.existsSync ()) return FreshnessResult (outputIsFresh: false );
4044 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 ();
4253 return digests == expectedDigests
4354 ? FreshnessResult (outputIsFresh: true , digest: digests)
4455 : FreshnessResult (outputIsFresh: false );
@@ -53,18 +64,18 @@ class Depfile {
5364 /// Writes a digest of all input files mentioned in [depfilePath] to
5465 /// [digestPath] .
5566 void writeDigest () {
56- File (digestPath).writeAsStringSync (_computeDigest ());
67+ _depfilePaths = _readPaths ();
68+ File (digestPath).writeAsStringSync (_digestPaths ());
5769 }
5870
59- String _computeDigest () {
71+ /// Reads input paths from the depfile.
72+ Set <String > _readPaths () {
6073 final depsFile = File (depfilePath).readAsStringSync ();
61- final paths = parse (depsFile);
62- _depfilePaths = paths.toSet ();
63- return _digestPaths (paths);
74+ return parse (depsFile);
6475 }
6576
6677 @visibleForTesting
67- static List <String > parse (String deps) {
78+ static Set <String > parse (String deps) {
6879 // The depfile has the output path followed by a colon then a
6980 // space-separated list of input paths. Backslashes and spaces in paths are
7081 // backslash escaped.
@@ -75,19 +86,25 @@ class Depfile {
7586 .replaceAll (r'\ ' , '\u 0000' )
7687 // And unescape backslashes.
7788 .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+ }
84101 return result;
85102 }
86103
87- String _digestPaths (Iterable < String > deps ) {
104+ String _digestPaths () {
88105 final digestSink = AccumulatorSink <Digest >();
89106 final result = md5.startChunkedConversion (digestSink);
90- for (final dep in deps ) {
107+ for (final dep in _depfilePaths ! ) {
91108 final file = File (dep);
92109 if (file.existsSync ()) {
93110 result.add ([1 ]);
0 commit comments