diff --git a/src/setup_utilities/workspace-setup.ts b/src/setup_utilities/workspace-setup.ts index 1b310b1..dceafdb 100644 --- a/src/setup_utilities/workspace-setup.ts +++ b/src/setup_utilities/workspace-setup.ts @@ -51,7 +51,7 @@ WorkspaceSetupFromWestGit import * as vscode from "vscode"; import * as fs from "fs-extra"; import * as path from "path"; -import { output, executeTaskHelper } from "../utilities/utils"; +import { output, executeTaskHelper, validateGitUrl } from "../utilities/utils"; import { westSelector, WestLocation } from "./west_selector"; import { WorkspaceConfig, GlobalConfig } from "./types"; import { setSetupState, loadExternalSetupState, setWorkspaceState, setGlobalState } from "./state-management"; @@ -147,17 +147,9 @@ export async function workspaceSetupFromGit(context: vscode.ExtensionContext, ws const gitUrl = await vscode.window.showInputBox({ prompt: "Enter the Git repository URL/clone string", placeHolder: - "https://github.com/mylonics/zephyr-ide-workspace-template.git", + "https://github.com/user/repo.git or git@github.com:user/repo.git", ignoreFocusOut: true, - validateInput: (value) => { - if (!value || value.trim() === "") { - return "Please enter a valid Git URL"; - } - if (!value.includes("://")) { - return "Please enter a valid Git URL (must include protocol)"; - } - return undefined; - }, + validateInput: validateGitUrl, }); if (!gitUrl) { @@ -206,17 +198,9 @@ export async function workspaceSetupFromWestGit(context: vscode.ExtensionContext const gitUrl = await vscode.window.showInputBox({ prompt: "Enter the Git repository URL for the West workspace", placeHolder: - "https://github.com/zephyrproject-rtos/example-application", + "https://github.com/user/repo.git or git@github.com:user/repo.git", ignoreFocusOut: true, - validateInput: (value) => { - if (!value || value.trim() === "") { - return "Please enter a valid Git URL"; - } - if (!value.includes("://")) { - return "Please enter a valid Git URL (must include protocol)"; - } - return undefined; - }, + validateInput: validateGitUrl, }); if (!gitUrl) { diff --git a/src/test/git-url-validation.test.ts b/src/test/git-url-validation.test.ts new file mode 100644 index 0000000..926358d --- /dev/null +++ b/src/test/git-url-validation.test.ts @@ -0,0 +1,57 @@ +/* +Copyright 2024 mylonics +Author Rijesh Augustine + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import * as assert from "assert"; +import { validateGitUrl } from "../utilities/utils"; + +suite("Git URL Validation Test Suite", () => { + + test("Validates HTTPS URLs correctly", () => { + assert.strictEqual(validateGitUrl("https://github.com/user/repo.git"), undefined); + assert.strictEqual(validateGitUrl("https://github.com/user/repo"), undefined); + assert.strictEqual(validateGitUrl("http://gitlab.com/user/repo.git"), undefined); + }); + + test("Validates SSH URLs correctly", () => { + // Traditional SSH format + assert.strictEqual(validateGitUrl("git@github.com:user/repo.git"), undefined); + assert.strictEqual(validateGitUrl("git@github.com:user/repo"), undefined); + assert.strictEqual(validateGitUrl("user@host.com:path/to/repo.git"), undefined); + + // SSH with protocol + assert.strictEqual(validateGitUrl("ssh://git@github.com/user/repo.git"), undefined); + }); + + test("Validates Git protocol URLs correctly", () => { + assert.strictEqual(validateGitUrl("git://github.com/user/repo.git"), undefined); + }); + + test("Rejects invalid URLs correctly", () => { + assert.strictEqual(validateGitUrl(""), "Please enter a valid Git URL"); + assert.strictEqual(validateGitUrl(" "), "Please enter a valid Git URL"); + assert.strictEqual(validateGitUrl("invalid-url"), "Please enter a valid Git URL (e.g., https://github.com/user/repo.git or git@github.com:user/repo.git)"); + assert.strictEqual(validateGitUrl("ftp://server.com/repo"), "Please enter a valid Git URL (supported protocols: http, https, ssh, git)"); + }); + + test("Validates URLs from issue examples", () => { + // The specific SSH URL mentioned in the issue + assert.strictEqual(validateGitUrl("git@github.com:some-user/some-repo.git"), undefined); + + // The HTTPS version should also work + assert.strictEqual(validateGitUrl("https://github.com/some-user/some-repo.git"), undefined); + }); +}); \ No newline at end of file diff --git a/src/utilities/utils.ts b/src/utilities/utils.ts index f53683c..43d89a3 100644 --- a/src/utilities/utils.ts +++ b/src/utilities/utils.ts @@ -243,4 +243,36 @@ export function reloadEnvironmentVariables(context: vscode.ExtensionContext, set context.environmentVariableCollection.replace("ZEPHYR_BASE", setupState.zephyrDir, { applyAtProcessCreation: true, applyAtShellIntegration: true }); } } +} + +/** + * Validates if a string is a valid Git URL + * Supports HTTP/HTTPS URLs and SSH URLs (both git@host:path and ssh://git@host/path formats) + */ +export function validateGitUrl(value: string): string | undefined { + if (!value || value.trim() === "") { + return "Please enter a valid Git URL"; + } + + const trimmedValue = value.trim(); + + // Check for HTTP/HTTPS/SSH with protocol (contains ://) + if (trimmedValue.includes("://")) { + // Additional validation for protocol-based URLs + if (trimmedValue.startsWith("http://") || + trimmedValue.startsWith("https://") || + trimmedValue.startsWith("ssh://") || + trimmedValue.startsWith("git://")) { + return undefined; + } + return "Please enter a valid Git URL (supported protocols: http, https, ssh, git)"; + } + + // Check for SSH format: user@host:path (without protocol) + const sshPattern = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+:[a-zA-Z0-9._/-]+$/; + if (sshPattern.test(trimmedValue)) { + return undefined; + } + + return "Please enter a valid Git URL (e.g., https://github.com/user/repo.git or git@github.com:user/repo.git)"; } \ No newline at end of file