Skip to content

Commit 57e4acf

Browse files
authored
Merge pull request #362 from aminya/git [skip ci]
feat: add git as an installable tool
2 parents 627988e + 15b21af commit 57e4acf

File tree

10 files changed

+149
-66
lines changed

10 files changed

+149
-66
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Setting up a **cross-platform** environment for building and testing C++/C proje
3131
| --------------- | ----------------------------------------------------------------------------------------------------------- |
3232
| compiler | llvm, gcc, msvc, apple-clang, vcvarsall |
3333
| build system | cmake, ninja, meson, make, task, bazel |
34-
| package manager | vcpkg, conan, choco, brew, nala, setup-cpp |
34+
| package manager | vcpkg, conan, choco, brew, nala, git, setup-cpp |
3535
| analyzer/linter | clang-tidy, clang-format, cppcheck, cpplint, flawfinder, lizard, infer, cmakelang, cmake-format, cmake-lint |
3636
| cache | ccache, sccache |
3737
| documentation | doxygen, graphviz |

dist/legacy/setup-cpp.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/legacy/setup-cpp.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/modern/setup-cpp.mjs

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

dist/modern/setup-cpp.mjs.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/cli-options.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { getInput } from "@actions/core"
22
import { info } from "ci-log"
3+
import type { AddPathOptions } from "envosman"
34
import mri from "mri"
45
import { untildifyUser } from "untildify-user"
56
import { type Inputs, inputs } from "./tool.js"
@@ -42,7 +43,7 @@ All the available tools:
4243
"build system": {
4344
tools: "--cmake, --ninja, --meson, --make, --task, --bazel",
4445
},
45-
"package manager": { tools: "--vcpkg, --conan, --choco, --brew, --nala, --setup-cpp" },
46+
"package manager": { tools: "--vcpkg, --conan, --choco, --brew, --nala, --git, --setup-cpp" },
4647
"analyzer/linter": {
4748
tools:
4849
"--clang-tidy, --clang-format, --cppcheck, --cpplint, --flawfinder, --lizard, --infer, , --cmakelang, --cmake-lint, --cmake-format",
@@ -88,7 +89,7 @@ export function getSuccessMessage(tool: string, installationInfo: InstallationIn
8889
return msg
8990
}
9091

91-
export const rcOptions = {
92+
export const rcOptions: AddPathOptions = {
9293
rcPath: untildifyUser("~/.cpprc"),
9394
guard: "cpp",
9495
}

src/git/__tests__/git.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import type { InstallationInfo } from "../../utils/setup/setupBin.js"
2+
import { testBin } from "../../utils/tests/test-helpers.js"
3+
import { setupGit } from "../git.js"
4+
5+
jest.setTimeout(300000)
6+
describe("setup-git", () => {
7+
it("should setup git", async () => {
8+
const installInfo = await setupGit("", "", process.arch)
9+
10+
await testBin("git", ["--version"], (installInfo as InstallationInfo | undefined)?.binDir)
11+
})
12+
})

src/git/git.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { existsSync } from "fs"
2+
import { info, warning } from "ci-log"
3+
import { addPath } from "envosman"
4+
import { installAptPack } from "setup-apt"
5+
import { installBrewPack } from "setup-brew"
6+
import which from "which"
7+
import { rcOptions } from "../cli-options.js"
8+
import { hasDnf } from "../utils/env/hasDnf.js"
9+
import { isArch } from "../utils/env/isArch.js"
10+
import { isUbuntu } from "../utils/env/isUbuntu.js"
11+
import { setupChocoPack } from "../utils/setup/setupChocoPack.js"
12+
import { setupDnfPack } from "../utils/setup/setupDnfPack.js"
13+
import { setupPacmanPack } from "../utils/setup/setupPacmanPack.js"
14+
15+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
16+
export async function setupGit(version: string, _setupDir: string, _arch: string) {
17+
const git = await which("git", { nothrow: true })
18+
if (git !== null) {
19+
info(`Git already installed at ${git}`)
20+
return
21+
}
22+
23+
switch (process.platform) {
24+
case "win32": {
25+
const result = await setupChocoPack("git", version)
26+
const gitDir = findWindowsGit()
27+
if (gitDir !== null) {
28+
await addPath(gitDir, rcOptions)
29+
}
30+
return result
31+
}
32+
case "darwin": {
33+
return installBrewPack("git", version)
34+
}
35+
case "linux": {
36+
if (isArch()) {
37+
return setupPacmanPack("git", version)
38+
} else if (hasDnf()) {
39+
return setupDnfPack([{ name: "git", version }])
40+
} else if (isUbuntu()) {
41+
return installAptPack([{ name: "git", version }])
42+
}
43+
throw new Error("Unsupported linux distribution")
44+
}
45+
default: {
46+
throw new Error("Unsupported platform")
47+
}
48+
}
49+
}
50+
51+
function findWindowsGit() {
52+
const candidates = [
53+
"C:/Program Files/Git/bin/git.exe",
54+
"C:/Program Files (x86)/Git/bin/git.exe",
55+
]
56+
for (const candidate of candidates) {
57+
if (existsSync(candidate)) {
58+
return candidate
59+
}
60+
}
61+
62+
warning("Git not found in the default locations. Add git to PATH manually.")
63+
return null
64+
}

src/tool.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { setupFlawfinder } from "./flawfinder/flawfinder.js"
1212
import { setupGcc } from "./gcc/gcc.js"
1313
import { setupMingw } from "./gcc/mingw.js"
1414
import { setupGcovr } from "./gcovr/gcovr.js"
15+
import { setupGit } from "./git/git.js"
1516
import { setupGraphviz } from "./graphviz/graphviz.js"
1617
import { setupInfer } from "./infer/infer.js"
1718
import { setupKcov } from "./kcov/kcov.js"
@@ -60,6 +61,7 @@ export const llvmTools = ["llvm", "clang", "clang++", "clang-tidy", "clang-forma
6061

6162
/** The setup functions */
6263
export const setups = {
64+
git: setupGit,
6365
nala: setupNala,
6466
brew: setupBrew,
6567
choco: setupChocolatey,

src/vcpkg/vcpkg.ts

Lines changed: 63 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { addShExt, addShRelativePrefix } from "patha"
88
import { installAptPack } from "setup-apt"
99
import which from "which"
1010
import { rcOptions } from "../cli-options.js"
11+
import { setupGit } from "../git/git.js"
1112
import { arm64 } from "../utils/env/arch.js"
1213
import { hasDnf } from "../utils/env/hasDnf.js"
1314
import { isArch } from "../utils/env/isArch.js"
@@ -19,74 +20,77 @@ import { setupPacmanPack } from "../utils/setup/setupPacmanPack.js"
1920
let hasVCPKG = false
2021

2122
export async function setupVcpkg(version: string, setupDir: string, arch: string): Promise<InstallationInfo> {
22-
if (!hasVCPKG || which.sync("vcpkg", { nothrow: true }) === null) {
23-
if (process.platform === "linux") {
24-
// vcpkg download and extraction dependencies
25-
if (isArch()) {
26-
await Promise.all([
27-
setupPacmanPack("curl"),
28-
setupPacmanPack("zip"),
29-
setupPacmanPack("unzip"),
30-
setupPacmanPack("tar"),
31-
setupPacmanPack("git"),
32-
setupPacmanPack("pkg-config"),
33-
])
34-
} else if (hasDnf()) {
35-
await setupDnfPack([
36-
{ name: "curl" },
37-
{ name: "zip" },
38-
{ name: "unzip" },
39-
{ name: "tar" },
40-
{ name: "git" },
41-
{ name: "pkg-config" },
42-
])
43-
} else if (isUbuntu()) {
44-
await installAptPack([
45-
{ name: "curl" },
46-
{ name: "zip" },
47-
{ name: "unzip" },
48-
{ name: "tar" },
49-
{ name: "git" },
50-
{ name: "pkg-config" },
51-
])
52-
}
53-
}
23+
const vcpkg = await which("vcpkg", { nothrow: true })
5424

55-
// clone if not already exists
56-
if (!(await pathExists(join(setupDir, addShExt("bootstrap-vcpkg", ".bat"))))) {
57-
execaSync("git", ["clone", "https://github.com/microsoft/vcpkg"], { cwd: dirname(setupDir), stdio: "inherit" })
58-
} else {
59-
notice(`Vcpkg folder already exists at ${setupDir}. Skipping the clone`)
60-
}
25+
if (hasVCPKG && vcpkg !== null) {
26+
return { binDir: dirname(vcpkg) }
27+
}
6128

62-
// if version specified, checkout the version
63-
if (version !== "" && version !== "true") {
64-
info(`Checking out vcpkg version ${version}`)
65-
execaSync("git", ["checkout", version], {
66-
cwd: setupDir,
67-
stdio: "inherit",
68-
})
69-
}
29+
// vcpkg dependencies
30+
await setupGit("", setupDir, arch)
7031

71-
// Add VCPKG_FORCE_SYSTEM_BINARIES=1 for Linux arm64
72-
if (process.platform === "linux" && arch in arm64) {
73-
await addEnv("VCPKG_FORCE_SYSTEM_BINARIES", "1")
32+
if (process.platform === "linux") {
33+
if (isArch()) {
34+
await Promise.all([
35+
setupPacmanPack("curl"),
36+
setupPacmanPack("zip"),
37+
setupPacmanPack("unzip"),
38+
setupPacmanPack("tar"),
39+
setupPacmanPack("pkg-config"),
40+
])
41+
} else if (hasDnf()) {
42+
await setupDnfPack([
43+
{ name: "curl" },
44+
{ name: "zip" },
45+
{ name: "unzip" },
46+
{ name: "tar" },
47+
{ name: "pkg-config" },
48+
])
49+
} else if (isUbuntu()) {
50+
await installAptPack([
51+
{ name: "curl" },
52+
{ name: "zip" },
53+
{ name: "unzip" },
54+
{ name: "tar" },
55+
{ name: "pkg-config" },
56+
])
7457
}
58+
}
59+
60+
// clone if not already exists
61+
if (!(await pathExists(join(setupDir, addShExt("bootstrap-vcpkg", ".bat"))))) {
62+
execaSync("git", ["clone", "https://github.com/microsoft/vcpkg"], { cwd: dirname(setupDir), stdio: "inherit" })
63+
} else {
64+
notice(`Vcpkg folder already exists at ${setupDir}. Skipping the clone`)
65+
}
7566

76-
// bootstrap vcpkg
77-
execaSync(addShExt(addShRelativePrefix("bootstrap-vcpkg"), ".bat"), {
67+
// if version specified, checkout the version
68+
if (version !== "" && version !== "true") {
69+
info(`Checking out vcpkg version ${version}`)
70+
execaSync("git", ["checkout", version], {
7871
cwd: setupDir,
79-
shell: true,
8072
stdio: "inherit",
8173
})
74+
}
8275

83-
await grantUserWriteAccess(setupDir)
84-
85-
await addPath(setupDir, rcOptions)
86-
// eslint-disable-next-line require-atomic-updates
87-
hasVCPKG = true
88-
return { binDir: setupDir }
76+
// Add VCPKG_FORCE_SYSTEM_BINARIES=1 for Linux arm64
77+
if (process.platform === "linux" && arch in arm64) {
78+
await addEnv("VCPKG_FORCE_SYSTEM_BINARIES", "1")
8979
}
9080

91-
return { binDir: dirname(which.sync("vcpkg")) }
81+
// bootstrap vcpkg
82+
execaSync(addShExt(addShRelativePrefix("bootstrap-vcpkg"), ".bat"), {
83+
cwd: setupDir,
84+
shell: true,
85+
stdio: "inherit",
86+
})
87+
88+
await grantUserWriteAccess(setupDir)
89+
90+
await addPath(setupDir, rcOptions)
91+
92+
// eslint-disable-next-line require-atomic-updates
93+
hasVCPKG = true
94+
95+
return { binDir: setupDir }
9296
}

0 commit comments

Comments
 (0)