Skip to content

Commit

Permalink
refactor: install via flags
Browse files Browse the repository at this point in the history
  • Loading branch information
nickfrosty committed Jan 30, 2025
1 parent 4b94cf9 commit 98a4d93
Show file tree
Hide file tree
Showing 2 changed files with 191 additions and 162 deletions.
5 changes: 5 additions & 0 deletions .changeset/dirty-buttons-brake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"mucho": minor
---

add option flags to the `install` command for core tools or all tools
348 changes: 186 additions & 162 deletions src/commands/install.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Argument, Command } from "@commander-js/extra-typings";
import { Argument, Command, Option } from "@commander-js/extra-typings";
import { cliOutputConfig } from "@/lib/cli";
import { titleMessage, warnMessage } from "@/lib/logs";
import { detectOperatingSystem } from "@/lib/shell";
import { titleMessage, warningOutro } from "@/lib/logs";
import { detectOperatingSystem, getCommandOutput } from "@/lib/shell";
import type { ToolNames } from "@/types";
import {
installAnchorVersionManager,
Expand Down Expand Up @@ -37,178 +37,202 @@ const toolNames: Array<ToolNames> = [
* Setup your local machine for Solana development
*/
export function installCommand() {
return (
new Command("install")
.configureOutput(cliOutputConfig)
.description("install Solana development tooling")
.addArgument(
new Argument("<tool>", "tool to install (default: all)")
.choices(toolNames)
.argOptional(),
)
.addArgument(
new Argument(
"<version>",
"desired tool version to install (default: stable)",
).argOptional(),
)
// .addOption(
// new Option(
// "--dry-run",
// "only check the versions of the installed tools, do not actually install anything",
// ).implies({
// drink: "small",
// }),
// )
.action(async (toolName, version, options) => {
titleMessage("Install Solana development tooling");

const os = detectOperatingSystem();

if (os == "windows") {
warnMessage(
"Windows is not yet natively supported for the rust based tooling.\n" +
"We recommend using WSL inside your Windows terminal.",
);
}
return new Command("install")
.configureOutput(cliOutputConfig)
.description("install Solana development tooling")
.addArgument(
new Argument("<tool>", "tool to install")
.choices(toolNames)
.argOptional(),
)
.addArgument(
new Argument(
"<version>",
"desired tool version to install (default: stable)",
).argOptional(),
)
.addOption(
new Option(
"--core",
"install only the core tools and their dependencies - rust, solana, anchor",
).default(true),
)
.addOption(
new Option(
"--all",
"install all the tools, not just the core tooling",
).default(false),
)
.action(async (toolName, version, options) => {
titleMessage("Install Solana development tools");
if (options.all) options.core = true;

const os = detectOperatingSystem();

if (os == "windows") {
return warningOutro(
"Windows is not yet natively supported for the rust based tooling.\n" +
"We recommend using WSL inside your Windows terminal.",
);
}

const postInstallMessages: string[] = [];

// track which commands may require a path/session refresh
const pathsToRefresh: string[] = [];

const updatesAvailable = await getNpmPackageUpdates("mucho", true);

if (options.all) {
console.log(""); // spacer
console.log("Core tools:");
}

// always check and install `mucho`
await installMucho({
os,
version,
updateAvailable: updatesAvailable.filter(
(data) => data.name.toLowerCase() == "mucho",
)[0],
});

// we require rust to check for available updates on many of the other tools
// so we install it first before performing that version check
if (!toolName || toolName == "rust") {
await installRust({
os,
version,
});

// track which commands may require a path/session refresh
const pathsToRefresh: string[] = [];
await checkShellPathSource(
TOOL_CONFIG.rust.version,
TOOL_CONFIG.rust.pathSource,
).then((status) =>
status == PathSourceStatus.MISSING_PATH
? pathsToRefresh.push(TOOL_CONFIG.rust.pathSource)
: true,
);
}

const anchorVersions = await getAvailableAnchorVersions();
if (
anchorVersions.current &&
anchorVersions.latest &&
isVersionNewer(anchorVersions.latest, anchorVersions.current)
) {
updatesAvailable.push({
installed: anchorVersions.current,
latest: anchorVersions.latest,
name: "anchor",
needsUpdate: true,
});
}

const updatesAvailable = await getNpmPackageUpdates("mucho", true);
// this requires cargo to already be installed, so we must do it after the rust check
updatesAvailable.push(...(await getCargoUpdateOutput()));

// always check and install `mucho`
await installMucho({
if (!toolName || toolName == "solana") {
const res = await installSolana({
os,
version,
updateAvailable: updatesAvailable.filter(
(data) => data.name.toLowerCase() == "mucho",
)[0],
});

if (!toolName || toolName == "rust") {
await installRust({
os,
version,
});

await checkShellPathSource(
TOOL_CONFIG.rust.version,
TOOL_CONFIG.rust.pathSource,
).then((status) =>
status == PathSourceStatus.MISSING_PATH
? pathsToRefresh.push(TOOL_CONFIG.rust.pathSource)
: true,
// string response means this was a fresh install
// so we can perform additional setup steps
if (typeof res == "string") {
await getCommandOutput("solana config set --url localhost");
postInstallMessages.push(
"Create a Solana wallet for your CLI with the following command: solana-keygen new",
);
}

const anchorVersions = await getAvailableAnchorVersions();
if (
anchorVersions.current &&
anchorVersions.latest &&
isVersionNewer(anchorVersions.latest, anchorVersions.current)
) {
updatesAvailable.push({
installed: anchorVersions.current,
latest: anchorVersions.latest,
name: "anchor",
needsUpdate: true,
});
}

// this requires cargo to already be installed, so we must do it after
updatesAvailable.push(...(await getCargoUpdateOutput()));

if (!toolName || toolName == "solana") {
const res = await installSolana({
os,
version,
});

// string response means this was a fresh install
if (typeof res == "string") {
}

await checkShellPathSource(
TOOL_CONFIG.solana.version,
TOOL_CONFIG.solana.pathSource,
).then((status) =>
status == PathSourceStatus.MISSING_PATH
? pathsToRefresh.push(TOOL_CONFIG.solana.pathSource)
: true,
);
}
if (!toolName || toolName == "avm") {
// const version = "0.28.0"; //"latest"; // v0.29.0 has the "ahash yanked" issue
await installAnchorVersionManager({
os,
version,
updateAvailable: updatesAvailable.filter(
(data) => data.name.toLowerCase() == "avm",
)[0],
});
}
if (!toolName || toolName == "anchor") {
await installAnchorUsingAvm({
os,
version,
updateAvailable: updatesAvailable.filter(
(data) => data.name.toLowerCase() == "anchor",
)[0],
});
}
if (!toolName || toolName == "trident") {
await installTrident({
os,
version,
updateAvailable: updatesAvailable.filter(
(data) => data.name.toLowerCase() == "trident-cli",
)[0],
});
}
if (!toolName || toolName == "zest") {
await installZest({
os,
version,
updateAvailable: updatesAvailable.filter(
(data) => data.name.toLowerCase() == "zest",
)[0],
});
}
if (!toolName || toolName == "verify") {
await installSolanaVerify({
os,
version,
updateAvailable: updatesAvailable.filter(
(data) => data.name.toLowerCase() == "solana-verify",
)[0],
});
}
if (!toolName || toolName == "yarn") {
await installYarn({
os,
version,
});
}
await checkShellPathSource(
TOOL_CONFIG.solana.version,
TOOL_CONFIG.solana.pathSource,
).then((status) =>
status == PathSourceStatus.MISSING_PATH
? pathsToRefresh.push(TOOL_CONFIG.solana.pathSource)
: true,
);
}

// anchor is installed via avm
if (!toolName || toolName == "avm" || toolName == "anchor") {
await installAnchorVersionManager({
os,
version,
updateAvailable: updatesAvailable.filter(
(data) => data.name.toLowerCase() == "avm",
)[0],
});
}
if (!toolName || toolName == "anchor") {
await installAnchorUsingAvm({
os,
version,
updateAvailable: updatesAvailable.filter(
(data) => data.name.toLowerCase() == "anchor",
)[0],
});
}

if (pathsToRefresh.length > 0) {
console.log(
"\nClose and reopen your terminal to apply the required",
"PATH changes \nor run the following in your existing shell:",
"\n",
);
console.log(`export PATH="${pathsToRefresh.join(":")}:$PATH"`, "\n");
}
if (!toolName || toolName == "verify") {
await installSolanaVerify({
os,
version,
updateAvailable: updatesAvailable.filter(
(data) => data.name.toLowerCase() == "solana-verify",
)[0],
});
}

// if (tools.allInstalled) {
// return successOutro("All tools are installed!");
// }
// yarn is considered a "core" tool because it is currently a dependency of anchor (sadly)
// this is expected to change in anchor 0.31
if (!toolName || toolName == "yarn") {
await installYarn({
os,
version,
});
}

// if (options.drink !== undefined) console.log(`drink: ${options.drink}`);
if (options.all) {
console.log(""); // spacer
console.log("Additional tools:");
}

// if (tool)
})
);
if ((options.all && !toolName) || toolName == "trident") {
await installTrident({
os,
version,
updateAvailable: updatesAvailable.filter(
(data) => data.name.toLowerCase() == "trident-cli",
)[0],
});
}

// .addCommand(setupInstallCommand())
if ((options.all && !toolName) || toolName == "zest") {
await installZest({
os,
version,
updateAvailable: updatesAvailable.filter(
(data) => data.name.toLowerCase() == "zest",
)[0],
});
}

if (pathsToRefresh.length > 0) {
console.log(
"\nClose and reopen your terminal to apply the required",
"PATH changes \nor run the following in your existing shell:",
"\n",
);
console.log(`export PATH="${pathsToRefresh.join(":")}:$PATH"`, "\n");
}

if (postInstallMessages.length > 0) {
console.log(); // spacer line
console.log(postInstallMessages.join("\n"));
}
});
}

0 comments on commit 98a4d93

Please sign in to comment.