haoshoku 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/publish-to-npm.yml +32 -0
- package/README.md +85 -0
- package/bun.lock +25 -0
- package/common/flatpacks_arch.txt +4 -0
- package/common/paru_applist.txt +52 -0
- package/configs/__init__.py +1 -0
- package/configs/alacritty/alacritty.toml +5 -0
- package/configs/fastfetch/config.jsonc +160 -0
- package/configs/fish/config.fish +66 -0
- package/configs/ghostty/config +6 -0
- package/configs/kde_shortcuts.kksrc +368 -0
- package/configs/kitty/kitty.conf +41 -0
- package/configs/vencord/trans.theme.css +90 -0
- package/deskback/20250228_234138~2.jpg +0 -0
- package/deskback/32977-1920x1080-desktop-full-hd-the-garden-of-words-wallpaper-photo.jpg +0 -0
- package/deskback/a_spring_night_by_bisbiswas_deekkf0.jpg +0 -0
- package/deskback/adia___east_hallegian_aurorae_by_rajavlitra_dasfxtu.png +0 -0
- package/deskback/anew_beginning_by_thekayeman_ddyp7ti.jpg +0 -0
- package/deskback/arachnophobia_by_bisbiswas_detjqyf.jpg +0 -0
- package/deskback/arise_by_bisbiswas_ddwcnjg.jpg +0 -0
- package/deskback/aurora_borealis__by_xxartymusexx_ddzt4e0.jpg +0 -0
- package/deskback/aurora_borealis_by_gaudibuendia_dajesxg.jpg +0 -0
- package/deskback/aurora_borealis_by_sephiroth_art_dawxmlz.jpg +0 -0
- package/deskback/aurora_by_rav89_dau22zv.jpg +0 -0
- package/deskback/aurora_lights_by_bisbiswas_dedov93.jpg +0 -0
- package/deskback/aurora_lights_by_bisbiswas_dedov93~3.jpg +0 -0
- package/deskback/bizarre_winter_night_by_bisbiswas_dfnsfxe.jpg +0 -0
- package/deskback/blazing_moon_by_bisbiswas_def6rgz.jpg +0 -0
- package/deskback/burning_tower_by_bisbiswas_dfciho6.jpg +0 -0
- package/deskback/christmas_night_commissioned__by_bisbiswas_deb2fgh.jpg +0 -0
- package/deskback/cold_night_drive_by_bisbiswas_dfqw4ev.jpg +0 -0
- package/deskback/creature_of_fantasyland_by_bisbiswas_dgjrpn6.jpg +0 -0
- package/deskback/crossing_road_by_bisbiswas_deksqsf.jpg +0 -0
- package/deskback/d9gpwju-04121643-6c14-4503-b2e3-60995901caf9.jpg +0 -0
- package/deskback/dreamy_night_by_bisbiswas_deaka30.jpg +0 -0
- package/deskback/emerald_moon_by_bisbiswas_demugqf.jpg +0 -0
- package/deskback/free_use_background__nebula__5400_by_ted_drakness_dfqq9bd.jpg +0 -0
- package/deskback/happy_new_year_2023_by_bisbiswas_dfly13l.jpg +0 -0
- package/deskback/hidden_between_the_mountans_by_bisbiswas_dhkgcji.jpg +0 -0
- package/deskback/long_night_drive_by_bisbiswas_defo5d1.jpg +0 -0
- package/deskback/magical_hour__commissioned__by_bisbiswas_dfi6fz5.jpg +0 -0
- package/deskback/magical_meteor_night1_by_bisbiswas_dfwosp2.jpg +0 -0
- package/deskback/melstrom_by_thekayeman_de0z6em.jpg +0 -0
- package/deskback/mermaid_s_arrival_by_bisbiswas_deko21g.jpg +0 -0
- package/deskback/meteor_shower_by_bisbiswas_deogvao.jpg +0 -0
- package/deskback/midnight_train_by_bisbiswas_dengl62.jpg +0 -0
- package/deskback/nebula_of_solitude_by_thekayeman_dedfpmk.jpg +0 -0
- package/deskback/night_lights_by_bisbiswas_de3gb5p.jpg +0 -0
- package/deskback/night_mirror_by_clearvector_d4s66cp.png +0 -0
- package/deskback/night_rider_by_bisbiswas_deiy9z0.jpg +0 -0
- package/deskback/nobara-41-1.png +0 -0
- package/deskback/nobara-41-2.png +0 -0
- package/deskback/nobara-41-3.png +0 -0
- package/deskback/nobara-41-4.png +0 -0
- package/deskback/nobara-41-5.png +0 -0
- package/deskback/northern_ambience_by_zizzyart_df0kj8f.jpg +0 -0
- package/deskback/northern_lights_by_goatsforbreakfast_de90t8s.jpg +0 -0
- package/deskback/northern_lights_by_lapis_lazuri_dcprksa.jpg +0 -0
- package/deskback/northern_magic_by_lapis_lazuri_dbm99nv.jpg +0 -0
- package/deskback/northern_splendour_by_lapis_lazuri_ddlygb0.jpg +0 -0
- package/deskback/old_lighthouse_by_bisbiswas_dg5he0x.jpg +0 -0
- package/deskback/on_a_spring_vacation_by_bisbiswas_dhv9h4o.jpg +0 -0
- package/deskback/polar_dreams_by_avogadium_de2s60i.jpg +0 -0
- package/deskback/purple_night_by_bisbiswas_de4ql0w.jpg +0 -0
- package/deskback/quiet_ocean_night_by_ebenezer42_de4h9nd.jpg +0 -0
- package/deskback/rail_gate_by_bisbiswas_dehq31u.jpg +0 -0
- package/deskback/the_aurora_stones_by_hyokka_dcyokk2 (1).png +0 -0
- package/deskback/the_aurora_stones_by_hyokka_dcyokk2.png +0 -0
- package/deskback/the_aurora_stones_by_hyokka_dcyokk2mirror (1).png +0 -0
- package/deskback/the_aurora_stones_by_hyokka_dcyokk2mirror.png +0 -0
- package/deskback/the_midnight_by_thekayeman_de36pew.jpg +0 -0
- package/deskback/through_the_haze_by_traemore_deqdnrp.png +0 -0
- package/deskback/tri_system_by_thekayeman_ddyfscv.jpg +0 -0
- package/deskback/verdant_moonlight__commissioned__by_bisbiswas_degzd3v.jpg +0 -0
- package/deskback/verdant_mountain_by_bisbiswas_derlepn.jpg +0 -0
- package/deskback/winter_scenery_by_bisbiswas_dgwj8rb.jpg +0 -0
- package/docs/haoshoku.md +47 -0
- package/haoshoku.js +88 -0
- package/icons/Gemini_Generated_Image_kwrza7kwrza7kwrz.png +0 -0
- package/icons/Google_Tasks_2021.svg +17 -0
- package/icons/artificial-intelligence.png +0 -0
- package/icons/chatgpt-icon.png +0 -0
- package/icons/favicon.svg +12 -0
- package/icons/icons8-chatgpt-50.png +0 -0
- package/icons/icons8-discord-96.png +0 -0
- package/icons/icons8-feed-64.png +0 -0
- package/icons/icons8-google-calendar-48.png +0 -0
- package/icons/icons8-messages-96.png +0 -0
- package/icons/icons8-notion-64.png +0 -0
- package/icons/icons8-whatsapp-96.png +0 -0
- package/icons/zed.png +0 -0
- package/info.txt +3 -0
- package/package.json +14 -0
- package/src/common/utils.js +46 -0
- package/src/helpers/configure_git.js +130 -0
- package/src/os_scripts/cachyos.js +342 -0
- package/src/os_scripts/debian_server.js +146 -0
- package/tests/test_cachyos.py +37 -0
- package/tests/test_common.py +73 -0
- package/tests/test_kde_config.py +69 -0
|
Binary file
|
|
Binary file
|
package/docs/haoshoku.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Haoshoku: Color of the Supreme King
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
`haoshoku` is a JavaScript-based command-line tool designed to dominate the setup of your development environment. It is built to run with the **Bun** runtime for speed and efficiency.
|
|
6
|
+
|
|
7
|
+
The tool bundles a collection of OS-specific scripts. It intelligently detects the host operating system (or asks the user) and then executes the appropriate script to configure the system. This approach provides a consistent, reliable, and automated way to provision a new machine.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## How It Works: A Step-by-Step Guide
|
|
12
|
+
|
|
13
|
+
The script follows a clear, linear sequence of operations:
|
|
14
|
+
|
|
15
|
+
### 1. **Initialization**
|
|
16
|
+
- The entry point is `haoshoku.js`.
|
|
17
|
+
- It uses `commander` to parse command-line arguments and define the CLI interface.
|
|
18
|
+
|
|
19
|
+
### 2. **OS Determination**
|
|
20
|
+
- **Command-Line Argument (`--os`)**: The user can explicitly specify the target OS (e.g., `haoshoku --os cachyos`).
|
|
21
|
+
- **Automatic Detection**: If no argument is provided, the script reads `/etc/os-release` to detect the distribution ID (e.g., `cachyos`, `debian`).
|
|
22
|
+
- **Manual Selection**: If auto-detection fails, the script uses `prompts` to ask the user to select their OS.
|
|
23
|
+
|
|
24
|
+
### 3. **Script Execution**
|
|
25
|
+
- Once the OS is determined, the corresponding setup function is imported dynamically from `src/os_scripts/`.
|
|
26
|
+
- The setup logic is executed, handling package installation, configuration copying, and system tweaks.
|
|
27
|
+
- Helper functions in `src/common/utils.js` handle command execution (`runCommand`), logging, and checks.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Technical Details
|
|
32
|
+
|
|
33
|
+
The project is built using modern JavaScript (ES Modules) and runs on Bun.
|
|
34
|
+
|
|
35
|
+
### Key Libraries
|
|
36
|
+
|
|
37
|
+
- **`commander`**: Handles CLI argument parsing and help generation.
|
|
38
|
+
- **`prompts`**: Provides interactive user prompts (selection, confirmation).
|
|
39
|
+
- **`chalk`**: Used for colorful terminal output and logging.
|
|
40
|
+
|
|
41
|
+
### Architecture
|
|
42
|
+
|
|
43
|
+
- **`haoshoku.js`**: Main entry point. Handles OS detection and routing.
|
|
44
|
+
- **`src/os_scripts/`**: Contains the setup logic for each supported OS (e.g., `cachyos.js`, `debian_server.js`).
|
|
45
|
+
- **`src/common/utils.js`**: Shared utilities for running shell commands, logging, and checking for file/command existence.
|
|
46
|
+
- **`src/helpers/`**: Standalone helper scripts (e.g., `configure_git.js`).
|
|
47
|
+
|
package/haoshoku.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import prompts from "prompts";
|
|
4
|
+
import { log } from "./src/common/utils.js";
|
|
5
|
+
import { runCachyOSSetup } from "./src/os_scripts/cachyos.js";
|
|
6
|
+
import { runDebianServerSetup } from "./src/os_scripts/debian_server.js";
|
|
7
|
+
|
|
8
|
+
import fs from "fs";
|
|
9
|
+
|
|
10
|
+
const program = new Command();
|
|
11
|
+
|
|
12
|
+
program
|
|
13
|
+
.name("haoshoku")
|
|
14
|
+
.description("Haoshoku: Color of the Supreme King. Dominate your setup.")
|
|
15
|
+
.version("2.0.0");
|
|
16
|
+
|
|
17
|
+
function detectOS() {
|
|
18
|
+
try {
|
|
19
|
+
const osRelease = fs.readFileSync("/etc/os-release", "utf-8");
|
|
20
|
+
const lines = osRelease.split("\n");
|
|
21
|
+
const info = {};
|
|
22
|
+
for (const line of lines) {
|
|
23
|
+
const [key, value] = line.split("=");
|
|
24
|
+
if (key && value) {
|
|
25
|
+
info[key] = value.replace(/"/g, "");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const id = info["ID"] ? info["ID"].toLowerCase() : "";
|
|
30
|
+
const idLike = info["ID_LIKE"] ? info["ID_LIKE"].toLowerCase() : "";
|
|
31
|
+
|
|
32
|
+
if (id.includes("cachyos") || idLike.includes("arch")) {
|
|
33
|
+
return "cachyos";
|
|
34
|
+
}
|
|
35
|
+
if (id.includes("debian") || idLike.includes("debian")) {
|
|
36
|
+
return "debian-server";
|
|
37
|
+
}
|
|
38
|
+
} catch (e) {
|
|
39
|
+
// Ignore error if file doesn't exist
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
program
|
|
45
|
+
.option("--os <type>", "Specify the target OS (cachyos, debian-server)")
|
|
46
|
+
.action(async (options) => {
|
|
47
|
+
let osType = options.os;
|
|
48
|
+
|
|
49
|
+
if (!osType) {
|
|
50
|
+
const detected = detectOS();
|
|
51
|
+
if (detected) {
|
|
52
|
+
log.info(`Detected OS: ${detected}`);
|
|
53
|
+
osType = detected;
|
|
54
|
+
} else {
|
|
55
|
+
const response = await prompts({
|
|
56
|
+
type: "select",
|
|
57
|
+
name: "os",
|
|
58
|
+
message: "Select the target operating system:",
|
|
59
|
+
choices: [
|
|
60
|
+
{ title: "CachyOS", value: "cachyos" },
|
|
61
|
+
{ title: "Debian Server", value: "debian-server" },
|
|
62
|
+
],
|
|
63
|
+
});
|
|
64
|
+
osType = response.os;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!osType) {
|
|
69
|
+
log.error("No OS selected. Exiting.");
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
log.info(`Starting setup for: ${osType}`);
|
|
74
|
+
|
|
75
|
+
switch (osType) {
|
|
76
|
+
case "cachyos":
|
|
77
|
+
await runCachyOSSetup();
|
|
78
|
+
break;
|
|
79
|
+
case "debian-server":
|
|
80
|
+
await runDebianServerSetup();
|
|
81
|
+
break;
|
|
82
|
+
default:
|
|
83
|
+
log.error(`Unsupported OS: ${osType}`);
|
|
84
|
+
process.exit(1);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
program.parse(process.argv);
|
|
Binary file
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
3
|
+
<svg version="1.1"
|
|
4
|
+
id="svg8849" inkscape:version="1.1 (c68e22c387, 2021-05-23)" sodipodi:docname="google tasks.svg" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg"
|
|
5
|
+
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="527.1px" height="500px"
|
|
6
|
+
viewBox="0 0 527.1 500" enable-background="new 0 0 527.1 500" xml:space="preserve">
|
|
7
|
+
<sodipodi:namedview bordercolor="#eeeeee" borderopacity="1" id="namedview8851" inkscape:bbox-nodes="true" inkscape:bbox-paths="true" inkscape:current-layer="layer1" inkscape:cx="280.62992" inkscape:cy="277.14384" inkscape:document-units="mm" inkscape:object-paths="true" inkscape:pagecheckerboard="0" inkscape:pageopacity="0" inkscape:pageshadow="0" inkscape:snap-bbox="true" inkscape:snap-bbox-edge-midpoints="true" inkscape:snap-bbox-midpoints="true" inkscape:snap-center="true" inkscape:snap-global="true" inkscape:snap-intersection-paths="true" inkscape:snap-midpoints="true" inkscape:snap-object-midpoints="true" inkscape:snap-page="true" inkscape:snap-smooth-nodes="true" inkscape:snap-text-baseline="true" inkscape:window-height="1009" inkscape:window-maximized="1" inkscape:window-width="1920" inkscape:window-x="1912" inkscape:window-y="760" inkscape:zoom="1.4342733" pagecolor="#505050" showgrid="false" units="px">
|
|
8
|
+
</sodipodi:namedview>
|
|
9
|
+
<g>
|
|
10
|
+
<polygon fill="#0066DA" points="410.4,58.3 368.8,81.2 348.2,120.6 368.8,168.8 407.8,211 450,187.5 475.9,142.8 450,87.5 "/>
|
|
11
|
+
<path fill="#2684FC" d="M249.3,219.4l98.9-98.9c29.1,22.1,50.5,53.8,59.6,90.4L272.1,346.7c-12.2,12.2-32,12.2-44.2,0l-91.5-91.5
|
|
12
|
+
c-9.8-9.8-9.8-25.6,0-35.3l39-39c9.8-9.8,25.6-9.8,35.3,0L249.3,219.4z M519.8,63.6l-39.7-39.7c-9.7-9.7-25.6-9.7-35.3,0
|
|
13
|
+
l-34.4,34.4c27.5,23,49.9,51.8,65.5,84.5l43.9-43.9C529.6,89.2,529.6,73.3,519.8,63.6z M412.5,250c0,89.8-72.8,162.5-162.5,162.5
|
|
14
|
+
S87.5,339.8,87.5,250S160.2,87.5,250,87.5c36.9,0,70.9,12.3,98.2,33.1l62.2-62.2C367,21.9,311.1,0,250,0C111.9,0,0,111.9,0,250
|
|
15
|
+
s111.9,250,250,250s250-111.9,250-250c0-38.3-8.7-74.7-24.1-107.2L407.8,211C410.8,223.5,412.5,236.6,412.5,250z"/>
|
|
16
|
+
</g>
|
|
17
|
+
</svg>
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="500" height="500" version="1.1" viewBox="0 0 500 500">
|
|
3
|
+
<!-- Generator: Adobe Illustrator 28.7.1, SVG Export Plug-In . SVG Version: 1.2.0 Build 142) -->
|
|
4
|
+
<g>
|
|
5
|
+
<g id="Layer_2">
|
|
6
|
+
<g>
|
|
7
|
+
<circle cx="246.93" cy="249.67" r="240"/>
|
|
8
|
+
<path d="M246.94,117.25c-83.4,0-151,67.04-151,149.77v71.7h27.83v-7.15c0-33.55,27.41-60.75,61.23-60.75s61.23,27.21,61.23,60.75v7.15h27.83v-7.15c0-48.8-39.89-88.33-89.07-88.33-19.15,0-36.89,5.99-51.42,16.21,15.2-29.97,46.51-50.53,82.65-50.53,51.06,0,92.46,41.07,92.46,91.71v38.1h27.84v-38.1c0-65.89-53.86-119.32-120.3-119.32-29.87,0-57.2,10.8-78.24,28.69,20.66-38.73,61.68-65.13,108.95-65.13,68.03,0,123.17,54.69,123.17,122.16v71.7h27.83v-71.7c0-82.72-67.6-149.77-151-149.77Z" fill="#fff"/>
|
|
9
|
+
</g>
|
|
10
|
+
</g>
|
|
11
|
+
</g>
|
|
12
|
+
</svg>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/icons/zed.png
ADDED
|
Binary file
|
package/info.txt
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { spawn } from "bun";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
|
|
4
|
+
export const log = {
|
|
5
|
+
info: (msg) => console.log(chalk.blue(msg)),
|
|
6
|
+
success: (msg) => console.log(chalk.green(msg)),
|
|
7
|
+
warning: (msg) => console.log(chalk.yellow(msg)),
|
|
8
|
+
error: (msg) => console.error(chalk.red(msg)),
|
|
9
|
+
dim: (msg) => console.log(chalk.dim(msg)),
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export async function runCommand(
|
|
13
|
+
command,
|
|
14
|
+
options = { check: true }
|
|
15
|
+
) {
|
|
16
|
+
log.dim(`Executing: ${command}`);
|
|
17
|
+
|
|
18
|
+
// Auto-detect shell usage if not explicitly set
|
|
19
|
+
const useShell = options.shell || ["|", "&&", ";", ">", "<", "*", "?", "$", '"', "'"].some(char => command.includes(char));
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
const proc = spawn(useShell ? ["sh", "-c", command] : command.split(" "), {
|
|
23
|
+
cwd: options.cwd,
|
|
24
|
+
stdout: "inherit",
|
|
25
|
+
stderr: "inherit",
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const exitCode = await proc.exited;
|
|
29
|
+
|
|
30
|
+
if (options.check && exitCode !== 0) {
|
|
31
|
+
log.error(`Command '${command}' failed with exit code ${exitCode}`);
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
return exitCode === 0;
|
|
35
|
+
} catch (error) {
|
|
36
|
+
log.error(`Failed to execute command: ${command}`);
|
|
37
|
+
console.error(error);
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function commandExists(command) {
|
|
43
|
+
const proc = spawn(["which", command], { stdout: "ignore", stderr: "ignore" });
|
|
44
|
+
const exitCode = await proc.exited;
|
|
45
|
+
return exitCode === 0;
|
|
46
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { log, runCommand } from "../common/utils";
|
|
2
|
+
import prompts from "prompts";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import fs from "fs";
|
|
5
|
+
import { homedir } from "os";
|
|
6
|
+
|
|
7
|
+
const HOME = homedir();
|
|
8
|
+
const SSH_DIR = path.join(HOME, ".ssh");
|
|
9
|
+
|
|
10
|
+
async function promptUser(message, initial = false) {
|
|
11
|
+
const response = await prompts({
|
|
12
|
+
type: "confirm",
|
|
13
|
+
name: "value",
|
|
14
|
+
message: message,
|
|
15
|
+
initial: initial,
|
|
16
|
+
});
|
|
17
|
+
return response.value;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async function createProfile(profileType) {
|
|
21
|
+
log.info(`--- Setting up ${profileType} Git profile ---`);
|
|
22
|
+
const profileDir = path.join(HOME, profileType);
|
|
23
|
+
fs.mkdirSync(profileDir, { recursive: true });
|
|
24
|
+
|
|
25
|
+
const response = await prompts([
|
|
26
|
+
{
|
|
27
|
+
type: "text",
|
|
28
|
+
name: "email",
|
|
29
|
+
message: `Enter ${profileType} email`,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
type: "text",
|
|
33
|
+
name: "username",
|
|
34
|
+
message: `Enter ${profileType} username`,
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
type: "text",
|
|
38
|
+
name: "githubUser",
|
|
39
|
+
message: `Enter GitHub username for ${profileType}`,
|
|
40
|
+
},
|
|
41
|
+
]);
|
|
42
|
+
|
|
43
|
+
if (!response.email || !response.username || !response.githubUser) {
|
|
44
|
+
log.error("Missing information. Skipping profile creation.");
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const keyPath = path.join(SSH_DIR, `${profileType}_key`);
|
|
49
|
+
const gitConfigPath = path.join(profileDir, `.gitconfig.${profileType}`);
|
|
50
|
+
|
|
51
|
+
// Generate SSH Key
|
|
52
|
+
log.info(`Generating SSH key for ${profileType}...`);
|
|
53
|
+
await runCommand(
|
|
54
|
+
`ssh-keygen -t ed25519 -C "${response.email}" -f ${keyPath} -N "" -q`
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
// Add to Agent
|
|
58
|
+
log.info(`Adding ${profileType} SSH key to agent...`);
|
|
59
|
+
await runCommand(`ssh-add ${keyPath}`);
|
|
60
|
+
|
|
61
|
+
// Create Git Config
|
|
62
|
+
const gitConfigContent = `[user]
|
|
63
|
+
email = ${response.email}
|
|
64
|
+
name = ${response.username}
|
|
65
|
+
signingkey = ${keyPath}
|
|
66
|
+
|
|
67
|
+
[github]
|
|
68
|
+
user = "${response.githubUser}"
|
|
69
|
+
|
|
70
|
+
[commit]
|
|
71
|
+
gpgsign = true
|
|
72
|
+
|
|
73
|
+
[gpg]
|
|
74
|
+
format = ssh
|
|
75
|
+
|
|
76
|
+
[core]
|
|
77
|
+
sshCommand = "ssh -i ${keyPath}"
|
|
78
|
+
`;
|
|
79
|
+
|
|
80
|
+
fs.writeFileSync(gitConfigPath, gitConfigContent);
|
|
81
|
+
log.info(`Created ${gitConfigPath}`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export async function configureGit() {
|
|
85
|
+
log.info("Configuring Git...");
|
|
86
|
+
fs.mkdirSync(SSH_DIR, { mode: 0o700, recursive: true });
|
|
87
|
+
|
|
88
|
+
// Start SSH Agent
|
|
89
|
+
try {
|
|
90
|
+
const agentProc = Bun.spawn(["ssh-agent", "-s"]);
|
|
91
|
+
const output = await new Response(agentProc.stdout).text();
|
|
92
|
+
const match = output.match(/SSH_AUTH_SOCK=([^;]+);/);
|
|
93
|
+
if (match) {
|
|
94
|
+
process.env.SSH_AUTH_SOCK = match[1];
|
|
95
|
+
}
|
|
96
|
+
const pidMatch = output.match(/SSH_AGENT_PID=([^;]+);/);
|
|
97
|
+
if (pidMatch) {
|
|
98
|
+
process.env.SSH_AGENT_PID = pidMatch[1];
|
|
99
|
+
}
|
|
100
|
+
} catch (e) {
|
|
101
|
+
log.warning("Could not start ssh-agent.");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
let workProfileCreated = false;
|
|
105
|
+
if (await promptUser("Do you want to create a work Git profile?", true)) {
|
|
106
|
+
await createProfile("work");
|
|
107
|
+
workProfileCreated = true;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
await createProfile("personal");
|
|
111
|
+
|
|
112
|
+
// Global Config
|
|
113
|
+
let globalConfigContent = `[includeIf "gitdir:~/personal/"]
|
|
114
|
+
path = ~/personal/.gitconfig.personal
|
|
115
|
+
`;
|
|
116
|
+
|
|
117
|
+
if (workProfileCreated) {
|
|
118
|
+
globalConfigContent += `[includeIf "gitdir:~/work/"]
|
|
119
|
+
path = ~/work/.gitconfig.work
|
|
120
|
+
`;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const globalGitConfigPath = path.join(HOME, ".gitconfig");
|
|
124
|
+
fs.writeFileSync(globalGitConfigPath, globalConfigContent);
|
|
125
|
+
|
|
126
|
+
log.info(`Created global git config at ${globalGitConfigPath}`);
|
|
127
|
+
log.warning(
|
|
128
|
+
"ACTION REQUIRED: Copy the contents of the .pub files in ~/.ssh and add them to your GitHub accounts."
|
|
129
|
+
);
|
|
130
|
+
}
|