Skip to content

Commit f1b4ea2

Browse files
authored
fix: included symlinked directories when reading a directory (#1290)
1 parent 284a7fd commit f1b4ea2

File tree

13 files changed

+158
-142
lines changed

13 files changed

+158
-142
lines changed

deno/common/DenoRuntime.ts

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -90,38 +90,25 @@ class DenoRuntimeFileSystem {
9090
return Deno.copyFileSync(srcPath, destPath);
9191
}
9292

93-
async fileExists(filePath: string) {
94-
try {
95-
const stat = await Deno.stat(filePath);
96-
return stat.isFile;
97-
} catch {
98-
return false;
99-
}
100-
}
101-
102-
fileExistsSync(filePath: string) {
103-
try {
104-
return Deno.statSync(filePath).isFile;
105-
} catch {
106-
return false;
107-
}
93+
async stat(filePath: string) {
94+
const stat = await Deno.stat(filePath);
95+
return this._toStat(stat);
10896
}
10997

110-
async directoryExists(dirPath: string) {
111-
try {
112-
const stat = await Deno.stat(dirPath);
113-
return stat.isDirectory;
114-
} catch {
115-
return false;
116-
}
98+
statSync(path: string) {
99+
const stat = Deno.statSync(path);
100+
return this._toStat(stat);
117101
}
118102

119-
directoryExistsSync(dirPath: string) {
120-
try {
121-
return Deno.statSync(dirPath).isDirectory;
122-
} catch (err) {
123-
return false;
124-
}
103+
private _toStat(stat: Deno.FileInfo) {
104+
return {
105+
isFile() {
106+
return stat.isFile;
107+
},
108+
isDirectory() {
109+
return stat.isDirectory;
110+
},
111+
};
125112
}
126113

127114
realpathSync(path: string) {

deno/common/ts_morph_common.d.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,11 @@ export interface RuntimeDirEntry {
914914
isSymlink: boolean;
915915
}
916916

917+
export interface RuntimeFileInfo {
918+
isFile(): boolean;
919+
isDirectory(): boolean;
920+
}
921+
917922
export interface RuntimeFileSystem {
918923
/** Gets if this file system is case sensitive. */
919924
isCaseSensitive(): boolean;
@@ -943,14 +948,10 @@ export interface RuntimeFileSystem {
943948
copy(srcPath: string, destPath: string): Promise<void>;
944949
/** Synchronously copies a file or directory. */
945950
copySync(srcPath: string, destPath: string): void;
946-
/** Asynchronously checks if a file exists. */
947-
fileExists(filePath: string): Promise<boolean>;
948-
/** Synchronously checks if a file exists. */
949-
fileExistsSync(filePath: string): boolean;
950-
/** Asynchronously checks if a directory exists. */
951-
directoryExists(dirPath: string): Promise<boolean>;
952-
/** Synchronously checks if a directory exists. */
953-
directoryExistsSync(dirPath: string): boolean;
951+
/** Asynchronously gets the path's stat information. */
952+
stat(path: string): Promise<RuntimeFileInfo>;
953+
/** Synchronously gets the path's stat information. */
954+
statSync(path: string): RuntimeFileInfo;
954955
/** See https://nodejs.org/api/fs.html#fs_fs_realpathsync_path_options */
955956
realpathSync(path: string): string;
956957
/** Gets the current directory of the environment. */

deno/common/ts_morph_common.js

Lines changed: 37 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

deno/ts_morph.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9214,6 +9214,8 @@ export declare class Symbol {
92149214
getExportSymbol(): Symbol;
92159215
/** Gets if the symbol is an alias. */
92169216
isAlias(): boolean;
9217+
/** Gets if the symbol is optional. */
9218+
isOptional(): boolean;
92179219
/** Gets the symbol flags. */
92189220
getFlags(): SymbolFlags;
92199221
/**
@@ -10124,6 +10126,8 @@ export declare class Type<TType extends ts.Type = ts.Type> {
1012410126
isAny(): boolean;
1012510127
/** Gets if this is an array type. */
1012610128
isArray(): boolean;
10129+
/** Gets if this is a template literal type. */
10130+
isTemplateLiteral(): boolean;
1012710131
/** Gets if this is a boolean type. */
1012810132
isBoolean(): boolean;
1012910133
/** Gets if this is a string type. */

deno/ts_morph.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16840,6 +16840,9 @@ class Symbol {
1684016840
isAlias() {
1684116841
return (this.getFlags() & SymbolFlags.Alias) === SymbolFlags.Alias;
1684216842
}
16843+
isOptional() {
16844+
return (this.getFlags() & SymbolFlags.Optional) === SymbolFlags.Optional;
16845+
}
1684316846
getFlags() {
1684416847
return this.compilerSymbol.getFlags();
1684516848
}
@@ -17971,6 +17974,9 @@ class Type {
1797117974
return false;
1797217975
return symbol.getName() === "Array" && this.getTypeArguments().length === 1;
1797317976
}
17977+
isTemplateLiteral() {
17978+
return this._hasTypeFlag(TypeFlags.TemplateLiteral);
17979+
}
1797417980
isBoolean() {
1797517981
return this._hasTypeFlag(TypeFlags.Boolean);
1797617982
}

packages/common/lib/ts-morph-common.d.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -913,6 +913,11 @@ export interface RuntimeDirEntry {
913913
isSymlink: boolean;
914914
}
915915

916+
export interface RuntimeFileInfo {
917+
isFile(): boolean;
918+
isDirectory(): boolean;
919+
}
920+
916921
export interface RuntimeFileSystem {
917922
/** Gets if this file system is case sensitive. */
918923
isCaseSensitive(): boolean;
@@ -942,14 +947,10 @@ export interface RuntimeFileSystem {
942947
copy(srcPath: string, destPath: string): Promise<void>;
943948
/** Synchronously copies a file or directory. */
944949
copySync(srcPath: string, destPath: string): void;
945-
/** Asynchronously checks if a file exists. */
946-
fileExists(filePath: string): Promise<boolean>;
947-
/** Synchronously checks if a file exists. */
948-
fileExistsSync(filePath: string): boolean;
949-
/** Asynchronously checks if a directory exists. */
950-
directoryExists(dirPath: string): Promise<boolean>;
951-
/** Synchronously checks if a directory exists. */
952-
directoryExistsSync(dirPath: string): boolean;
950+
/** Asynchronously gets the path's stat information. */
951+
stat(path: string): Promise<RuntimeFileInfo>;
952+
/** Synchronously gets the path's stat information. */
953+
statSync(path: string): RuntimeFileInfo;
953954
/** See https://nodejs.org/api/fs.html#fs_fs_realpathsync_path_options */
954955
realpathSync(path: string): string;
955956
/** Gets the current directory of the environment. */

packages/common/src/fileSystem/RealFileSystemHost.ts

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,18 @@ export class RealFileSystemHost implements FileSystemHost {
2929
readDirSync(dirPath: string): RuntimeDirEntry[] {
3030
try {
3131
const entries = fs.readDirSync(dirPath);
32-
for (const entry of entries)
32+
for (const entry of entries) {
3333
entry.name = FileUtils.pathJoin(dirPath, entry.name);
34+
if (entry.isSymlink) {
35+
try {
36+
const info = fs.statSync(entry.name);
37+
entry.isDirectory = info.isDirectory();
38+
entry.isFile = info.isFile();
39+
} catch {
40+
// ignore
41+
}
42+
}
43+
}
3444
return entries;
3545
} catch (err) {
3646
throw this.getDirectoryNotFoundErrorIfNecessary(err, dirPath);
@@ -96,23 +106,39 @@ export class RealFileSystemHost implements FileSystemHost {
96106
}
97107

98108
/** @inheritdoc */
99-
fileExists(filePath: string) {
100-
return fs.fileExists(filePath);
109+
async fileExists(filePath: string) {
110+
try {
111+
return (await fs.stat(filePath)).isFile();
112+
} catch {
113+
return false;
114+
}
101115
}
102116

103117
/** @inheritdoc */
104118
fileExistsSync(filePath: string) {
105-
return fs.fileExistsSync(filePath);
119+
try {
120+
return fs.statSync(filePath).isFile();
121+
} catch {
122+
return false;
123+
}
106124
}
107125

108126
/** @inheritdoc */
109-
directoryExists(dirPath: string) {
110-
return fs.directoryExists(dirPath);
127+
async directoryExists(dirPath: string) {
128+
try {
129+
return (await fs.stat(dirPath)).isDirectory();
130+
} catch {
131+
return false;
132+
}
111133
}
112134

113135
/** @inheritdoc */
114136
directoryExistsSync(dirPath: string) {
115-
return fs.directoryExistsSync(dirPath);
137+
try {
138+
return fs.statSync(dirPath).isDirectory();
139+
} catch {
140+
return false;
141+
}
116142
}
117143

118144
/** @inheritdoc */

packages/common/src/runtimes/BrowserRuntime.ts

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import minimatch from "minimatch";
2-
import { Runtime, RuntimeDirEntry, RuntimeFileSystem, RuntimePath } from "./Runtime";
2+
import { Runtime, RuntimeDirEntry, RuntimeFileInfo, RuntimeFileSystem, RuntimePath } from "./Runtime";
33

44
const path = require("path-browserify");
55

@@ -90,19 +90,11 @@ class BrowserRuntimeFileSystem implements RuntimeFileSystem {
9090
throw new Error(this._errorMessage);
9191
}
9292

93-
fileExists(_filePath: string): Promise<boolean> {
93+
stat(_path: string): Promise<RuntimeFileInfo> {
9494
return Promise.reject(new Error(this._errorMessage));
9595
}
9696

97-
fileExistsSync(_filePath: string): boolean {
98-
throw new Error(this._errorMessage);
99-
}
100-
101-
directoryExists(_dirPath: string): Promise<boolean> {
102-
return Promise.reject(new Error(this._errorMessage));
103-
}
104-
105-
directoryExistsSync(_dirPath: string): boolean {
97+
statSync(_path: string): RuntimeFileInfo {
10698
throw new Error(this._errorMessage);
10799
}
108100

packages/common/src/runtimes/DenoRuntime.ts

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -95,38 +95,25 @@ class DenoRuntimeFileSystem {
9595
return Deno.copyFileSync(srcPath, destPath);
9696
}
9797

98-
async fileExists(filePath: string) {
99-
try {
100-
const stat = await Deno.stat(filePath);
101-
return stat.isFile;
102-
} catch {
103-
return false;
104-
}
105-
}
106-
107-
fileExistsSync(filePath: string) {
108-
try {
109-
return Deno.statSync(filePath).isFile;
110-
} catch {
111-
return false;
112-
}
98+
async stat(filePath: string) {
99+
const stat = await Deno.stat(filePath);
100+
return this._toStat(stat);
113101
}
114102

115-
async directoryExists(dirPath: string) {
116-
try {
117-
const stat = await Deno.stat(dirPath);
118-
return stat.isDirectory;
119-
} catch {
120-
return false;
121-
}
103+
statSync(path: string) {
104+
const stat = Deno.statSync(path);
105+
return this._toStat(stat);
122106
}
123107

124-
directoryExistsSync(dirPath: string) {
125-
try {
126-
return Deno.statSync(dirPath).isDirectory;
127-
} catch (err) {
128-
return false;
129-
}
108+
private _toStat(stat: Deno.FileInfo) {
109+
return {
110+
isFile() {
111+
return stat.isFile;
112+
},
113+
isDirectory() {
114+
return stat.isDirectory;
115+
},
116+
};
130117
}
131118

132119
realpathSync(path: string) {

0 commit comments

Comments
 (0)