From 5b6b96f0bd474aa96119d10a0b79f8e4fb3877b6 Mon Sep 17 00:00:00 2001 From: neverland Date: Sun, 9 Aug 2026 21:46:12 +0800 Subject: [PATCH] feat: support --no-git option --- README.md | 3 +-- src/index.ts | 20 ++++++++++++----- test/git.test.ts | 24 ++++++++++++++++++-- test/help.test.ts | 57 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index a4372c3..2bc265c 100644 --- a/README.md +++ b/README.md @@ -54,8 +54,7 @@ By default, the toolkit initializes a Git repository after creating the project. If the target directory is already inside a Git worktree, the existing repository is reused to avoid creating a nested repository. -Set `git` to `false` to skip Git initialization. Integrations can map their own -CLI option, such as `--not-git`, to this value: +Set `git` to `false` to disable Git initialization: ```ts create({ diff --git a/src/index.ts b/src/index.ts index ef5bd85..fc98b9e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -127,6 +127,7 @@ export type Argv = { help?: boolean; dir?: string; template?: string; + git?: boolean; override?: boolean; tools?: string | string[]; skill?: string | string[]; @@ -172,6 +173,7 @@ function resolveBuiltinTools( function logHelpMessage( name: string, templates: string[], + git: boolean, builtinTools: BuiltinToolName[] | undefined, extraTools?: ExtraTool[], extraSkills?: ExtraSkill[], @@ -197,6 +199,9 @@ function logHelpMessage( } const hasTools = toolsList.length > 0; + const gitOptionLine = git + ? ' --no-git skip Git repository initialization\n' + : ''; const toolsOptionLine = hasTools ? ' --tools add additional tools, comma separated\n' : ''; @@ -222,7 +227,7 @@ function logHelpMessage( -h, --help display help for command -d, --dir create project in specified directory -t, --template specify the template to use -${toolsOptionLine}${skillsOptionLine} --override override files in target directory +${gitOptionLine}${toolsOptionLine}${skillsOptionLine} --override override files in target directory --packageName specify the package name --template-version specify the npm template version @@ -396,6 +401,8 @@ const readPackageJson = async (filePath: string) => const parseArgv = (processArgv: string[]) => { const argv = minimist(processArgv.slice(2), { alias: { h: 'help', d: 'dir', t: 'template' }, + boolean: ['git'], + default: { git: true }, }); // Set dir to first argument if not specified via `--dir` @@ -656,8 +663,8 @@ export async function create({ version?: Record | string; noteInformation?: string[]; /** - * Whether to initialize a Git repository when the target directory is not - * already inside one. + * Whether to initialize a Git repository by default when the target directory + * is not already inside one. Users can opt out with `--no-git`. * * @default true */ @@ -693,9 +700,10 @@ export async function create({ } const argv = parseArgv(processArgv); + const shouldInitGit = git && argv.git !== false; if (argv.help) { - logHelpMessage(name, templates, builtinTools, extraTools, extraSkills); + logHelpMessage(name, templates, git, builtinTools, extraTools, extraSkills); return; } @@ -773,7 +781,7 @@ export async function create({ skipFiles, }); - if (git) { + if (shouldInitGit) { initGit(distFolder); } @@ -817,7 +825,7 @@ export async function create({ skipFiles: localSkipFiles, }); - if (git) { + if (shouldInitGit) { initGit(distFolder); } diff --git a/test/git.test.ts b/test/git.test.ts index e6da020..fa8540a 100644 --- a/test/git.test.ts +++ b/test/git.test.ts @@ -42,14 +42,26 @@ beforeEach(() => { }; }); -async function createProject(projectDir: string, git?: boolean) { +async function createProject( + projectDir: string, + git?: boolean, + extraArgv: string[] = [], +) { await create({ name: 'test', root: fixturesDir, templates: ['vanilla'], getTemplateName: async () => 'vanilla', git, - argv: ['node', 'test', '--dir', projectDir, '--template', 'vanilla'], + argv: [ + 'node', + 'test', + '--dir', + projectDir, + '--template', + 'vanilla', + ...extraArgv, + ], }); } @@ -102,6 +114,14 @@ test('should skip Git initialization when disabled', async () => { expect(mocks.xSync).not.toHaveBeenCalled(); }); +test('should skip Git initialization with --no-git', async () => { + const projectDir = path.join(testDir, 'no-git'); + + await createProject(projectDir, undefined, ['--no-git']); + + expect(mocks.xSync).not.toHaveBeenCalled(); +}); + test('should continue when Git initialization fails', async () => { const projectDir = path.join(testDir, 'failure'); rs.mocked(mocks.xSync).mockImplementation((_command, args) => diff --git a/test/help.test.ts b/test/help.test.ts index 2288826..8e29c23 100644 --- a/test/help.test.ts +++ b/test/help.test.ts @@ -2,6 +2,63 @@ import { expect, test } from '@rstest/core'; import { logger } from 'rslog'; import { create } from '../src'; +test('help message includes the Git opt-out option', async () => { + const logs: string[] = []; + const originalLog = logger.log; + + logger.override({ + log: (message?: unknown) => { + logs.push(String(message ?? '')); + }, + }); + + try { + await create({ + name: 'test', + root: '.', + templates: ['vanilla'], + getTemplateName: async () => 'vanilla', + argv: ['node', 'test', '--help'], + }); + } finally { + logger.override({ + log: originalLog, + }); + } + + expect(logs.join('\n')).toContain( + '--no-git skip Git repository initialization', + ); +}); + +test('help message hides the Git opt-out option when Git is disabled', async () => { + const logs: string[] = []; + const originalLog = logger.log; + + logger.override({ + log: (message?: unknown) => { + logs.push(String(message ?? '')); + }, + }); + + try { + await create({ + name: 'test', + root: '.', + templates: ['vanilla'], + getTemplateName: async () => 'vanilla', + git: false, + argv: ['node', 'test', '--help'], + }); + } finally { + logger.override({ + log: originalLog, + }); + } + + expect(logs.join('\n')).not.toContain('--no-git'); +}); + test('help message includes extra tools', async () => { const logs: string[] = []; const originalLog = logger.log;