1 import { promisify } from "util";
2 import { exec } from "child_process";
3 import Logger from "../logger.mjs";
4 import { unlink } from "fs/promises";
5 import type Settings from "../settings.mjs";
6 import { SettingsKey, HOME_VAR } from "../settings.mjs";
7 import { homedir } from "os";
8 import which from "which";
9 import { window } from "vscode";
11 export const execAsync = promisify(exec);
14 * Get installed version of git, and install it if it isn't already
16 export async function getGit(
18 ): Promise<string | undefined> {
19 let gitExecutable: string | undefined =
21 .getString(SettingsKey.gitPath)
22 ?.replace(HOME_VAR, homedir().replaceAll("\\", "/")) || "git";
23 let gitPath = await which(gitExecutable, { nothrow: true });
24 if (gitPath === null) {
25 // if git is not in path then checkForInstallationRequirements
26 // maye downloaded it, so reload
28 gitExecutable = settings
29 .getString(SettingsKey.gitPath)
30 ?.replace(HOME_VAR, homedir().replaceAll("\\", "/"));
31 if (gitExecutable === null || gitExecutable === undefined) {
32 Logger.log("Error: Git not found.");
34 await window.showErrorMessage(
35 "Git not found. Please install and add to PATH or " +
36 "set the path to the git executable in global settings."
41 gitPath = await which(gitExecutable, { nothrow: true });
49 * Initialize git submodules in downloaded Pico-SDK.
51 * @param sdkDirectory The directory of the downloaded Pico-SDK.
52 * @returns True if the submodules were initialized successfully, false otherwise.
54 export async function initSubmodules(
56 gitExecutable: string = "git"
59 // Use the "git submodule update --init" command in the specified directory
61 `cd "${sdkDirectory}" && ` +
63 process.env.ComSpec === "powershell.exe" ? "&" : ""
64 }"${gitExecutable}" submodule update --init`;
65 await execAsync(command);
75 export async function cloneRepository(
78 targetDirectory: string,
79 gitExecutable: string = "git"
81 // Clone the repository at the specified tag into the target directory
84 process.env.ComSpec === "powershell.exe" ? "&" : ""
85 }"${gitExecutable}" -c advice.detachedHead=false clone --branch ` +
86 `${branch} ${repository} "${targetDirectory}"`;
89 await execAsync(cloneCommand);
91 Logger.log(`${repository} ${branch} has been cloned and installed.`);
96 await unlink(targetDirectory);
101 const err = error instanceof Error ? error.message : (error as string);
102 if (err.includes("already exists")) {
105 Logger.log(`Error while cloning repository: ${err}`);
111 export async function sparseCloneRepository(
114 targetDirectory: string,
115 gitExecutable: string = "git"
116 ): Promise<boolean> {
117 // Clone the repository at the specified tag into the target directory
120 process.env.ComSpec === "powershell.exe" ? "&" : ""
121 }"${gitExecutable}" -c advice.detachedHead=false clone ` +
122 "--filter=blob:none --sparse --branch " +
123 `${branch} ${repository} "${targetDirectory}"`;
126 await execAsync(cloneCommand);
128 `cd "${targetDirectory}" && ${
129 process.env.ComSpec === "powershell.exe" ? "&" : ""
130 }"${gitExecutable}" sparse-checkout set --cone`
134 `${repository} ${branch} has been cloned with a sparse-checkout.`
140 await unlink(targetDirectory);
145 const err = error instanceof Error ? error.message : (error as string);
146 if (err.includes("already exists")) {
149 Logger.log(`Error while cloning repository: ${err}`);
156 * Add a path to the sparse-checkout of a repository.
158 * @param repoDirectory The directory of the git repository (absolute).
159 * @param checkoutPath The repo-relative path to add to the sparse-checkout.
160 * @param gitExecutable The path to the git executable.
161 * @returns True if the path was added successfully, false otherwise.
163 export async function sparseCheckout(
164 repoDirectory: string,
165 checkoutPath: string,
166 gitExecutable: string = "git"
167 ): Promise<boolean> {
170 `cd "${repoDirectory}" && ${
171 process.env.ComSpec === "powershell.exe" ? "&" : ""
172 }"${gitExecutable}" sparse-checkout add ${checkoutPath}`
177 const err = error instanceof Error ? error.message : (error as string);
178 Logger.log(`Error while cloning repository: ${err}`);