isaacscript 1.2.26 → 1.2.29
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/dist/package.json +5 -5
- package/dist/src/commands/copy/copy.js +0 -1
- package/dist/src/commands/copy/copy.js.map +1 -1
- package/dist/src/commands/init/checkIfProjectPathExists.js +14 -8
- package/dist/src/commands/init/checkIfProjectPathExists.js.map +1 -1
- package/dist/src/commands/init/checkModSubdirectory.js +2 -2
- package/dist/src/commands/init/checkModSubdirectory.js.map +1 -1
- package/dist/src/commands/init/checkModTargetDirectory.js +12 -6
- package/dist/src/commands/init/checkModTargetDirectory.js.map +1 -1
- package/dist/src/commands/init/createMod.js +11 -96
- package/dist/src/commands/init/createMod.js.map +1 -1
- package/dist/src/commands/init/getProjectPath.js +13 -4
- package/dist/src/commands/init/getProjectPath.js.map +1 -1
- package/dist/src/commands/init/git.js +176 -0
- package/dist/src/commands/init/git.js.map +1 -0
- package/dist/src/commands/init/init.js +11 -6
- package/dist/src/commands/init/init.js.map +1 -1
- package/dist/src/commands/init/promptSaveSlot.js +4 -1
- package/dist/src/commands/init/promptSaveSlot.js.map +1 -1
- package/dist/src/commands/monitor/modDirectorySyncer/modDirectorySyncer.js +0 -5
- package/dist/src/commands/monitor/modDirectorySyncer/modDirectorySyncer.js.map +1 -1
- package/dist/src/commands/publish/publish.js +3 -20
- package/dist/src/commands/publish/publish.js.map +1 -1
- package/dist/src/configFile.js +4 -3
- package/dist/src/configFile.js.map +1 -1
- package/dist/src/parseArgs.js +5 -0
- package/dist/src/parseArgs.js.map +1 -1
- package/dist/src/prompt.js +1 -0
- package/dist/src/prompt.js.map +1 -1
- package/file-templates/static/.github/workflows/ci.yml +3 -3
- package/{src → file-templates/static}/plugins/addCrashDebugStatements.ts +0 -0
- package/file-templates/static/plugins/addIsaacScriptCommentHeader.ts +35 -0
- package/file-templates/static/tsconfig.json +8 -0
- package/isaacscript-watcher/metadata.xml +5 -5
- package/package.json +5 -5
- package/src/commands/copy/copy.ts +0 -1
- package/src/commands/init/checkIfProjectPathExists.ts +19 -12
- package/src/commands/init/checkModSubdirectory.ts +2 -2
- package/src/commands/init/checkModTargetDirectory.ts +17 -11
- package/src/commands/init/createMod.ts +21 -170
- package/src/commands/init/getProjectPath.ts +14 -4
- package/src/commands/init/git.ts +248 -0
- package/src/commands/init/init.ts +21 -6
- package/src/commands/init/promptSaveSlot.ts +5 -0
- package/src/commands/monitor/modDirectorySyncer/modDirectorySyncer.ts +0 -6
- package/src/commands/publish/publish.ts +1 -25
- package/src/configFile.ts +5 -4
- package/src/exec.ts +1 -1
- package/src/parseArgs.ts +6 -0
- package/src/prompt.ts +1 -0
- package/dist/src/monkeyPatch.js +0 -82
- package/dist/src/monkeyPatch.js.map +0 -1
- package/dist/src/plugins/addCrashDebugStatements.js +0 -44
- package/dist/src/plugins/addCrashDebugStatements.js.map +0 -1
- package/src/monkeyPatch.ts +0 -62
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
|
-
import commandExists from "command-exists";
|
|
3
2
|
import path from "path";
|
|
4
|
-
import yaml from "yaml";
|
|
5
3
|
import * as configFile from "../../configFile";
|
|
6
4
|
import {
|
|
7
5
|
GITIGNORE,
|
|
@@ -14,29 +12,24 @@ import {
|
|
|
14
12
|
METADATA_XML_TEMPLATE_PATH,
|
|
15
13
|
PACKAGE_JSON,
|
|
16
14
|
PACKAGE_JSON_TEMPLATE_PATH,
|
|
17
|
-
PROJECT_NAME,
|
|
18
15
|
README_MD,
|
|
19
16
|
README_MD_TEMPLATES_PATH,
|
|
20
17
|
TEMPLATES_STATIC_DIR,
|
|
21
18
|
} from "../../constants";
|
|
22
19
|
import { execShell } from "../../exec";
|
|
23
20
|
import * as file from "../../file";
|
|
24
|
-
import {
|
|
25
|
-
import { GitHubCLIHostsYAML } from "../../types/GitHubCLIHostsYAML";
|
|
26
|
-
import { error, parseSemVer } from "../../utils";
|
|
21
|
+
import { initGitRepository } from "./git";
|
|
27
22
|
|
|
28
|
-
|
|
29
|
-
const REQUIRED_GIT_MINOR_VERSION = 30;
|
|
30
|
-
|
|
31
|
-
export async function createMod(
|
|
23
|
+
export function createMod(
|
|
32
24
|
projectName: string,
|
|
33
25
|
projectPath: string,
|
|
34
26
|
createNewDir: boolean,
|
|
35
27
|
modsDirectory: string,
|
|
36
28
|
saveSlot: number,
|
|
29
|
+
gitRemoteURL: string | undefined,
|
|
37
30
|
skipNPMInstall: boolean,
|
|
38
31
|
verbose: boolean,
|
|
39
|
-
):
|
|
32
|
+
): void {
|
|
40
33
|
if (createNewDir) {
|
|
41
34
|
file.makeDir(projectPath, verbose);
|
|
42
35
|
}
|
|
@@ -45,54 +38,17 @@ export async function createMod(
|
|
|
45
38
|
configFile.createFile(projectPath, config, verbose);
|
|
46
39
|
const targetModDirectory = path.join(config.modsDirectory, projectName);
|
|
47
40
|
|
|
48
|
-
await initGitRepository(projectPath, projectName, verbose);
|
|
49
41
|
makeSubdirectories(projectPath, verbose);
|
|
50
42
|
copyStaticFiles(projectPath, verbose);
|
|
51
43
|
copyDynamicFiles(projectName, projectPath, targetModDirectory, verbose);
|
|
52
44
|
updateNodeModules(projectPath, verbose);
|
|
53
45
|
installNodeModules(projectPath, skipNPMInstall, verbose);
|
|
46
|
+
formatFiles(projectPath, verbose);
|
|
54
47
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
async function initGitRepository(
|
|
59
|
-
projectPath: string,
|
|
60
|
-
projectName: string,
|
|
61
|
-
verbose: boolean,
|
|
62
|
-
) {
|
|
63
|
-
if (!commandExists.sync("git")) {
|
|
64
|
-
console.log(
|
|
65
|
-
'Git does not seem to be installed. (The "git" command is not in the path.) Skipping Git-related things.',
|
|
66
|
-
);
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
checkOldGitVersion(verbose);
|
|
71
|
-
|
|
72
|
-
const remoteURL = await getGitRemoteURL(projectName);
|
|
73
|
-
if (remoteURL === "") {
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
48
|
+
// Only make the initial commit once all of the files have been copied and formatted
|
|
49
|
+
initGitRepository(projectPath, gitRemoteURL, verbose);
|
|
76
50
|
|
|
77
|
-
|
|
78
|
-
execShell("git", ["branch", "-M", "main"], verbose, false, projectPath);
|
|
79
|
-
execShell(
|
|
80
|
-
"git",
|
|
81
|
-
["remote", "add", "origin", remoteURL],
|
|
82
|
-
verbose,
|
|
83
|
-
false,
|
|
84
|
-
projectPath,
|
|
85
|
-
);
|
|
86
|
-
if (isGitNameAndEmailConfigured(verbose)) {
|
|
87
|
-
execShell("git", ["add", "--all"], verbose, false, projectPath);
|
|
88
|
-
execShell(
|
|
89
|
-
"git",
|
|
90
|
-
["commit", "--message", `${PROJECT_NAME} template`],
|
|
91
|
-
verbose,
|
|
92
|
-
false,
|
|
93
|
-
projectPath,
|
|
94
|
-
);
|
|
95
|
-
}
|
|
51
|
+
console.log(`Successfully created mod: ${chalk.green(projectName)}`);
|
|
96
52
|
}
|
|
97
53
|
|
|
98
54
|
function makeSubdirectories(projectPath: string, verbose: boolean) {
|
|
@@ -103,7 +59,7 @@ function makeSubdirectories(projectPath: string, verbose: boolean) {
|
|
|
103
59
|
}
|
|
104
60
|
}
|
|
105
61
|
|
|
106
|
-
|
|
62
|
+
/** Copy static files, like ".eslintrc.js", "tsconfig.json", etc. */
|
|
107
63
|
function copyStaticFiles(projectPath: string, verbose: boolean) {
|
|
108
64
|
const staticFileList = file.getDirList(TEMPLATES_STATIC_DIR);
|
|
109
65
|
staticFileList.forEach((fileName: string) => {
|
|
@@ -115,7 +71,7 @@ function copyStaticFiles(projectPath: string, verbose: boolean) {
|
|
|
115
71
|
});
|
|
116
72
|
}
|
|
117
73
|
|
|
118
|
-
|
|
74
|
+
/** Copy files that need to have text replaced inside of them. */
|
|
119
75
|
function copyDynamicFiles(
|
|
120
76
|
projectName: string,
|
|
121
77
|
projectPath: string,
|
|
@@ -198,6 +154,7 @@ function copyDynamicFiles(
|
|
|
198
154
|
}
|
|
199
155
|
}
|
|
200
156
|
|
|
157
|
+
/** The "package.json" file has to be copied first before this step. */
|
|
201
158
|
function updateNodeModules(projectPath: string, verbose: boolean) {
|
|
202
159
|
console.log("Finding out the latest versions of the NPM packages...");
|
|
203
160
|
execShell(
|
|
@@ -209,122 +166,6 @@ function updateNodeModules(projectPath: string, verbose: boolean) {
|
|
|
209
166
|
);
|
|
210
167
|
}
|
|
211
168
|
|
|
212
|
-
async function getGitRemoteURL(projectName: string) {
|
|
213
|
-
const guessedRemoteURL = guessRemoteURL(projectName);
|
|
214
|
-
if (guessedRemoteURL !== undefined) {
|
|
215
|
-
const shouldUseGuessedURL = await getInputYesNo(
|
|
216
|
-
`Do you want to use a Git remote URL of: ${chalk.green(
|
|
217
|
-
guessedRemoteURL,
|
|
218
|
-
)}`,
|
|
219
|
-
);
|
|
220
|
-
if (shouldUseGuessedURL) {
|
|
221
|
-
return guessedRemoteURL;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
return getInputString(`Paste in the remote Git URL for your project.
|
|
226
|
-
For example, if you have an SSH key, it would be something like:
|
|
227
|
-
${chalk.green("git@github.com:Alice/green-candle.git")}
|
|
228
|
-
If you don't have an SSH key, it would be something like:
|
|
229
|
-
${chalk.green("https://github.com/Alice/green-candle.git")}
|
|
230
|
-
If you don't want to initialize a Git repository for this project, press enter to skip.
|
|
231
|
-
`);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
function checkOldGitVersion(verbose: boolean) {
|
|
235
|
-
const [, stdout] = execShell("git", ["--version"], verbose);
|
|
236
|
-
|
|
237
|
-
const outputPrefix = "git version ";
|
|
238
|
-
if (!stdout.startsWith(outputPrefix)) {
|
|
239
|
-
error(
|
|
240
|
-
`Failed to parse the output from the "git --version" command: ${stdout}`,
|
|
241
|
-
);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
const gitVersionString = stdout.slice(outputPrefix.length);
|
|
245
|
-
const [majorVersion, minorVersion] = parseSemVer(gitVersionString);
|
|
246
|
-
|
|
247
|
-
if (
|
|
248
|
-
majorVersion >= REQUIRED_GIT_MAJOR_VERSION &&
|
|
249
|
-
minorVersion >= REQUIRED_GIT_MINOR_VERSION
|
|
250
|
-
) {
|
|
251
|
-
return;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
console.error(`Your Git version is: ${chalk.red(gitVersionString)}`);
|
|
255
|
-
console.error(
|
|
256
|
-
`${PROJECT_NAME} requires a Git version of ${chalk.red(
|
|
257
|
-
`${REQUIRED_GIT_MAJOR_VERSION}.${REQUIRED_GIT_MINOR_VERSION}.0`,
|
|
258
|
-
)} or greater.`,
|
|
259
|
-
);
|
|
260
|
-
console.error(
|
|
261
|
-
`Please upgrade your version of Git before using ${PROJECT_NAME}.`,
|
|
262
|
-
);
|
|
263
|
-
process.exit(1);
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
function guessRemoteURL(projectName: string) {
|
|
267
|
-
const gitHubUsername = getGitHubUsername();
|
|
268
|
-
if (gitHubUsername === undefined) {
|
|
269
|
-
return undefined;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
return `git@github.com:${gitHubUsername}/${projectName}.git`;
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
function getGitHubUsername() {
|
|
276
|
-
// If the GitHub CLI is installed, we can derive the user's GitHub username
|
|
277
|
-
if (
|
|
278
|
-
!commandExists.sync("gh") ||
|
|
279
|
-
process.env.APPDATA === undefined ||
|
|
280
|
-
process.env.APPDATA === ""
|
|
281
|
-
) {
|
|
282
|
-
return undefined;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
const githubCLIHostsPath = path.join(
|
|
286
|
-
process.env.APPDATA,
|
|
287
|
-
"GitHub CLI",
|
|
288
|
-
"hosts.yml",
|
|
289
|
-
);
|
|
290
|
-
if (!file.exists(githubCLIHostsPath)) {
|
|
291
|
-
return undefined;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
const configYAMLRaw = file.read(githubCLIHostsPath);
|
|
295
|
-
const configYAML = yaml.parse(configYAMLRaw) as GitHubCLIHostsYAML;
|
|
296
|
-
|
|
297
|
-
const githubCom = configYAML["github.com"];
|
|
298
|
-
if (githubCom === undefined) {
|
|
299
|
-
return undefined;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
const { user } = githubCom;
|
|
303
|
-
if (user === "") {
|
|
304
|
-
return undefined;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
return user;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
function isGitNameAndEmailConfigured(verbose: boolean) {
|
|
311
|
-
const [nameExitStatus] = execShell(
|
|
312
|
-
"git",
|
|
313
|
-
["config", "--global", "user.name"],
|
|
314
|
-
verbose,
|
|
315
|
-
true,
|
|
316
|
-
);
|
|
317
|
-
|
|
318
|
-
const [emailExitStatus] = execShell(
|
|
319
|
-
"git",
|
|
320
|
-
["config", "--global", "user.email"],
|
|
321
|
-
verbose,
|
|
322
|
-
true,
|
|
323
|
-
);
|
|
324
|
-
|
|
325
|
-
return nameExitStatus === 0 && emailExitStatus === 0;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
169
|
function installNodeModules(
|
|
329
170
|
projectPath: string,
|
|
330
171
|
skipNPMInstall: boolean,
|
|
@@ -337,3 +178,13 @@ function installNodeModules(
|
|
|
337
178
|
console.log("Installing node modules... (This can take a long time.)");
|
|
338
179
|
execShell("npm", ["install"], verbose, false, projectPath);
|
|
339
180
|
}
|
|
181
|
+
|
|
182
|
+
function formatFiles(projectPath: string, verbose: boolean) {
|
|
183
|
+
execShell(
|
|
184
|
+
"npx",
|
|
185
|
+
["prettier", "--write", projectPath],
|
|
186
|
+
verbose,
|
|
187
|
+
false,
|
|
188
|
+
projectPath,
|
|
189
|
+
);
|
|
190
|
+
}
|
|
@@ -19,20 +19,28 @@ const ILLEGAL_CHARACTERS_FOR_WINDOWS_FILENAMES = [
|
|
|
19
19
|
|
|
20
20
|
export async function getProjectPath(
|
|
21
21
|
argv: Record<string, unknown>,
|
|
22
|
+
useCurrentDir: boolean,
|
|
23
|
+
yes: boolean,
|
|
22
24
|
): Promise<[string, boolean]> {
|
|
23
25
|
let projectName = getProjectNameFromCommandLineArgument(argv);
|
|
24
26
|
let projectPath: string;
|
|
25
27
|
let createNewDir: boolean;
|
|
26
|
-
if (
|
|
28
|
+
if (useCurrentDir) {
|
|
27
29
|
// The "--use-current-dir" command-line flag was specified,
|
|
28
30
|
// so there is no need to prompt the user
|
|
29
31
|
projectName = CURRENT_DIRECTORY_NAME;
|
|
30
32
|
projectPath = CWD;
|
|
31
33
|
createNewDir = false;
|
|
32
|
-
} else if (projectName !==
|
|
34
|
+
} else if (projectName !== undefined) {
|
|
33
35
|
// The project name was specified on the command-line
|
|
34
36
|
projectPath = path.join(CWD, projectName);
|
|
35
37
|
createNewDir = true;
|
|
38
|
+
} else if (yes) {
|
|
39
|
+
// The "--yes" command-line flag was specified and the project name was not specified on the
|
|
40
|
+
// command-line, so default to using the current directory
|
|
41
|
+
projectName = CURRENT_DIRECTORY_NAME;
|
|
42
|
+
projectPath = CWD;
|
|
43
|
+
createNewDir = false;
|
|
36
44
|
} else {
|
|
37
45
|
// The project name was not specified on the command-line, so prompt the user for it
|
|
38
46
|
[projectName, projectPath, createNewDir] = await getNewProjectName();
|
|
@@ -48,8 +56,10 @@ export async function getProjectPath(
|
|
|
48
56
|
|
|
49
57
|
function getProjectNameFromCommandLineArgument(
|
|
50
58
|
argv: Record<string, unknown>,
|
|
51
|
-
): string |
|
|
52
|
-
return typeof argv.name === "string" && argv.name !== ""
|
|
59
|
+
): string | undefined {
|
|
60
|
+
return typeof argv.name === "string" && argv.name !== ""
|
|
61
|
+
? argv.name
|
|
62
|
+
: undefined;
|
|
53
63
|
}
|
|
54
64
|
|
|
55
65
|
async function getNewProjectName(): Promise<[string, string, boolean]> {
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import commandExists from "command-exists";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import yaml from "yaml";
|
|
5
|
+
import { PROJECT_NAME } from "../../constants";
|
|
6
|
+
import { execShell } from "../../exec";
|
|
7
|
+
import * as file from "../../file";
|
|
8
|
+
import { getInputString, getInputYesNo } from "../../prompt";
|
|
9
|
+
import { GitHubCLIHostsYAML } from "../../types/GitHubCLIHostsYAML";
|
|
10
|
+
import { error, parseSemVer } from "../../utils";
|
|
11
|
+
|
|
12
|
+
const REQUIRED_GIT_MAJOR_VERSION = 2;
|
|
13
|
+
const REQUIRED_GIT_MINOR_VERSION = 30;
|
|
14
|
+
|
|
15
|
+
export async function promptGitHubRepoOrGitRemoteURL(
|
|
16
|
+
projectName: string,
|
|
17
|
+
yes: boolean,
|
|
18
|
+
verbose: boolean,
|
|
19
|
+
): Promise<string | undefined> {
|
|
20
|
+
// We do not need to prompt the user if they do not have Git installed
|
|
21
|
+
if (!commandExists.sync("git")) {
|
|
22
|
+
console.log(
|
|
23
|
+
'Git does not seem to be installed. (The "git" command is not in the path.) Skipping Git-related things.',
|
|
24
|
+
);
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
validateNewGitVersion(verbose);
|
|
29
|
+
|
|
30
|
+
const gitHubUsername = getGitHubUsername();
|
|
31
|
+
if (gitHubUsername !== undefined) {
|
|
32
|
+
const [exitStatus] = execShell(
|
|
33
|
+
"gh",
|
|
34
|
+
["repo", "view", projectName],
|
|
35
|
+
verbose,
|
|
36
|
+
true,
|
|
37
|
+
);
|
|
38
|
+
const gitHubRepoExists = exitStatus === 0;
|
|
39
|
+
const url = `https://github.com/${gitHubUsername}/${projectName}`;
|
|
40
|
+
|
|
41
|
+
if (gitHubRepoExists) {
|
|
42
|
+
console.log(
|
|
43
|
+
`Detected an existing GitHub repository at: ${chalk.green(url)}`,
|
|
44
|
+
);
|
|
45
|
+
const guessedRemoteURL = getGitRemoteURL(projectName, gitHubUsername);
|
|
46
|
+
|
|
47
|
+
if (yes) {
|
|
48
|
+
console.log(
|
|
49
|
+
`Using a Git remote URL of: ${chalk.green(guessedRemoteURL)}`,
|
|
50
|
+
);
|
|
51
|
+
return guessedRemoteURL;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const shouldUseGuessedURL = await getInputYesNo(
|
|
55
|
+
`Do you want to use a Git remote URL of: ${chalk.green(
|
|
56
|
+
guessedRemoteURL,
|
|
57
|
+
)}`,
|
|
58
|
+
);
|
|
59
|
+
if (shouldUseGuessedURL) {
|
|
60
|
+
return guessedRemoteURL;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Assume that since they do not want to connect this project to the existing GitHub
|
|
64
|
+
// repository, they do not want to initialize a remote Git URL at all
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (yes) {
|
|
69
|
+
execShell("gh", ["repo", "create", projectName, "--public"]);
|
|
70
|
+
console.log(`Created a new GitHub repository at: ${url}`);
|
|
71
|
+
return getGitRemoteURL(projectName, gitHubUsername);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const createNewGitHubRepo = await getInputYesNo(
|
|
75
|
+
`Would you like to create a new GitHub repository at: ${chalk.green(
|
|
76
|
+
url,
|
|
77
|
+
)}`,
|
|
78
|
+
);
|
|
79
|
+
if (createNewGitHubRepo) {
|
|
80
|
+
execShell("gh", ["repo", "create", projectName, "--public"]);
|
|
81
|
+
console.log("Successfully created a new GitHub repository.");
|
|
82
|
+
return getGitRemoteURL(projectName, gitHubUsername);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Assume that since they do not want to create a new GitHub repository, they do not want to
|
|
86
|
+
// initialize a remote Git URL at all
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const gitRemoteURL =
|
|
91
|
+
await getInputString(`Paste in the remote Git URL for your project.
|
|
92
|
+
For example, if you have an SSH key, it would be something like:
|
|
93
|
+
${chalk.green("git@github.com:Alice/green-candle.git")}
|
|
94
|
+
If you don't have an SSH key, it would be something like:
|
|
95
|
+
${chalk.green("https://github.com/Alice/green-candle.git")}
|
|
96
|
+
If you don't want to initialize a Git repository for this project, press enter to skip.
|
|
97
|
+
`);
|
|
98
|
+
|
|
99
|
+
return gitRemoteURL === "" ? undefined : gitRemoteURL;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function validateNewGitVersion(verbose: boolean) {
|
|
103
|
+
const [, stdout] = execShell("git", ["--version"], verbose);
|
|
104
|
+
|
|
105
|
+
const outputPrefix = "git version ";
|
|
106
|
+
if (!stdout.startsWith(outputPrefix)) {
|
|
107
|
+
error(
|
|
108
|
+
`Failed to parse the output from the "git --version" command: ${stdout}`,
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const gitVersionString = stdout.slice(outputPrefix.length);
|
|
113
|
+
const [majorVersion, minorVersion] = parseSemVer(gitVersionString);
|
|
114
|
+
|
|
115
|
+
if (
|
|
116
|
+
majorVersion >= REQUIRED_GIT_MAJOR_VERSION &&
|
|
117
|
+
minorVersion >= REQUIRED_GIT_MINOR_VERSION
|
|
118
|
+
) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
console.error(`Your Git version is: ${chalk.red(gitVersionString)}`);
|
|
123
|
+
console.error(
|
|
124
|
+
`${PROJECT_NAME} requires a Git version of ${chalk.red(
|
|
125
|
+
`${REQUIRED_GIT_MAJOR_VERSION}.${REQUIRED_GIT_MINOR_VERSION}.0`,
|
|
126
|
+
)} or greater.`,
|
|
127
|
+
);
|
|
128
|
+
console.error(
|
|
129
|
+
`Please upgrade your version of Git before using ${PROJECT_NAME}.`,
|
|
130
|
+
);
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function getGitHubUsername() {
|
|
135
|
+
// If the GitHub CLI is installed, we can derive the user's GitHub username
|
|
136
|
+
if (
|
|
137
|
+
!commandExists.sync("gh") ||
|
|
138
|
+
process.env.APPDATA === undefined ||
|
|
139
|
+
process.env.APPDATA === ""
|
|
140
|
+
) {
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const githubCLIHostsPath = path.join(
|
|
145
|
+
process.env.APPDATA,
|
|
146
|
+
"GitHub CLI",
|
|
147
|
+
"hosts.yml",
|
|
148
|
+
);
|
|
149
|
+
if (!file.exists(githubCLIHostsPath)) {
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const configYAMLRaw = file.read(githubCLIHostsPath);
|
|
154
|
+
const configYAML = yaml.parse(configYAMLRaw) as GitHubCLIHostsYAML;
|
|
155
|
+
|
|
156
|
+
const githubCom = configYAML["github.com"];
|
|
157
|
+
if (githubCom === undefined) {
|
|
158
|
+
return undefined;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const { user } = githubCom;
|
|
162
|
+
if (user === "") {
|
|
163
|
+
return undefined;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return user;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function getGitRemoteURL(projectName: string, gitHubUsername: string) {
|
|
170
|
+
return `git@github.com:${gitHubUsername}/${projectName}.git`;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export function initGitRepository(
|
|
174
|
+
projectPath: string,
|
|
175
|
+
gitRemoteURL: string | undefined,
|
|
176
|
+
verbose: boolean,
|
|
177
|
+
): void {
|
|
178
|
+
if (!commandExists.sync("git")) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
execShell("git", ["init"], verbose, false, projectPath);
|
|
183
|
+
execShell("git", ["branch", "-M", "main"], verbose, false, projectPath);
|
|
184
|
+
|
|
185
|
+
if (isGitNameAndEmailConfigured(verbose)) {
|
|
186
|
+
execShell("git", ["add", "--all"], verbose, false, projectPath);
|
|
187
|
+
execShell(
|
|
188
|
+
"git",
|
|
189
|
+
["commit", "--message", `${PROJECT_NAME} template`],
|
|
190
|
+
verbose,
|
|
191
|
+
false,
|
|
192
|
+
projectPath,
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if (gitRemoteURL !== undefined) {
|
|
197
|
+
execShell(
|
|
198
|
+
"git",
|
|
199
|
+
["remote", "add", "origin", gitRemoteURL],
|
|
200
|
+
verbose,
|
|
201
|
+
false,
|
|
202
|
+
projectPath,
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function isGitNameAndEmailConfigured(verbose: boolean) {
|
|
208
|
+
const [nameExitStatus] = execShell(
|
|
209
|
+
"git",
|
|
210
|
+
["config", "--global", "user.name"],
|
|
211
|
+
verbose,
|
|
212
|
+
true,
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
const [emailExitStatus] = execShell(
|
|
216
|
+
"git",
|
|
217
|
+
["config", "--global", "user.email"],
|
|
218
|
+
verbose,
|
|
219
|
+
true,
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
return nameExitStatus === 0 && emailExitStatus === 0;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export function isGitDirty(verbose: boolean): boolean {
|
|
226
|
+
// From: https://remarkablemark.org/blog/2017/10/12/check-git-dirty/
|
|
227
|
+
const [, stdout] = execShell("git", ["status", "--porcelain"], verbose);
|
|
228
|
+
return stdout !== "";
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export function gitCommitIfChanges(version: string, verbose: boolean): void {
|
|
232
|
+
// Throw an error if this is not a git repository
|
|
233
|
+
execShell("git", ["status"], verbose);
|
|
234
|
+
|
|
235
|
+
if (!isGitDirty(verbose)) {
|
|
236
|
+
console.log("There are no changes to commit.");
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const commitMessage = `v${version}`;
|
|
241
|
+
execShell("git", ["add", "-A"], verbose);
|
|
242
|
+
execShell("git", ["commit", "-m", commitMessage], verbose);
|
|
243
|
+
execShell("git", ["push"], verbose);
|
|
244
|
+
|
|
245
|
+
console.log(
|
|
246
|
+
`Committed and pushed to the git repository with a message of: ${commitMessage}`,
|
|
247
|
+
);
|
|
248
|
+
}
|
|
@@ -8,33 +8,48 @@ import { checkModTargetDirectory } from "./checkModTargetDirectory";
|
|
|
8
8
|
import { createMod } from "./createMod";
|
|
9
9
|
import { getModsDir } from "./getModsDir";
|
|
10
10
|
import { getProjectPath } from "./getProjectPath";
|
|
11
|
+
import { promptGitHubRepoOrGitRemoteURL } from "./git";
|
|
11
12
|
import { installVSCodeExtensions } from "./installVSCodeExtensions";
|
|
12
13
|
import { promptSaveSlot } from "./promptSaveSlot";
|
|
13
14
|
import { promptVSCode } from "./promptVSCode";
|
|
14
15
|
|
|
15
16
|
export async function init(argv: Record<string, unknown>): Promise<void> {
|
|
16
|
-
const vscode = argv.vscode === true;
|
|
17
17
|
const skipNPMInstall = argv.skipNpmInstall === true;
|
|
18
|
+
const useCurrentDir = argv.useCurrentDir === true;
|
|
18
19
|
const verbose = argv.verbose === true;
|
|
20
|
+
const vscode = argv.vscode === true;
|
|
21
|
+
const yes = argv.yes === true;
|
|
19
22
|
|
|
20
23
|
// Prompt the end-user for some information (and validate it as we go)
|
|
21
|
-
const [projectPath, createNewDir] = await getProjectPath(
|
|
22
|
-
|
|
24
|
+
const [projectPath, createNewDir] = await getProjectPath(
|
|
25
|
+
argv,
|
|
26
|
+
useCurrentDir,
|
|
27
|
+
yes,
|
|
28
|
+
);
|
|
29
|
+
await checkIfProjectPathExists(projectPath, yes, verbose);
|
|
23
30
|
const modsDirectory = await getModsDir(argv);
|
|
24
31
|
checkModSubdirectory(projectPath, modsDirectory);
|
|
25
32
|
const projectName = path.basename(projectPath);
|
|
26
|
-
await checkModTargetDirectory(modsDirectory, projectName, verbose);
|
|
27
|
-
const saveSlot = await promptSaveSlot(argv);
|
|
33
|
+
await checkModTargetDirectory(modsDirectory, projectName, yes, verbose);
|
|
34
|
+
const saveSlot = await promptSaveSlot(argv, yes);
|
|
35
|
+
const gitRemoteURL = await promptGitHubRepoOrGitRemoteURL(
|
|
36
|
+
projectName,
|
|
37
|
+
yes,
|
|
38
|
+
verbose,
|
|
39
|
+
);
|
|
28
40
|
|
|
29
|
-
|
|
41
|
+
// Now that we have asked the user all of the questions we need, we can create the project
|
|
42
|
+
createMod(
|
|
30
43
|
projectName,
|
|
31
44
|
projectPath,
|
|
32
45
|
createNewDir,
|
|
33
46
|
modsDirectory,
|
|
34
47
|
saveSlot,
|
|
48
|
+
gitRemoteURL,
|
|
35
49
|
skipNPMInstall,
|
|
36
50
|
verbose,
|
|
37
51
|
);
|
|
52
|
+
|
|
38
53
|
await openVSCode(projectPath, vscode, verbose);
|
|
39
54
|
printFinishMessage(projectPath, projectName);
|
|
40
55
|
}
|
|
@@ -3,6 +3,7 @@ import { error } from "../../utils";
|
|
|
3
3
|
|
|
4
4
|
export async function promptSaveSlot(
|
|
5
5
|
argv: Record<string, unknown>,
|
|
6
|
+
yes: boolean,
|
|
6
7
|
): Promise<number> {
|
|
7
8
|
if (argv.saveSlot !== undefined) {
|
|
8
9
|
// They specified the "--save-slot" command-line flag,
|
|
@@ -10,6 +11,10 @@ export async function promptSaveSlot(
|
|
|
10
11
|
return argv.saveSlot as number;
|
|
11
12
|
}
|
|
12
13
|
|
|
14
|
+
if (yes) {
|
|
15
|
+
return 1;
|
|
16
|
+
}
|
|
17
|
+
|
|
13
18
|
const saveSlot = await getInputInt(
|
|
14
19
|
"In-game, will you test your mod on save slot 1, 2, or 3?",
|
|
15
20
|
);
|
|
@@ -41,12 +41,6 @@ function afterEachSync(params?: {
|
|
|
41
41
|
return;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
/*
|
|
45
|
-
if (params.relativePath === path.sep + MAIN_LUA) {
|
|
46
|
-
monkeyPatchMainLua(modTargetPath);
|
|
47
|
-
}
|
|
48
|
-
*/
|
|
49
|
-
|
|
50
44
|
if (params.eventType !== "init:copy") {
|
|
51
45
|
send(`${FILE_SYNCED_MESSAGE} ${params.relativePath}`);
|
|
52
46
|
}
|
|
@@ -17,6 +17,7 @@ import * as file from "../../file";
|
|
|
17
17
|
import { Config } from "../../types/Config";
|
|
18
18
|
import { error, getModTargetDirectoryName, parseIntSafe } from "../../utils";
|
|
19
19
|
import { compileAndCopy } from "../copy/copy";
|
|
20
|
+
import { gitCommitIfChanges, isGitDirty } from "../init/git";
|
|
20
21
|
|
|
21
22
|
const UPDATE_SCRIPT_NAME = "update.sh";
|
|
22
23
|
|
|
@@ -289,31 +290,6 @@ function runReleaseScriptPostCopy(verbose: boolean) {
|
|
|
289
290
|
}
|
|
290
291
|
}
|
|
291
292
|
|
|
292
|
-
function gitCommitIfChanges(version: string, verbose: boolean) {
|
|
293
|
-
// Throw an error if this is not a git repository
|
|
294
|
-
execShell("git", ["status"], verbose);
|
|
295
|
-
|
|
296
|
-
if (!isGitDirty(verbose)) {
|
|
297
|
-
console.log("There are no changes to commit.");
|
|
298
|
-
return;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
const commitMessage = `v${version}`;
|
|
302
|
-
execShell("git", ["add", "-A"], verbose);
|
|
303
|
-
execShell("git", ["commit", "-m", commitMessage], verbose);
|
|
304
|
-
execShell("git", ["push"], verbose);
|
|
305
|
-
|
|
306
|
-
console.log(
|
|
307
|
-
`Committed and pushed to the git repository with a message of: ${commitMessage}`,
|
|
308
|
-
);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
function isGitDirty(verbose: boolean) {
|
|
312
|
-
// From: https://remarkablemark.org/blog/2017/10/12/check-git-dirty/
|
|
313
|
-
const [, stdout] = execShell("git", ["status", "--porcelain"], verbose);
|
|
314
|
-
return stdout !== "";
|
|
315
|
-
}
|
|
316
|
-
|
|
317
293
|
function purgeRoomXMLs(modTargetPath: string, verbose: boolean) {
|
|
318
294
|
const roomsPath = path.join(modTargetPath, "resources", "rooms");
|
|
319
295
|
if (!file.exists(roomsPath) || !file.isDir(roomsPath)) {
|