mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-08-28 05:25:25 +00:00
fix(scan): canonicalize traversal without order-sensitive Rust binding
This commit is contained in:
parent
1482c0bc89
commit
f0f316a7b2
3 changed files with 51 additions and 2 deletions
|
|
@ -83,6 +83,11 @@ export const walkRepositoryPaths = async (
|
|||
}
|
||||
}
|
||||
|
||||
// Filesystem/glob traversal order is not stable across filesystems or repeated
|
||||
// scans. Canonicalize once at the scan boundary so every downstream phase sees
|
||||
// the same repository order.
|
||||
entries.sort((left, right) => (left.path < right.path ? -1 : left.path > right.path ? 1 : 0));
|
||||
|
||||
if (skippedLarge > 0) {
|
||||
const isDefault = maxFileSizeBytes === DEFAULT_MAX_FILE_SIZE_BYTES;
|
||||
const isOverrideUnset = !process.env.GITNEXUS_MAX_FILE_SIZE;
|
||||
|
|
|
|||
|
|
@ -89,6 +89,13 @@ export function populateRustRangeBindings(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Publish per-type member bindings for the whole workspace before resolving
|
||||
// assignments. Otherwise an importer processed before its defining file can
|
||||
// miss a field or identity-method type solely because of file order.
|
||||
const scopeMap = new Map(parsed.scopes.map((scope) => [scope.id, scope]));
|
||||
processFieldTypeBindings(tree.rootNode, parsed, scopeMap);
|
||||
processIdentityMethodBindings(parsed);
|
||||
}
|
||||
|
||||
for (const parsed of parsedFiles) {
|
||||
|
|
@ -122,8 +129,6 @@ export function populateRustRangeBindings(
|
|||
const moduleScope = parsed.scopes.find((s) => s.kind === 'Module');
|
||||
if (moduleScope === undefined) continue;
|
||||
|
||||
processFieldTypeBindings(tree.rootNode, parsed, scopeMap);
|
||||
processIdentityMethodBindings(parsed);
|
||||
processForLoops(tree.rootNode, parsed, scopeMap, moduleScope, allReturnTypes);
|
||||
processPatternBindings(tree.rootNode, parsed, scopeMap, moduleScope);
|
||||
processStructDestructuring(tree.rootNode, parsed, scopeMap, moduleScope, allFieldTypes);
|
||||
|
|
|
|||
39
gitnexus/test/unit/filesystem-walker-order.test.ts
Normal file
39
gitnexus/test/unit/filesystem-walker-order.test.ts
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import fs from 'node:fs/promises';
|
||||
import os from 'node:os';
|
||||
import path from 'node:path';
|
||||
|
||||
import { glob } from 'glob';
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
vi.mock('glob', () => ({ glob: vi.fn() }));
|
||||
vi.mock('../../src/config/ignore-service.js', () => ({
|
||||
createIgnoreFilter: vi.fn(async () => []),
|
||||
}));
|
||||
|
||||
import { walkRepositoryPaths } from '../../src/core/ingestion/filesystem-walker.js';
|
||||
|
||||
const temporaryRoots: string[] = [];
|
||||
|
||||
afterEach(async () => {
|
||||
vi.mocked(glob).mockReset();
|
||||
await Promise.all(
|
||||
temporaryRoots.splice(0).map((root) => fs.rm(root, { recursive: true, force: true })),
|
||||
);
|
||||
});
|
||||
|
||||
describe('walkRepositoryPaths ordering', () => {
|
||||
it('returns accepted files in canonical path order when glob order is unstable', async () => {
|
||||
const root = await fs.mkdtemp(path.join(os.tmpdir(), 'gitnexus-scan-order-'));
|
||||
temporaryRoots.push(root);
|
||||
await Promise.all(
|
||||
['zeta.ts', 'alpha.ts', 'middle.ts'].map((file) =>
|
||||
fs.writeFile(path.join(root, file), `export const ${file[0]} = true;\n`),
|
||||
),
|
||||
);
|
||||
vi.mocked(glob).mockResolvedValue(['zeta.ts', 'alpha.ts', 'middle.ts']);
|
||||
|
||||
const result = await walkRepositoryPaths(root);
|
||||
|
||||
expect(result.map((entry) => entry.path)).toEqual(['alpha.ts', 'middle.ts', 'zeta.ts']);
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Reference in a new issue