Merge pull request #114 from aminya/monorepo [skip ci]

This commit is contained in:
Amin Yahyaabadi 2022-08-08 00:47:11 -07:00 committed by GitHub
commit 547d9b47ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
80 changed files with 2090 additions and 329 deletions

6
.gitignore vendored
View File

@ -11,11 +11,9 @@ temp-*
*.tsbuildinfo
# Build directories
./dist/
!./dist/setup_cpp.js
!./dist/setup_cpp.js.map
packages/*/dist/
.parcel-cache
exe/
*.log
*.exe
.cache/
.cache/

View File

@ -14,13 +14,12 @@ words:
- applellvm
- bazel
- bazelisk
- copr
- vbatts
- buildtools
- caxa
- ccache
- choco
- cmake
- copr
- CPATH
- Cppcheck
- CPPFLAGS
@ -38,6 +37,7 @@ words:
- ghes
- Graphviz
- isci
- isroot
- kcov
- LDFLAGS
- lefticus
@ -68,6 +68,7 @@ words:
- tsbuildinfo
- ucrt
- untildify
- vbatts
- vcpkg
- vcvarsall
- visualc

61
dev/readme/template.md Normal file
View File

@ -0,0 +1,61 @@
<h1 align="center"><%= projectName %></h1>
<p>
<% if (isProjectOnNpm) { -%>
<a href="https://www.npmjs.com/package/<%= projectName %>" target="_blank">
<img alt="Version" src="https://img.shields.io/npm/v/<%= projectName %>.svg">
</a>
<% } -%>
<% if (projectVersion && !isProjectOnNpm) { -%>
<img alt="Version" src="https://img.shields.io/badge/version-<%= projectVersion %>-blue.svg?cacheSeconds=2592000" />
<% } -%>
<% if (projectPrerequisites) { -%>
<% projectPrerequisites.map(({ name, value }) => { -%>
<img src="https://img.shields.io/badge/<%= name %>-<%= encodeURIComponent(value) %>-blue.svg" />
<% }) -%>
<% } -%>
<% if (projectDocumentationUrl) { -%>
<a href="<%= projectDocumentationUrl %>" target="_blank">
<img alt="Documentation" src="https://img.shields.io/badge/documentation-yes-brightgreen.svg" />
</a>
<% } -%>
<% if (isGithubRepos) { -%>
<a href="<%= repositoryUrl %>/graphs/commit-activity" target="_blank">
<img alt="Maintenance" src="https://img.shields.io/badge/Maintained%3F-yes-green.svg" />
</a>
<% } -%>
<% if (licenseName) { -%>
<a href="<%= licenseUrl ? licenseUrl : '#' %>" target="_blank">
<img alt="License: <%= licenseName %>" src="https://img.shields.io/<%= isGithubRepos ? `github/license/${authorGithubUsername}/${projectName}` : `badge/License-${licenseName}-yellow.svg` %>" />
</a>
<% } -%>
<% if (authorTwitterUsername) { -%>
<a href="https://twitter.com/<%= authorTwitterUsername %>" target="_blank">
<img alt="Twitter: <%= authorTwitterUsername %>" src="https://img.shields.io/twitter/follow/<%= authorTwitterUsername %>.svg?style=social" />
</a>
<% } -%>
</p>
<% if (projectDescription) { -%>
> <%= projectDescription %>
> <% } -%>
## Install
```sh
npm install --save <%= projectName %>
```
## Usage
<!-- INSERT GENERATED DOCS START -->
<!-- INSERT GENERATED DOCS END -->
## 🤝 Contributing
You can sponsor my work here:
https://github.com/sponsors/aminya
Pull requests, issues and feature requests are welcome.
See the [Contributing guide](https://github.com/aminya/setup-cpp/blob/master/CONTRIBUTING.md).

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/actions_python.dfab21e0.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/actions_python.dfab21e0.js.map vendored Normal file

File diff suppressed because one or more lines are too long

2
dist/actions_python.feac98a0.js vendored Normal file

File diff suppressed because one or more lines are too long

1
dist/actions_python.feac98a0.js.map vendored Normal file

File diff suppressed because one or more lines are too long

2
dist/setup_cpp.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/setup_cpp.mjs vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -27,6 +27,7 @@
"clean": "shx rm -rf .parcel-cache dist exe",
"copy.matchers": "shx cp ./src/gcc/gcc_matcher.json ./dist/ && shx cp ./src/msvc/msvc_matcher.json ./dist && shx cp ./src/python/python_matcher.json ./dist/ && shx cp ./src/llvm/llvm_matcher.json ./dist/ ",
"dev": "cross-env NODE_ENV=development parcel watch",
"docs": "shx rm -rf packages/*/README.md && pnpm -r exec readme --path ../../dev/readme/template.md -y && pnpm -r exec ts-readme",
"format": "run-s lint.prettier",
"lint": "run-p --aggregate-output --continue-on-error lint.cspell lint.eslint lint.prettier lint.tsc",
"lint.cspell": "cspell lint --no-progress --show-suggestions",
@ -34,7 +35,7 @@
"lint.prettier": "prettier --write .",
"lint.tsc": "tsc --noEmit | loose-ts-check",
"pack.exe": "shx rm -rf ./dist/tsconfig.tsbuildinfo && node ./dev/scripts/pack-exe.js",
"prepare": "npm run build",
"prepare": "pnpm run -r build && pnpm run -w build",
"start.docker": "docker run -t setup_cpp .",
"start.docker.arch": "docker run -t setup_cpp:arch .",
"start.docker.fedora": "docker run -t setup_cpp:fedora .",
@ -54,16 +55,22 @@
"@actions/exec": "^1.1.1",
"@actions/io": "^1.1.2",
"@actions/tool-cache": "^2.0.1",
"escape-path-with-spaces": "^1.0.0",
"@npmcli/ci-detect": "github:aminya/ci-detect#37fe40075bebec96794ba0a7c4a6d5c70cbea00d",
"escape-path-with-spaces": "github:aminya/escape-path-with-spaces#d9f81ee649203ddc55783a2f96ada59df06118e3",
"exec-powershell": "workspace:*",
"execa": "^5.1.1",
"extension-tools": "workspace:*",
"get-works": "workspace:*",
"mri": "^1.2.0",
"msvc-dev-cmd": "github:aminya/msvc-dev-cmd#9f672c1",
"numerous": "1.0.3",
"root-tools": "workspace:*",
"semver": "7.3.7",
"setup-python": "github:actions/setup-python#c474c82340438924daab9282d07300bfe7e3692d",
"time-delta": "github:aminya/time-delta#69d91a41cef28e569be9a2991129f5f7d1f0d00e",
"ubuntu-version": "^2.0.0",
"untildify": "^4.0.0",
"untildify-user": "workspace:*",
"user-access": "workspace:*",
"which": "^2.0.2"
},
"devDependencies": {
@ -79,6 +86,7 @@
"cspell": "^6.5.0",
"eslint": "^8.21.0",
"eslint-config-atomic": "^1.18.1",
"gen-readme": "^1.6.0",
"jest": "^28.1.3",
"loose-ts-check": "^1.2.0",
"npm-check-updates": "^16.0.5",
@ -86,9 +94,11 @@
"parcel": "2.6.2",
"prettier": "2.7.1",
"prettier-config-atomic": "^3.0.10",
"readme-md-generator": "^1.0.0",
"shx": "0.3.4",
"terser-config-atomic": "^0.1.1",
"ts-jest": "^28.0.7",
"ts-readme": "^1.1.3",
"typescript": "^4.7.4"
},
"engines": {
@ -113,6 +123,9 @@
"ninja",
"meson"
],
"alias": {
"electron": false
},
"pnpm": {
"overrides": {
"semver": "7.3.7",

View File

@ -0,0 +1,60 @@
<h1 align="center">exec-powershell</h1>
<p>
<img alt="Version" src="https://img.shields.io/badge/version-1.0.0-blue.svg?cacheSeconds=2592000" />
<a href="#" target="_blank">
<img alt="License: Apache--2.0" src="https://img.shields.io/badge/License-Apache--2.0-yellow.svg" />
</a>
</p>
> Run a powershell command.
## Install
```sh
npm install --save exec-powershell
```
## Usage
<!-- INSERT GENERATED DOCS START -->
### `execPowershell` (function)
Asynchronously execute a powershell command.
**Parameters:**
- command (`string`) - The powershell command to execute
- startupFlags (`string[]`) - The optional startup flags to be passed to powershell. Defaults to `["-NoProfile", "-NoLogo", "-NonInteractive"]`. This means that the Powershell profile is not sourced first.
- execOptions (`execa.Options`) - The options passed to `execa`. Defaults to `{ stdio: "inherit" }`
**returns:** execa.ExecaChildProcess<string>
### `execPowershellSync` (function)
Execute a powershell command.
**Parameters:**
- command (`string`) - The powershell command to execute
- startupFlags (`string[]`) - The optional startup flags to be passed to powershell. Defaults to `["-NoProfile", "-NoLogo", "-NonInteractive"]`. This means that the Powershell profile is not sourced first.
- execOptions (`execa.SyncOptions`) - The options passed to `execa`. Defaults to `{ stdio: "inherit" }`
**returns:** execa.ExecaSyncReturnValue<string>
### `getPowerShell` (function)
Get the path to the powershell executable.
**returns:** string
<!-- INSERT GENERATED DOCS END -->
## 🤝 Contributing
You can sponsor my work here:
https://github.com/sponsors/aminya
Pull requests, issues and feature requests are welcome.
See the [Contributing guide](https://github.com/aminya/setup-cpp/blob/master/CONTRIBUTING.md).

View File

@ -0,0 +1,33 @@
{
"name": "exec-powershell",
"version": "1.0.0",
"description": "Run a powershell command.",
"homepage": "https://github.com/aminya/setup-cpp",
"license": "Apache-2.0",
"author": "Amin Yahyaabadi",
"main": "./dist/index.js",
"source": "./src/index.ts",
"scripts": {
"build": "tsc"
},
"dependencies": {
"execa": "^5.1.1",
"which": "^2.0.2"
},
"devDependencies": {
"@types/which": "^2.0.1"
},
"keywords": [
"powershell",
"pwsh",
"exec",
"execa",
"spawn",
"system",
"github-actions",
"github",
"actions",
"gitlab",
"ci"
]
}

View File

@ -0,0 +1,64 @@
import execa from "execa"
import which from "which"
/** The cached powershell path */
let powershell: string | undefined
/**
* Asynchronously execute a powershell command.
*
* @param command The powershell command to execute
* @param startupFlags The optional startup flags to be passed to powershell. Defaults to `["-NoProfile", "-NoLogo",
* "-NonInteractive"]`. This means that the Powershell profile is not sourced first.
* @param execOptions The options passed to `execa`. Defaults to `{ stdio: "inherit" }`
* @returns A promise to the execution result
* @note It prefers `pwsh` over `powershell`
*/
export function execPowershell(
command: string,
startupFlags: string[] = ["-NoProfile", "-NoLogo", "-NonInteractive"],
execOptions: execa.Options = { stdio: "inherit" }
): execa.ExecaChildProcess<string> {
return execa(getPowerShell(), [...startupFlags, "-c", command], execOptions)
}
/**
* Execute a powershell command.
*
* @param command The powershell command to execute
* @param startupFlags The optional startup flags to be passed to powershell. Defaults to `["-NoProfile", "-NoLogo",
* "-NonInteractive"]`. This means that the Powershell profile is not sourced first.
* @param execOptions The options passed to `execa`. Defaults to `{ stdio: "inherit" }`
* @returns The execution result
* @note It prefers `pwsh` over `powershell`
*/
export function execPowershellSync(
command: string,
startupFlags: string[] = ["-NoProfile", "-NoLogo", "-NonInteractive"],
execOptions: execa.SyncOptions = { stdio: "inherit" }
): execa.ExecaSyncReturnValue<string> {
return execa.sync(getPowerShell(), [...startupFlags, "-c", command], execOptions)
}
/**
* Get the path to the powershell executable.
*
* @note It prefers `pwsh` over `powershell`
* @note It caches the path for the subsequent calls to this function
*/
export function getPowerShell() {
if (powershell === undefined) {
const maybePwsh = which.sync("pwsh", { nothrow: true })
if (maybePwsh !== null) {
powershell = maybePwsh
}
const maybePowerShell = which.sync("powershell", { nothrow: true })
if (maybePowerShell !== null) {
powershell = maybePowerShell
}
}
if (powershell === undefined) {
throw new Error("Could not find powershell")
}
return powershell
}

View File

@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist"
},
"include": ["./src"]
}

View File

@ -0,0 +1,66 @@
<h1 align="center">extension-tools</h1>
<p>
<a href="https://www.npmjs.com/package/extension-tools" target="_blank">
<img alt="Version" src="https://img.shields.io/npm/v/extension-tools.svg">
</a>
<a href="#" target="_blank">
<img alt="License: Apache--2.0" src="https://img.shields.io/badge/License-Apache--2.0-yellow.svg" />
</a>
</p>
> Tools for working with file extensions such as getting the binary and shell extension on different platforms.
## Install
```sh
npm install --save extension-tools
```
## Usage
<!-- INSERT GENERATED DOCS START -->
### `addBinExtension` (function)
Add bin extension to the given binary name.
**Parameters:**
- name (`string`) - The name you want to add the shell extension to
- win_ext (`string`) - `.exe` on Windows
- unix_ext (`string`) - `""` On unix.
**returns:** string
### `addShellExtension` (function)
Add native shell extension to the given name
**Parameters:**
- name (`string`) - The name you want to add the shell extension to
- win_ext (`string`) - `.bat` on Windows
- unix_ext (`string`) - `.sh` On unix.
**returns:** string
### `addShellHere` (function)
Prefix a `./` for unix shell and nothing for the cmd shell
**Parameters:**
- name (`string`)
**returns:** string
<!-- INSERT GENERATED DOCS END -->
## 🤝 Contributing
You can sponsor my work here:
https://github.com/sponsors/aminya
Pull requests, issues and feature requests are welcome.
See the [Contributing guide](https://github.com/aminya/setup-cpp/blob/master/CONTRIBUTING.md).

View File

@ -0,0 +1,33 @@
{
"name": "extension-tools",
"version": "1.0.0",
"description": "Tools for working with file extensions such as getting the binary and shell extension on different platforms.",
"homepage": "https://github.com/aminya/setup-cpp",
"license": "Apache-2.0",
"author": "Amin Yahyaabadi",
"main": "./dist/index.js",
"source": "./src/index.ts",
"scripts": {
"build": "tsc"
},
"keywords": [
"extension",
"shell",
"bin",
"windows",
"sh",
"cmd",
"bat",
"exec",
"execa",
"spawn",
"system",
"unix",
"linux",
"github-actions",
"github",
"actions",
"gitlab",
"ci"
]
}

View File

@ -0,0 +1,35 @@
/**
* Add bin extension to the given binary name.
*
* @param name The name you want to add the shell extension to
* @param win_ext `.exe` on Windows
* @param unix_ext `""` On unix.
*/
export function addBinExtension(name: string, win_ext = ".exe", unix_ext = "") {
if (process.platform === "win32") {
return `${name}${win_ext}`
}
return `${name}${unix_ext}`
}
/**
* Add native shell extension to the given name
*
* @param name The name you want to add the shell extension to
* @param win_ext `.bat` on Windows
* @param unix_ext `.sh` On unix.
*/
export function addShellExtension(name: string, win_ext = ".bat", unix_ext = ".sh") {
if (process.platform === "win32") {
return `${name}${win_ext}`
}
return `${name}${unix_ext}`
}
/** Prefix a `./` for unix shell and nothing for the cmd shell */
export function addShellHere(name: string) {
if (process.platform === "win32") {
return name
}
return `./${name}`
}

View File

@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist"
},
"include": ["./src"]
}

View File

@ -0,0 +1,40 @@
<h1 align="center">get-works</h1>
<p>
<img alt="Version" src="https://img.shields.io/badge/version-1.0.0-blue.svg?cacheSeconds=2592000" />
<a href="#" target="_blank">
<img alt="License: Apache--2.0" src="https://img.shields.io/badge/License-Apache--2.0-yellow.svg" />
</a>
</p>
> Check if the GET request for the given URL works
## Install
```sh
npm install --save get-works
```
## Usage
<!-- INSERT GENERATED DOCS START -->
### `getWorks` (function)
Check if the GET request for the given URL works
**Parameters:**
- url (`string`) - The given URL
**returns:** Promise<boolean>
<!-- INSERT GENERATED DOCS END -->
## 🤝 Contributing
You can sponsor my work here:
https://github.com/sponsors/aminya
Pull requests, issues and feature requests are welcome.
See the [Contributing guide](https://github.com/aminya/setup-cpp/blob/master/CONTRIBUTING.md).

View File

@ -0,0 +1,26 @@
{
"name": "get-works",
"version": "1.0.0",
"description": "Check if the GET request for the given URL works",
"homepage": "https://github.com/aminya/setup-cpp",
"license": "Apache-2.0",
"author": "Amin Yahyaabadi",
"main": "./dist/index.js",
"source": "./src/index.ts",
"scripts": {
"build": "tsc"
},
"dependencies": {
"root-tools": "workspace:*"
},
"keywords": [
"url",
"link",
"uri",
"working",
"check",
"alive",
"ok",
"broken"
]
}

View File

@ -1,6 +1,12 @@
import * as https from "https"
export function isValidUrl(url: string) {
/**
* Check if the GET request for the given URL works
*
* @param url The given URL
* @returns A promise that resolves to a boolean indicating if the URL works
*/
export function getWorks(url: string): Promise<boolean> {
return new Promise<boolean>((resolve) => {
https.get(url, (res) => {
if (res.statusCode !== undefined && res.statusCode >= 200 && res.statusCode <= 399) {

View File

@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist"
},
"include": ["./src"]
}

View File

@ -0,0 +1,76 @@
<h1 align="center">root-tools</h1>
<p>
<img alt="Version" src="https://img.shields.io/badge/version-1.0.0-blue.svg?cacheSeconds=2592000" />
<a href="#" target="_blank">
<img alt="License: Apache--2.0" src="https://img.shields.io/badge/License-Apache--2.0-yellow.svg" />
</a>
</p>
> Tools for working with root and sudo such as executing command as root, detecting root, etc.
## Install
```sh
npm install --save root-tools
```
## Usage
<!-- INSERT GENERATED DOCS START -->
### `isSudo` (function)
Detect if sudo is available and the user has root privileges
**returns:** boolean
### `isRoot` (function)
Detect if the process has root privileges
**returns:** boolean
### `prependSudo` (function)
Prepend `sudo` to the command if sudo is available
**Parameters:**
- command (`string`)
**returns:** string
### `execRootSync` (function)
Execute a command as root if sudo is available. Otherwise executes the command normally without sudo.
**Parameters:**
- program (`string`) - The program to spawn
- args (`string[]`) - The command arguments
- execOptions (`execa.SyncOptions`) - The options passed to `execa`. Defaults to `{ stdio: "inherit", shell: true }`
**returns:** execa.ExecaSyncReturnValue<string>
### `execRoot` (function)
Asynchronously execute a command as root if sudo is available. Otherwise executes the command normally without sudo.
**Parameters:**
- program (`string`) - The program to spawn
- args (`string[]`) - The command arguments
- execOptions (`execa.Options`) - The options passed to `execa`. Defaults to `{ stdio: "inherit", shell: true }`
**returns:** execa.ExecaChildProcess<string>
<!-- INSERT GENERATED DOCS END -->
## 🤝 Contributing
You can sponsor my work here:
https://github.com/sponsors/aminya
Pull requests, issues and feature requests are welcome.
See the [Contributing guide](https://github.com/aminya/setup-cpp/blob/master/CONTRIBUTING.md).

View File

@ -0,0 +1,41 @@
{
"name": "root-tools",
"version": "1.0.0",
"description": "Tools for working with root and sudo such as executing command as root, detecting root, etc.",
"homepage": "https://github.com/aminya/setup-cpp",
"license": "Apache-2.0",
"author": "Amin Yahyaabadi",
"main": "./dist/index.js",
"source": "./src/index.ts",
"scripts": {
"build": "tsc"
},
"dependencies": {
"execa": "^5.1.1",
"which": "^2.0.2"
},
"devDependencies": {
"@types/which": "^2.0.1"
},
"keywords": [
"sudo",
"root",
"is-root",
"is-sudo",
"exec-sudo",
"exec-root",
"isroot",
"issudo",
"exec",
"execa",
"spawn",
"system",
"unix",
"linux",
"github-actions",
"github",
"actions",
"gitlab",
"ci"
]
}

View File

@ -0,0 +1,60 @@
import which from "which"
import execa from "execa"
/** Detect if sudo is available and the user has root privileges */
export function isSudo(): boolean {
return (Boolean(process.env.CI) || isRoot()) && which.sync("sudo", { nothrow: true }) !== null
}
/** Detect if the process has root privileges */
export function isRoot(): boolean {
return process.getuid?.() === 0
}
/** Prepend `sudo` to the command if sudo is available */
export function prependSudo(command: string) {
if (isSudo()) {
return `sudo ${command}`
}
return command
}
/**
* Execute a command as root if sudo is available. Otherwise executes the command normally without sudo.
*
* @param program The program to spawn
* @param args The command arguments
* @param execOptions The options passed to `execa`. Defaults to `{ stdio: "inherit", shell: true }`
* @returns The execution result
*/
export function execRootSync(
program: string,
args: string[] = [],
execOptions: execa.SyncOptions = { stdio: "inherit", shell: true }
): execa.ExecaSyncReturnValue<string> {
if (isSudo()) {
return execa.commandSync(`sudo ${[program, ...args].map((arg) => `'${arg}'`).join(" ")}`, execOptions)
} else {
return execa.sync(program, args, execOptions)
}
}
/**
* Asynchronously execute a command as root if sudo is available. Otherwise executes the command normally without sudo.
*
* @param program The program to spawn
* @param args The command arguments
* @param execOptions The options passed to `execa`. Defaults to `{ stdio: "inherit", shell: true }`
* @returns A promise to the execution result
*/
export function execRoot(
program: string,
args: string[] = [],
execOptions: execa.Options = { stdio: "inherit", shell: true }
): execa.ExecaChildProcess<string> {
if (isSudo()) {
return execa.command(`sudo ${[program, ...args].map((arg) => `'${arg}'`).join(" ")}`, execOptions)
} else {
return execa(program, args, execOptions)
}
}

View File

@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist"
},
"include": ["./src"]
}

View File

@ -0,0 +1,38 @@
<h1 align="center">untildify-user</h1>
<p>
<img alt="Version" src="https://img.shields.io/badge/version-1.0.0-blue.svg?cacheSeconds=2592000" />
<a href="#" target="_blank">
<img alt="License: Apache--2.0" src="https://img.shields.io/badge/License-Apache--2.0-yellow.svg" />
</a>
</p>
> Untildify a path for the current user even if it is root
## Install
```sh
npm install --save untildify-user
```
## Usage
<!-- INSERT GENERATED DOCS START -->
### `untildifyUser` (function)
**Parameters:**
- path (`string`)
**returns:** any
<!-- INSERT GENERATED DOCS END -->
## 🤝 Contributing
You can sponsor my work here:
https://github.com/sponsors/aminya
Pull requests, issues and feature requests are welcome.
See the [Contributing guide](https://github.com/aminya/setup-cpp/blob/master/CONTRIBUTING.md).

View File

@ -0,0 +1,29 @@
{
"name": "untildify-user",
"version": "1.0.0",
"description": "Untildify a path for the current user even if it is root",
"homepage": "https://github.com/aminya/setup-cpp",
"license": "Apache-2.0",
"author": "Amin Yahyaabadi",
"main": "./dist/index.js",
"source": "./src/index.ts",
"scripts": {
"build": "tsc"
},
"dependencies": {
"root-tools": "workspace:*",
"untildify": "^4.0.0"
},
"keywords": [
"tilde",
"expansion",
"expand",
"untildify",
"path",
"home",
"directory",
"user",
"shell",
"bash"
]
}

View File

@ -1,9 +1,9 @@
import { join } from "path"
import untildify from "untildify"
import { isRoot } from "../env/sudo"
import { isSudo } from "root-tools"
export function untildify_user(path: string) {
if (isRoot() && typeof process.env.SUDO_USER === "string") {
export function untildifyUser(path: string) {
if (isSudo() && typeof process.env.SUDO_USER === "string") {
// use the user profile even if root
if (process.platform === "darwin") {
return join("/Users/", process.env.SUDO_USER, path)

View File

@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist"
},
"include": ["./src"]
}

View File

@ -0,0 +1,41 @@
<h1 align="center">user-access</h1>
<p>
<img alt="Version" src="https://img.shields.io/badge/version-1.0.0-blue.svg?cacheSeconds=2592000" />
<a href="#" target="_blank">
<img alt="License: Apache--2.0" src="https://img.shields.io/badge/License-Apache--2.0-yellow.svg" />
</a>
</p>
> Give user access to the given path
## Install
```sh
npm install --save user-access
```
## Usage
<!-- INSERT GENERATED DOCS START -->
### `giveUserAccess` (function)
Give the user access to the given path and its sub-directories. It changes the owner to the SUDO_USER. This allows
the user to use the folder without sudo
**Parameters:**
- path (`string`) - The path to give the user access to
**returns:** void
<!-- INSERT GENERATED DOCS END -->
## 🤝 Contributing
You can sponsor my work here:
https://github.com/sponsors/aminya
Pull requests, issues and feature requests are welcome.
See the [Contributing guide](https://github.com/aminya/setup-cpp/blob/master/CONTRIBUTING.md).

View File

@ -0,0 +1,29 @@
{
"name": "user-access",
"version": "1.0.0",
"description": "Give user access to the given path",
"homepage": "https://github.com/aminya/setup-cpp",
"license": "Apache-2.0",
"author": "Amin Yahyaabadi",
"main": "./dist/index.js",
"source": "./src/index.ts",
"scripts": {
"build": "tsc"
},
"dependencies": {
"root-tools": "workspace:*"
},
"keywords": [
"chown",
"recursive",
"user-access",
"user",
"access",
"path",
"fs",
"home",
"directory",
"shell",
"bash"
]
}

View File

@ -0,0 +1,17 @@
import { isSudo, execRootSync } from "root-tools"
/**
* Give the user access to the given path and its sub-directories. It changes the owner to the SUDO_USER. This allows
* the user to use the folder without sudo
*
* @param path The path to give the user access to
*/
export function giveUserAccess(path: string) {
if (
(process.platform === "linux" || process.platform === "darwin") &&
isSudo() &&
process.env.SUDO_USER !== undefined
) {
execRootSync("chown", ["-R", process.env.SUDO_USER, path], { cwd: path, stdio: "inherit", shell: true })
}
}

View File

@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist"
},
"include": ["./src"]
}

File diff suppressed because it is too large Load Diff

3
pnpm-workspace.yaml Normal file
View File

@ -0,0 +1,3 @@
packages:
- "./"
- "packages/*"

View File

@ -5,7 +5,7 @@ import { isArch } from "../utils/env/isArch"
import { hasDnf } from "../utils/env/hasDnf"
import { setupDnfPack } from "../utils/setup/setupDnfPack"
import { isUbuntu } from "../utils/env/isUbuntu"
import { execSudo } from "../utils/exec/sudo"
import { execRootSync } from "root-tools"
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export async function setupBazel(version: string, _setupDir: string, _arch: string) {
@ -24,7 +24,7 @@ export async function setupBazel(version: string, _setupDir: string, _arch: stri
} else if (hasDnf()) {
// https://bazel.build/install/redhat
setupDnfPack("dnf-plugins-core", undefined)
execSudo("dnf", ["copr", "enable", "vbatts/bazel"])
execRootSync("dnf", ["copr", "enable", "vbatts/bazel"])
return setupDnfPack("bazel4", undefined)
} else if (isUbuntu()) {
// https://bazel.build/install/ubuntu
@ -32,7 +32,7 @@ export async function setupBazel(version: string, _setupDir: string, _arch: stri
"bazel-archive-keyring.gpg",
"https://bazel.build/bazel-release.pub.gpg"
)
execSudo("bash", [
execRootSync("bash", [
"-c",
`echo "deb [arch=amd64 signed-by=${keyFileName}] https://storage.googleapis.com/bazel-apt stable jdk1.8" | tee /etc/apt/sources.list.d/bazel.list`,
])

View File

@ -1,6 +1,6 @@
import { setupCmake } from "../cmake"
import { setupTmpDir, cleanupTmpDir, testBin } from "../../utils/tests/test-helpers"
import { isGitHubCI } from "../../utils/env/isCI"
import ciDetect from "@npmcli/ci-detect"
import { getVersion } from "../../default_versions"
jest.setTimeout(300000)
@ -19,7 +19,7 @@ describe("setup-cmake", () => {
it("should find CMake in the cache", async () => {
const { binDir } = await setupCmake(getVersion("cmake", "true"), directory, process.arch)
await testBin("cmake", ["--version"], binDir)
if (isGitHubCI()) {
if (ciDetect() === "github-actions") {
expect(binDir).toMatch(process.env.RUNNER_TOOL_CACHE ?? "hostedtoolcache")
}
})

View File

@ -2,7 +2,7 @@ import { extractTar } from "@actions/tool-cache"
import semverLte from "semver/functions/lte"
import semverCoerce from "semver/functions/coerce"
import { setupBin, PackageInfo, InstallationInfo } from "../utils/setup/setupBin"
import { addBinExtension } from "../utils/extension/extension"
import { addBinExtension } from "extension-tools"
import { extractZip } from "../utils/setup/extract"
/** Get the platform data for cmake */

View File

@ -4,7 +4,7 @@ import { setupPacmanPack } from "../utils/setup/setupPacmanPack"
import { InstallationInfo, PackageInfo, setupBin } from "../utils/setup/setupBin"
import { setupBrewPack } from "../utils/setup/setupBrewPack"
import { setupChocoPack } from "../utils/setup/setupChocoPack"
import { addBinExtension } from "../utils/extension/extension"
import { addBinExtension } from "extension-tools"
import { extractTar, extractZip } from "../utils/setup/extract"
import { notice } from "../utils/io/io"
import { setupGraphviz } from "../graphviz/graphviz"

View File

@ -3,7 +3,7 @@ import { setupGcc } from "../gcc"
import { getVersion } from "../../default_versions"
import path from "path"
import execa from "execa"
import { addBinExtension } from "../../utils/extension/extension"
import { addBinExtension } from "extension-tools"
import { chmodSync } from "fs"
jest.setTimeout(3000000)

View File

@ -9,8 +9,8 @@ import semverCoerce from "semver/functions/coerce"
import { setupMacOSSDK } from "../macos-sdk/macos-sdk"
import path from "path"
import { warning, info } from "../utils/io/io"
import { isGitHubCI } from "../utils/env/isCI"
import { addBinExtension } from "../utils/extension/extension"
import ciDetect from "@npmcli/ci-detect"
import { addBinExtension } from "extension-tools"
import { InstallationInfo, PackageInfo, setupBin } from "../utils/setup/setupBin"
import { extract7Zip } from "../utils/setup/extract"
import { isArch } from "../utils/env/isArch"
@ -186,7 +186,7 @@ async function activateGcc(version: string, binDir: string) {
promises.push(setupMacOSSDK())
if (isGitHubCI()) {
if (ciDetect() === "github-actions") {
addGccLoggingMatcher()
}

View File

@ -39,7 +39,7 @@ describe("setup-Kcov", () => {
// it("should find Kcov in the cache", async () => {
// const binDir = await testKcov("v39", directory)
// if (isGitHubCI()) {
// if (ciDetect() === "github-actions") {
// expect(binDir).toMatch(process.env.RUNNER_TOOL_CACHE ?? "hostedtoolcache")
// }
// await cleanupTmpDir("kcov-v39")

View File

@ -3,7 +3,7 @@ import { join } from "path"
import which from "which"
import { setupCmake } from "../cmake/cmake"
import { getVersion } from "../default_versions"
import { addBinExtension } from "../utils/extension/extension"
import { addBinExtension } from "extension-tools"
import { extractTarByExe } from "../utils/setup/extract"
import { setupAptPack } from "../utils/setup/setupAptPack"
import { setupPacmanPack } from "../utils/setup/setupPacmanPack"
@ -14,7 +14,7 @@ import { setupDnfPack } from "../utils/setup/setupDnfPack"
import { isUbuntu } from "../utils/env/isUbuntu"
import { addVPrefix, removeVPrefix } from "../utils/setup/version"
import { info } from "../utils/io/io"
import { untildify_user } from "../utils/path/untildify"
import { untildifyUser } from "untildify-user"
import { setupNinja } from "../ninja/ninja"
function getDownloadKcovPackageInfo(version: string): PackageInfo {
@ -61,7 +61,7 @@ async function buildKcov(file: string, dest: string) {
stdio: "inherit",
})
await execa(cmake, ["--build", buildDir, "--config", "Release"], { cwd: out, stdio: "inherit" })
// execSudo(cmake, ["--install", buildDir], out)
// execRootSync(cmake, ["--install", buildDir], out)
// return "user/local/bin" // the cmake install prefix
return out
}
@ -69,12 +69,12 @@ async function buildKcov(file: string, dest: string) {
async function getCmake() {
let cmake = which.sync("cmake", { nothrow: true })
if (cmake === null) {
const { binDir } = await setupCmake(getVersion("cmake", undefined), join(untildify_user(""), "cmake"), "")
const { binDir } = await setupCmake(getVersion("cmake", undefined), join(untildifyUser(""), "cmake"), "")
cmake = join(binDir, "cmake")
}
const ninja = which.sync("ninja", { nothrow: true })
if (ninja === null) {
await setupNinja(getVersion("ninja", undefined), join(untildify_user(""), "ninja"), "")
await setupNinja(getVersion("ninja", undefined), join(untildifyUser(""), "ninja"), "")
}
return cmake
}

View File

@ -1,11 +1,11 @@
import { setupLLVM, VERSIONS, getUrl, setupClangTools, getLinuxUrl } from "../llvm"
import { getSpecificVersionAndUrl } from "../../utils/setup/version"
import { isValidUrl } from "../../utils/http/validate_url"
import { getWorks } from "get-works"
import { setupTmpDir, cleanupTmpDir, testBin } from "../../utils/tests/test-helpers"
import { isGitHubCI } from "../../utils/env/isCI"
import ciDetect from "@npmcli/ci-detect"
import execa from "execa"
import path from "path"
import { addBinExtension } from "../../utils/extension/extension"
import { addBinExtension } from "extension-tools"
import { chmodSync } from "fs"
import { getVersion } from "../../default_versions"
import { ubuntuVersion } from "../../utils/env/ubuntu_version"
@ -14,7 +14,7 @@ jest.setTimeout(400000)
async function testUrl(version: string) {
const [specificVersion, url] = await getSpecificVersionAndUrl(VERSIONS, process.platform, version, getUrl)
if (!(await isValidUrl(url))) {
if (!(await getWorks(url))) {
throw new Error(`Failed to install Version: ${version} => ${specificVersion} \n URL: ${url}`)
}
}
@ -101,7 +101,7 @@ describe("setup-llvm", () => {
const { binDir } = await setupLLVM(getVersion("llvm", "true", osVersion), directory, process.arch)
await testBin("clang++", ["--version"], binDir)
if (isGitHubCI() && process.platform !== "linux") {
if (ciDetect() === "github-actions" && process.platform !== "linux") {
expect(binDir).toMatch(process.env.RUNNER_TOOL_CACHE ?? "hostedtoolcache")
// TODO returns the install dir on linux
}
@ -109,7 +109,7 @@ describe("setup-llvm", () => {
expect(process.env.CC?.includes("clang")).toBeTruthy()
expect(process.env.CXX?.includes("clang++")).toBeTruthy()
if (isGitHubCI() && process.platform !== "linux") {
if (ciDetect() === "github-actions" && process.platform !== "linux") {
expect(process.env.CC).toMatch("hostedtoolcache")
expect(process.env.CXX).toMatch("hostedtoolcache")
}

View File

@ -1,7 +1,7 @@
import * as path from "path"
import semverLte from "semver/functions/lte"
import semverMajor from "semver/functions/major"
import { isValidUrl } from "../utils/http/validate_url"
import { getWorks } from "get-works"
import { InstallationInfo, PackageInfo, setupBin } from "../utils/setup/setupBin"
import { extractExe, extractTarByExe } from "../utils/setup/extract"
import {
@ -11,13 +11,13 @@ import {
semverCoerceIfInvalid,
} from "../utils/setup/version"
import { setupMacOSSDK } from "../macos-sdk/macos-sdk"
import { addBinExtension } from "../utils/extension/extension"
import { addBinExtension } from "extension-tools"
import { addEnv } from "../utils/env/addEnv"
import { setOutput } from "@actions/core"
import { setupAptPack, updateAptAlternatives } from "../utils/setup/setupAptPack"
import { info, warning } from "../utils/io/io"
import { existsSync } from "fs"
import { isGitHubCI } from "../utils/env/isCI"
import ciDetect from "@npmcli/ci-detect"
import { setupGcc } from "../gcc/gcc"
import { getVersion } from "../default_versions"
import { isArch } from "../utils/env/isArch"
@ -231,7 +231,7 @@ async function getWin32Url(version: string): Promise<string | null> {
let fallback = false
if (olderThan9_1) {
url = getReleaseUrl(version, prefix, suffix)
if (!(await isValidUrl(url))) {
if (!(await getWorks(url))) {
fallback = true // fallback to github
}
}
@ -353,7 +353,7 @@ export async function activateLLVM(directory: string, versionGiven: string) {
updateAptAlternatives("llvm-ar", `${directory}/bin/llvm-ar`)
}
if (isGitHubCI()) {
if (ciDetect() === "github-actions") {
addLLVMLoggingMatcher()
}
@ -362,7 +362,7 @@ export async function activateLLVM(directory: string, versionGiven: string) {
/** Setup llvm tools (clang tidy, clang format, etc) without activating llvm and using it as the compiler */
export function setupClangTools(version: string, setupDir: string, arch: string): Promise<InstallationInfo> {
if (isGitHubCI()) {
if (ciDetect() === "github-actions") {
addLLVMLoggingMatcher()
}
return _setupLLVM(version, setupDir, arch)

View File

@ -16,8 +16,8 @@ import { setupNinja } from "./ninja/ninja"
import { setupOpencppcoverage } from "./opencppcoverage/opencppcoverage"
import { setupPython } from "./python/python"
import mri from "mri"
import { untildify_user as untildify } from "./utils/path/untildify"
import { isGitHubCI } from "./utils/env/isCI"
import { untildifyUser } from "untildify-user"
import ciDetect from "@npmcli/ci-detect"
import * as timeDelta from "time-delta"
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
@ -113,7 +113,7 @@ const inputs: Array<Inputs> = ["compiler", "architecture", ...tools]
/** The main entry function */
export async function main(args: string[]): Promise<number> {
if (!isGitHubCI()) {
if (ciDetect() !== "github-actions") {
process.env.ACTIONS_ALLOW_UNSECURE_COMMANDS = "true"
}
@ -129,7 +129,7 @@ export async function main(args: string[]): Promise<number> {
const arch = opts.architecture ?? process.arch
// the installation dir for the tools that are downloaded directly
const setupCppDir = process.env.SETUP_CPP_DIR ?? untildify("")
const setupCppDir = process.env.SETUP_CPP_DIR ?? untildifyUser("")
// report messages
const successMessages: string[] = []
@ -281,7 +281,7 @@ export async function main(args: string[]): Promise<number> {
info("setup_cpp finished")
if (!isGitHubCI()) {
if (ciDetect() !== "github-actions") {
switch (process.platform) {
case "win32": {
warning("Run `RefreshEnv.cmd` or restart your shell to update the environment.")

View File

@ -3,7 +3,7 @@ import { setupVCVarsall } from "../vcvarsall/vcvarsall"
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import { vsversion_to_versionnumber, findVcvarsall } from "msvc-dev-cmd/lib.js"
import { isGitHubCI } from "../utils/env/isCI"
import ciDetect from "@npmcli/ci-detect"
import path from "path"
import { existsSync } from "fs"
import { error, info, warning } from "../utils/io/io"
@ -65,7 +65,7 @@ export async function setupMSVC(
// run vcvarsall.bat environment variables
await setupVCVarsall(version, VCTargetsPath, arch, toolset, sdk, uwp, spectre)
if (isGitHubCI()) {
if (ciDetect() === "github-actions") {
addMSVCLoggingMatcher()
}
}

View File

@ -1,7 +1,7 @@
import { dirname } from "path"
import which from "which"
import { isUbuntu } from "../utils/env/isUbuntu"
import { execSudo } from "../utils/exec/sudo"
import { execRootSync } from "root-tools"
import { addAptKeyViaDownload, setupAptPack } from "../utils/setup/setupAptPack"
let binDir: string | undefined
@ -26,7 +26,7 @@ export async function setupNala(version: string, _setupDir: string, _arch: strin
"volian-archive-scar-unstable.gpg",
"https://deb.volian.org/volian/scar.key"
)
execSudo("/bin/bash", [
execRootSync("/bin/bash", [
"-c",
`echo "deb [signed-by=${keyFileName}] http://deb.volian.org/volian/ scar main" | tee /etc/apt/sources.list.d/volian-archive-scar-unstable.list`,
])

View File

@ -1,6 +1,6 @@
import { setupNinja } from "../ninja"
import { setupTmpDir, cleanupTmpDir, testBin } from "../../utils/tests/test-helpers"
import { isGitHubCI } from "../../utils/env/isCI"
import ciDetect from "@npmcli/ci-detect"
import { getVersion } from "../../default_versions"
jest.setTimeout(300000)
@ -22,7 +22,7 @@ describe("setup-ninja", () => {
it("should find Ninja in the cache", async () => {
const binDir = await testNinja(directory)
if (isGitHubCI()) {
if (ciDetect() === "github-actions") {
expect(binDir).toMatch(process.env.RUNNER_TOOL_CACHE ?? "hostedtoolcache")
}
})

View File

@ -1,4 +1,4 @@
import { addBinExtension } from "../utils/extension/extension"
import { addBinExtension } from "extension-tools"
import { extractZip } from "../utils/setup/extract"
import { setupBin, PackageInfo, InstallationInfo } from "../utils/setup/setupBin"

View File

@ -2,7 +2,7 @@ import { setupPython } from "../python"
import { cleanupTmpDir, setupTmpDir, testBin } from "../../utils/tests/test-helpers"
import { getVersion } from "../../default_versions"
import { ubuntuVersion } from "../../utils/env/ubuntu_version"
import { isGitHubCI } from "../../utils/env/isCI"
import ciDetect from "@npmcli/ci-detect"
import { info } from "../../utils/io/io"
jest.setTimeout(300000)
@ -13,7 +13,7 @@ describe("setup-python", () => {
})
it("should setup python in GitHub Actions", async () => {
if (isGitHubCI()) {
if (ciDetect() === "github-actions") {
info("Installing python in GitHub Actions")
const { setupActionsPython } = await import("../actions_python")
await setupActionsPython(getVersion("python", "true", await ubuntuVersion()), directory, process.arch)

View File

@ -4,7 +4,7 @@ import { existsSync } from "fs"
import { info, warning } from "../utils/io/io"
import { debug } from "@actions/core"
import path from "path"
import { isGitHubCI } from "../utils/env/isCI"
import ciDetect from "@npmcli/ci-detect"
import { isCacheFeatureAvailable, IS_LINUX, IS_WINDOWS } from "setup-python/src/utils"
import { getCacheDistributor } from "setup-python/src/cache-distributions/cache-factory"
@ -72,7 +72,7 @@ export async function setupActionsPython(version: string, _setupDir: string, arc
}
}
if (isGitHubCI()) {
if (ciDetect() === "github-actions") {
addPythonLoggingMatcher()
}

View File

@ -3,7 +3,7 @@ import { setupAptPack } from "../utils/setup/setupAptPack"
import { setupPacmanPack } from "../utils/setup/setupPacmanPack"
import { setupBrewPack } from "../utils/setup/setupBrewPack"
import { setupChocoPack } from "../utils/setup/setupChocoPack"
import { isGitHubCI } from "../utils/env/isCI"
import ciDetect from "@npmcli/ci-detect"
import { warning, info } from "../utils/io/io"
import { isArch } from "../utils/env/isArch"
import which from "which"
@ -14,7 +14,7 @@ import { setupDnfPack } from "../utils/setup/setupDnfPack"
import { isUbuntu } from "../utils/env/isUbuntu"
export async function setupPython(version: string, setupDir: string, arch: string) {
if (!isGitHubCI()) {
if (ciDetect() !== "github-actions") {
// TODO parse version
return setupPythonViaSystem(version, setupDir, arch)
}

View File

@ -1,6 +1,6 @@
import { setupTask } from "../task"
import { cleanupTmpDir, setupTmpDir, testBin } from "../../utils/tests/test-helpers"
import { isGitHubCI } from "../../utils/env/isCI"
import ciDetect from "@npmcli/ci-detect"
import { getVersion } from "../../default_versions"
jest.setTimeout(300000)
@ -18,7 +18,7 @@ describe("setup-task", () => {
it("should find task in the cache", async () => {
const { binDir } = await setupTask(getVersion("task", "true"), directory, process.arch)
if (isGitHubCI()) {
if (ciDetect() === "github-actions") {
expect(binDir).toMatch(process.env.RUNNER_TOOL_CACHE ?? "hostedtoolcache")
}
})

View File

@ -1,4 +1,4 @@
import { addBinExtension } from "../utils/extension/extension"
import { addBinExtension } from "extension-tools"
import { extractTarByExe, extractZip } from "../utils/setup/extract"
import { setupBin, PackageInfo, InstallationInfo } from "../utils/setup/setupBin"

View File

@ -1,17 +1,21 @@
import { exportVariable, addPath as ghAddPath, info, setFailed } from "@actions/core"
import { isGitHubCI } from "./isCI"
import { untildify_user as untildify } from "../path/untildify"
import ciDetect from "@npmcli/ci-detect"
import { untildifyUser } from "untildify-user"
import { appendFileSync, existsSync, readFileSync } from "fs"
import { error, warning } from "../io/io"
import { execPowershell } from "../exec/powershell"
import { execPowershell } from "exec-powershell"
import { delimiter } from "path"
import { escapeSpace } from "../path/escape_space"
import escapeSpace from "escape-path-with-spaces"
/** An add path function that works locally or inside GitHub Actions */
/**
* Add an environment variable.
*
* This function is cross-platforms and works in all the local or CI systems.
*/
export async function addEnv(name: string, valGiven: string | undefined, shouldEscapeSpace: boolean = false) {
const val = shouldEscapeSpace ? escapeSpace(valGiven) : valGiven
const val = shouldEscapeSpace ? escapeSpace(valGiven ?? "") : valGiven
try {
if (isGitHubCI()) {
if (ciDetect() === "github-actions") {
try {
exportVariable(name, val)
} catch (err) {
@ -27,11 +31,15 @@ export async function addEnv(name: string, valGiven: string | undefined, shouldE
}
}
/** An add path function that works locally or inside GitHub Actions */
/**
* Add a path to the PATH environment variable.
*
* This function is cross-platforms and works in all the local or CI systems.
*/
export async function addPath(path: string) {
process.env.PATH = `${path}${delimiter}${process.env.PATH}`
try {
if (isGitHubCI()) {
if (ciDetect() === "github-actions") {
try {
ghAddPath(path)
} catch (err) {
@ -47,7 +55,7 @@ export async function addPath(path: string) {
}
}
export const cpprc_path = untildify(".cpprc")
export const cpprc_path = untildifyUser(".cpprc")
async function addEnvSystem(name: string, valGiven: string | undefined) {
const val = valGiven ?? ""
@ -121,12 +129,12 @@ export function setupCppInProfile() {
try {
// source cpprc in .profile
const profile_path = untildify(".profile")
const profile_path = untildifyUser(".profile")
appendFileSync(profile_path, source_cpprc_string)
info(`${source_cpprc_string} was added to ${profile_path}`)
// source cpprc in .bashrc too
const bashrc_path = untildify(".bashrc")
const bashrc_path = untildifyUser(".bashrc")
appendFileSync(bashrc_path, source_cpprc_string)
info(`${source_cpprc_string} was added to ${bashrc_path}`)
} catch (err) {

View File

@ -1,7 +0,0 @@
export function isCI() {
return process.env.CI === "true"
}
export function isGitHubCI() {
return isCI() && process.env.GITHUB_ACTIONS === "true"
}

19
src/utils/env/sudo.ts vendored
View File

@ -1,19 +0,0 @@
import which from "which"
let _issudo: boolean | undefined = undefined
export function isRoot(): boolean {
if (_issudo !== undefined) {
return _issudo
}
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions, @typescript-eslint/no-unnecessary-condition
_issudo = (Boolean(process.env.CI) || process.getuid?.() === 0) && which.sync("sudo", { nothrow: true }) !== null
return _issudo
}
export function mightSudo(command: string) {
if (isRoot()) {
return `sudo ${command}`
}
return command
}

View File

@ -1,25 +0,0 @@
import execa from "execa"
import which from "which"
let powershell: string | undefined
export function execPowershell(command: string, startupFlags: string[] = ["-NoProfile", "-NoLogo", "-NonInteractive"]) {
return execa(getPowerShell(), [...startupFlags, "-c", command], { stdio: "inherit" })
}
function getPowerShell() {
if (powershell === undefined) {
const maybePwsh = which.sync("pwsh", { nothrow: true })
if (maybePwsh !== null) {
powershell = maybePwsh
}
const maybePowerShell = which.sync("powershell", { nothrow: true })
if (maybePowerShell !== null) {
powershell = maybePowerShell
}
}
if (powershell === undefined) {
throw new Error("Could not find powershell")
}
return powershell
}

View File

@ -1,14 +0,0 @@
import execa from "execa"
import { isRoot } from "../env/sudo"
export function execSudo(file: string, args: string[], cwd?: string) {
if (isRoot()) {
return execa.commandSync(`sudo ${[file, ...args].map((arg) => `'${arg}'`).join(" ")}`, {
shell: true,
cwd,
stdio: "inherit",
})
} else {
return execa.sync(file, args, { stdio: "inherit" })
}
}

View File

@ -1,23 +0,0 @@
/** Add bin extension to a binary. This will be `.exe` on Windows. */
export function addBinExtension(name: string) {
if (process.platform === "win32") {
return `${name}.exe`
}
return name
}
/** Add native shell extension. This will be `.bat` on Windows and `sh` on unix. */
export function addShellExtension(name: string) {
if (process.platform === "win32") {
return `${name}.bat`
}
return `${name}.sh`
}
/** Add ./ for unix shell */
export function addShellHere(name: string) {
if (process.platform === "win32") {
return name
}
return `./${name}`
}

View File

@ -1,13 +0,0 @@
import { isRoot } from "../env/sudo"
import { execSudo } from "../exec/sudo"
/// change the owner to the SUDO_USER. This is required so the user can use the folder without sudo
export function folderUserAccess(folder: string) {
if (
(process.platform === "linux" || process.platform === "darwin") &&
isRoot() &&
process.env.SUDO_USER !== undefined
) {
execSudo("chown", ["-R", process.env.SUDO_USER, folder], folder)
}
}

View File

@ -1,8 +1,8 @@
import * as core from "@actions/core"
import { isGitHubCI } from "../env/isCI"
import ciDetect from "@npmcli/ci-detect"
export function error(err: string | Error) {
return isGitHubCI() ? core.error(err) : console.log(`\x1b[31m${err}\x1b[0m`)
return ciDetect() === "github-actions" ? core.error(err) : console.log(`\x1b[31m${err}\x1b[0m`)
}
export function success(msg: string) {
@ -10,13 +10,13 @@ export function success(msg: string) {
}
export function warning(msg: string) {
return isGitHubCI() ? core.warning(msg) : console.log(`\x1b[33m${msg}\x1b[0m`)
return ciDetect() === "github-actions" ? core.warning(msg) : console.log(`\x1b[33m${msg}\x1b[0m`)
}
export function notice(msg: string) {
return isGitHubCI() ? core.notice(msg) : console.log(`\x1b[94m${msg}\x1b[0m`)
return ciDetect() === "github-actions" ? core.notice(msg) : console.log(`\x1b[94m${msg}\x1b[0m`)
}
export function info(msg: string) {
return isGitHubCI() ? core.info(msg) : console.log(msg)
return ciDetect() === "github-actions" ? core.info(msg) : console.log(msg)
}

View File

@ -1,11 +0,0 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import escape from "escape-path-with-spaces"
/// Escape the spaces in the given path
export function escapeSpace(path: string | undefined): string {
if (path === undefined) {
return ""
}
return escape(path)
}

View File

@ -3,7 +3,7 @@ import { mkdirP } from "@actions/io"
import which from "which"
import { setupSevenZip } from "../../sevenzip/sevenzip"
import { warning } from "../io/io"
import { folderUserAccess } from "../fs/userAccess"
import { giveUserAccess } from "user-access"
export { extractTar, extractXar } from "@actions/tool-cache"
let sevenZip: string | undefined
@ -11,7 +11,7 @@ let sevenZip: string | undefined
/// Extract 7z using 7z
export async function extract7Zip(file: string, dest: string) {
await execa(await getSevenZip(), ["x", file, `-o${dest}`, "-y"], { stdio: "inherit" })
folderUserAccess(dest)
giveUserAccess(dest)
return dest
}
@ -55,6 +55,6 @@ export async function extractTarByExe(file: string, dest: string, flags = ["--st
}
}
folderUserAccess(dest)
giveUserAccess(dest)
return dest
}

View File

@ -1,8 +1,8 @@
/* eslint-disable require-atomic-updates */
import { InstallationInfo } from "./setupBin"
import { execSudo } from "../exec/sudo"
import { execRootSync } from "root-tools"
import { info } from "@actions/core"
import { isGitHubCI } from "../env/isCI"
import ciDetect from "@npmcli/ci-detect"
import { addEnv, cpprc_path, setupCppInProfile } from "../env/addEnv"
import { appendFileSync, existsSync } from "fs"
import which from "which"
@ -36,19 +36,19 @@ export async function setupAptPack(
if (Array.isArray(repositories) && repositories.length !== 0) {
for (const repo of repositories) {
// eslint-disable-next-line no-await-in-loop
execSudo("add-apt-repository", ["--update", "-y", repo])
execRootSync("add-apt-repository", ["--update", "-y", repo])
}
updateRepos(apt)
}
if (version !== undefined && version !== "") {
try {
execSudo(apt, ["install", "--fix-broken", "-y", `${name}=${version}`])
execRootSync(apt, ["install", "--fix-broken", "-y", `${name}=${version}`])
} catch {
execSudo(apt, ["install", "--fix-broken", "-y", `${name}-${version}`])
execRootSync(apt, ["install", "--fix-broken", "-y", `${name}-${version}`])
}
} else {
execSudo(apt, ["install", "--fix-broken", "-y", name])
execRootSync(apt, ["install", "--fix-broken", "-y", name])
}
return { binDir: "/usr/bin/" }
@ -65,12 +65,12 @@ function getApt() {
}
function updateRepos(apt: string) {
execSudo(apt, apt !== "nala" ? ["update", "-y"] : ["update"])
execRootSync(apt, apt !== "nala" ? ["update", "-y"] : ["update"])
}
/** Install apt utils and certificates (usually missing from docker containers) */
async function initApt(apt: string) {
execSudo(apt, [
execRootSync(apt, [
"install",
"--fix-broken",
"-y",
@ -89,7 +89,7 @@ async function initApt(apt: string) {
}
function initGpg() {
execSudo("gpg", ["-k"])
execRootSync("gpg", ["-k"])
}
export function addAptKeyViaServer(keys: string[], name: string, server = "keyserver.ubuntu.com") {
@ -97,7 +97,7 @@ export function addAptKeyViaServer(keys: string[], name: string, server = "keyse
if (!existsSync(fileName)) {
initGpg()
for (const key of keys) {
execSudo("gpg", [
execRootSync("gpg", [
"--no-default-keyring",
"--keyring",
`gnupg-ring:${fileName}`,
@ -106,7 +106,7 @@ export function addAptKeyViaServer(keys: string[], name: string, server = "keyse
"--recv-keys",
key,
])
execSudo("chmod", ["644", fileName])
execRootSync("chmod", ["644", fileName])
}
}
return fileName
@ -117,15 +117,15 @@ export async function addAptKeyViaDownload(name: string, url: string) {
if (!existsSync(fileName)) {
initGpg()
await setupAptPack("curl", undefined)
execSudo("bash", ["-c", `curl -s ${url} | gpg --no-default-keyring --keyring gnupg-ring:${fileName} --import`])
execSudo("chmod", ["644", fileName])
execRootSync("bash", ["-c", `curl -s ${url} | gpg --no-default-keyring --keyring gnupg-ring:${fileName} --import`])
execRootSync("chmod", ["644", fileName])
}
return fileName
}
export function updateAptAlternatives(name: string, path: string) {
if (isGitHubCI()) {
return execSudo("update-alternatives", ["--install", `/usr/bin/${name}`, name, path, "40"])
if (ciDetect() === "github-actions") {
return execRootSync("update-alternatives", ["--install", `/usr/bin/${name}`, name, path, "40"])
} else {
setupCppInProfile()
return appendFileSync(

View File

@ -4,7 +4,7 @@ import { addPath } from "../env/addEnv"
import { join } from "path"
import { existsSync } from "fs"
import { tmpdir } from "os"
import { isGitHubCI } from "../env/isCI"
import ciDetect from "@npmcli/ci-detect"
import { setupAptPack } from "./setupAptPack"
import { setupPacmanPack } from "./setupPacmanPack"
import { isArch } from "../env/isArch"
@ -64,7 +64,7 @@ export async function setupBin(
)
// Restore from cache (if found).
if (isGitHubCI()) {
if (ciDetect() === "github-actions") {
try {
const dir = find(name, version)
if (dir) {
@ -129,7 +129,7 @@ export async function setupBin(
await addPath(binDir)
// check if inside Github Actions. If so, cache the installation
if (isGitHubCI() && typeof process.env.RUNNER_TOOL_CACHE === "string") {
if (ciDetect() === "github-actions" && typeof process.env.RUNNER_TOOL_CACHE === "string") {
await cacheDir(setupDir, name, version)
}

View File

@ -1,6 +1,6 @@
/* eslint-disable require-atomic-updates */
import { InstallationInfo } from "./setupBin"
import { execSudo } from "../exec/sudo"
import { execRootSync } from "root-tools"
import { info, warning } from "../io/io"
// let didUpdate: boolean = false
@ -12,19 +12,19 @@ export function setupDnfPack(name: string, version?: string): InstallationInfo {
const dnf = "dnf"
// if (!didUpdate) {
// execSudo(dnf, ["-y", "check-update"])
// execRootSync(dnf, ["-y", "check-update"])
// didUpdate = true
// }
if (version !== undefined && version !== "") {
try {
execSudo(dnf, ["-y", "install", `${name}-${version}`])
execRootSync(dnf, ["-y", "install", `${name}-${version}`])
} catch (err) {
warning(`${(err as Error).toString()}\nInstalling the default version available via dnf`)
execSudo(dnf, ["-y", "install", name])
execRootSync(dnf, ["-y", "install", name])
}
} else {
execSudo(dnf, ["-y", "install", name])
execRootSync(dnf, ["-y", "install", name])
}
return { binDir: "/usr/bin/" }

View File

@ -1,6 +1,6 @@
/* eslint-disable require-atomic-updates */
import { InstallationInfo } from "./setupBin"
import { execSudo } from "../exec/sudo"
import { execRootSync } from "root-tools"
import { info } from "../io/io"
let didUpdate: boolean = false
@ -13,24 +13,24 @@ export function setupPacmanPack(name: string, version?: string, aur?: string): I
const pacman = "pacman"
if (!didUpdate) {
execSudo(pacman, ["-Syuu", "--noconfirm"])
execRootSync(pacman, ["-Syuu", "--noconfirm"])
didUpdate = true
}
if (!didInit) {
// install base-devel
execSudo(pacman, ["-Sy", "--noconfirm", "base-devel"])
execRootSync(pacman, ["-Sy", "--noconfirm", "base-devel"])
didInit = true
}
if (version !== undefined && version !== "") {
try {
execSudo(aur ?? pacman, ["-S", "--noconfirm", `${name}=${version}`])
execRootSync(aur ?? pacman, ["-S", "--noconfirm", `${name}=${version}`])
} catch {
execSudo(aur ?? pacman, ["-S", "--noconfirm", `${name}${version}`])
execRootSync(aur ?? pacman, ["-S", "--noconfirm", `${name}${version}`])
}
} else {
execSudo(aur ?? pacman, ["-S", "--noconfirm", name])
execRootSync(aur ?? pacman, ["-S", "--noconfirm", name])
}
return { binDir: "/usr/bin/" }

View File

@ -1,4 +1,4 @@
import { isValidUrl } from "../http/validate_url"
import { getWorks } from "get-works"
import semverCompare from "semver/functions/compare"
import semverCoerce from "semver/functions/coerce"
import semverValid from "semver/functions/valid"
@ -42,7 +42,7 @@ export async function getSpecificVersionAndUrl(
if (platform === "linux" && version.includes("ubuntu")) {
const url = await getUrl(platform, version)
// eslint-disable-next-line no-await-in-loop
if (url !== null && (await isValidUrl(url))) {
if (url !== null && (await getWorks(url))) {
return [version, url]
}
}
@ -55,7 +55,7 @@ export async function getSpecificVersionAndUrl(
// eslint-disable-next-line no-await-in-loop
const url = await getUrl(platform, specificVersion)
// eslint-disable-next-line no-await-in-loop
if (url !== null && (await isValidUrl(url))) {
if (url !== null && (await getWorks(url))) {
return [specificVersion, url]
}
}

View File

@ -1,7 +1,7 @@
import * as io from "@actions/io"
import { tmpdir } from "os"
import * as path from "path"
import { addBinExtension } from "../extension/extension"
import { addBinExtension } from "extension-tools"
import { join } from "path"
import spawn from "cross-spawn"
import { existsSync } from "fs"

View File

@ -3,7 +3,7 @@ import { existsSync } from "fs"
import { dirname, join } from "path"
import which from "which"
import { addPath } from "../utils/env/addEnv"
import { addShellExtension, addShellHere } from "../utils/extension/extension"
import { addShellExtension, addShellHere } from "extension-tools"
import { notice } from "../utils/io/io"
import { setupAptPack } from "../utils/setup/setupAptPack"
import { setupPacmanPack } from "../utils/setup/setupPacmanPack"
@ -12,7 +12,7 @@ import { isArch } from "../utils/env/isArch"
import { hasDnf } from "../utils/env/hasDnf"
import { setupDnfPack } from "../utils/setup/setupDnfPack"
import { isUbuntu } from "../utils/env/isUbuntu"
import { folderUserAccess } from "../utils/fs/userAccess"
import { giveUserAccess } from "user-access"
let hasVCPKG = false
@ -53,7 +53,7 @@ export async function setupVcpkg(_version: string, setupDir: string, _arch: stri
execa.sync(addShellExtension(addShellHere("bootstrap-vcpkg")), { cwd: setupDir, shell: true, stdio: "inherit" })
folderUserAccess(setupDir)
giveUserAccess(setupDir)
await addPath(setupDir)
// eslint-disable-next-line require-atomic-updates

View File

@ -17,8 +17,8 @@
"preserveSymlinks": true,
"removeComments": false,
"skipLibCheck": false,
"lib": ["ES2018", "dom"],
"target": "ES2018",
"lib": ["ES2020", "dom"],
"target": "ES2020",
"allowJs": true,
"esModuleInterop": true,
"resolveJsonModule": true,
@ -28,5 +28,5 @@
"outDir": "./dist"
},
"compileOnSave": false,
"include": ["./src"]
"include": ["./src", "packages/untildify-user/untildify.ts"]
}