Merge pull request #34521 from amcasey/LazyDirectoryCreation
Stop pre-emptively creating directories
This commit is contained in:
commit
8cf13249ea
|
@ -96,35 +96,51 @@ namespace ts {
|
||||||
if (existingDirectories.has(directoryPath)) {
|
if (existingDirectories.has(directoryPath)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (system.directoryExists(directoryPath)) {
|
if ((compilerHost.directoryExists || system.directoryExists)(directoryPath)) {
|
||||||
existingDirectories.set(directoryPath, true);
|
existingDirectories.set(directoryPath, true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ensureDirectoriesExist(directoryPath: string) {
|
function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) {
|
||||||
if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) {
|
try {
|
||||||
const parentDirectory = getDirectoryPath(directoryPath);
|
performance.mark("beforeIOWrite");
|
||||||
ensureDirectoriesExist(parentDirectory);
|
|
||||||
if (compilerHost.createDirectory) {
|
// NOTE: If patchWriteFileEnsuringDirectory has been called,
|
||||||
compilerHost.createDirectory(directoryPath);
|
// the system.writeFile will do its own directory creation and
|
||||||
}
|
// the ensureDirectoriesExist call will always be redundant.
|
||||||
else {
|
writeFileEnsuringDirectories(
|
||||||
system.createDirectory(directoryPath);
|
fileName,
|
||||||
|
data,
|
||||||
|
writeByteOrderMark,
|
||||||
|
(path, data, writeByteOrderMark) => writeFileWorker(path, data, writeByteOrderMark),
|
||||||
|
path => (compilerHost.createDirectory || system.createDirectory)(path),
|
||||||
|
path => directoryExists(path));
|
||||||
|
|
||||||
|
performance.mark("afterIOWrite");
|
||||||
|
performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite");
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
if (onError) {
|
||||||
|
onError(e.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let outputFingerprints: Map<OutputFingerprint>;
|
let outputFingerprints: Map<OutputFingerprint>;
|
||||||
|
function writeFileWorker(fileName: string, data: string, writeByteOrderMark: boolean) {
|
||||||
|
if (!isWatchSet(options) || !system.createHash || !system.getModifiedTime) {
|
||||||
|
system.writeFile(fileName, data, writeByteOrderMark);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
function writeFileIfUpdated(fileName: string, data: string, writeByteOrderMark: boolean): void {
|
|
||||||
if (!outputFingerprints) {
|
if (!outputFingerprints) {
|
||||||
outputFingerprints = createMap<OutputFingerprint>();
|
outputFingerprints = createMap<OutputFingerprint>();
|
||||||
}
|
}
|
||||||
|
|
||||||
const hash = system.createHash!(data); // TODO: GH#18217
|
const hash = system.createHash(data);
|
||||||
const mtimeBefore = system.getModifiedTime!(fileName); // TODO: GH#18217
|
const mtimeBefore = system.getModifiedTime(fileName);
|
||||||
|
|
||||||
if (mtimeBefore) {
|
if (mtimeBefore) {
|
||||||
const fingerprint = outputFingerprints.get(fileName);
|
const fingerprint = outputFingerprints.get(fileName);
|
||||||
|
@ -139,7 +155,7 @@ namespace ts {
|
||||||
|
|
||||||
system.writeFile(fileName, data, writeByteOrderMark);
|
system.writeFile(fileName, data, writeByteOrderMark);
|
||||||
|
|
||||||
const mtimeAfter = system.getModifiedTime!(fileName) || missingFileModifiedTime; // TODO: GH#18217
|
const mtimeAfter = system.getModifiedTime(fileName) || missingFileModifiedTime;
|
||||||
|
|
||||||
outputFingerprints.set(fileName, {
|
outputFingerprints.set(fileName, {
|
||||||
hash,
|
hash,
|
||||||
|
@ -148,28 +164,6 @@ namespace ts {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) {
|
|
||||||
try {
|
|
||||||
performance.mark("beforeIOWrite");
|
|
||||||
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
|
|
||||||
|
|
||||||
if (isWatchSet(options) && system.createHash && system.getModifiedTime) {
|
|
||||||
writeFileIfUpdated(fileName, data, writeByteOrderMark);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
system.writeFile(fileName, data, writeByteOrderMark);
|
|
||||||
}
|
|
||||||
|
|
||||||
performance.mark("afterIOWrite");
|
|
||||||
performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite");
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
if (onError) {
|
|
||||||
onError(e.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDefaultLibLocation(): string {
|
function getDefaultLibLocation(): string {
|
||||||
return getDirectoryPath(normalizePath(system.getExecutingFilePath()));
|
return getDirectoryPath(normalizePath(system.getExecutingFilePath()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -522,17 +522,6 @@ namespace ts {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function recursiveCreateDirectory(directoryPath: string, sys: System) {
|
|
||||||
const basePath = getDirectoryPath(directoryPath);
|
|
||||||
const shouldCreateParent = basePath !== "" && directoryPath !== basePath && !sys.directoryExists(basePath);
|
|
||||||
if (shouldCreateParent) {
|
|
||||||
recursiveCreateDirectory(basePath, sys);
|
|
||||||
}
|
|
||||||
if (shouldCreateParent || !sys.directoryExists(directoryPath)) {
|
|
||||||
sys.createDirectory(directoryPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* patch writefile to create folder before writing the file
|
* patch writefile to create folder before writing the file
|
||||||
*/
|
*/
|
||||||
|
@ -540,13 +529,14 @@ namespace ts {
|
||||||
export function patchWriteFileEnsuringDirectory(sys: System) {
|
export function patchWriteFileEnsuringDirectory(sys: System) {
|
||||||
// patch writefile to create folder before writing the file
|
// patch writefile to create folder before writing the file
|
||||||
const originalWriteFile = sys.writeFile;
|
const originalWriteFile = sys.writeFile;
|
||||||
sys.writeFile = (path, data, writeBom) => {
|
sys.writeFile = (path, data, writeBom) =>
|
||||||
const directoryPath = getDirectoryPath(normalizeSlashes(path));
|
writeFileEnsuringDirectories(
|
||||||
if (directoryPath && !sys.directoryExists(directoryPath)) {
|
path,
|
||||||
recursiveCreateDirectory(directoryPath, sys);
|
data,
|
||||||
}
|
!!writeBom,
|
||||||
originalWriteFile.call(sys, path, data, writeBom);
|
(path, data, writeByteOrderMark) => originalWriteFile.call(sys, path, data, writeByteOrderMark),
|
||||||
};
|
path => sys.createDirectory(path),
|
||||||
|
path => sys.directoryExists(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*@internal*/
|
/*@internal*/
|
||||||
|
|
|
@ -3700,6 +3700,36 @@ namespace ts {
|
||||||
}, sourceFiles);
|
}, sourceFiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ensureDirectoriesExist(
|
||||||
|
directoryPath: string,
|
||||||
|
createDirectory: (path: string) => void,
|
||||||
|
directoryExists: (path: string) => boolean): void {
|
||||||
|
if (directoryPath.length > getRootLength(directoryPath) && !directoryExists(directoryPath)) {
|
||||||
|
const parentDirectory = getDirectoryPath(directoryPath);
|
||||||
|
ensureDirectoriesExist(parentDirectory, createDirectory, directoryExists);
|
||||||
|
createDirectory(directoryPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function writeFileEnsuringDirectories(
|
||||||
|
path: string,
|
||||||
|
data: string,
|
||||||
|
writeByteOrderMark: boolean,
|
||||||
|
writeFile: (path: string, data: string, writeByteOrderMark: boolean) => void,
|
||||||
|
createDirectory: (path: string) => void,
|
||||||
|
directoryExists: (path: string) => boolean): void {
|
||||||
|
|
||||||
|
// PERF: Checking for directory existence is expensive. Instead, assume the directory exists
|
||||||
|
// and fall back to creating it if the file write fails.
|
||||||
|
try {
|
||||||
|
writeFile(path, data, writeByteOrderMark);
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
ensureDirectoriesExist(getDirectoryPath(normalizePath(path)), createDirectory, directoryExists);
|
||||||
|
writeFile(path, data, writeByteOrderMark);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function getLineOfLocalPosition(currentSourceFile: SourceFile, pos: number) {
|
export function getLineOfLocalPosition(currentSourceFile: SourceFile, pos: number) {
|
||||||
return getLineAndCharacterOfPosition(currentSourceFile, pos).line;
|
return getLineAndCharacterOfPosition(currentSourceFile, pos).line;
|
||||||
}
|
}
|
||||||
|
|
|
@ -303,20 +303,20 @@ namespace ts {
|
||||||
readDirectory: maybeBind(host, host.readDirectory),
|
readDirectory: maybeBind(host, host.readDirectory),
|
||||||
};
|
};
|
||||||
|
|
||||||
function ensureDirectoriesExist(directoryPath: string) {
|
|
||||||
if (directoryPath.length > getRootLength(directoryPath) && !host.directoryExists!(directoryPath)) {
|
|
||||||
const parentDirectory = getDirectoryPath(directoryPath);
|
|
||||||
ensureDirectoriesExist(parentDirectory);
|
|
||||||
if (host.createDirectory) host.createDirectory(directoryPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function writeFile(fileName: string, text: string, writeByteOrderMark: boolean, onError: (message: string) => void) {
|
function writeFile(fileName: string, text: string, writeByteOrderMark: boolean, onError: (message: string) => void) {
|
||||||
try {
|
try {
|
||||||
performance.mark("beforeIOWrite");
|
performance.mark("beforeIOWrite");
|
||||||
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
|
|
||||||
|
|
||||||
host.writeFile!(fileName, text, writeByteOrderMark);
|
// NOTE: If patchWriteFileEnsuringDirectory has been called,
|
||||||
|
// the host.writeFile will do its own directory creation and
|
||||||
|
// the ensureDirectoriesExist call will always be redundant.
|
||||||
|
writeFileEnsuringDirectories(
|
||||||
|
fileName,
|
||||||
|
text,
|
||||||
|
writeByteOrderMark,
|
||||||
|
(path, data, writeByteOrderMark) => host.writeFile!(path, data, writeByteOrderMark),
|
||||||
|
path => host.createDirectory!(path),
|
||||||
|
path => host.directoryExists!(path));
|
||||||
|
|
||||||
performance.mark("afterIOWrite");
|
performance.mark("afterIOWrite");
|
||||||
performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite");
|
performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite");
|
||||||
|
|
Loading…
Reference in a new issue