Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/cli/commands/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export const command: CommandDefinition = {
name: 'build [dir]',
description: 'Parse repo and build graph in .codegraph/graph.db',
options: [
['-d, --db <path>', 'Path to graph.db (default: <dir>/.codegraph/graph.db)'],
['--no-incremental', 'Force full rebuild (ignore file hashes)'],
['--no-ast', 'Skip AST node extraction (calls, new, string, regex, throw, await)'],
['--no-complexity', 'Skip complexity metrics computation'],
Expand All @@ -23,6 +24,7 @@ export const command: CommandDefinition = {
engine: engine as EngineMode,
dataflow: opts.dataflow as boolean,
cfg: opts.cfg as boolean,
dbPath: opts.db ? path.resolve(opts.db as string) : undefined,
});
},
};
4 changes: 3 additions & 1 deletion src/domain/graph/builder/pipeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,9 @@ function loadAliases(ctx: PipelineContext): void {

function setupPipeline(ctx: PipelineContext): void {
ctx.rootDir = path.resolve(ctx.rootDir);
ctx.dbPath = path.join(ctx.rootDir, '.codegraph', 'graph.db');
ctx.dbPath = ctx.opts.dbPath
? path.resolve(ctx.opts.dbPath)
: path.join(ctx.rootDir, '.codegraph', 'graph.db');

// Detect whether native engine is available.
const enginePref = ctx.opts.engine || 'auto';
Expand Down
6 changes: 6 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1072,6 +1072,12 @@ export interface BuildGraphOpts {
*/
exclude?: string[];
skipRegistry?: boolean;
/**
* Override the graph.db location. Resolved absolute. When omitted, the
* pipeline writes to `<rootDir>/.codegraph/graph.db` — same default as
* `findDbPath` for every other DB-scoped command.
*/
dbPath?: string;
}

/** Build timing result from buildGraph. */
Expand Down
42 changes: 42 additions & 0 deletions tests/integration/build.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,48 @@ describe('buildGraph', () => {
});
});

describe('buildGraph with custom dbPath (issue #1177)', () => {
let customDir: string, customDbPath: string;

beforeAll(async () => {
customDir = fs.mkdtempSync(path.join(os.tmpdir(), 'codegraph-custom-db-'));
for (const [name, content] of Object.entries(FIXTURE_FILES)) {
fs.writeFileSync(path.join(customDir, name), content);
}
customDbPath = path.join(os.tmpdir(), `codegraph-custom-${Date.now()}.db`);
await buildGraph(customDir, { skipRegistry: true, dbPath: customDbPath });
});

afterAll(() => {
if (customDir) fs.rmSync(customDir, { recursive: true, force: true });
if (customDbPath && fs.existsSync(customDbPath)) {
fs.rmSync(customDbPath, { force: true });
// Clean up sidecar WAL/SHM files
for (const ext of ['-wal', '-shm', '.lock']) {
const sidecar = `${customDbPath}${ext}`;
if (fs.existsSync(sidecar)) fs.rmSync(sidecar, { force: true });
}
}
});

test('writes DB to the custom path, not <rootDir>/.codegraph/graph.db', () => {
expect(fs.existsSync(customDbPath)).toBe(true);
expect(fs.existsSync(path.join(customDir, '.codegraph', 'graph.db'))).toBe(false);
});

test('custom DB contains expected nodes and edges', () => {
const db = new Database(customDbPath, { readonly: true });
const files = db
.prepare("SELECT file FROM nodes WHERE kind = 'file'")
.all()
.map((r) => r.file);
db.close();
expect(files).toContain('math.js');
expect(files).toContain('utils.js');
expect(files).toContain('index.js');
});
});

describe('three-tier incremental builds', () => {
let incrDir: string, incrDbPath: string;

Expand Down
Loading