From c7e80e19f0bf61d9097e89e4dc1864e51b128821 Mon Sep 17 00:00:00 2001 From: vilicvane Date: Sat, 6 Feb 2016 16:51:25 +0800 Subject: [PATCH] Avoid writing files that are not changed while compiling incrementally. --- src/compiler/sys.ts | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 9c3972b275..69277f65a9 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -39,6 +39,15 @@ namespace ts { referenceCount: number; } + interface OutputFingerprint { + hash: string; + mtime: Date; + } + + interface OutputFingerprintMap { + [fileName: string]: OutputFingerprint; + } + declare var require: any; declare var module: any; declare var process: any; @@ -226,6 +235,7 @@ namespace ts { const _fs = require("fs"); const _path = require("path"); const _os = require("os"); + const _crypto = require("crypto"); // average async stat takes about 30 microseconds // set chunk size to do 30 files in < 1 millisecond @@ -439,12 +449,26 @@ namespace ts { return buffer.toString("utf8"); } + const outputFingerprintMap: OutputFingerprintMap = {}; + function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void { // If a BOM is required, emit one if (writeByteOrderMark) { data = "\uFEFF" + data; } + const md5 = getMd5(data); + const mtimeBefore = _fs.existsSync(fileName) && _fs.statSync(fileName).mtime; + + if (mtimeBefore && outputFingerprintMap.hasOwnProperty(fileName)) { + const fingerprint = outputFingerprintMap[fileName]; + + // If output has not been changed, and the file has no external modification + if (fingerprint.hash === md5 && fingerprint.mtime.getTime() === mtimeBefore.getTime()) { + return; + } + } + let fd: number; try { @@ -456,6 +480,19 @@ namespace ts { _fs.closeSync(fd); } } + + const mtimeAfter = _fs.statSync(fileName).mtime; + + outputFingerprintMap[fileName] = { + hash: md5, + mtime: mtimeAfter + }; + } + + function getMd5(data: string): string { + const hash = _crypto.createHash("md5"); + hash.update(data); + return hash.digest("hex"); } function getCanonicalPath(path: string): string {