fix(cli): --skip-git treats cwd as index root instead of walking up to parent git repo (#1245)
This commit is contained in:
@@ -107,3 +107,4 @@ local_docs/
|
||||
.tmp/
|
||||
.agents/
|
||||
.context/
|
||||
gitnexus/web/
|
||||
|
||||
@@ -218,21 +218,19 @@ export const analyzeCommand = async (inputPath?: string, options?: AnalyzeOption
|
||||
let repoPath: string;
|
||||
if (inputPath) {
|
||||
repoPath = path.resolve(inputPath);
|
||||
} else if (options?.skipGit) {
|
||||
// --skip-git: treat cwd as the index root, do not walk up to a parent git repo.
|
||||
repoPath = path.resolve(process.cwd());
|
||||
} else {
|
||||
const gitRoot = getGitRoot(process.cwd());
|
||||
if (!gitRoot) {
|
||||
if (!options?.skipGit) {
|
||||
console.log(
|
||||
' Not inside a git repository.\n Tip: pass --skip-git to index any folder without a .git directory.\n',
|
||||
);
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
// --skip-git: fall back to cwd as the root
|
||||
repoPath = path.resolve(process.cwd());
|
||||
} else {
|
||||
repoPath = gitRoot;
|
||||
console.log(
|
||||
' Not inside a git repository.\n Tip: pass --skip-git to index any folder without a .git directory.\n',
|
||||
);
|
||||
process.exitCode = 1;
|
||||
return;
|
||||
}
|
||||
repoPath = gitRoot;
|
||||
}
|
||||
|
||||
const repoHasGit = hasGitDir(repoPath);
|
||||
|
||||
@@ -32,7 +32,10 @@ program
|
||||
.option('--skills', 'Generate repo-specific skill files from detected communities')
|
||||
.option('--skip-agents-md', 'Skip updating the gitnexus section in AGENTS.md and CLAUDE.md')
|
||||
.option('--no-stats', 'Omit volatile file/symbol counts from AGENTS.md and CLAUDE.md')
|
||||
.option('--skip-git', 'Index a folder without requiring a .git directory')
|
||||
.option(
|
||||
'--skip-git',
|
||||
'Treat the provided path/cwd as the index root and skip parent git-root discovery',
|
||||
)
|
||||
.option(
|
||||
'--name <alias>',
|
||||
'Register this repo under a custom name in ~/.gitnexus/registry.json ' +
|
||||
|
||||
@@ -36,4 +36,140 @@ describe('--skip-git CLI flag', () => {
|
||||
fs.rmSync(tmpDir, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
|
||||
describe('--skip-git does not walk up to parent git repo (#1232)', () => {
|
||||
const cliPath = path.resolve(__dirname, '../../dist/cli/index.js');
|
||||
let parentDir: string;
|
||||
|
||||
function testEnv() {
|
||||
return {
|
||||
...process.env,
|
||||
HOME: parentDir,
|
||||
GITNEXUS_HOME: path.join(parentDir, '.gitnexus-home'),
|
||||
GITNEXUS_LBUG_EXTENSION_INSTALL: 'never',
|
||||
};
|
||||
}
|
||||
|
||||
function readRegistry(): Array<{ name: string; path: string }> {
|
||||
const registryPath = path.join(parentDir, '.gitnexus-home', 'registry.json');
|
||||
expect(fs.existsSync(registryPath)).toBe(true);
|
||||
return JSON.parse(fs.readFileSync(registryPath, 'utf8'));
|
||||
}
|
||||
|
||||
function canonicalPath(filePath: string): string {
|
||||
return fs.realpathSync(filePath);
|
||||
}
|
||||
|
||||
function expectCoolioRegistryEntry() {
|
||||
const registry = readRegistry();
|
||||
const entry = registry.find((e) => e.name === 'COOLIO');
|
||||
expect(entry).toBeTruthy();
|
||||
if (!entry) throw new Error('Expected COOLIO registry entry');
|
||||
expect(canonicalPath(entry.path)).toBe(canonicalPath(path.join(parentDir, 'COOLIO')));
|
||||
expect(
|
||||
registry.find((e) => canonicalPath(e.path) === canonicalPath(parentDir)),
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
registry.find(
|
||||
(e) => canonicalPath(e.path) === canonicalPath(path.join(parentDir, 'SubWooder')),
|
||||
),
|
||||
).toBeUndefined();
|
||||
return entry;
|
||||
}
|
||||
|
||||
function initParentGitRepo() {
|
||||
execSync('git init', { cwd: parentDir, stdio: 'ignore' });
|
||||
execSync(
|
||||
'git -c user.name=test -c user.email=test@example.com commit --allow-empty -m init',
|
||||
{
|
||||
cwd: parentDir,
|
||||
stdio: 'ignore',
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
function createTestStructure() {
|
||||
// Create structure:
|
||||
// parentDir/
|
||||
// .git/ (parent is a git repo)
|
||||
// COOLIO/
|
||||
// package.json
|
||||
// src/index.ts
|
||||
// SubWooder/
|
||||
// package.json
|
||||
// src/index.ts
|
||||
parentDir = fs.mkdtempSync(path.join(os.tmpdir(), 'gn-skip-git-'));
|
||||
initParentGitRepo();
|
||||
fs.mkdirSync(path.join(parentDir, 'COOLIO', 'src'), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(parentDir, 'COOLIO', 'package.json'),
|
||||
JSON.stringify({ name: 'coolio' }),
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(parentDir, 'COOLIO', 'src', 'index.ts'),
|
||||
'export const hello = "world";',
|
||||
);
|
||||
fs.mkdirSync(path.join(parentDir, 'SubWooder', 'src'), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(parentDir, 'SubWooder', 'package.json'),
|
||||
JSON.stringify({ name: 'subwooder' }),
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(parentDir, 'SubWooder', 'src', 'index.ts'),
|
||||
'export const bass = 42;',
|
||||
);
|
||||
return parentDir;
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
if (parentDir) {
|
||||
fs.rmSync(parentDir, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
|
||||
it('from subdir inside parent git repo, indexes subdir not parent', () => {
|
||||
createTestStructure();
|
||||
try {
|
||||
// Run analyze from COOLIO with --skip-git
|
||||
const output = execSync(`node "${cliPath}" analyze --skip-git --skip-agents-md`, {
|
||||
cwd: path.join(parentDir, 'COOLIO'),
|
||||
encoding: 'utf8',
|
||||
timeout: 60000,
|
||||
env: testEnv(),
|
||||
});
|
||||
// Should mention COOLIO not the parent dir name
|
||||
expect(output).toContain('COOLIO');
|
||||
|
||||
expectCoolioRegistryEntry();
|
||||
|
||||
const siblingQuery = execSync(`node "${cliPath}" query bass --repo COOLIO`, {
|
||||
cwd: path.join(parentDir, 'COOLIO'),
|
||||
encoding: 'utf8',
|
||||
timeout: 60000,
|
||||
env: testEnv(),
|
||||
});
|
||||
expect(siblingQuery).not.toContain('SubWooder');
|
||||
expect(siblingQuery).not.toContain('bass');
|
||||
} finally {
|
||||
cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
it('explicit input path with --skip-git indexes subdir', () => {
|
||||
createTestStructure();
|
||||
try {
|
||||
const output = execSync(`node "${cliPath}" analyze ./COOLIO --skip-git --skip-agents-md`, {
|
||||
cwd: parentDir,
|
||||
encoding: 'utf8',
|
||||
timeout: 60000,
|
||||
env: testEnv(),
|
||||
});
|
||||
expect(output).toContain('COOLIO');
|
||||
|
||||
expectCoolioRegistryEntry();
|
||||
} finally {
|
||||
cleanup();
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user