2022-11-29 22:26:34 -08:00
|
|
|
|
#!/usr/bin/env zx
|
|
|
|
|
|
2022-12-04 21:46:23 -08:00
|
|
|
|
const execSync = require("child_process").execSync;
|
2022-11-29 22:26:34 -08:00
|
|
|
|
|
2022-12-02 15:07:52 -08:00
|
|
|
|
// Log symbols
|
|
|
|
|
const figuresDefault = {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
bullet: "●",
|
|
|
|
|
circle: "◯",
|
|
|
|
|
cross: "✖",
|
|
|
|
|
lozenge: "◆",
|
|
|
|
|
play: "▶",
|
|
|
|
|
pointer: "❯",
|
|
|
|
|
square: "◼",
|
|
|
|
|
star: "★",
|
|
|
|
|
tick: "✔",
|
|
|
|
|
};
|
2022-12-02 15:07:52 -08:00
|
|
|
|
|
|
|
|
|
const figuresFallback = {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
bullet: "■",
|
|
|
|
|
circle: "□",
|
|
|
|
|
cross: "×",
|
|
|
|
|
lozenge: "♦",
|
|
|
|
|
play: "►",
|
|
|
|
|
pointer: ">",
|
|
|
|
|
square: "■",
|
|
|
|
|
star: "✶",
|
|
|
|
|
tick: "√",
|
|
|
|
|
};
|
2022-12-02 15:07:52 -08:00
|
|
|
|
|
|
|
|
|
function isUnicodeSupported() {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
if (process.platform !== "win32") {
|
2022-12-02 15:07:52 -08:00
|
|
|
|
// Linux console (kernel)
|
2022-12-04 21:46:23 -08:00
|
|
|
|
return process.env.TERM !== "linux";
|
2022-12-02 15:07:52 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
Boolean(process.env.CI) ||
|
|
|
|
|
// Windows Terminal
|
|
|
|
|
Boolean(process.env.WT_SESSION) ||
|
|
|
|
|
// ConEmu and cmder
|
2022-12-04 21:46:23 -08:00
|
|
|
|
process.env.ConEmuTask === "{cmd::Cmder}" ||
|
|
|
|
|
process.env.TERM_PROGRAM === "vscode" ||
|
|
|
|
|
process.env.TERM === "xterm-256color" ||
|
|
|
|
|
process.env.TERM === "alacritty"
|
|
|
|
|
);
|
2022-12-02 15:07:52 -08:00
|
|
|
|
}
|
|
|
|
|
|
2022-12-04 21:46:23 -08:00
|
|
|
|
const figures = isUnicodeSupported() ? figuresDefault : figuresFallback;
|
2022-12-02 15:07:52 -08:00
|
|
|
|
|
|
|
|
|
function log(type, label, msg) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
let icon, message;
|
|
|
|
|
if (type === "info") {
|
|
|
|
|
icon = chalk.cyanBright(figures.pointer);
|
|
|
|
|
message = chalk.gray.bold(msg);
|
|
|
|
|
} else if (type === "star") {
|
|
|
|
|
icon = chalk.yellowBright(figures.star);
|
|
|
|
|
message = chalk.bold(msg);
|
|
|
|
|
} else if (type === "success") {
|
|
|
|
|
icon = chalk.greenBright(figures.play);
|
|
|
|
|
message = chalk.bold(msg);
|
|
|
|
|
} else if (type === "warn") {
|
|
|
|
|
icon = `${chalk.yellowBright(
|
|
|
|
|
figures.lozenge
|
|
|
|
|
)} ${chalk.bold.black.bgYellowBright(" WARNING ")}`;
|
|
|
|
|
message = chalk.yellowBright(msg);
|
|
|
|
|
} else if (type === "error") {
|
|
|
|
|
icon = `${chalk.redBright(figures.cross)} ${chalk.black.bold.bgRedBright(
|
|
|
|
|
" ERROR "
|
|
|
|
|
)}`;
|
|
|
|
|
message = chalk.redBright(msg);
|
2022-12-02 15:07:52 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
const outputMessage = `${icon} ${chalk.bold(label)} ${message}`;
|
|
|
|
|
console.log(outputMessage);
|
2022-12-02 15:07:52 -08:00
|
|
|
|
}
|
|
|
|
|
|
2022-12-04 21:46:23 -08:00
|
|
|
|
let installData;
|
2022-11-29 22:26:34 -08:00
|
|
|
|
const installOrders = {};
|
|
|
|
|
const installOrdersPre = [];
|
|
|
|
|
const installOrdersPost = [];
|
2022-12-04 21:46:23 -08:00
|
|
|
|
let osType, osID;
|
2022-11-29 22:26:34 -08:00
|
|
|
|
|
|
|
|
|
// Download the installation map
|
|
|
|
|
async function downloadInstallData() {
|
|
|
|
|
const response = await fetch(
|
2022-11-30 01:43:30 -08:00
|
|
|
|
"https://gitlab.com/megabyte-labs/misc/dotfiles/-/raw/master/.local/share/chezmoi/software.yml"
|
2022-11-29 22:26:34 -08:00
|
|
|
|
);
|
|
|
|
|
if (response.ok) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
const text = await response.text();
|
|
|
|
|
return YAML.parse(text);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
} else {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log("error", "Catalog Download", `Failed to download the installation map`);
|
2022-12-05 10:33:02 -08:00
|
|
|
|
log("info", "Catalog Download", `Falling back to local version of software.yml`);
|
|
|
|
|
const text = fs.readFileSync(process.env.HOME + "/.local/share/chezmoi/software.yml");
|
|
|
|
|
return YAML.parse(text);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Creates the installOrders object which maps package managers to arrays of packages to install
|
|
|
|
|
async function generateInstallOrders() {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
const logStage = "Install Orders";
|
2022-11-29 22:26:34 -08:00
|
|
|
|
const packagesToInstall = process.argv.slice(3);
|
2022-12-04 21:46:23 -08:00
|
|
|
|
const installerPreference = await OSTypeInstallerKey();
|
|
|
|
|
log(
|
|
|
|
|
"info",
|
|
|
|
|
logStage,
|
|
|
|
|
`Installer preference category detected as ${installerPreference}`
|
|
|
|
|
);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
const preferenceOrder = installData.installerPreference[installerPreference];
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log("info", logStage, `Preference order acquired:`);
|
|
|
|
|
console.log(preferenceOrder);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
const softwarePackages = installData.softwarePackages;
|
2022-12-04 21:46:23 -08:00
|
|
|
|
pkgFor: for (let pkg of packagesToInstall) {
|
2022-11-29 22:26:34 -08:00
|
|
|
|
let packageKey;
|
|
|
|
|
if (softwarePackages[pkg + ":" + osID]) {
|
|
|
|
|
packageKey = pkg + ":" + osID;
|
|
|
|
|
} else if (softwarePackages[pkg + ":" + osType]) {
|
|
|
|
|
packageKey = pkg + ":" + osType;
|
|
|
|
|
} else if (softwarePackages[pkg]) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
packageKey = pkg;
|
2022-11-29 22:26:34 -08:00
|
|
|
|
} else {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log(
|
|
|
|
|
"warn",
|
|
|
|
|
logStage,
|
|
|
|
|
`The package \`${pkg}\` was not found in the installation map`
|
|
|
|
|
);
|
|
|
|
|
continue;
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
|
|
|
|
for (let preference of preferenceOrder) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
let currentSelector,
|
|
|
|
|
doubleScoped,
|
|
|
|
|
scopedPkgManager,
|
|
|
|
|
scopedSystem,
|
|
|
|
|
normalCheck;
|
|
|
|
|
if (
|
|
|
|
|
softwarePackages[packageKey][preference + ":" + osID] ||
|
|
|
|
|
softwarePackages[packageKey][preference + ":" + osType] ||
|
|
|
|
|
softwarePackages[packageKey][preference]
|
|
|
|
|
) {
|
|
|
|
|
// Handle the _when attribute
|
|
|
|
|
currentSelector = "when";
|
|
|
|
|
doubleScoped =
|
2022-12-04 22:23:18 -08:00
|
|
|
|
softwarePackages[packageKey][
|
|
|
|
|
"_" + currentSelector + ":" + preference + ":" + osID
|
|
|
|
|
] ||
|
|
|
|
|
softwarePackages[packageKey][
|
|
|
|
|
"_" + currentSelector + ":" + osID + ":" + preference
|
|
|
|
|
] ||
|
|
|
|
|
softwarePackages[packageKey][
|
|
|
|
|
"_" + currentSelector + ":" + preference + ":" + osType
|
|
|
|
|
] ||
|
|
|
|
|
softwarePackages[packageKey][
|
|
|
|
|
"_" + currentSelector + ":" + osType + ":" + preference
|
|
|
|
|
];
|
2022-12-04 21:46:23 -08:00
|
|
|
|
scopedPkgManager =
|
2022-12-04 22:23:18 -08:00
|
|
|
|
softwarePackages[packageKey][
|
2022-12-04 21:46:23 -08:00
|
|
|
|
"_" + currentSelector + ":" + preference
|
|
|
|
|
];
|
|
|
|
|
scopedSystem =
|
2022-12-04 22:23:18 -08:00
|
|
|
|
softwarePackages[packageKey]["_" + currentSelector + ":" + osID] ||
|
|
|
|
|
softwarePackages[packageKey]["_" + currentSelector + ":" + osType];
|
2022-12-04 22:24:27 -08:00
|
|
|
|
normalCheck = softwarePackages[packageKey]["_" + currentSelector];
|
2022-12-04 21:46:23 -08:00
|
|
|
|
if (doubleScoped) {
|
|
|
|
|
try {
|
2022-12-04 22:10:55 -08:00
|
|
|
|
await $doubleScoped;
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} catch (e) {
|
|
|
|
|
let pref;
|
|
|
|
|
if (
|
2022-12-04 22:23:18 -08:00
|
|
|
|
softwarePackages[packageKey][
|
2022-12-04 21:46:23 -08:00
|
|
|
|
"_" + currentSelector + ":" + preference + ":" + osID
|
|
|
|
|
]
|
|
|
|
|
) {
|
|
|
|
|
pref = preference + ":" + osID;
|
|
|
|
|
} else if (
|
2022-12-04 22:23:18 -08:00
|
|
|
|
softwarePackages[packageKey][
|
2022-12-04 21:46:23 -08:00
|
|
|
|
"_" + currentSelector + ":" + preference + ":" + osType
|
|
|
|
|
]
|
|
|
|
|
) {
|
|
|
|
|
pref = preference + ":" + osType;
|
|
|
|
|
} else if (
|
2022-12-04 22:23:18 -08:00
|
|
|
|
softwarePackages[packageKey][
|
2022-12-04 21:46:23 -08:00
|
|
|
|
"_" + currentSelector + ":" + osID + ":" + preference
|
|
|
|
|
]
|
|
|
|
|
) {
|
|
|
|
|
pref = osID + ":" + preference;
|
|
|
|
|
} else if (
|
2022-12-04 22:23:18 -08:00
|
|
|
|
softwarePackages[packageKey][
|
2022-12-04 21:46:23 -08:00
|
|
|
|
"_" + currentSelector + ":" + osType + ":" + preference
|
|
|
|
|
]
|
|
|
|
|
) {
|
|
|
|
|
pref = osType + ":" + preference;
|
|
|
|
|
}
|
|
|
|
|
log(
|
|
|
|
|
"info",
|
|
|
|
|
"Skipping Package",
|
|
|
|
|
`${pkg} is being skipped because of the _when:${pref} condition`
|
|
|
|
|
);
|
|
|
|
|
continue pkgFor;
|
|
|
|
|
}
|
|
|
|
|
} else if (scopedPkgManager) {
|
|
|
|
|
try {
|
2022-12-04 22:10:55 -08:00
|
|
|
|
await $scopedPkgManager;
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} catch (e) {
|
|
|
|
|
const pref = preference;
|
|
|
|
|
log(
|
|
|
|
|
"info",
|
|
|
|
|
"Skipping Package",
|
|
|
|
|
`${pkg} is being skipped because of the _when:${pref} condition`
|
|
|
|
|
);
|
|
|
|
|
continue pkgFor;
|
|
|
|
|
}
|
|
|
|
|
} else if (scopedSystem) {
|
|
|
|
|
try {
|
2022-12-04 22:10:55 -08:00
|
|
|
|
await $scopedSystem;
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} catch (e) {
|
|
|
|
|
let pref;
|
|
|
|
|
if (
|
2022-12-04 22:23:18 -08:00
|
|
|
|
softwarePackages[packageKey]["_" + currentSelector + ":" + osID]
|
2022-12-04 21:46:23 -08:00
|
|
|
|
) {
|
|
|
|
|
pref = osID;
|
|
|
|
|
} else if (
|
2022-12-04 22:23:18 -08:00
|
|
|
|
softwarePackages[packageKey]["_" + currentSelector + ":" + osType]
|
2022-12-04 21:46:23 -08:00
|
|
|
|
) {
|
|
|
|
|
pref = osType;
|
|
|
|
|
}
|
|
|
|
|
log(
|
|
|
|
|
"info",
|
|
|
|
|
"Skipping Package",
|
|
|
|
|
`${pkg} is being skipped because of the _when:${pref} condition`
|
|
|
|
|
);
|
|
|
|
|
continue pkgFor;
|
|
|
|
|
}
|
|
|
|
|
} else if (normalCheck) {
|
|
|
|
|
try {
|
|
|
|
|
await $(normalCheck);
|
|
|
|
|
} catch (e) {
|
|
|
|
|
log(
|
|
|
|
|
"info",
|
|
|
|
|
"Skipping Package",
|
|
|
|
|
`${pkg} is being skipped because of the _when condition`
|
|
|
|
|
);
|
|
|
|
|
continue pkgFor;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Handle the _bin attribute
|
|
|
|
|
currentSelector = "bin";
|
|
|
|
|
doubleScoped =
|
2022-12-04 22:23:18 -08:00
|
|
|
|
softwarePackages[packageKey][
|
|
|
|
|
"_" + currentSelector + ":" + preference + ":" + osID
|
|
|
|
|
] ||
|
|
|
|
|
softwarePackages[packageKey][
|
|
|
|
|
"_" + currentSelector + ":" + osID + ":" + preference
|
|
|
|
|
] ||
|
|
|
|
|
softwarePackages[packageKey][
|
|
|
|
|
"_" + currentSelector + ":" + preference + ":" + osType
|
|
|
|
|
] ||
|
|
|
|
|
softwarePackages[packageKey][
|
|
|
|
|
"_" + currentSelector + ":" + osType + ":" + preference
|
|
|
|
|
];
|
2022-12-04 21:46:23 -08:00
|
|
|
|
scopedPkgManager =
|
2022-12-04 22:23:18 -08:00
|
|
|
|
softwarePackages[packageKey][
|
2022-12-04 21:46:23 -08:00
|
|
|
|
"_" + currentSelector + ":" + preference
|
|
|
|
|
];
|
|
|
|
|
scopedSystem =
|
2022-12-04 22:23:18 -08:00
|
|
|
|
softwarePackages[packageKey]["_" + currentSelector + ":" + osID] ||
|
|
|
|
|
softwarePackages[packageKey]["_" + currentSelector + ":" + osType];
|
|
|
|
|
normalCheck = softwarePackages[packageKey]["_" + currentSelector];
|
2022-12-04 21:46:23 -08:00
|
|
|
|
if (doubleScoped) {
|
|
|
|
|
const bin = which.sync(doubleScoped, { nothrow: true });
|
2022-12-04 22:26:27 -08:00
|
|
|
|
if (bin) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
let pref;
|
|
|
|
|
if (
|
2022-12-04 22:23:18 -08:00
|
|
|
|
softwarePackages[packageKey][
|
2022-12-04 21:46:23 -08:00
|
|
|
|
"_" + currentSelector + ":" + preference + ":" + osID
|
|
|
|
|
]
|
|
|
|
|
) {
|
|
|
|
|
pref = preference + ":" + osID;
|
|
|
|
|
} else if (
|
2022-12-04 22:23:18 -08:00
|
|
|
|
softwarePackages[packageKey][
|
2022-12-04 21:46:23 -08:00
|
|
|
|
"_" + currentSelector + ":" + preference + ":" + osType
|
|
|
|
|
]
|
|
|
|
|
) {
|
|
|
|
|
pref = preference + ":" + osType;
|
|
|
|
|
} else if (
|
2022-12-04 22:23:18 -08:00
|
|
|
|
softwarePackages[packageKey][
|
2022-12-04 21:46:23 -08:00
|
|
|
|
"_" + currentSelector + ":" + osID + ":" + preference
|
|
|
|
|
]
|
|
|
|
|
) {
|
|
|
|
|
pref = osID + ":" + preference;
|
|
|
|
|
} else if (
|
2022-12-04 22:23:18 -08:00
|
|
|
|
softwarePackages[packageKey][
|
2022-12-04 21:46:23 -08:00
|
|
|
|
"_" + currentSelector + ":" + osType + ":" + preference
|
|
|
|
|
]
|
|
|
|
|
) {
|
|
|
|
|
pref = osType + ":" + preference;
|
|
|
|
|
}
|
|
|
|
|
log(
|
|
|
|
|
"info",
|
|
|
|
|
"Skipping Package",
|
|
|
|
|
`${pkg} is being skipped because of the _bin:${pref} condition`
|
|
|
|
|
);
|
|
|
|
|
log("info", "Skipping Package", `${bin} is already in the PATH`);
|
|
|
|
|
continue pkgFor;
|
|
|
|
|
}
|
|
|
|
|
} else if (scopedPkgManager) {
|
|
|
|
|
const bin = which.sync(scopedPkgManager, { nothrow: true });
|
2022-12-04 22:26:27 -08:00
|
|
|
|
if (bin) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
const pref = preference;
|
|
|
|
|
log(
|
|
|
|
|
"info",
|
|
|
|
|
"Skipping Package",
|
|
|
|
|
`${pkg} is being skipped because of the _bin:${pref} condition`
|
|
|
|
|
);
|
|
|
|
|
log("info", "Skipping Package", `${bin} is already in the PATH`);
|
|
|
|
|
continue pkgFor;
|
|
|
|
|
}
|
|
|
|
|
} else if (scopedSystem) {
|
|
|
|
|
const bin = which.sync(scopedSystem, { nothrow: true });
|
2022-12-04 22:26:27 -08:00
|
|
|
|
if (bin) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
let pref;
|
|
|
|
|
if (
|
2022-12-04 22:23:18 -08:00
|
|
|
|
softwarePackages[packageKey]["_" + currentSelector + ":" + osID]
|
2022-12-04 21:46:23 -08:00
|
|
|
|
) {
|
|
|
|
|
pref = osID;
|
|
|
|
|
} else if (
|
2022-12-04 22:23:18 -08:00
|
|
|
|
softwarePackages[packageKey]["_" + currentSelector + ":" + osType]
|
2022-12-04 21:46:23 -08:00
|
|
|
|
) {
|
|
|
|
|
pref = osType;
|
|
|
|
|
}
|
|
|
|
|
log(
|
|
|
|
|
"info",
|
|
|
|
|
"Skipping Package",
|
|
|
|
|
`${pkg} is being skipped because of the _bin:${pref} condition`
|
|
|
|
|
);
|
|
|
|
|
log("info", "Skipping Package", `${bin} is already in the PATH`);
|
|
|
|
|
continue pkgFor;
|
|
|
|
|
}
|
|
|
|
|
} else if (normalCheck) {
|
|
|
|
|
const bin = which.sync(normalCheck, { nothrow: true });
|
2022-12-04 22:26:27 -08:00
|
|
|
|
if (bin) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log(
|
|
|
|
|
"info",
|
|
|
|
|
"Skipping Package",
|
|
|
|
|
`${pkg} is being skipped because of the _bin condition`
|
|
|
|
|
);
|
|
|
|
|
log("info", "Skipping Package", `${bin} is already in the PATH`);
|
|
|
|
|
continue pkgFor;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (softwarePackages[packageKey][preference + ":" + osID]) {
|
|
|
|
|
await updateInstallMaps(
|
|
|
|
|
preference,
|
|
|
|
|
softwarePackages[packageKey],
|
|
|
|
|
preference + ":" + osID,
|
|
|
|
|
pkg,
|
|
|
|
|
packageKey
|
|
|
|
|
);
|
|
|
|
|
break;
|
|
|
|
|
} else if (softwarePackages[packageKey][preference + ":" + osType]) {
|
|
|
|
|
await updateInstallMaps(
|
|
|
|
|
preference,
|
|
|
|
|
softwarePackages[packageKey],
|
|
|
|
|
preference + ":" + osType,
|
|
|
|
|
pkg,
|
|
|
|
|
packageKey
|
|
|
|
|
);
|
|
|
|
|
break;
|
|
|
|
|
} else if (softwarePackages[packageKey][preference]) {
|
|
|
|
|
await updateInstallMaps(
|
|
|
|
|
preference,
|
|
|
|
|
softwarePackages[packageKey],
|
|
|
|
|
preference,
|
|
|
|
|
pkg,
|
|
|
|
|
packageKey
|
|
|
|
|
);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return installOrders;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update install, pre-hook, and post-hook objects
|
2022-12-04 21:46:23 -08:00
|
|
|
|
async function updateInstallMaps(
|
|
|
|
|
preference,
|
|
|
|
|
packages,
|
|
|
|
|
scopedPreference,
|
|
|
|
|
pkg,
|
|
|
|
|
packageKey
|
|
|
|
|
) {
|
2022-11-29 22:26:34 -08:00
|
|
|
|
const preHook = getHook(packages, "pre", scopedPreference, preference);
|
|
|
|
|
if (preHook) {
|
|
|
|
|
installOrdersPre.concat(typeof preHook === "string" ? [preHook] : preHook);
|
|
|
|
|
}
|
|
|
|
|
const postHook = getHook(packages, "post", scopedPreference, preference);
|
|
|
|
|
if (postHook) {
|
|
|
|
|
installOrdersPost.concat(
|
|
|
|
|
typeof postHook === "string" ? [postHook] : postHook
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
if (!installOrders[preference]) {
|
|
|
|
|
installOrders[preference] = [];
|
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log(
|
|
|
|
|
"info",
|
|
|
|
|
"Install Orders",
|
|
|
|
|
`Found a match for the package \`${pkg}\` (${packageKey} via ${scopedPreference})`
|
|
|
|
|
);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
const newPackages = packages[scopedPreference];
|
2022-12-04 21:46:23 -08:00
|
|
|
|
const newPkgs = typeof newPackages === "string" ? [newPackages] : newPackages;
|
2022-12-02 16:13:21 -08:00
|
|
|
|
installOrders[preference] = installOrders[preference].concat(newPkgs);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get pre / post install hooks
|
|
|
|
|
function getHook(packages, hook, scopedPreference, preference) {
|
|
|
|
|
const hookLabel = "_" + hook + ":";
|
|
|
|
|
if (packages[hookLabel + scopedPreference]) {
|
|
|
|
|
return packages[hookLabel + scopedPreference];
|
|
|
|
|
} else if (packages[hookLabel + preference]) {
|
|
|
|
|
return packages[hookLabel + preference];
|
|
|
|
|
} else if (packages[hookLabel + osID]) {
|
|
|
|
|
return packages;
|
|
|
|
|
} else if (packages[hookLabel + osType]) {
|
|
|
|
|
return packages[hookLabel + osType];
|
|
|
|
|
} else if (packages["_" + hook]) {
|
|
|
|
|
return packages["_" + hook];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Acquire OS type installer key (for the installerPreference data key)
|
|
|
|
|
async function OSTypeInstallerKey() {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
const apt = which.sync("apt-get", { nothrow: true });
|
|
|
|
|
const dnf = which.sync("dnf", { nothrow: true });
|
|
|
|
|
const freebsd = which.sync("pkg", { nothrow: true });
|
|
|
|
|
const pacman = which.sync("pacman", { nothrow: true });
|
|
|
|
|
const yum = which.sync("yum", { nothrow: true });
|
|
|
|
|
const zypper = which.sync("zypper", { nothrow: true });
|
2022-11-29 22:26:34 -08:00
|
|
|
|
if (apt) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
return "apt";
|
2022-11-29 22:26:34 -08:00
|
|
|
|
} else if (dnf || yum) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
return "dnf";
|
|
|
|
|
} else if (pacman) {
|
|
|
|
|
return "pacman";
|
|
|
|
|
} else if (zypper) {
|
|
|
|
|
return "zypper";
|
2022-11-29 22:26:34 -08:00
|
|
|
|
} else if (freebsd) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
return "freebsd";
|
2022-11-29 22:26:34 -08:00
|
|
|
|
} else {
|
2022-12-02 08:55:33 -08:00
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`test -d /Applications && test -d /Library`;
|
|
|
|
|
return "darwin";
|
2022-12-02 08:55:33 -08:00
|
|
|
|
} catch (e) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
return "windows";
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Acquire OS type
|
|
|
|
|
async function OSType() {
|
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`test -d /Applications && test -d /Library`;
|
|
|
|
|
return "darwin";
|
|
|
|
|
} catch (e) {
|
2022-11-29 22:26:34 -08:00
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`test -f /etc/os-release`;
|
|
|
|
|
return "linux";
|
2022-11-29 22:26:34 -08:00
|
|
|
|
} catch (e) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
return "windows";
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Acquire release ID (for Linux)
|
|
|
|
|
async function releaseID() {
|
|
|
|
|
const ID = await $`
|
|
|
|
|
if [ -f /etc/os-release ]; then
|
|
|
|
|
. /etc/os-release
|
|
|
|
|
echo -n $ID
|
|
|
|
|
fi
|
|
|
|
|
`;
|
|
|
|
|
return ID.stdout;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Post-install hook
|
|
|
|
|
async function afterInstall(packageManager) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
const logStage = "Post-Install Package Manager";
|
|
|
|
|
if (packageManager === "appimage") {
|
|
|
|
|
} else if (packageManager === "ansible") {
|
|
|
|
|
log(
|
|
|
|
|
"info",
|
|
|
|
|
logStage,
|
|
|
|
|
`Ensuring temporary passwordless sudo privileges used by Ansible are removed`
|
|
|
|
|
);
|
|
|
|
|
const gsed = which.sync("gsed", { nothrow: true });
|
2022-12-02 15:28:30 -08:00
|
|
|
|
if (gsed) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`sudo gsed -i '/# TEMPORARY FOR ANSIBLE INSTALL/d' /etc/sudoers`;
|
2022-12-02 15:28:30 -08:00
|
|
|
|
} else {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`sudo sed -i '/# TEMPORARY FOR ANSIBLE INSTALL/d' /etc/sudoers`;
|
2022-12-02 15:28:30 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "apk") {
|
|
|
|
|
} else if (packageManager === "apt") {
|
|
|
|
|
} else if (packageManager === "basher") {
|
|
|
|
|
} else if (packageManager === "binary") {
|
|
|
|
|
} else if (packageManager === "brew" || packageManager === "cask") {
|
|
|
|
|
} else if (packageManager === "cargo") {
|
|
|
|
|
} else if (packageManager === "choco") {
|
|
|
|
|
} else if (packageManager === "crew") {
|
|
|
|
|
} else if (packageManager === "dnf") {
|
|
|
|
|
} else if (packageManager === "flatpak") {
|
|
|
|
|
} else if (packageManager === "gem") {
|
|
|
|
|
} else if (packageManager === "go") {
|
|
|
|
|
} else if (packageManager === "nix") {
|
|
|
|
|
} else if (packageManager === "npm") {
|
|
|
|
|
} else if (packageManager === "pacman") {
|
|
|
|
|
} else if (packageManager === "pipx") {
|
|
|
|
|
} else if (packageManager === "pkg") {
|
|
|
|
|
} else if (packageManager === "port") {
|
|
|
|
|
} else if (packageManager === "scoop") {
|
|
|
|
|
} else if (packageManager === "snap") {
|
|
|
|
|
} else if (packageManager === "whalebrew") {
|
|
|
|
|
} else if (packageManager === "winget") {
|
|
|
|
|
} else if (packageManager === "yay") {
|
|
|
|
|
} else if (packageManager === "zypper") {
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Pre-install hook
|
|
|
|
|
async function beforeInstall(packageManager) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
const logStage = "Pre-Install Package Manager";
|
|
|
|
|
if (packageManager === "appimage") {
|
|
|
|
|
} else if (packageManager === "ansible") {
|
|
|
|
|
log(
|
|
|
|
|
"info",
|
|
|
|
|
logStage,
|
|
|
|
|
`Temporarily enabling passwordless sudo for Ansible role installations`
|
|
|
|
|
);
|
|
|
|
|
await $`echo "$(whoami) ALL=(ALL:ALL) NOPASSWD: ALL # TEMPORARY FOR ANSIBLE INSTALL" | sudo tee -a`;
|
2022-12-05 12:15:57 -08:00
|
|
|
|
log('info', logStage, 'Running Ansible setup task so facts are cached')
|
|
|
|
|
await $`ansible localhost -m setup -e ansible_user=${process.env.USER}`;
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "apk") {
|
|
|
|
|
await $`sudo apk update`;
|
|
|
|
|
} else if (packageManager === "apt") {
|
|
|
|
|
await $`sudo apt-get update`;
|
|
|
|
|
} else if (packageManager === "basher") {
|
|
|
|
|
} else if (packageManager === "binary") {
|
|
|
|
|
} else if (packageManager === "brew" || packageManager === "cask") {
|
|
|
|
|
await $`brew update`;
|
|
|
|
|
} else if (packageManager === "cargo") {
|
|
|
|
|
} else if (packageManager === "choco") {
|
|
|
|
|
} else if (packageManager === "crew") {
|
|
|
|
|
await $`crew update`;
|
|
|
|
|
} else if (packageManager === "dnf") {
|
|
|
|
|
const dnf = which.sync("dnf", { nothrow: true });
|
|
|
|
|
const yum = which.sync("yum", { nothrow: true });
|
2022-12-04 19:51:47 -08:00
|
|
|
|
if (dnf) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`dnf check-update`;
|
2022-12-04 19:51:47 -08:00
|
|
|
|
} else if (yum) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`yum check-update`;
|
2022-12-04 19:51:47 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "flatpak") {
|
|
|
|
|
await $`sudo flatpak update`;
|
|
|
|
|
} else if (packageManager === "gem") {
|
|
|
|
|
} else if (packageManager === "go") {
|
|
|
|
|
} else if (packageManager === "nix") {
|
|
|
|
|
await $`nix-channel --update`;
|
|
|
|
|
} else if (packageManager === "npm") {
|
|
|
|
|
} else if (packageManager === "pacman") {
|
|
|
|
|
await $`sudo pacman -Syu`;
|
|
|
|
|
} else if (packageManager === "pipx") {
|
|
|
|
|
} else if (packageManager === "pkg") {
|
|
|
|
|
await $`sudo pkg upgrade`;
|
|
|
|
|
} else if (packageManager === "port") {
|
|
|
|
|
const port = which.sync("port", { nothrow: true });
|
2022-12-04 20:12:14 -08:00
|
|
|
|
if (port) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`sudo port sync`;
|
2022-12-04 20:12:14 -08:00
|
|
|
|
} else {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"Port Not Installed",
|
|
|
|
|
"Skipping sudo port sync step because port is not installed"
|
|
|
|
|
);
|
2022-12-04 20:12:14 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "scoop") {
|
|
|
|
|
await $`scoop update`;
|
|
|
|
|
} else if (packageManager === "snap") {
|
|
|
|
|
await $`sudo snap refresh`;
|
|
|
|
|
} else if (packageManager === "whalebrew") {
|
|
|
|
|
if (osType === "darwin") {
|
|
|
|
|
const docker = which.sync("docker", { nothrow: true });
|
2022-12-02 09:09:59 -08:00
|
|
|
|
if (!docker) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`brew install --cask docker`;
|
2022-12-02 09:09:59 -08:00
|
|
|
|
}
|
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`docker run --rm hello-world`;
|
2022-12-02 09:09:59 -08:00
|
|
|
|
} catch (e) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log(
|
|
|
|
|
"warn",
|
|
|
|
|
logStage,
|
|
|
|
|
`The command \`docker run --rm hello-world\` failed`
|
|
|
|
|
);
|
2022-12-02 09:09:59 -08:00
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log(
|
|
|
|
|
"info",
|
|
|
|
|
logStage,
|
|
|
|
|
"Attempting to open `/Applications/Docker.app` (Docker Desktop for macOS). This should take about 30 seconds."
|
|
|
|
|
);
|
|
|
|
|
const promises = [
|
|
|
|
|
$`test -d /Applications/Docker.app`,
|
|
|
|
|
$`open /Applications/Docker.app`,
|
|
|
|
|
];
|
|
|
|
|
await Promise.all(promises);
|
|
|
|
|
const gum = which.sync("gum", { nothrow: true });
|
2022-12-02 09:09:59 -08:00
|
|
|
|
if (gum) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
execSync(
|
|
|
|
|
'gum spin --spinner dot --title "Waiting for Docker Desktop to start up.." -- sleep 30',
|
|
|
|
|
{ stdio: "inherit", shell: true }
|
|
|
|
|
);
|
2022-12-02 09:09:59 -08:00
|
|
|
|
} else {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`sleep 30`;
|
2022-12-02 09:09:59 -08:00
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log("warn", logStage, `Docker Desktop appears to not be installed!`);
|
2022-12-02 09:09:59 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-12-02 09:01:47 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "winget") {
|
|
|
|
|
await $`winget source update`;
|
|
|
|
|
} else if (packageManager === "yay") {
|
|
|
|
|
} else if (packageManager === "zypper") {
|
|
|
|
|
await $`sudo zypper update`;
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function ensureInstalled(bin, callback) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
const logStage = "Package Manager Install";
|
|
|
|
|
const installed = which.sync(bin, { nothrow: true });
|
2022-11-29 22:26:34 -08:00
|
|
|
|
if (installed) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log("info", logStage, `\`${bin}\` is available`);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
} else {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log("warn", logStage, `\`${bin}\` is not installed!`);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
if (callback) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await callback;
|
2022-11-29 22:26:34 -08:00
|
|
|
|
} else {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
logStage,
|
|
|
|
|
`There does not appear to be an installation method available for \`${bin}\``
|
|
|
|
|
);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-02 09:50:31 -08:00
|
|
|
|
async function ensurePackageManagerAnsible() {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`pipx install ansible`;
|
|
|
|
|
await $`pipx inject ansible PyObjC PyObjC-core docker lxml netaddr pexpect python-vagrant pywinrm requests-credssp watchdog`;
|
|
|
|
|
await $`mkdir -p "$HOME/.cache/megabyte-labs"`;
|
|
|
|
|
await $`touch "$HOME/.cache/megabyte-labs/ansible-installed"`;
|
|
|
|
|
log(
|
|
|
|
|
"info",
|
|
|
|
|
"Package Manager Install",
|
|
|
|
|
`Ansible and its supporting packages are now installed via pipx`
|
|
|
|
|
);
|
2022-12-02 09:50:31 -08:00
|
|
|
|
}
|
|
|
|
|
|
2022-11-29 22:26:34 -08:00
|
|
|
|
// Ensure the package manager is available
|
|
|
|
|
let packageManagerInstalled = {};
|
|
|
|
|
async function ensurePackageManager(packageManager) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
const logStage = "Package Manager Install";
|
|
|
|
|
log("info", logStage, `Ensuring \`${packageManager}\` is set up`);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
if (packageManagerInstalled[packageManager]) {
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
packageManagerInstalled[packageManager] = true;
|
|
|
|
|
}
|
|
|
|
|
if (packageManager === "ansible") {
|
|
|
|
|
await ensurePackageManager("pipx");
|
|
|
|
|
}
|
|
|
|
|
if (
|
|
|
|
|
packageManager === "gem" ||
|
|
|
|
|
packageManager === "go" ||
|
|
|
|
|
packageManager === "npm" ||
|
|
|
|
|
packageManager === "pipx" ||
|
|
|
|
|
packageManager === "whalebrew"
|
|
|
|
|
) {
|
|
|
|
|
await ensurePackageManager("brew");
|
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
if (packageManager === "appimage") {
|
|
|
|
|
} else if (packageManager === "ansible") {
|
2022-12-02 09:50:31 -08:00
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`test -f "$HOME/.cache/megabyte-labs/ansible-installed"`;
|
|
|
|
|
const ansible = which.sync("ansible", { nothrow: true });
|
2022-12-02 09:50:31 -08:00
|
|
|
|
if (ansible) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log(
|
|
|
|
|
"info",
|
|
|
|
|
logStage,
|
|
|
|
|
`\`ansible\` and its supporting packages appear to be installed`
|
|
|
|
|
);
|
2022-12-02 09:50:31 -08:00
|
|
|
|
} else {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await ensurePackageManagerAnsible();
|
2022-12-02 09:50:31 -08:00
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await ensurePackageManagerAnsible();
|
2022-12-02 09:50:31 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "apk") {
|
|
|
|
|
await ensureInstalled("apk", false);
|
|
|
|
|
} else if (packageManager === "apt") {
|
|
|
|
|
await ensureInstalled("apt", false);
|
|
|
|
|
} else if (packageManager === "basher") {
|
|
|
|
|
await ensureInstalled(
|
|
|
|
|
"basher",
|
|
|
|
|
$`
|
2022-11-29 22:26:34 -08:00
|
|
|
|
# TODO
|
|
|
|
|
echo "Bash script that installs basher here"
|
2022-12-04 21:46:23 -08:00
|
|
|
|
`
|
|
|
|
|
);
|
|
|
|
|
} else if (packageManager === "binary") {
|
|
|
|
|
} else if (packageManager === "bpkg") {
|
|
|
|
|
await ensureInstalled(
|
|
|
|
|
"bpkg",
|
|
|
|
|
$`
|
2022-11-29 22:26:34 -08:00
|
|
|
|
# TODO
|
|
|
|
|
echo "Bash script that installs bpkg here"
|
2022-12-04 21:46:23 -08:00
|
|
|
|
`
|
|
|
|
|
);
|
|
|
|
|
} else if (packageManager === "brew" || packageManager === "cask") {
|
|
|
|
|
const brew = which.sync("brew", { nothrow: true });
|
2022-12-02 06:30:38 -08:00
|
|
|
|
if (!brew) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await ensureInstalled(
|
|
|
|
|
"brew",
|
|
|
|
|
$`
|
2022-12-02 06:30:38 -08:00
|
|
|
|
if command -v sudo > /dev/null && sudo -n true; then
|
|
|
|
|
echo | bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
|
|
|
|
else
|
2022-12-02 16:13:21 -08:00
|
|
|
|
log('info', logStage, 'Homebrew is not installed. Password may be required.')
|
2022-12-02 06:30:38 -08:00
|
|
|
|
bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" || BREW_EXIT_CODE="$?"
|
|
|
|
|
if [ -n "$BREW_EXIT_CODE" ]; then
|
|
|
|
|
if command -v brew > /dev/null; then
|
2022-12-02 16:13:21 -08:00
|
|
|
|
log('warn', logStage, 'Homebrew was installed but part of the installation failed. Attempting to fix..')
|
2022-12-02 06:30:38 -08:00
|
|
|
|
BREW_DIRS="share/man share/doc share/zsh/site-functions etc/bash_completion.d"
|
|
|
|
|
for BREW_DIR in $BREW_DIRS; do
|
|
|
|
|
if [ -d "$(brew --prefix)/$BREW_DIR" ]; then
|
|
|
|
|
sudo chown -R "$(whoami)" "$(brew --prefix)/$BREW_DIR"
|
|
|
|
|
fi
|
|
|
|
|
done
|
|
|
|
|
brew update --force --quiet
|
|
|
|
|
fi
|
2022-11-29 22:26:34 -08:00
|
|
|
|
fi
|
|
|
|
|
fi
|
2022-12-04 21:46:23 -08:00
|
|
|
|
`
|
|
|
|
|
);
|
2022-12-02 06:30:38 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "cargo") {
|
|
|
|
|
await ensureInstalled(
|
|
|
|
|
"cargo",
|
|
|
|
|
$`
|
2022-11-29 22:26:34 -08:00
|
|
|
|
# TODO Bash script that installs cargo
|
2022-12-04 21:46:23 -08:00
|
|
|
|
`
|
|
|
|
|
);
|
|
|
|
|
} else if (packageManager === "choco") {
|
|
|
|
|
await ensureInstalled(
|
|
|
|
|
"choco",
|
|
|
|
|
$`
|
2022-11-29 22:26:34 -08:00
|
|
|
|
powershell "Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))"
|
2022-12-04 21:46:23 -08:00
|
|
|
|
`
|
|
|
|
|
);
|
|
|
|
|
} else if (packageManager === "crew") {
|
|
|
|
|
await ensureInstalled(
|
|
|
|
|
"crew",
|
|
|
|
|
$`
|
2022-11-29 22:26:34 -08:00
|
|
|
|
# TODO Bash script that installs crew here
|
|
|
|
|
# Source: https://github.com/chromebrew/chromebrew
|
|
|
|
|
curl -Ls git.io/vddgY | bash
|
2022-12-04 21:46:23 -08:00
|
|
|
|
`
|
|
|
|
|
);
|
|
|
|
|
} else if (packageManager === "dnf") {
|
|
|
|
|
const dnf = which.sync("dnf", { nothrow: true });
|
|
|
|
|
const yum = which.sync("yum", { nothrow: true });
|
2022-11-29 22:26:34 -08:00
|
|
|
|
if (dnf) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log("info", logStage, `\`dnf\` is available`);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
} else if (yum) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log("info", logStage, `\`yum\` is available`);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
} else {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log("error", logStage, `Both \`dnf\` and \`yum\` are not available`);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "flatpak") {
|
|
|
|
|
const flatpak = which.sync("flatpak", { nothrow: true });
|
2022-11-29 22:26:34 -08:00
|
|
|
|
if (flatpak) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log("info", logStage, `\`flatpak\` is available`);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
} else {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
const apk = which.sync("apk", { nothrow: true });
|
|
|
|
|
const apt = which.sync("apt", { nothrow: true });
|
|
|
|
|
const dnf = which.sync("dnf", { nothrow: true });
|
|
|
|
|
const yum = which.sync("yum", { nothrow: true });
|
|
|
|
|
const pacman = which.sync("pacman", { nothrow: true });
|
|
|
|
|
const zypper = which.sync("zypper", { nothrow: true });
|
2022-11-29 22:26:34 -08:00
|
|
|
|
if (apk) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
$`sudo apk add flatpak`;
|
|
|
|
|
} else if (apt) {
|
2022-11-29 22:26:34 -08:00
|
|
|
|
$`
|
|
|
|
|
sudo apt install -y flatpak
|
|
|
|
|
if [ -f /usr/bin/gnome-shell ]; then
|
|
|
|
|
sudo apt install -y gnome-software-plugin-flatpak
|
|
|
|
|
fi
|
|
|
|
|
if [ -f /usr/bin/plasmashell ]; then
|
|
|
|
|
sudo apt install -y plasmashell
|
|
|
|
|
fi
|
2022-12-04 21:46:23 -08:00
|
|
|
|
`;
|
|
|
|
|
} else if (dnf) {
|
|
|
|
|
await $`sudo dnf install -y flatpak`;
|
|
|
|
|
} else if (yum) {
|
|
|
|
|
await $`sudo yum install -y flatpak`;
|
2022-11-29 22:26:34 -08:00
|
|
|
|
} else if (pacman) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`sudo pacman -Sy flatpak`;
|
2022-11-29 22:26:34 -08:00
|
|
|
|
} else if (zypper) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`sudo zypper install -y flatpak`;
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
const flatpakPost = which.sync("flatpak", { nothrow: true });
|
2022-11-29 22:26:34 -08:00
|
|
|
|
if (flatpakPost) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo`;
|
2022-11-29 22:26:34 -08:00
|
|
|
|
} else {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log("error", logStage, `\`flatpak\` failed to install!`);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log(
|
|
|
|
|
"info",
|
|
|
|
|
logStage,
|
|
|
|
|
`\`flatpak\` was installed. It may require a reboot to function correctly.`
|
|
|
|
|
);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "gem") {
|
|
|
|
|
await ensureInstalled("gem", $`brew install ruby`);
|
|
|
|
|
} else if (packageManager === "go") {
|
|
|
|
|
await ensureInstalled("gem", $`brew install go`);
|
|
|
|
|
} else if (packageManager === "nix") {
|
|
|
|
|
await ensureInstalled(
|
|
|
|
|
"nix",
|
|
|
|
|
$`
|
2022-11-29 22:26:34 -08:00
|
|
|
|
if [ -d /Applications ] && [ -d /Library ]; then
|
|
|
|
|
sh <(curl -L https://nixos.org/nix/install)
|
|
|
|
|
else
|
|
|
|
|
sh <(curl -L https://nixos.org/nix/install) --daemon
|
|
|
|
|
fi
|
2022-12-04 21:46:23 -08:00
|
|
|
|
`
|
|
|
|
|
);
|
|
|
|
|
} else if (packageManager === "npm") {
|
|
|
|
|
const npm = which("npm", { nothrow: true });
|
|
|
|
|
const node = which("node", { nothrow: true });
|
|
|
|
|
const volta = which("volta", { nothrow: true });
|
2022-11-29 22:26:34 -08:00
|
|
|
|
if (npm && node && volta) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log("info", logStage, `\`npm\`, \`node\`, and \`volta\` are available`);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
} else {
|
|
|
|
|
if (!volta) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`brew install volta`;
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
|
|
|
|
await $`
|
|
|
|
|
if [ -z "$VOLTA_HOME" ]; then
|
|
|
|
|
volta setup
|
|
|
|
|
fi
|
|
|
|
|
export PATH="$VOLTA_HOME/bin:$PATH"
|
|
|
|
|
volta install node
|
2022-12-04 21:46:23 -08:00
|
|
|
|
`;
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "pacman") {
|
|
|
|
|
await ensureInstalled("pacman", false);
|
|
|
|
|
} else if (packageManager === "pipx") {
|
|
|
|
|
await ensureInstalled("pipx", $`brew install pipx && pipx ensurepath`);
|
|
|
|
|
} else if (packageManager === "pkg") {
|
|
|
|
|
await ensureInstalled("pkg", false);
|
|
|
|
|
} else if (packageManager === "port") {
|
2022-12-05 12:25:46 -08:00
|
|
|
|
const port = which.sync('port', { nothrow: true })
|
|
|
|
|
if (!port) {
|
|
|
|
|
log('info', logStage, `Installing ${packageManager}`)
|
|
|
|
|
await ensureInstalled(
|
|
|
|
|
"port",
|
|
|
|
|
$`
|
2022-12-05 22:26:29 -08:00
|
|
|
|
set -ex
|
2022-12-05 12:25:46 -08:00
|
|
|
|
sudo mkdir -p /opt/mports
|
|
|
|
|
cd /opt/mports
|
2022-12-05 21:42:36 -08:00
|
|
|
|
sudo rm -rf macports-base
|
2022-12-05 12:25:46 -08:00
|
|
|
|
sudo git clone https://github.com/macports/macports-base.git
|
|
|
|
|
cd macports-base
|
|
|
|
|
sudo git checkout v2.8.0
|
2022-12-05 21:42:36 -08:00
|
|
|
|
sudo ./configure --enable-readline
|
2022-12-05 22:26:29 -08:00
|
|
|
|
make
|
|
|
|
|
make install
|
|
|
|
|
make distclean
|
2022-12-05 12:25:46 -08:00
|
|
|
|
`
|
|
|
|
|
);
|
|
|
|
|
log('info', logStage, `${packageManager} is now installed`)
|
|
|
|
|
} else {
|
|
|
|
|
log("info", logStage, `\`port\` is available`);
|
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "scoop") {
|
|
|
|
|
await ensureInstalled(
|
|
|
|
|
"scoop",
|
|
|
|
|
$`
|
2022-11-29 22:26:34 -08:00
|
|
|
|
powershell 'Set-ExecutionPolicy RemoteSigned -Scope CurrentUser'
|
|
|
|
|
powershell 'irm get.scoop.sh | iex
|
2022-12-04 21:46:23 -08:00
|
|
|
|
`
|
|
|
|
|
);
|
|
|
|
|
} else if (packageManager === "snap") {
|
|
|
|
|
const apk = which.sync("apk", { nothrow: true });
|
|
|
|
|
const apt = which.sync("apt-get", { nothrow: true });
|
|
|
|
|
const dnf = which.sync("dnf", { nothrow: true });
|
|
|
|
|
const yum = which.sync("yum", { nothrow: true });
|
|
|
|
|
const pacman = which.sync("pacman", { nothrow: true });
|
|
|
|
|
const zypper = which.sync("zypper", { nothrow: true });
|
|
|
|
|
if (apt) {
|
|
|
|
|
await $`
|
2022-11-29 22:26:34 -08:00
|
|
|
|
if [ -f /etc/apt/preferences.d/nosnap.pref ]; then
|
|
|
|
|
sudo mv /etc/apt/preferences.d/nosnap.pref /etc/apt/nosnap.pref.bak
|
|
|
|
|
fi
|
|
|
|
|
sudo apt install -y snapd
|
2022-12-04 21:46:23 -08:00
|
|
|
|
`;
|
|
|
|
|
// TODO Following may be required on Kali -> https://snapcraft.io/docs/installing-snap-on-kali
|
|
|
|
|
// systemctl enable --now snapd apparmor
|
|
|
|
|
} else if (dnf) {
|
|
|
|
|
await $`
|
2022-11-29 22:26:34 -08:00
|
|
|
|
sudo dnf install -y snapd
|
|
|
|
|
if [ ! -d /snap ]; then
|
|
|
|
|
sudo ln -s /var/lib/snapd/snap /snap
|
|
|
|
|
fi
|
2022-12-04 21:46:23 -08:00
|
|
|
|
`;
|
|
|
|
|
} else if (yum) {
|
|
|
|
|
await $`
|
2022-11-29 22:26:34 -08:00
|
|
|
|
sudo yum install -y snapd
|
|
|
|
|
sudo systemctl enable --now snapd.socket
|
|
|
|
|
if [ ! -d /snap ]; then
|
|
|
|
|
sudo ln -s /var/lib/snapd/snap /snap
|
|
|
|
|
fi
|
2022-12-04 21:46:23 -08:00
|
|
|
|
`;
|
|
|
|
|
} else if (pacman) {
|
|
|
|
|
await $`
|
2022-11-29 22:26:34 -08:00
|
|
|
|
if [ -f /etc/arch-release ]; then
|
|
|
|
|
sudo git clone https://aur.archlinux.org/snapd.git /usr/local/src/snapd
|
|
|
|
|
cd /usr/local/src/snapd
|
|
|
|
|
sudo makepkg -si
|
|
|
|
|
else
|
|
|
|
|
sudo pacman -S snapd
|
|
|
|
|
sudo systemctl enable --now snapd.socket
|
|
|
|
|
if [ ! -d /snap ]; then
|
|
|
|
|
sudo ln -s /var/lib/snapd/snap /snap
|
|
|
|
|
fi
|
|
|
|
|
fi
|
2022-12-04 21:46:23 -08:00
|
|
|
|
`;
|
|
|
|
|
} else if (zypper) {
|
|
|
|
|
// TODO See https://snapcraft.io/docs/installing-snap-on-opensuse
|
|
|
|
|
await $`
|
2022-11-29 22:26:34 -08:00
|
|
|
|
echo "TODO - Bash script that installs snap w/ zypper"
|
2022-12-04 21:46:23 -08:00
|
|
|
|
`;
|
|
|
|
|
}
|
|
|
|
|
const snap = which.sync("snap", { nothrow: true });
|
|
|
|
|
if (snap) {
|
|
|
|
|
$`sudo snap install core`;
|
|
|
|
|
}
|
|
|
|
|
} else if (packageManager === "whalebrew") {
|
|
|
|
|
await ensureInstalled("whalebrew", $`brew install whalebrew`);
|
|
|
|
|
} else if (packageManager === "winget") {
|
|
|
|
|
await ensureInstalled(
|
|
|
|
|
"winget",
|
|
|
|
|
$`
|
2022-11-29 22:26:34 -08:00
|
|
|
|
echo "TODO - Script that installs winget here"
|
2022-12-04 21:46:23 -08:00
|
|
|
|
`
|
|
|
|
|
);
|
|
|
|
|
} else if (packageManager === "yay") {
|
|
|
|
|
const yay = which.sync("yay", { nothrow: true });
|
|
|
|
|
await $`sudo pacman -S --needed base-devel git`;
|
2022-11-29 22:26:34 -08:00
|
|
|
|
await $`
|
|
|
|
|
if [ -d /usr/local/src ]; then
|
|
|
|
|
git clone https://aur.archlinux.org/yay.git /usr/local/src/yay
|
|
|
|
|
cd /usr/local/src/yay
|
|
|
|
|
makepkg -si
|
|
|
|
|
fi
|
2022-12-04 21:46:23 -08:00
|
|
|
|
`;
|
|
|
|
|
} else if (packageManager === "zypper") {
|
|
|
|
|
await ensureInstalled("zypper", false);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Installs a list of packages via the specified package manager
|
|
|
|
|
async function installPackageList(packageManager, packages) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
const logStage = "Package Install";
|
2022-11-29 22:26:34 -08:00
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
if (packageManager === "appimage") {
|
|
|
|
|
} else if (packageManager === "ansible") {
|
2022-12-02 15:15:45 -08:00
|
|
|
|
for (let pkg of packages) {
|
2022-12-02 16:44:43 -08:00
|
|
|
|
try {
|
2022-12-05 12:16:22 -08:00
|
|
|
|
await $`ansible localhost -vvvvv -m include_role -a name=${pkg} -e ansible_user=${process.env.USER} -e include_homebrew_install=false`;
|
2022-12-02 16:44:43 -08:00
|
|
|
|
} catch (e) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"Ansible Role Failure",
|
|
|
|
|
`There was an error installing ${pkg} with Ansible`
|
|
|
|
|
);
|
2022-12-02 16:44:43 -08:00
|
|
|
|
}
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "apk") {
|
2022-12-02 15:15:45 -08:00
|
|
|
|
for (let pkg of packages) {
|
2022-12-02 17:39:29 -08:00
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`sudo apk add ${pkg}`;
|
2022-12-02 17:39:29 -08:00
|
|
|
|
} catch (e) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"APK Install Failure",
|
|
|
|
|
`There was an error installing ${pkg} with apk`
|
|
|
|
|
);
|
2022-12-02 17:39:29 -08:00
|
|
|
|
}
|
2022-12-02 15:15:45 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "apt") {
|
2022-12-02 15:15:45 -08:00
|
|
|
|
for (let pkg of packages) {
|
2022-12-02 17:39:29 -08:00
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`sudo apt-get install -y ${pkg}`;
|
2022-12-02 17:39:29 -08:00
|
|
|
|
} catch (e) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"apt-get Failure",
|
|
|
|
|
`There was an error installing ${pkg} with apt-get`
|
|
|
|
|
);
|
2022-12-02 17:39:29 -08:00
|
|
|
|
}
|
2022-12-02 15:15:45 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "basher") {
|
2022-12-04 19:51:47 -08:00
|
|
|
|
for (let pkg of packages) {
|
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`basher install ${pkg}`;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"Basher Failure",
|
|
|
|
|
`There was an error installing ${pkg} with basher`
|
|
|
|
|
);
|
2022-12-04 19:51:47 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "binary") {
|
|
|
|
|
} else if (packageManager === "brew") {
|
2022-12-02 15:15:45 -08:00
|
|
|
|
for (let pkg of packages) {
|
2022-12-02 17:39:29 -08:00
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`brew install ${pkg}`;
|
2022-12-02 17:39:29 -08:00
|
|
|
|
} catch (e) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"Homebrew Failure",
|
|
|
|
|
`There was an error installing ${pkg} with brew`
|
|
|
|
|
);
|
2022-12-02 17:39:29 -08:00
|
|
|
|
}
|
2022-12-02 15:15:45 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "cask") {
|
2022-12-02 15:15:45 -08:00
|
|
|
|
for (let pkg of packages) {
|
2022-12-02 17:39:29 -08:00
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`brew install --cask ${pkg}`;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"Homebrew Cask Failure",
|
|
|
|
|
`There was an error installing ${pkg} with Homebrew Cask`
|
|
|
|
|
);
|
2022-12-02 17:39:29 -08:00
|
|
|
|
}
|
2022-12-02 15:15:45 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "cargo") {
|
2022-12-02 06:40:47 -08:00
|
|
|
|
for (const pkg of packages) {
|
2022-12-02 17:39:29 -08:00
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`cargo install ${pkg}`;
|
2022-12-02 17:39:29 -08:00
|
|
|
|
} catch (e) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"Cargo Failure",
|
|
|
|
|
`There was an error installing ${pkg} with Cargo`
|
|
|
|
|
);
|
2022-12-02 17:39:29 -08:00
|
|
|
|
}
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "choco") {
|
2022-12-02 15:15:45 -08:00
|
|
|
|
for (let pkg of packages) {
|
2022-12-02 17:39:29 -08:00
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`choco install -y ${pkg}`;
|
2022-12-02 17:39:29 -08:00
|
|
|
|
} catch (e) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"Chocolatey Failure",
|
|
|
|
|
`There was an error installing ${pkg} with Chocolatey`
|
|
|
|
|
);
|
2022-12-02 17:39:29 -08:00
|
|
|
|
}
|
2022-12-02 15:15:45 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "crew") {
|
|
|
|
|
} else if (packageManager === "dnf") {
|
|
|
|
|
const dnf = which.sync("dnf", { nothrow: true });
|
|
|
|
|
const yum = which.sync("yum", { nothrow: true });
|
2022-11-29 22:26:34 -08:00
|
|
|
|
if (dnf) {
|
2022-12-02 15:15:45 -08:00
|
|
|
|
for (let pkg of packages) {
|
2022-12-02 17:39:29 -08:00
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`sudo dnf install -y ${pkg}`;
|
2022-12-02 17:39:29 -08:00
|
|
|
|
} catch (e) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"dnf Failure",
|
|
|
|
|
`There was an error installing ${pkg} with dnf`
|
|
|
|
|
);
|
2022-12-02 17:39:29 -08:00
|
|
|
|
}
|
2022-12-02 15:15:45 -08:00
|
|
|
|
}
|
2022-11-29 22:26:34 -08:00
|
|
|
|
} else if (yum) {
|
2022-12-02 15:15:45 -08:00
|
|
|
|
for (let pkg of packages) {
|
2022-12-02 17:39:29 -08:00
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`sudo yum install -y ${pkg}`;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"yum Failure",
|
|
|
|
|
`There was an error installing ${pkg} with yum`
|
|
|
|
|
);
|
2022-12-02 17:39:29 -08:00
|
|
|
|
}
|
2022-12-02 15:15:45 -08:00
|
|
|
|
}
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "flatpak") {
|
2022-12-02 06:40:47 -08:00
|
|
|
|
for (let pkg of packages) {
|
2022-12-02 17:39:29 -08:00
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`sudo flatpak install flathub ${pkg}`;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"Flatpak Failure",
|
|
|
|
|
`There was an error installing ${pkg} with flatpak`
|
|
|
|
|
);
|
2022-12-02 17:39:29 -08:00
|
|
|
|
}
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "gem") {
|
2022-12-02 06:40:47 -08:00
|
|
|
|
for (let pkg of packages) {
|
2022-12-02 17:39:29 -08:00
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`gem install ${pkg}`;
|
2022-12-02 17:39:29 -08:00
|
|
|
|
} catch (e) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"Gem Failure",
|
|
|
|
|
`There was an error installing ${pkg} with gem`
|
|
|
|
|
);
|
2022-12-02 17:39:29 -08:00
|
|
|
|
}
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "go") {
|
2022-12-02 06:40:47 -08:00
|
|
|
|
for (let pkg of packages) {
|
2022-12-02 17:39:29 -08:00
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`go install ${pkg}`;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"Go Failure",
|
|
|
|
|
`There was an error installing ${pkg} with go`
|
|
|
|
|
);
|
2022-12-02 17:39:29 -08:00
|
|
|
|
}
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "nix") {
|
|
|
|
|
} else if (packageManager === "npm") {
|
2022-12-02 06:40:47 -08:00
|
|
|
|
for (let pkg of packages) {
|
2022-12-02 17:39:29 -08:00
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`volta install ${pkg}`;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"Volta Failure",
|
|
|
|
|
`There was an error installing ${pkg} with volta`
|
|
|
|
|
);
|
2022-12-02 17:39:29 -08:00
|
|
|
|
}
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "pacman") {
|
2022-12-02 15:15:45 -08:00
|
|
|
|
for (let pkg of packages) {
|
2022-12-02 17:39:29 -08:00
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`sudo pacman -Sy --noconfirm --needed ${pkg}`;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"Pacman Failure",
|
|
|
|
|
`There was an error installing ${pkg} with pacman`
|
|
|
|
|
);
|
2022-12-02 17:39:29 -08:00
|
|
|
|
}
|
2022-12-02 15:15:45 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "pipx") {
|
2022-12-02 06:40:47 -08:00
|
|
|
|
for (let pkg of packages) {
|
2022-12-02 17:39:29 -08:00
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`pipx install ${pkg}`;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"PIPX Failure",
|
|
|
|
|
`There was an error installing ${pkg} with pipx`
|
|
|
|
|
);
|
2022-12-02 17:39:29 -08:00
|
|
|
|
}
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "pkg") {
|
|
|
|
|
} else if (packageManager === "port") {
|
|
|
|
|
const port = which.sync("port", { nothrow: true });
|
2022-12-04 19:39:40 -08:00
|
|
|
|
if (port) {
|
|
|
|
|
for (let pkg of packages) {
|
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`sudo port install ${pkg}`;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"Port Failure",
|
|
|
|
|
`There was an error installing ${pkg} with port`
|
|
|
|
|
);
|
2022-12-04 19:39:40 -08:00
|
|
|
|
}
|
2022-12-02 17:39:29 -08:00
|
|
|
|
}
|
2022-12-04 19:39:40 -08:00
|
|
|
|
} else {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"Port Not Installed",
|
|
|
|
|
`Unable to install with port because it is not installed. Skipping installation of ${packages}`
|
|
|
|
|
);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "scoop") {
|
2022-12-02 06:40:47 -08:00
|
|
|
|
for (let pkg of packages) {
|
2022-12-02 17:39:29 -08:00
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`scoop install ${pkg}`;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"Scoop Failure",
|
|
|
|
|
`There was an error installing ${pkg} with scoop`
|
|
|
|
|
);
|
2022-12-02 17:39:29 -08:00
|
|
|
|
}
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "snap") {
|
2022-12-02 06:40:47 -08:00
|
|
|
|
for (let pkg of packages) {
|
2022-12-02 17:39:29 -08:00
|
|
|
|
// TODO _snapClassic
|
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`sudo snap install -y ${pkg}`;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"Snap Failure",
|
|
|
|
|
`There was an error installing ${pkg} with snap`
|
|
|
|
|
);
|
2022-12-02 17:39:29 -08:00
|
|
|
|
}
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "whalebrew") {
|
2022-12-02 06:40:47 -08:00
|
|
|
|
for (let pkg of packages) {
|
2022-12-02 17:39:29 -08:00
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`whalebrew install ${pkg}`;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"Whalebrew Failure",
|
|
|
|
|
`There was an error installing ${pkg} with whalebrew`
|
|
|
|
|
);
|
2022-12-02 17:39:29 -08:00
|
|
|
|
}
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "winget") {
|
2022-12-04 19:51:47 -08:00
|
|
|
|
for (let pkg of packages) {
|
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`winget install ${pkg}`;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"Winget Failure",
|
|
|
|
|
`There was an error installing ${pkg} with winget`
|
|
|
|
|
);
|
2022-12-04 19:51:47 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "yay") {
|
2022-12-02 06:40:47 -08:00
|
|
|
|
for (let pkg of packages) {
|
2022-12-02 17:39:29 -08:00
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`yay -Sy --noconfirm --needed ${pkg}`;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"Yay Failure",
|
|
|
|
|
`There was an error installing ${pkg} with yay`
|
|
|
|
|
);
|
2022-12-02 17:39:29 -08:00
|
|
|
|
}
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
} else if (packageManager === "zypper") {
|
2022-12-02 15:15:45 -08:00
|
|
|
|
for (let pkg of packages) {
|
2022-12-02 17:39:29 -08:00
|
|
|
|
try {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
await $`sudo zypper install -y ${packages}`;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
"Zypper Failure",
|
|
|
|
|
`There was an error installing ${pkg} with zypper`
|
|
|
|
|
);
|
2022-12-02 17:39:29 -08:00
|
|
|
|
}
|
2022-12-02 15:15:45 -08:00
|
|
|
|
}
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log(
|
|
|
|
|
"error",
|
|
|
|
|
logStage,
|
|
|
|
|
`Possibly encountered an error while installing via \`${packageManager}\``
|
|
|
|
|
);
|
|
|
|
|
log("info", logStage, `Proceeding with the installation..`);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// main process
|
|
|
|
|
async function main() {
|
2022-12-04 21:46:23 -08:00
|
|
|
|
osType = await OSType();
|
|
|
|
|
osID = osType;
|
|
|
|
|
if (osType === "linux") {
|
|
|
|
|
osID = await releaseID();
|
|
|
|
|
}
|
|
|
|
|
log(
|
|
|
|
|
"info",
|
|
|
|
|
"Catalog Download",
|
|
|
|
|
`Fetching the latest version of the installation map`
|
|
|
|
|
);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
installData = await downloadInstallData();
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log("info", "Install Orders", `Calculating the install orders`);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
await generateInstallOrders();
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log(
|
|
|
|
|
"info",
|
|
|
|
|
"Ensure Package Manager Installed",
|
|
|
|
|
`Ensuring any package managers that will be used are installed / configured`
|
|
|
|
|
);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
const packageManagers = Object.keys(installOrders);
|
|
|
|
|
for (const packageManager of packageManagers) {
|
|
|
|
|
await ensurePackageManager(packageManager);
|
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log("info", "Install Orders", `The install orders were generated:`);
|
|
|
|
|
console.log(installOrders);
|
|
|
|
|
log(
|
|
|
|
|
"info",
|
|
|
|
|
"Package Manager Pre-Install",
|
|
|
|
|
`Running package manager pre-installation steps`
|
|
|
|
|
);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
for (const packageManager of packageManagers) {
|
|
|
|
|
await beforeInstall(packageManager);
|
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log(
|
|
|
|
|
"info",
|
|
|
|
|
"Package Pre-Install",
|
|
|
|
|
`Running package-specific pre-installation steps`
|
|
|
|
|
);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
for (const script of installOrdersPre) {
|
|
|
|
|
await $`${script}`;
|
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log("info", "Package Install", `Installing the packages`);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
for (const packageManager of packageManagers) {
|
2022-12-04 22:10:55 -08:00
|
|
|
|
const asyncOrders = [];
|
2022-11-29 22:26:34 -08:00
|
|
|
|
asyncOrders.push(
|
2022-12-04 21:46:23 -08:00
|
|
|
|
installPackageList(packageManager, installOrders[packageManager])
|
2022-11-29 22:26:34 -08:00
|
|
|
|
);
|
|
|
|
|
await Promise.all(asyncOrders);
|
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log(
|
|
|
|
|
"info",
|
|
|
|
|
"Package Post-Install",
|
|
|
|
|
`Running package-specific post-installation steps`
|
|
|
|
|
);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
for (const script of installOrdersPost) {
|
|
|
|
|
await $`${script}`;
|
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log(
|
|
|
|
|
"info",
|
|
|
|
|
"Package Manager Post-Install",
|
|
|
|
|
`Running package manager post-installation steps`
|
|
|
|
|
);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
for (const packageManager of packageManagers) {
|
|
|
|
|
await afterInstall(packageManager);
|
|
|
|
|
}
|
2022-12-04 21:46:23 -08:00
|
|
|
|
log("success", "Installation Complete", `Done!`);
|
2022-11-29 22:26:34 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Start the main process
|
2022-12-04 21:56:39 -08:00
|
|
|
|
await main();
|