1
1
// Copyright (c) Microsoft Corporation. All rights reserved.
2
2
// Licensed under the MIT License.
3
3
4
+ import * as fsextra from 'fs-extra' ;
4
5
import { Container } from 'inversify' ;
6
+ import * as path from 'path' ;
5
7
import { anything , instance , mock , when } from 'ts-mockito' ;
6
8
import * as TypeMoq from 'typemoq' ;
7
9
import { Disposable , Memento , OutputChannel } from 'vscode' ;
@@ -12,7 +14,7 @@ import { FileSystem } from '../client/common/platform/fileSystem';
12
14
import { PathUtils } from '../client/common/platform/pathUtils' ;
13
15
import { PlatformService } from '../client/common/platform/platformService' ;
14
16
import { registerTypes as platformRegisterTypes } from '../client/common/platform/serviceRegistry' ;
15
- import { IFileSystem , IPlatformService } from '../client/common/platform/types' ;
17
+ import { FileStat , FileType , IFileSystem , IPlatformService } from '../client/common/platform/types' ;
16
18
import { BufferDecoder } from '../client/common/process/decoder' ;
17
19
import { ProcessService } from '../client/common/process/proc' ;
18
20
import { PythonExecutionFactory } from '../client/common/process/pythonExecutionFactory' ;
@@ -21,6 +23,7 @@ import { registerTypes as processRegisterTypes } from '../client/common/process/
21
23
import { IBufferDecoder , IProcessServiceFactory , IPythonExecutionFactory , IPythonToolExecutionService } from '../client/common/process/types' ;
22
24
import { registerTypes as commonRegisterTypes } from '../client/common/serviceRegistry' ;
23
25
import { GLOBAL_MEMENTO , ICurrentProcess , IDisposableRegistry , ILogger , IMemento , IOutputChannel , IPathUtils , IsWindows , WORKSPACE_MEMENTO } from '../client/common/types' ;
26
+ import { createDeferred } from '../client/common/utils/async' ;
24
27
import { registerTypes as variableRegisterTypes } from '../client/common/variables/serviceRegistry' ;
25
28
import { registerTypes as formattersRegisterTypes } from '../client/formatters/serviceRegistry' ;
26
29
import { EnvironmentActivationService } from '../client/interpreter/activation/service' ;
@@ -43,7 +46,77 @@ import { MockMemento } from './mocks/mementos';
43
46
import { MockProcessService } from './mocks/proc' ;
44
47
import { MockProcess } from './mocks/process' ;
45
48
49
+ // This is necessary for unit tests and functional tests, since they
50
+ // do not run under VS Code so they do not have access to the actual
51
+ // "vscode" namespace.
52
+ class LegacyFileSystem extends FileSystem {
53
+ public async readFile ( filename : string ) : Promise < string > {
54
+ return fsextra . readFile ( filename , 'utf8' ) ;
55
+ }
56
+ public async writeFile ( filename : string , data : { } ) : Promise < void > {
57
+ const options : fsextra . WriteFileOptions = {
58
+ encoding : 'utf8'
59
+ } ;
60
+ return fsextra . writeFile ( filename , data , options ) ;
61
+ }
62
+ public async deleteDirectory ( dirname : string ) : Promise < void > {
63
+ return fsextra . stat ( dirname )
64
+ . then ( ( ) => fsextra . remove ( dirname ) ) ;
65
+ }
66
+ public async deleteFile ( filename : string ) : Promise < void > {
67
+ return fsextra . unlink ( filename ) ;
68
+ }
69
+ public async listdir ( dirname : string ) : Promise < [ string , FileType ] [ ] > {
70
+ const names : string [ ] = await fsextra . readdir ( dirname ) ;
71
+ const promises = names
72
+ . map ( name => {
73
+ const filename = path . join ( dirname , name ) ;
74
+ return this . raw . lstat ( filename )
75
+ . then ( stat => [ name , stat . type ] as [ string , FileType ] )
76
+ . catch ( ( ) => [ name , FileType . Unknown ] as [ string , FileType ] ) ;
77
+ } ) ;
78
+ return Promise . all ( promises ) ;
79
+ }
80
+ public async createDirectory ( dirname : string ) : Promise < void > {
81
+ return fsextra . mkdirp ( dirname ) ;
82
+ }
83
+ public async copyFile ( src : string , dest : string ) : Promise < void > {
84
+ const deferred = createDeferred < void > ( ) ;
85
+ const rs = fsextra . createReadStream ( src )
86
+ . on ( 'error' , ( err ) => {
87
+ deferred . reject ( err ) ;
88
+ } ) ;
89
+ const ws = fsextra . createWriteStream ( dest )
90
+ . on ( 'error' , ( err ) => {
91
+ deferred . reject ( err ) ;
92
+ } ) . on ( 'close' , ( ) => {
93
+ deferred . resolve ( ) ;
94
+ } ) ;
95
+ rs . pipe ( ws ) ;
96
+ return deferred . promise ;
97
+ }
98
+ protected async _stat ( filePath : string ) : Promise < FileStat > {
99
+ const stat = await fsextra . stat ( filePath ) ;
100
+ let fileType = FileType . Unknown ;
101
+ if ( stat . isFile ( ) ) {
102
+ fileType = FileType . File ;
103
+ } else if ( stat . isDirectory ( ) ) {
104
+ fileType = FileType . Directory ;
105
+ } else if ( stat . isSymbolicLink ( ) ) {
106
+ fileType = FileType . SymbolicLink ;
107
+ }
108
+ return {
109
+ type : fileType ,
110
+ size : stat . size ,
111
+ ctime : stat . ctimeMs ,
112
+ mtime : stat . mtimeMs
113
+ } ;
114
+ }
115
+ }
116
+
46
117
export class IocContainer {
118
+ public vscode = true ;
119
+
47
120
public readonly serviceManager : IServiceManager ;
48
121
public readonly serviceContainer : IServiceContainer ;
49
122
@@ -90,7 +163,10 @@ export class IocContainer {
90
163
}
91
164
public registerFileSystemTypes ( ) {
92
165
this . serviceManager . addSingleton < IPlatformService > ( IPlatformService , PlatformService ) ;
93
- this . serviceManager . addSingleton < IFileSystem > ( IFileSystem , FileSystem ) ;
166
+ this . serviceManager . addSingleton < IFileSystem > (
167
+ IFileSystem ,
168
+ this . vscode ? FileSystem : LegacyFileSystem
169
+ ) ;
94
170
}
95
171
public registerProcessTypes ( ) {
96
172
processRegisterTypes ( this . serviceManager ) ;
0 commit comments