33 * Licensed under the MIT License. See License.txt in the project root for license information.
44 *--------------------------------------------------------------------------------------------*/
55
6- import { mkdir , open , close , read , write , fdatasync } from 'fs' ;
6+ import { mkdir , open , close , read , write , fdatasync , Dirent , Stats } from 'fs' ;
77import { promisify } from 'util' ;
88import { IDisposable , Disposable , toDisposable , dispose , combinedDisposable } from 'vs/base/common/lifecycle' ;
99import { IFileSystemProvider , FileSystemProviderCapabilities , IFileChange , IWatchOptions , IStat , FileType , FileDeleteOptions , FileOverwriteOptions , FileWriteOptions , FileOpenOptions , FileSystemProviderErrorCode , createFileSystemProviderError , FileSystemProviderError } from 'vs/platform/files/common/files' ;
1010import { URI } from 'vs/base/common/uri' ;
1111import { Event , Emitter } from 'vs/base/common/event' ;
1212import { isLinux , isWindows } from 'vs/base/common/platform' ;
13- import { statLink , readdir , unlink , move , copy , readFile , truncate , rimraf , RimRafMode , exists } from 'vs/base/node/pfs' ;
13+ import { statLink , unlink , move , copy , readFile , truncate , rimraf , RimRafMode , exists , readdirWithFileTypes } from 'vs/base/node/pfs' ;
1414import { normalize , basename , dirname } from 'vs/base/common/path' ;
1515import { joinPath } from 'vs/base/common/resources' ;
1616import { isEqual } from 'vs/base/common/extpath' ;
@@ -62,15 +62,8 @@ export class DiskFileSystemProvider extends Disposable implements IFileSystemPro
6262 try {
6363 const { stat, isSymbolicLink } = await statLink ( this . toFilePath ( resource ) ) ; // cannot use fs.stat() here to support links properly
6464
65- let type : number ;
66- if ( isSymbolicLink ) {
67- type = FileType . SymbolicLink | ( stat . isDirectory ( ) ? FileType . Directory : FileType . File ) ;
68- } else {
69- type = stat . isFile ( ) ? FileType . File : stat . isDirectory ( ) ? FileType . Directory : FileType . Unknown ;
70- }
71-
7265 return {
73- type,
66+ type : this . toType ( stat , isSymbolicLink ) ,
7467 ctime : stat . ctime . getTime ( ) ,
7568 mtime : stat . mtime . getTime ( ) ,
7669 size : stat . size
@@ -82,13 +75,19 @@ export class DiskFileSystemProvider extends Disposable implements IFileSystemPro
8275
8376 async readdir ( resource : URI ) : Promise < [ string , FileType ] [ ] > {
8477 try {
85- const children = await readdir ( this . toFilePath ( resource ) ) ;
78+ const children = await readdirWithFileTypes ( this . toFilePath ( resource ) ) ;
8679
8780 const result : [ string , FileType ] [ ] = [ ] ;
8881 await Promise . all ( children . map ( async child => {
8982 try {
90- const stat = await this . stat ( joinPath ( resource , child ) ) ;
91- result . push ( [ child , stat . type ] ) ;
83+ let type : FileType ;
84+ if ( child . isSymbolicLink ( ) ) {
85+ type = ( await this . stat ( joinPath ( resource , child . name ) ) ) . type ; // always resolve target the link points to if any
86+ } else {
87+ type = this . toType ( child ) ;
88+ }
89+
90+ result . push ( [ child . name , type ] ) ;
9291 } catch ( error ) {
9392 this . logService . trace ( error ) ; // ignore errors for individual entries that can arise from permission denied
9493 }
@@ -100,6 +99,14 @@ export class DiskFileSystemProvider extends Disposable implements IFileSystemPro
10099 }
101100 }
102101
102+ private toType ( entry : Stats | Dirent , isSymbolicLink = entry . isSymbolicLink ( ) ) : FileType {
103+ if ( isSymbolicLink ) {
104+ return FileType . SymbolicLink | ( entry . isDirectory ( ) ? FileType . Directory : FileType . File ) ;
105+ }
106+
107+ return entry . isFile ( ) ? FileType . File : entry . isDirectory ( ) ? FileType . Directory : FileType . Unknown ;
108+ }
109+
103110 //#endregion
104111
105112 //#region File Reading/Writing
0 commit comments