diff --git a/package.json b/package.json index 13e1113..e1a3747 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "color": "#D6B872", "theme": "dark" }, - "version": "0.4.0", + "version": "0.4.1", "engines": { "vscode": "^1.56.0" }, @@ -197,6 +197,16 @@ "type": "boolean", "default": true, "description": "Prompt for PROS CLI install on startup." + }, + "pros.OneClick: CliDownloadURL": { + "type": "string", + "default": "default", + "description": "URL to download PROS CLI from. SHOULD NOT BE CHANGED BY MOST USERS!" + }, + "pros.OneClick: ToolchainDownloadURL": { + "type": "string", + "default": "default", + "description": "URL to download PROS Toolchain from. SHOULD NOT BE CHANGED BY MOST USERS!" } } } diff --git a/src/commands/build.ts b/src/commands/build.ts index 7f65a7e..e61ecf9 100644 --- a/src/commands/build.ts +++ b/src/commands/build.ts @@ -23,7 +23,7 @@ const runBuild = async () => { async (progress, token) => { try { // Command to run to build project - var command = `pros make --project "${vscode.workspace.workspaceFolders?.[0].uri.fsPath}" --machine-output ${process.env["VSCODE FLAGS"]}`; + var command = `pros make --project "${vscode.workspace.workspaceFolders?.[0].uri.fsPath}" --machine-output ${process.env["PROS_VSCODE_FLAGS"]}`; console.log(command); console.log(process.env["PATH"]); const { stdout, stderr } = await promisify(child_process.exec)( diff --git a/src/commands/buildUpload.ts b/src/commands/buildUpload.ts index 9b6e24a..f8e2c53 100644 --- a/src/commands/buildUpload.ts +++ b/src/commands/buildUpload.ts @@ -21,7 +21,7 @@ const runBuildUpload = async () => { async (progress, token) => { try { // Command to run to build and upload project - var command = `pros mu --project "${vscode.workspace.workspaceFolders?.[0].uri.fsPath}" --machine-output ${process.env["VSCODE FLAGS"]}`; + var command = `pros mu --project "${vscode.workspace.workspaceFolders?.[0].uri.fsPath}" --machine-output ${process.env["PROS_VSCODE_FLAGS"]}`; console.log(command); const { stdout, stderr } = await promisify(child_process.exec)( command, @@ -30,6 +30,7 @@ const runBuildUpload = async () => { ...process.env, PATH: getChildProcessPath(), }, + maxBuffer: 1024 * 1024 * 50 } ); await vscode.window.showInformationMessage("Project Built!"); diff --git a/src/commands/capture.ts b/src/commands/capture.ts index a1c4b13..ae73ccd 100644 --- a/src/commands/capture.ts +++ b/src/commands/capture.ts @@ -46,7 +46,7 @@ const runCapture = async (output: string) => { async (progress, token) => { try { // Command to run to clean project - var command = `pros v5 capture ${output} --force ${process.env["VSCODE FLAGS"]} --machine-output`; + var command = `pros v5 capture ${output} --force ${process.env["PROS_VSCODE_FLAGS"]} --machine-output`; console.log(command); const { stdout, stderr } = await promisify(child_process.exec)( command, diff --git a/src/commands/clean.ts b/src/commands/clean.ts index dcec2e5..b161a00 100644 --- a/src/commands/clean.ts +++ b/src/commands/clean.ts @@ -20,7 +20,7 @@ const runClean = async () => { async (progress, token) => { try { // Command to run to clean project - var command = `pros make clean --project "${vscode.workspace.workspaceFolders?.[0].uri.fsPath}" --machine-output ${process.env["VSCODE FLAGS"]}`; + var command = `pros make clean --project "${vscode.workspace.workspaceFolders?.[0].uri.fsPath}" --machine-output ${process.env["PROS_VSCODE_FLAGS"]}`; console.log(command); const { stdout, stderr } = await promisify(child_process.exec)( command, diff --git a/src/commands/create-project.ts b/src/commands/create-project.ts index e9d0be1..824a11f 100644 --- a/src/commands/create-project.ts +++ b/src/commands/create-project.ts @@ -75,7 +75,7 @@ const selectProjectName = async () => { */ const selectKernelVersion = async (target: string) => { // Command to run to fetch all kernel versions - var command = `pros c ls-templates --target ${target} --machine-output ${process.env["VSCODE FLAGS"]}`; + var command = `pros c ls-templates --target ${target} --machine-output ${process.env["PROS_VSCODE_FLAGS"]}`; console.log(command); const { stdout, stderr } = await promisify(child_process.exec)(command, { env: { @@ -140,7 +140,7 @@ const runCreateProject = async ( try { // Command to run to make a new project with // user specified name, version, and location - var command = `pros c n "${projectPath}" ${target} ${version} --machine-output --build-cache ${process.env["VSCODE FLAGS"]}`; + var command = `pros c n "${projectPath}" ${target} ${version} --machine-output --build-cache ${process.env["PROS_VSCODE_FLAGS"]}`; console.log(command); const { stdout, stderr } = await promisify(child_process.exec)( command, diff --git a/src/commands/upgrade-project.ts b/src/commands/upgrade-project.ts index 0931a9c..fbe750f 100644 --- a/src/commands/upgrade-project.ts +++ b/src/commands/upgrade-project.ts @@ -17,7 +17,7 @@ const fetchTarget = async (): Promise<{ curOkapi: string | undefined; }> => { // Command to run to fetch the current project that needs to be updated - var command = `pros c info-project --project "${vscode.workspace.workspaceFolders?.[0].uri.fsPath}" --machine-output ${process.env["VSCODE FLAGS"]}`; + var command = `pros c info-project --project "${vscode.workspace.workspaceFolders?.[0].uri.fsPath}" --machine-output ${process.env["PROS_VSCODE_FLAGS"]}`; // console.log(command); const { stdout, stderr } = await promisify(child_process.exec)(command, { env: { @@ -55,7 +55,7 @@ const fetchServerVersions = async ( target: string ): Promise<{ newKernel: string; newOkapi: string | undefined }> => { // Command to run to fetch latest okapi and kernel versions - var command = `pros c q --target ${target} --machine-output ${process.env["VSCODE FLAGS"]}`; + var command = `pros c q --target ${target} --machine-output ${process.env["PROS_VSCODE_FLAGS"]}`; // console.log(command); const { stdout, stderr } = await promisify(child_process.exec)(command, { env: { @@ -91,7 +91,7 @@ const fetchServerVersions = async ( */ const runUpgrade = async () => { // Command to run to upgrade project to a newer version - var command = `pros c u --project "${vscode.workspace.workspaceFolders?.[0].uri.fsPath}" --machine-output ${process.env["VSCODE FLAGS"]}`; + var command = `pros c u --project "${vscode.workspace.workspaceFolders?.[0].uri.fsPath}" --machine-output ${process.env["PROS_VSCODE_FLAGS"]}`; console.log(command); const { stdout, stderr } = await promisify(child_process.exec)(command, { encoding: "utf8", diff --git a/src/commands/upload.ts b/src/commands/upload.ts index af6ebc6..a46d9b4 100644 --- a/src/commands/upload.ts +++ b/src/commands/upload.ts @@ -31,7 +31,7 @@ const runUpload = async () => { async (progress, token) => { try { // Command to run to upload project to brain - var command = `pros u --project "${vscode.workspace.workspaceFolders?.[0].uri.fsPath}" --machine-output ${process.env["VSCODE FLAGS"]}`; + var command = `pros u --project "${vscode.workspace.workspaceFolders?.[0].uri.fsPath}" --machine-output ${process.env["PROS_VSCODE_FLAGS"]}`; console.log(command); const { stdout, stderr } = await promisify(child_process.exec)( command, diff --git a/src/one-click/download.ts b/src/one-click/download.ts index a0bd3a7..f1636ed 100644 --- a/src/one-click/download.ts +++ b/src/one-click/download.ts @@ -29,7 +29,6 @@ async function download( async (progress, token) => { var out: fs.WriteStream; token.onCancellationRequested(() => { - console.log("User canceled the long running operation"); out!.destroy(); }); // Fetch the file to download @@ -44,12 +43,10 @@ async function download( response.body.on("data", (chunk: Buffer) => { progress.report({ increment: chunk.length * 100 / total_size }); }); - console.log("Write stream created") // Write file contents to "sigbots.pros/download/filename.tar.bz2" out = fs.createWriteStream( path.join(globalPath, "download", storagePath) ); - console.log("Start stream pipeline"); await promisify(stream.pipeline)(response.body, out).catch((e) => { // Clean up the partial file if the download failed. fs.unlink( @@ -59,11 +56,9 @@ async function download( console.log(e); throw e; }); - console.log("Finished downloading") } ); - console.log("returning bz2 status"); return bz2; } @@ -91,12 +86,11 @@ export async function extract( if (bz2) { // Read the contents of the bz2 file - console.log("Extracting bz2 file"); var compressedData = await fs.promises.readFile( path.join(globalPath, "download", storagePath) ); - console.log("Decoding bz2"); + // Decrypt the bz2 file contents. let decompressedData; try { @@ -104,18 +98,16 @@ export async function extract( } catch(e: any) { console.log(e); vscode.window.showErrorMessage("An error occured while decoding the toolchain"); - console.log("Decoding failed"); } - console.log("Bz2 decoded"); + storagePath = storagePath.replace(".bz2", ""); await fs.promises.writeFile( path.join(globalPath, "download", storagePath), decompressedData ); - console.log("Completed extraction of bz2 file"); // Write contents of the decrypted bz2 into "sigbots.pros/download/filename.tar" - console.log("Extracting tar file"); + await new Promise(function(resolve, reject) { // Create our read stream @@ -166,24 +158,21 @@ export async function extract( } // if bz2 else { - console.log("start extraction"); let readPath = path.join(globalPath, "download", storagePath); storagePath = storagePath.replace(".zip",""); let writePath = path.join(globalPath, "install", storagePath); // Extract the contents of the zip file await fs.createReadStream(readPath).pipe(unzipper.Extract({ path: writePath})).promise(); - console.log("Start file moving"); if (storagePath.includes("pros-toolchain-windows")) { // create tmp folder - console.log("Create tmp folder"); await fs.promises.mkdir( path.join(globalPath, "install", "pros-toolchain-windows", "tmp") ); // extract contents of gcc-arm-none-eabi-version folder - console.log("began reading usr"); + const files = await fs.promises.readdir( path.join(globalPath, "install", "pros-toolchain-windows", "usr") ); diff --git a/src/one-click/install.ts b/src/one-click/install.ts index 331e78d..43b2d0e 100644 --- a/src/one-click/install.ts +++ b/src/one-click/install.ts @@ -5,13 +5,13 @@ import * as os from "os"; import { downloadextract, chmod } from "./download"; import { getCurrentVersion, - getCliVersion, + getCurrentReleaseVersion, getInstallPromptTitle, } from "./installed"; import * as fs from "fs"; import { promisify } from "util"; import * as child_process from "child_process"; -import { O_RDONLY } from "constants"; +import { URL } from "url"; import { getChildProcessPath, getIntegratedTerminalPaths, getChildProcessProsToolchainPath } from "./path"; @@ -77,42 +77,67 @@ export async function uninstall(context: vscode.ExtensionContext) { } } -async function getUrls(version: number) { - var downloadCli = `https://github.com/purduesigbots/pros-cli/releases/download/${version}/pros_cli-${version}-lin-64bit.zip`; +async function getUrls(cliVersion: number, toolchainVersion: string) { + var downloadCli = `https://github.com/purduesigbots/pros-cli/releases/download/${cliVersion}/pros_cli-${cliVersion}-lin-64bit.zip`; var downloadToolchain = "https://developer.arm.com/-/media/Files/downloads/gnu-rm/10.3-2021.10/gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2"; if (getOperatingSystem() === "windows") { // Set system, path seperator, and downloads to windows version - downloadCli = `https://github.com/purduesigbots/pros-cli/releases/download/${version}/pros_cli-${version}-win-64bit.zip`; + downloadCli = `https://github.com/purduesigbots/pros-cli/releases/download/${cliVersion}/pros_cli-${cliVersion}-win-64bit.zip`; downloadToolchain = - "https://artprodcus3.artifacts.visualstudio.com/A268c8aad-3bb0-47d2-9a57-cf06a843d2e8/3a3f509b-ad80-4d2a-8bba-174ad5fd1dde/_apis/artifact/cGlwZWxpbmVhcnRpZmFjdDovL3B1cmR1ZS1hY20tc2lnYm90cy9wcm9qZWN0SWQvM2EzZjUwOWItYWQ4MC00ZDJhLThiYmEtMTc0YWQ1ZmQxZGRlL2J1aWxkSWQvMjg4Ni9hcnRpZmFjdE5hbWUvdG9vbGNoYWluLTY0Yml00/content?format=file&subPath=%2Fpros-toolchain-w64-3.0.1-standalone.zip"; + `https://github.com/purduesigbots/toolchain/releases/download/${toolchainVersion}/pros-toolchain-windows.zip`; } else if (getOperatingSystem() === "macos") { // Set system, path seperator, and downloads to windows version - downloadCli = `https://github.com/purduesigbots/pros-cli/releases/download/${version}/pros_cli-${version}-macos-64bit.zip`; + downloadCli = `https://github.com/purduesigbots/pros-cli/releases/download/${cliVersion}/pros_cli-${cliVersion}-macos-64bit.zip`; downloadToolchain = "https://developer.arm.com/-/media/Files/downloads/gnu-rm/10.3-2021.10/gcc-arm-none-eabi-10.3-2021.10-mac.tar.bz2"; os.cpus().some((cpu) => { if (cpu.model.includes("Apple M")) { - downloadCli = `https://github.com/purduesigbots/pros-cli/releases/download/${version}/pros_cli-${version}-macos-arm64bit.zip`; + downloadCli = `https://github.com/purduesigbots/pros-cli/releases/download/${cliVersion}/pros_cli-${cliVersion}-macos-arm64bit.zip`; } }); } + const custom_cli = vscode.workspace.getConfiguration("pros").get("OneClick: CliDownloadURL")??"default"; + const custom_toolchain = vscode.workspace.getConfiguration("pros").get("OneClick: ToolchainDownloadURL")??"default"; + + try { + const cliurl = new URL(custom_cli); + downloadCli = custom_cli === "default" ? downloadCli : custom_cli; + } catch(e: any) { + console.log(e); + console.log("CLI Url specified in PROS extension settings was invalid. Using default instead"); + } + + try { + const toolchainurl = new URL(custom_toolchain); + downloadToolchain = custom_toolchain === "default" ? downloadToolchain : custom_toolchain; + } catch(e: any) { + console.log(e); + console.log("Toolchain Url specified in PROS extension settings was invalid. Using default instead"); + } + + + + return [downloadCli, downloadToolchain]; } export async function install(context: vscode.ExtensionContext) { const globalPath = context.globalStorageUri.fsPath; const system = getOperatingSystem(); - var version = await getCliVersion( + var cliVersion = await getCurrentReleaseVersion( "https://api.github.com/repos/purduesigbots/pros-cli/releases/latest" ); - console.log("Latest Available CLI Version: " + version); + const toolchainVersion = await getCurrentReleaseVersion( + "https://api.github.com/repos/purduesigbots/toolchain/releases/latest" + ) + console.log("Latest Available CLI Version: " + cliVersion); // Get system type, path string separator, CLI download url, and toolchain download url. // Default variables are based on linux. - let [downloadCli, downloadToolchain] = await getUrls(version); + let [downloadCli, downloadToolchain] = await getUrls(cliVersion, toolchainVersion); // Set the installed file names var cliName = `pros-cli-${system}.zip`; // Title of prompt depending on user's installed CLI @@ -127,8 +152,8 @@ export async function install(context: vscode.ExtensionContext) { system === "windows" ? `${system}.zip` : `${system}.tar.bz2` }`; // Does the user's CLI have an update or does the user need to install/update - const cliVersion = title.includes("up to date") ? "UTD" : null; - if (cliVersion === null) { + const cliUpToDate = title.includes("up to date") ? "UTD" : null; + if (cliUpToDate === null) { // Ask user to install CLI if it is not installed. const labelResponse = await vscode.window.showInformationMessage( title, @@ -211,10 +236,14 @@ export async function updateCLI( } catch (err) { console.log(err); } - var version = await getCliVersion( + var cliVersion = await getCurrentReleaseVersion( "https://api.github.com/repos/purduesigbots/pros-cli/releases/latest" ); - let [downloadCli, downloadToolchain] = await getUrls(version); + const toolchainVersion = await getCurrentReleaseVersion( + "https://api.github.com/repos/purduesigbots/toolchain/releases/latest" + ) + + let [downloadCli, downloadToolchain] = await getUrls(cliVersion, toolchainVersion); // Set the installed file names var cliName = `pros-cli-${system}.zip`; // Title of prompt depending on user's installed CLI @@ -251,17 +280,18 @@ export async function cleanup( await configurePaths(context); // Ensure that toolchain and cli are working - const cliSuccess = await verifyCli(); - const toolchainSuccess = await verifyToolchain(); + let cliSuccess = await verifyCli().catch((err) => {})??false; + let toolchainSuccess = await verifyToolchain().catch((err) => {console.log(err);})??false; if (cliSuccess && toolchainSuccess) { vscode.window.showInformationMessage( "CLI and Toolchain are working!" ); } else { vscode.window.showErrorMessage( - `${cliSuccess ? "" : "CLI"} ${ - !cliSuccess && !toolchainSuccess ? "" : "and" - } ${toolchainSuccess ? "" : "Toolchain"} Installation Failed!` + `${cliSuccess ? "" : "CLI"} + ${!cliSuccess && !toolchainSuccess ? " and " : ""} + ${toolchainSuccess ? "" : "Toolchain"} + Installation Failed!` ); vscode.window.showInformationMessage( `Please try installing again! If this problem persists, consider trying an alternative install method: https://pros.cs.purdue.edu/v5/getting-started/${system}.html` @@ -297,26 +327,20 @@ export async function configurePaths(context: vscode.ExtensionContext) { "pros" ) ); - process.env["VSCODE FLAGS"] = + process.env["PROS_VSCODE_FLAGS"] = version >= 324 ? "--no-sentry --no-analytics" : ""; console.log(`${isOneClickInstall} | ${version}`); - if (!isOneClickInstall) { - // Use system defaults if user does not have one-click CLI - CLI_EXEC_PATH = ""; - TOOLCHAIN = "LOCAL"; - return; - } PATH_SEP = getOperatingSystem() === "windows" ? ";" : ":"; - TOOLCHAIN = toolchainPath; + TOOLCHAIN = isOneClickInstall?toolchainPath:(process.env["PROS_TOOLCHAIN"] ?? ""); // Set CLI environmental variable file location CLI_EXEC_PATH = cliExecPath; // Prepend CLI and TOOLCHAIN to path - process.env["PATH"] = `${ + process.env["PATH"] = `${PATH_SEP}${cliExecPath}${PATH_SEP}${path.join(toolchainPath, "bin")}${ process.env["PATH"] - }${PATH_SEP}${cliExecPath}${PATH_SEP}${path.join(toolchainPath, "bin")}`; + }`; // Make PROS_TOOCLHAIN variable process.env["PROS_TOOLCHAIN"] = `${TOOLCHAIN}`; @@ -325,7 +349,7 @@ export async function configurePaths(context: vscode.ExtensionContext) { } async function verifyCli() { - var command = `pros c ls-templates --machine-output ${process.env["VSCODE FLAGS"]}`; + var command = `pros c --help --machine-output ${process.env["PROS_VSCODE_FLAGS"]}`; const { stdout, stderr } = await promisify(child_process.exec)(command, { timeout: 30000, env: { @@ -337,11 +361,11 @@ async function verifyCli() { console.log(stderr); } console.log(stdout); - return stdout.includes(`'kernel', 'version': '3.5.4'`); + return stdout.includes(`Uc&42BWAaQ{"type": "log/message", "level": "DEBUG", "message": "DEBUG - pros:callback - CLI Version:`); } async function verifyToolchain() { - let toolchainPath = getChildProcessProsToolchainPath(); + let toolchainPath = getChildProcessProsToolchainPath()??''; if (!toolchainPath) { return false; } @@ -352,7 +376,7 @@ async function verifyToolchain() { "arm-none-eabi-g++" )}" --version`; - const { stdout, stderr } = await promisify(child_process.exec)(command, { + const { stdout, stderr } = await promisify(child_process.exec)("arm-none-eabi-g++ --version", { timeout: 5000, env: { ...process.env, @@ -362,5 +386,5 @@ async function verifyToolchain() { if (stderr) { console.log(stderr); } - return stdout.startsWith(`arm-none-eabi-g++ (GNU Arm Embedded Toolchain`); + return stdout.replace(".exe","").startsWith(`arm-none-eabi-g++ (G`); } diff --git a/src/one-click/installed.ts b/src/one-click/installed.ts index 3cfdf2a..ade7cac 100644 --- a/src/one-click/installed.ts +++ b/src/one-click/installed.ts @@ -3,7 +3,7 @@ import { promisify } from "util"; import { getChildProcessPath } from "./path"; var fetch = require("node-fetch"); -export async function getCliVersion(url: string) { +export async function getCurrentReleaseVersion(url: string) { // Fetch the url const response = await fetch(url); if (!response.ok) { @@ -11,7 +11,8 @@ export async function getCliVersion(url: string) { throw new Error(`Can't fetch release: ${response.statusText}`); } // Get the version number from the returned json - var vString = (await response.json()).tag_name; + const json = await response.json(); + var vString = json.tag_name; return vString; } @@ -55,7 +56,7 @@ export async function getCurrentVersion(oneClickPath: string) { export async function getInstallPromptTitle(oneClickPath: string) { const recent = +( - await getCliVersion( + await getCurrentReleaseVersion( "https://api.github.com/repos/purduesigbots/pros-cli/releases/latest" ) ).replace(/\./gi, "");