Skip to content

Commit 0a2c7b1

Browse files
authored
update for existing project creation (#306)
fixes #305
1 parent 01eda1e commit 0a2c7b1

File tree

4 files changed

+90
-13
lines changed

4 files changed

+90
-13
lines changed

src/extension.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ export async function activate(context: ExtensionContext): Promise<PythonEnviron
8888
const projectCreators: ProjectCreators = new ProjectCreatorsImpl();
8989
context.subscriptions.push(
9090
projectCreators,
91-
projectCreators.registerPythonProjectCreator(new ExistingProjects()),
91+
projectCreators.registerPythonProjectCreator(new ExistingProjects(projectManager)),
9292
projectCreators.registerPythonProjectCreator(new AutoFindProjects(projectManager)),
9393
);
9494

src/features/creators/autoFindProjects.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import * as path from 'path';
22
import { Uri } from 'vscode';
3-
import { showQuickPickWithButtons } from '../../common/window.apis';
3+
import { showQuickPickWithButtons, showWarningMessage } from '../../common/window.apis';
44
import { ProjectCreatorString } from '../../common/localize';
55
import { PythonProject, PythonProjectCreator, PythonProjectCreatorOptions } from '../../api';
66
import { PythonProjectManager } from '../../internal.api';
77
import { showErrorMessage } from '../../common/errors/utils';
88
import { findFiles } from '../../common/workspace.apis';
9+
import { traceInfo } from '../../common/logging';
910

1011
function getUniqueUri(uris: Uri[]): {
1112
label: string;
@@ -68,8 +69,9 @@ export class AutoFindProjects implements PythonProjectCreator {
6869
const filtered = files.filter((uri) => {
6970
const p = this.pm.get(uri);
7071
if (p) {
71-
// If there ia already a project with the same path, skip it.
72-
// If there is a project with the same parent path, skip it.
72+
// Skip this project if:
73+
// 1. There's already a project registered with exactly the same path
74+
// 2. There's already a project registered with this project's parent directory path
7375
const np = path.normalize(p.uri.fsPath);
7476
const nf = path.normalize(uri.fsPath);
7577
const nfp = path.dirname(nf);
@@ -79,11 +81,20 @@ export class AutoFindProjects implements PythonProjectCreator {
7981
});
8082

8183
if (filtered.length === 0) {
84+
// No new projects found that are not already in the project manager
85+
traceInfo('All discovered projects are already registered in the project manager');
86+
setImmediate(() => {
87+
showWarningMessage('No new projects found');
88+
});
8289
return;
8390
}
8491

92+
traceInfo(`Found ${filtered.length} new potential projects that aren't already registered`);
93+
8594
const projects = await pickProjects(filtered);
8695
if (!projects || projects.length === 0) {
96+
// User cancelled the selection.
97+
traceInfo('User cancelled project selection.');
8798
return;
8899
}
89100

Lines changed: 72 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
import * as path from 'path';
22
import { PythonProject, PythonProjectCreator, PythonProjectCreatorOptions } from '../../api';
33
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';
59

610
export class ExistingProjects implements PythonProjectCreator {
711
public readonly name = 'existingProjects';
812
public readonly displayName = ProjectCreatorString.addExistingProjects;
913

14+
constructor(private readonly pm: PythonProjectManager) {}
15+
1016
async create(_options?: PythonProjectCreatorOptions): Promise<PythonProject | PythonProject[] | undefined> {
1117
const results = await showOpenDialog({
1218
canSelectFiles: true,
@@ -19,12 +25,73 @@ export class ExistingProjects implements PythonProjectCreator {
1925
});
2026

2127
if (!results || results.length === 0) {
28+
// User cancelled the dialog & doesn't want to add any projects
2229
return;
2330
}
2431

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+
}
2996
}
3097
}

src/features/envCommands.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -348,10 +348,6 @@ export async function addPythonProject(
348348
return;
349349
}
350350

351-
if (resource instanceof ProjectPackageRootTreeItem || resource instanceof ProjectPackage) {
352-
await addPythonProject(undefined, wm, em, pc);
353-
}
354-
355351
if (resource instanceof Uri) {
356352
const uri = resource as Uri;
357353
const envManagerId = getDefaultEnvManagerSetting(wm, uri);
@@ -416,6 +412,9 @@ export async function addPythonProject(
416412
}
417413
await addPythonProjectSetting(edits);
418414
return projects;
415+
} else {
416+
// If the context is not a Uri or ProjectItem, rerun function with undefined context
417+
await addPythonProject(undefined, wm, em, pc);
419418
}
420419
}
421420

0 commit comments

Comments
 (0)