Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions src/theia/theia.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as vscode from "vscode";
import * as path from "path";
import simpleGit, { GitConfigScope } from "simple-git";
import { hostname } from "os";
import { cloneByGivenURL } from "../participation/cloning.service";
Expand Down Expand Up @@ -32,15 +33,20 @@ export async function initTheia() {
vscode.commands.executeCommand("setContext", "scorpio.theia.givenExercise", true);
}

// clone repository
// clone repository and set it as the workspace folder
if (theiaEnv.GIT_URI) {
const workspaceFolderUri = getWorkspaceFolder();
if (!workspaceFolderUri) {
vscode.window.showErrorMessage("No workspace folder available to clone repository");
return;
}

cloneByGivenURL(theiaEnv.GIT_URI, workspaceFolderUri.fsPath);
// Skip if the workspace is already the cloned repo (window reloads after openFolder)
const repoName = path.basename(theiaEnv.GIT_URI.pathname, ".git");
if (path.basename(workspaceFolderUri.fsPath) !== repoName) {
Comment on lines +45 to +46

Copilot AI Apr 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

path.basename(theiaEnv.GIT_URI.pathname, ".git") will return an empty string if GIT_URI ends with a trailing slash (e.g., .../repo.git/). Consider normalizing the pathname first (trim trailing /) before deriving repoName, otherwise the guard and clone path computation can break.

Copilot uses AI. Check for mistakes.
Comment on lines +44 to +46

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Basename-only guard can skip cloning in valid first-run scenarios.

At Line 45-46, clone is skipped when folder name matches the repo name, even if the folder is not actually the cloned repo (e.g., empty workspace named the same as repo). This can leave users in an empty/non-repo workspace.

Suggested hardening
-    const repoName = path.basename(theiaEnv.GIT_URI.pathname, ".git");
-    if (path.basename(workspaceFolderUri.fsPath) !== repoName) {
+    const repoName = path.basename(theiaEnv.GIT_URI.pathname, ".git");
+    const sameFolderName = path.basename(workspaceFolderUri.fsPath) === repoName;
+    const hasGitDir = await vscode.workspace.fs
+      .stat(vscode.Uri.file(path.join(workspaceFolderUri.fsPath, ".git")))
+      .then(() => true)
+      .catch(() => false);
+
+    if (!(sameFolderName && hasGitDir)) {
       const clonePath = await cloneByGivenURL(theiaEnv.GIT_URI, workspaceFolderUri.fsPath);
       await vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(clonePath));
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Skip if the workspace is already the cloned repo (window reloads after openFolder)
const repoName = path.basename(theiaEnv.GIT_URI.pathname, ".git");
if (path.basename(workspaceFolderUri.fsPath) !== repoName) {
// Skip if the workspace is already the cloned repo (window reloads after openFolder)
const repoName = path.basename(theiaEnv.GIT_URI.pathname, ".git");
const sameFolderName = path.basename(workspaceFolderUri.fsPath) === repoName;
const hasGitDir = await vscode.workspace.fs
.stat(vscode.Uri.file(path.join(workspaceFolderUri.fsPath, ".git")))
.then(() => true)
.catch(() => false);
if (!(sameFolderName && hasGitDir)) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/theia/theia.ts` around lines 44 - 46, The current basename-only guard
using repoName and workspaceFolderUri can falsely skip cloning for an empty or
unrelated folder that happens to share the repo name; update the guard in the
theia bootstrap logic to verify the folder is actually the target repo before
skipping clone by checking for a real git repository (e.g., presence of a .git
directory) and, preferably, confirming the remote/origin URL matches
theiaEnv.GIT_URI (or at minimum that .git exists) — replace the simple basename
comparison with this stronger verification so clone proceeds when the folder is
not the intended repo; reference repoName, workspaceFolderUri, and
theiaEnv.GIT_URI to locate the code to change.

const clonePath = await cloneByGivenURL(theiaEnv.GIT_URI, workspaceFolderUri.fsPath);
Comment on lines +44 to +47

Copilot AI Apr 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reactivation guard only compares folder names. If the user launches into an empty destination folder that already happens to be named like the repo (e.g., workspace folder basename equals repoName), cloning will be skipped even though the repo is not present. Consider making the guard check for an actual existing clone (e.g., .git present and/or remote matches GIT_URI) rather than only the folder name.

Copilot uses AI. Check for mistakes.
await vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(clonePath));
}
Comment on lines +47 to +49

Copilot AI Apr 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cloneByGivenURL currently catches clone errors and still returns clonePath (see cloning.service.ts), so this code will attempt to openFolder even when cloning failed. Please handle clone failures explicitly (e.g., wrap clone+openFolder in try/catch and show an error, and/or make cloneByGivenURL throw/return a failure signal so openFolder is only executed on success).

Copilot uses AI. Check for mistakes.
Comment on lines +47 to +49

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Workspace switch runs even when clone may have failed.

Line 47-48 assumes cloneByGivenURL(...) fails by throwing. But in src/participation/cloning.service.ts (Line 75-88), clone errors are caught and not rethrown, and clonePath is still returned. That means openFolder can run after a failed clone and mask the failure.

Suggested defensive handling in caller
-      const clonePath = await cloneByGivenURL(theiaEnv.GIT_URI, workspaceFolderUri.fsPath);
-      await vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(clonePath));
+      try {
+        const clonePath = await cloneByGivenURL(theiaEnv.GIT_URI, workspaceFolderUri.fsPath);
+        await vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(clonePath));
+      } catch (e: any) {
+        vscode.window.showErrorMessage(`Failed to clone repository: ${e?.message ?? "Unknown error"}`);
+        return;
+      }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const clonePath = await cloneByGivenURL(theiaEnv.GIT_URI, workspaceFolderUri.fsPath);
await vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(clonePath));
}
try {
const clonePath = await cloneByGivenURL(theiaEnv.GIT_URI, workspaceFolderUri.fsPath);
await vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(clonePath));
} catch (e: any) {
vscode.window.showErrorMessage(`Failed to clone repository: ${e?.message ?? "Unknown error"}`);
return;
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/theia/theia.ts` around lines 47 - 49, The caller assumes cloneByGivenURL
throws on failure but cloning.service.ts swallows errors and still returns a
path, so vscode.commands.executeCommand("vscode.openFolder", ...) can run after
a failed clone; update the caller in theia.ts to defensively verify the clone
succeeded before calling openFolder: check the result from cloneByGivenURL
(e.g., validate the returned clonePath exists and/or have cloneByGivenURL return
an explicit success flag), and only call
vscode.commands.executeCommand("vscode.openFolder", vscode.Uri.file(clonePath))
when that verification passes; use the existing function names cloneByGivenURL
and vscode.commands.executeCommand("vscode.openFolder") to locate and change the
logic.

}

// set git config values
Expand Down
Loading