From 94bac984e1b2b59d706213a791336272fc27bef1 Mon Sep 17 00:00:00 2001 From: artemis_admin Date: Tue, 26 Nov 2024 18:21:01 +0100 Subject: [PATCH] fix repo detection for theia --- .vscode/launch.json | 10 +++++++- src/authentication/authentication_provider.ts | 4 ++- src/exercise/exercise.api.ts | 3 ++- src/shared/repository.ts | 25 +++++++++++-------- src/theia/cloning.ts | 8 ++++++ src/theia/theia.ts | 4 +-- src/utils/filetree.ts | 25 +++++++++++++++++++ 7 files changed, 64 insertions(+), 15 deletions(-) create mode 100644 src/utils/filetree.ts diff --git a/.vscode/launch.json b/.vscode/launch.json index 01cb7e9..07088ab 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -11,7 +11,15 @@ "request": "launch", "args": ["--extensionDevelopmentPath=${workspaceFolder}"], "outFiles": ["${workspaceFolder}/dist/**/*.js"], - "preLaunchTask": "${defaultBuildTask}" + "preLaunchTask": "${defaultBuildTask}", + "env": { + // "THEIA":"true", + "ARTEMIS_TOKEN":"eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhcnRlbWlzX2FkbWluIiwiYXV0aCI6IlJPTEVfVVNFUixST0xFX0FETUlOIiwidG9vbHMiOiJTQ09SUElPIiwiZXhwIjoxNzM1MjMwNzM3fQ.ipSGyQ4E3iE_g5v1ZLAMxs5E3CJ_TgyUoM9-Ni3tdz63dhFcEWtqSmM-WQlzPmjp0Bf_6t6Uu6OOsT8fIyMGVw", + "ARTEMIS_URL":"https://artemis-test9.artemis.cit.tum.de", + "GIT_URI":"https://artemis_admin@artemis-test9.artemis.cit.tum.de/git/THEIATESTTESTEXERCISE/theiatesttestexercise-artemis_admin.git", + "GIT_USER":"artemis_admin", + "GIT_MAIL":"artemis.admin@tum.de" + } }, { "name": "Extension Tests", diff --git a/src/authentication/authentication_provider.ts b/src/authentication/authentication_provider.ts index ec986c5..32251ae 100644 --- a/src/authentication/authentication_provider.ts +++ b/src/authentication/authentication_provider.ts @@ -1,10 +1,11 @@ import * as vscode from "vscode"; import { authenticateToken } from "./authentication_api"; import { theiaEnv } from "../theia/theia"; +import { settings } from "../shared/settings"; export const AUTH_ID = "artemis"; const AUTH_NAME = `Credentials`; // what is displayed on the profile button -const SESSIONS_SECRET_KEY = `${AUTH_ID}.sessions`; +var SESSIONS_SECRET_KEY = `${AUTH_ID}.sessions`; class ArtemisSession implements vscode.AuthenticationSession { id: string = AUTH_ID; @@ -27,6 +28,7 @@ export class ArtemisAuthenticationProvider implements vscode.AuthenticationProvi private sessionPromise: Promise; constructor(private readonly secretStorage: vscode.SecretStorage) { + SESSIONS_SECRET_KEY = `${AUTH_ID}.${settings.base_url}.sessions`; this.sessionPromise = this.getSessionFromStorage(); this._disposable = vscode.Disposable.from( diff --git a/src/exercise/exercise.api.ts b/src/exercise/exercise.api.ts index 87d0938..d6bbe9c 100644 --- a/src/exercise/exercise.api.ts +++ b/src/exercise/exercise.api.ts @@ -89,8 +89,9 @@ export async function fetch_course_exercise_projectKey( }) .then(async (response) => { if (!response.ok) { + const errorText = await response.text(); throw new Error( - `HTTP error! status: ${response.status} message: ${response.text}` + `HTTP error! status: ${response.status} message: ${errorText}` ); } diff --git a/src/shared/repository.ts b/src/shared/repository.ts index 22666b9..eeb7487 100644 --- a/src/shared/repository.ts +++ b/src/shared/repository.ts @@ -9,6 +9,7 @@ import { set_state, state } from "./state"; import simpleGit, { RemoteWithRefs, SimpleGit } from "simple-git"; import * as path from "path"; import { retrieveVcsAccessToken } from "../authentication/authentication_api"; +import { getLevel1SubfoldersOfWorkspace } from "../utils/filetree"; var gitRepo: SimpleGit | undefined; @@ -165,15 +166,20 @@ async function getArtemisRepo( return undefined; } - for (const folder of workspaceFolders) { - const folderPath = folder.uri.fsPath; - const git: SimpleGit = simpleGit(folderPath); + // Get all level 1 subfolders of the workspace + const level1SubfoldersPath = await getLevel1SubfoldersOfWorkspace(workspaceFolders); + + for (const folderPath of level1SubfoldersPath) { + const git: SimpleGit = simpleGit(folderPath.fsPath); try { const isRepo = await git.checkIsRepo(); if (isRepo) { const remotes = await git.getRemotes(true); - if (remotes.length > 0) { - return { repo: git, remote: remotes[0] }; + for(const remote of remotes) { + const url = new URL(remote.refs.fetch!); + if(url.hostname == new URL(settings.base_url).hostname && url.username == username) { + return { repo: git, remote: remote }; + } } } } catch (error: any) { @@ -186,12 +192,11 @@ async function getArtemisRepo( function getProjectKeyFromRepoUrl(repoUrl: string): string { // extract projectKey {protocol}://{username}@{host}:{port}/git/{PROJECT_KEY}/{project_key}-{username}.git - const projectKeyMatch = repoUrl.match( - /^[a-zA-Z]+:\/\/[^@]+@[^:]+:[0-9]+\/git\/([^\/]+)\/[^\/]+-[^\/]+\.git$/ - ); - if (!projectKeyMatch) { + const parts = repoUrl.split("/"); + if(parts.length < 5) { throw new Error("Invalid artemis repository URL does not contain project key"); } - return projectKeyMatch[1]; + const projectKey = parts[4] + return projectKey; } diff --git a/src/theia/cloning.ts b/src/theia/cloning.ts index 4f5bb75..43697a3 100644 --- a/src/theia/cloning.ts +++ b/src/theia/cloning.ts @@ -2,6 +2,7 @@ import * as vscode from "vscode"; import simpleGit, { GitConfigScope } from "simple-git"; import * as path from "path"; import { theiaEnv } from "./theia"; +import { getLevel1Subfolders } from "../utils/filetree"; export async function cloneTheia(cloneUrl: URL) { // Check if a workspace is available in which the exercise can be cloned @@ -17,6 +18,13 @@ export async function cloneTheia(cloneUrl: URL) { const repoName = path.basename(cloneUrl.pathname, ".git"); // Use repository name as subdirectory name const clonePath = path.join(destinationPath, repoName); + // check if repo already exists + const subfolders = await getLevel1Subfolders(vscode.Uri.file(destinationPath)); + if (subfolders.some((folder) => folder.fsPath === clonePath)) { + vscode.window.showInformationMessage("Repository already cloned"); + return; + } + // Clone the repository const git = simpleGit(destinationPath); diff --git a/src/theia/theia.ts b/src/theia/theia.ts index ef7cff2..5ce9c7e 100644 --- a/src/theia/theia.ts +++ b/src/theia/theia.ts @@ -5,7 +5,7 @@ import { execSync } from "child_process"; type theiaEnv = { ARTEMIS_TOKEN: string | undefined; - ARTEMIS_URL: URL | undefined; + ARTEMIS_URL: string | undefined; GIT_URI: URL | undefined; GIT_USER: string | undefined; GIT_MAIL: string | undefined; @@ -18,7 +18,7 @@ function readTheiaEnv(): theiaEnv | undefined { const theiaArtemisToken = getEnvVariable("ARTEMIS_TOKEN"); const theiaArtemisUrlString = getEnvVariable("ARTEMIS_URL"); - const theiaArtemisUrl = theiaArtemisUrlString ? new URL(theiaArtemisUrlString) : undefined; + const theiaArtemisUrl = theiaArtemisUrlString ? theiaArtemisUrlString : undefined; const theiaGitCloneUrlString = getEnvVariable("GIT_URI"); const theiaGitCloneUrl = theiaGitCloneUrlString ? new URL(theiaGitCloneUrlString) : undefined; const theiaGitUserName = getEnvVariable("GIT_USER"); diff --git a/src/utils/filetree.ts b/src/utils/filetree.ts new file mode 100644 index 0000000..9c147af --- /dev/null +++ b/src/utils/filetree.ts @@ -0,0 +1,25 @@ +import * as vscode from "vscode"; + +export async function getLevel1Subfolders(folderUri: vscode.Uri): Promise { + const subfolders: vscode.Uri[] = []; + const entries = await vscode.workspace.fs.readDirectory(folderUri); + + for (const [name, type] of entries) { + if (type === vscode.FileType.Directory) { + subfolders.push(vscode.Uri.joinPath(folderUri, name)); + } + } + + return subfolders; + } + + export async function getLevel1SubfoldersOfWorkspace(workspaceFolders :readonly vscode.WorkspaceFolder[]) + : Promise { + return Promise.all( + workspaceFolders.map((folder) => getLevel1Subfolders(folder.uri)) + ).then((results) => { + const level1SubfoldersPath = results.flat(); + return level1SubfoldersPath; + }); + } + \ No newline at end of file