Skip to content

Commit 65c779e

Browse files
authored
fix: Initializing git repo on project creation (#2620)
1 parent 1c69d9f commit 65c779e

3 files changed

Lines changed: 60 additions & 13 deletions

File tree

‎packages/wxt/src/cli/__tests__/index.test.ts‎

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -491,34 +491,56 @@ describe('CLI', () => {
491491
mockArgv('init');
492492
await importCli();
493493

494-
expect(initializeMock).toBeCalledWith({});
494+
expect(initializeMock).toBeCalledWith(
495+
expect.objectContaining({ requireGit: true }),
496+
);
495497
});
496498

497499
it('should respect the provided folder', async () => {
498500
mockArgv('init', 'path/to/folder');
499501
await importCli();
500502

501-
expect(initializeMock).toBeCalledWith({
502-
directory: 'path/to/folder',
503-
});
503+
expect(initializeMock).toBeCalledWith(
504+
expect.objectContaining({
505+
directory: 'path/to/folder',
506+
requireGit: true,
507+
}),
508+
);
504509
});
505510

506511
it('should respect passing --template', async () => {
507512
mockArgv('init', '-t', 'vue');
508513
await importCli();
509514

510-
expect(initializeMock).toBeCalledWith({
511-
template: 'vue',
512-
});
515+
expect(initializeMock).toBeCalledWith(
516+
expect.objectContaining({
517+
template: 'vue',
518+
requireGit: true,
519+
}),
520+
);
513521
});
514522

515523
it('should respect passing --pm', async () => {
516524
mockArgv('init', '--pm', 'pnpm');
517525
await importCli();
518526

519-
expect(initializeMock).toBeCalledWith({
520-
packageManager: 'pnpm',
521-
});
527+
expect(initializeMock).toBeCalledWith(
528+
expect.objectContaining({
529+
packageManager: 'pnpm',
530+
requireGit: true,
531+
}),
532+
);
533+
});
534+
535+
it('should respect passing --no-git', async () => {
536+
mockArgv('init', '--no-git');
537+
await importCli();
538+
539+
expect(initializeMock).toBeCalledWith(
540+
expect.objectContaining({
541+
requireGit: false,
542+
}),
543+
);
522544
});
523545
});
524546
});

‎packages/wxt/src/cli/commands.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,13 +151,15 @@ cli
151151
.command('init [directory]', 'initialize a new project')
152152
.option('-t, --template <template>', 'template to use')
153153
.option('--pm <packageManager>', 'which package manager to use')
154+
.option('--no-git', 'skip initialize git repo')
154155
.action(
155156
wrapAction(
156157
async (directory, flags) => {
157158
await initialize({
158159
directory,
159160
template: flags.template,
160161
packageManager: flags.pm,
162+
requireGit: flags.git,
161163
});
162164
},
163165
{ disableFinishedLog: true },

‎packages/wxt/src/initialize.ts‎

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
1-
import { question, select } from '@topcli/prompts';
1+
import { question, select, confirm } from '@topcli/prompts';
22
import { consola } from 'consola';
33
import { downloadTemplate } from 'giget';
44
import { readdir, rename } from 'node:fs/promises';
55
import { pathExists } from './internal-utils/fs-utils';
6+
import { normalizePath } from './internal-utils/path-utils';
67
import path from 'node:path';
78
import { styleText } from 'node:util';
89
import { TextStyle } from './internal-utils/type-utils';
910
import { createSpinner } from './internal/spinner';
11+
import { x as spawn } from 'tinyexec';
1012

1113
export async function initialize(options: {
1214
directory?: string;
1315
template?: string;
1416
packageManager?: string;
17+
requireGit?: boolean;
1518
}) {
1619
consola.info('Initializing new project');
1720

@@ -51,6 +54,11 @@ export async function initialize(options: {
5154
],
5255
}));
5356

57+
// Asks whether require git initialized or not?
58+
const requireGitInitialized =
59+
options.requireGit ??
60+
(await confirm('Initialize a new git repository?', { initial: true }));
61+
5462
const isExists = await pathExists(directory);
5563
if (isExists) {
5664
const isEmpty =
@@ -62,7 +70,7 @@ export async function initialize(options: {
6270
process.exit(1);
6371
}
6472
}
65-
await cloneProject({ directory, template });
73+
await cloneProject({ directory, template, requireGitInitialized });
6674

6775
const cdPath = path.relative(process.cwd(), path.resolve(directory));
6876
console.log();
@@ -151,14 +159,16 @@ async function listTemplatesGithub(): Promise<Template[]> {
151159
async function cloneProject({
152160
directory,
153161
template,
162+
requireGitInitialized,
154163
}: {
155164
directory: string;
156165
template: Template;
166+
requireGitInitialized: boolean;
157167
}) {
158168
const spinner = createSpinner('Downloading template').start();
159169
try {
160170
// 1. Clone repo
161-
await downloadTemplate(`gh:${REPO}/${template.path}`, {
171+
const response = await downloadTemplate(`gh:${REPO}/${template.path}`, {
162172
dir: directory,
163173
force: true,
164174
});
@@ -171,6 +181,19 @@ async function cloneProject({
171181
consola.warn('Failed to move _gitignore to .gitignore:', err),
172182
);
173183

184+
// 3. Initializing Git
185+
if (requireGitInitialized) {
186+
try {
187+
const dirPath = normalizePath(response.dir);
188+
await spawn('git', ['init'], {
189+
throwOnError: true,
190+
nodeOptions: { cwd: dirPath, shell: true },
191+
});
192+
} catch (error) {
193+
console.error(error);
194+
}
195+
}
196+
174197
spinner.success();
175198
} catch (err) {
176199
spinner.error();

0 commit comments

Comments
 (0)