isaacscript
Version:
A command line tool for managing Isaac mods written in TypeScript.
140 lines • 6.39 kB
JavaScript
import chalk from "chalk";
import { commandExists, isFile, readFile } from "complete-node";
import path from "node:path";
import yaml from "yaml";
import { HOME_DIR, PROJECT_NAME, PROJECT_VERSION } from "./constants.js";
import { execShell, execShellString } from "./exec.js";
import { getInputString, getInputYesNo } from "./prompt.js";
export async function promptGitHubRepoOrGitRemoteURL(projectName, yes, skipGit, dev, verbose) {
if (skipGit || dev) {
return undefined;
}
// Hard-code certain project names as never causing a Git repository to be initialized.
if (projectName.startsWith("test") || projectName === "foo") {
return undefined;
}
// We do not need to prompt the user if they do not have Git installed.
const gitExists = await commandExists("git");
if (!gitExists) {
console.log('Git does not seem to be installed. (The "git" command is not in the path.) Skipping Git-related things.');
return undefined;
}
const gitHubUsername = await getGitHubUsername();
if (gitHubUsername !== undefined) {
const { exitStatus } = execShell("gh", ["repo", "view", projectName], verbose, true);
const gitHubRepoExists = exitStatus === 0;
const url = `https://github.com/${gitHubUsername}/${projectName}`;
if (gitHubRepoExists) {
console.log(`Detected an existing GitHub repository at: ${chalk.green(url)}`);
const guessedRemoteURL = getGitRemoteURL(projectName, gitHubUsername);
if (yes) {
console.log(`Using a Git remote URL of: ${chalk.green(guessedRemoteURL)}`);
return guessedRemoteURL;
}
const shouldUseGuessedURL = await getInputYesNo(`Do you want to use a Git remote URL of: ${chalk.green(guessedRemoteURL)}`);
if (shouldUseGuessedURL) {
return guessedRemoteURL;
}
// Assume that since they do not want to connect this project to the existing GitHub
// repository, they do not want to initialize a remote Git URL at all.
return undefined;
}
if (yes) {
execShell("gh", ["repo", "create", projectName, "--public"]);
console.log(`Created a new GitHub repository at: ${chalk.green(url)}`);
return getGitRemoteURL(projectName, gitHubUsername);
}
const createNewGitHubRepo = await getInputYesNo(`Would you like to create a new GitHub repository at: ${chalk.green(url)}`);
if (createNewGitHubRepo) {
execShell("gh", ["repo", "create", projectName, "--public"]);
console.log("Successfully created a new GitHub repository.");
return getGitRemoteURL(projectName, gitHubUsername);
}
// Assume that since they do not want to create a new GitHub repository, they do not want to
// initialize a remote Git URL at all.
return undefined;
}
const gitRemoteURL = await getInputString(`Paste in the remote Git URL for your project.
For example, if you have an SSH key, it would be something like:
${chalk.green("git@github.com:Alice/green-candle.git")}
If you don't have an SSH key, it would be something like:
${chalk.green("https://github.com/Alice/green-candle.git")}
If you don't want to initialize a Git repository for this project, press enter to skip.
`);
return gitRemoteURL === "" ? undefined : gitRemoteURL;
}
/**
* If the GitHub CLI is installed, we can derive the user's GitHub username from their YAML
* configuration.
*/
async function getGitHubUsername() {
const ghExists = await commandExists("gh");
if (!ghExists) {
return undefined;
}
const githubCLIHostsPath = getGithubCLIHostsPath();
if (githubCLIHostsPath === undefined) {
return undefined;
}
const file = await isFile(githubCLIHostsPath);
if (!file) {
return undefined;
}
const configYAMLRaw = await readFile(githubCLIHostsPath);
const configYAML = yaml.parse(configYAMLRaw);
const githubCom = configYAML["github.com"];
if (githubCom === undefined) {
return undefined;
}
const { user } = githubCom;
if (user === undefined || user === "") {
return undefined;
}
return user;
}
function getGithubCLIHostsPath() {
if (process.platform === "win32") {
const appData = process.env["APPDATA"];
if (appData === undefined || appData === "") {
return undefined;
}
return path.join(appData, "GitHub CLI", "hosts.yml");
}
// The location is the same on both macOS and Linux.
return path.join(HOME_DIR, ".config", "gh", "hosts.yml");
}
function getGitRemoteURL(projectName, gitHubUsername) {
return `git@github.com:${gitHubUsername}/${projectName}.git`;
}
export async function initGitRepository(projectPath, gitRemoteURL, verbose) {
const gitExists = await commandExists("git");
if (!gitExists) {
return;
}
if (gitRemoteURL === undefined) {
return;
}
execShellString("git init --initial-branch main", verbose, false, projectPath);
execShell("git", ["remote", "add", "origin", gitRemoteURL], verbose, false, projectPath);
if (isGitNameAndEmailConfigured(verbose)) {
execShellString("git add --all", verbose, false, projectPath);
const commitMessage = `chore: add files from ${PROJECT_NAME} ${PROJECT_VERSION} template`;
execShell("git", ["commit", "--message", commitMessage], verbose, false, projectPath);
execShellString("git push --set-upstream origin main", verbose, false, projectPath);
}
}
function isGitNameAndEmailConfigured(verbose) {
const nameExitStatus = execShellString("git config --global user.name", verbose, true).exitStatus;
const emailExitStatus = execShellString("git config --global user.email", verbose, true).exitStatus;
return nameExitStatus === 0 && emailExitStatus === 0;
}
export function gitCommitAllAndPush(message, verbose) {
execShellString("git add --all", verbose);
execShell("git", ["commit", "--message", message], verbose);
execShellString("git push", verbose);
console.log(`Committed and pushed to the git repository with a message of: ${message}`);
}
export function getReleaseGitCommitMessage(version) {
return `chore: release ${version}`;
}
//# sourceMappingURL=git.js.map