Skip to content

Commit 68d9ab3

Browse files
authored
consider mtime for generated files (#1153)
* consider mtime for generated files * deterministic test mtime
1 parent 0186815 commit 68d9ab3

File tree

2 files changed

+20
-5
lines changed

2 files changed

+20
-5
lines changed

src/dataloader.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import {createHash} from "node:crypto";
12
import {type WriteStream, createReadStream, existsSync, statSync} from "node:fs";
23
import {mkdir, open, readFile, rename, unlink} from "node:fs/promises";
34
import {dirname, extname, join, relative} from "node:path/posix";
@@ -7,7 +8,7 @@ import JSZip from "jszip";
78
import {extract} from "tar-stream";
89
import {maybeStat, prepareOutput} from "./files.js";
910
import {FileWatchers} from "./fileWatchers.js";
10-
import {getFileHash, getFileInfo} from "./javascript/module.js";
11+
import {getFileInfo} from "./javascript/module.js";
1112
import type {Logger, Writer} from "./logger.js";
1213
import {cyan, faint, green, red, yellow} from "./tty.js";
1314

@@ -155,8 +156,19 @@ export class LoaderResolver {
155156
return path;
156157
}
157158

159+
/**
160+
* Returns the hash of the file with the given name within the source root, or
161+
* if the name refers to a file generated by a data loader, the hash of the
162+
* corresponding data loader source and its modification time. The latter
163+
* ensures that if the data loader is “touched” (even without changing its
164+
* contents) that the data loader will be re-run.
165+
*/
158166
getSourceFileHash(name: string): string {
159-
return getFileHash(this.root, this.getSourceFilePath(name));
167+
const path = this.getSourceFilePath(name);
168+
const info = getFileInfo(this.root, path);
169+
if (!info) return createHash("sha256").digest("hex");
170+
const {hash} = info;
171+
return path === name ? hash : createHash("sha256").update(hash).update(String(info.mtimeMs)).digest("hex");
160172
}
161173

162174
getSourceLastModified(name: string): number | undefined {

test/dataloaders-test.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,16 @@ describe("LoaderResolver.find(path, {useStale: true})", () => {
100100
});
101101

102102
describe("LoaderResolver.getSourceFileHash(path)", () => {
103+
const time = new Date(Date.UTC(2023, 11, 1));
103104
it("returns the content hash for the specified file’s data loader", async () => {
105+
await utimes("test/input/build/archives.posix/dynamic.zip.sh", time, time);
106+
await utimes("test/input/build/archives.posix/static.zip", time, time);
104107
const loaders = new LoaderResolver({root: "test/input/build/archives.posix"});
105108
assert.strictEqual(loaders.getSourceFileHash("dynamic.zip.sh"), "516cec2431ce8f1181a7a2a161db8bdfcaea132d3b2c37f863ea6f05d64d1d10"); // prettier-ignore
106-
assert.strictEqual(loaders.getSourceFileHash("dynamic.zip"), "516cec2431ce8f1181a7a2a161db8bdfcaea132d3b2c37f863ea6f05d64d1d10"); // prettier-ignore
107-
assert.strictEqual(loaders.getSourceFileHash("dynamic/file.txt"), "516cec2431ce8f1181a7a2a161db8bdfcaea132d3b2c37f863ea6f05d64d1d10"); // prettier-ignore
109+
assert.strictEqual(loaders.getSourceFileHash("dynamic.zip"), "64acd011e27907a2594fda3272bfc951e75db4c80495ce41e84ced61383bbb60"); // prettier-ignore
110+
assert.strictEqual(loaders.getSourceFileHash("dynamic/file.txt"), "64acd011e27907a2594fda3272bfc951e75db4c80495ce41e84ced61383bbb60"); // prettier-ignore
108111
assert.strictEqual(loaders.getSourceFileHash("static.zip"), "e6afff224da77b900cfe3ab8789f2283883300e1497548c30af66dfe4c29b429"); // prettier-ignore
109-
assert.strictEqual(loaders.getSourceFileHash("static/file.txt"), "e6afff224da77b900cfe3ab8789f2283883300e1497548c30af66dfe4c29b429"); // prettier-ignore
112+
assert.strictEqual(loaders.getSourceFileHash("static/file.txt"), "76ac155a1184b392ed40fb79eff680d5bf57e8afd9a494b1066f26dfd1e4c5e6"); // prettier-ignore
110113
});
111114
it("returns the empty hash if the specified file does not exist", async () => {
112115
const loaders = new LoaderResolver({root: "test/input/build/files"});

0 commit comments

Comments
 (0)