1
1
import * as path from 'path' ;
2
2
import { PythonProject , PythonProjectCreator , PythonProjectCreatorOptions } from '../../api' ;
3
3
import { ProjectCreatorString } from '../../common/localize' ;
4
- import { showOpenDialog } from '../../common/window.apis' ;
4
+ import { showOpenDialog , showWarningMessage } from '../../common/window.apis' ;
5
+ import { PythonProjectManager } from '../../internal.api' ;
6
+ import { traceInfo } from '../../common/logging' ;
7
+ import { Uri , window , workspace } from 'vscode' ;
8
+ import { traceLog } from '../../common/logging' ;
5
9
6
10
export class ExistingProjects implements PythonProjectCreator {
7
11
public readonly name = 'existingProjects' ;
8
12
public readonly displayName = ProjectCreatorString . addExistingProjects ;
9
13
14
+ constructor ( private readonly pm : PythonProjectManager ) { }
15
+
10
16
async create ( _options ?: PythonProjectCreatorOptions ) : Promise < PythonProject | PythonProject [ ] | undefined > {
11
17
const results = await showOpenDialog ( {
12
18
canSelectFiles : true ,
@@ -19,12 +25,73 @@ export class ExistingProjects implements PythonProjectCreator {
19
25
} ) ;
20
26
21
27
if ( ! results || results . length === 0 ) {
28
+ // User cancelled the dialog & doesn't want to add any projects
22
29
return ;
23
30
}
24
31
25
- return results . map ( ( r ) => ( {
26
- name : path . basename ( r . fsPath ) ,
27
- uri : r ,
28
- } ) ) ;
32
+ // do we have any limitations that need to be applied here?
33
+ // like selected folder not child of workspace folder?
34
+
35
+ const filtered = results . filter ( ( uri ) => {
36
+ const p = this . pm . get ( uri ) ;
37
+ if ( p ) {
38
+ // Skip this project if there's already a project registered with exactly the same path
39
+ const np = path . normalize ( p . uri . fsPath ) ;
40
+ const nf = path . normalize ( uri . fsPath ) ;
41
+ return np !== nf ;
42
+ }
43
+ return true ;
44
+ } ) ;
45
+
46
+ if ( filtered . length === 0 ) {
47
+ // No new projects found that are not already in the project manager
48
+ traceInfo ( 'All discovered projects are already registered in the project manager' ) ;
49
+ setImmediate ( ( ) => {
50
+ showWarningMessage ( 'No new projects found' ) ;
51
+ } ) ;
52
+ return ;
53
+ }
54
+
55
+ // for all the selected files / folders, check to make sure they are in the workspace
56
+ const resultsOutsideWorkspace : Uri [ ] = [ ] ;
57
+ const workspaceRoots : Uri [ ] = workspace . workspaceFolders ?. map ( ( w ) => w . uri ) || [ ] ;
58
+ const resultsInWorkspace = filtered . filter ( ( r ) => {
59
+ const exists = workspaceRoots . some ( ( w ) => r . fsPath . startsWith ( w . fsPath ) ) ;
60
+ if ( ! exists ) {
61
+ traceLog ( `File ${ r . fsPath } is not in the workspace, ignoring it from 'add projects' list.` ) ;
62
+ resultsOutsideWorkspace . push ( r ) ;
63
+ }
64
+ return exists ;
65
+ } ) ;
66
+ if ( resultsInWorkspace . length === 0 ) {
67
+ // Show a single error message with option to add to workspace
68
+ const response = await window . showErrorMessage (
69
+ 'Selected items are not in the current workspace.' ,
70
+ 'Add to Workspace' ,
71
+ 'Cancel' ,
72
+ ) ;
73
+
74
+ if ( response === 'Add to Workspace' ) {
75
+ // Use the command palette to let user adjust which folders to add
76
+ // Add folders programmatically using workspace API
77
+ for ( const r of resultsOutsideWorkspace ) {
78
+ // if the user selects a file, add that file to the workspace
79
+ await // if the user selects a folder, add that folder to the workspace
80
+ await workspace . updateWorkspaceFolders (
81
+ workspace . workspaceFolders ?. length || 0 , // Start index
82
+ 0 , // Delete count
83
+ {
84
+ uri : r ,
85
+ } ,
86
+ ) ;
87
+ }
88
+ }
89
+ return ;
90
+ } else {
91
+ return resultsInWorkspace . map ( ( uri ) => ( {
92
+ name : path . basename ( uri . fsPath ) ,
93
+ uri,
94
+ } ) ) as PythonProject [ ] ;
95
+ }
29
96
}
30
97
}
0 commit comments