mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-04 02:31:36 +00:00
* fix(lbug): resolve non-ASCII paths to 8.3 short form on Windows (#1811) KuzuDB's native C++ layer uses ANSI file APIs (fopen) on Windows. When the repo path contains CJK or other non-ASCII characters, the UTF-8 bytes from Node.js are misinterpreted as the system's Active Code Page (e.g. GBK), producing a garbled path — "Error 3: The system cannot find the path specified." Add `toNativeSafePath()` which converts non-ASCII paths to their Windows 8.3 short-name form (all-ASCII) before passing them to the native layer. Applied to both the database open path and the COPY CSV paths. No-ops on non-Windows and on all-ASCII paths. Closes #1811 * test(lbug): add unit + integration tests for non-ASCII path handling (#1811) - Unit tests for toNativeSafePath: ASCII passthrough, non-Windows no-op, Windows short-path conversion, nonexistent-path fallback - Integration test: full initLbug + loadGraphToLbug round-trip with CJK characters in the storage path — runs on all platforms - Fix toNativeSafePath to reject cmd.exe output containing '?' chars (replacement for unrepresentable Unicode in the console code page) - Register integration test in vitest lbug-db project and cross-platform-tests.ts matrix * chore(autofix): apply prettier + eslint fixes via /autofix command * feat(lbug): junction fallback, tmpdir CSV staging, pool-adapter coverage (#1811) U1+U4: toNativeSafePath now tries 8.3 short path → NTFS junction fallback → diagnostic warning. Junctions target path.dirname(p) and reconstruct the leaf. Handles EEXIST races. Registers cleanup on exit/SIGTERM/SIGINT. Orphan scan on first call removes stale junctions from prior crashes. U2: loadGraphToLbug redirects csvDir to os.tmpdir() when storagePath contains non-ASCII on Windows, avoiding non-ASCII characters in COPY FROM paths entirely. U3: All 4 createLbugDatabase call sites in pool-adapter.ts now wrap dbPath with toNativeSafePath. * fix(test): fix CI failures from toNativeSafePath addition (#1811) - Fix lbug-non-ascii-path integration test: use CodeRelation (actual relationship table name) instead of CALLS - Add toNativeSafePath to lbug-config.js mocks in pool-wal-recovery and lbug-pool-win-fts-probe tests — pool-adapter now imports it * fix(lbug): sanitize path before cmd.exe shell expansion (CodeQL) Reject paths containing cmd.exe metacharacters (" % | & < > ^) before interpolating into the `for %I` short-path command. Prevents command injection via crafted path names. * fix(lbug): address code review findings in non-ASCII path implementation - U1: Use process.exit(0) on Windows instead of process.kill re-raise (SIGTERM forcefully kills on Windows, handlers never fire) - U2: Pass safePath to openWithLockRetry so sidecar sweep targets the path KuzuDB actually opened, not the original non-ASCII path - U3: Skip junction creation in worker threads (isMainThread guard) to prevent junction leaks from pool-adapter workers - U4: Replace existsSync with lstatSync in orphan scan to avoid 30s blocking on unreachable UNC network targets * chore(autofix): apply prettier + eslint fixes via /autofix command * fix(lbug): correct SIGTERM exit code and run Prettier (#1811) - Use exit code 143 (SIGTERM) / 130 (SIGINT) on Windows instead of 0 so termination is not masked as success - Run Prettier to fix formatting (CI Gate blocker) * fix(lbug): eliminate CodeQL command-injection taint in tryShortPath Pass the path via GITNEXUS_SP environment variable instead of interpolating it into the cmd.exe command string. The FOR loop reads %GITNEXUS_SP% from the environment, so the command text is entirely static — no user-controlled data in the shell command. Also removes CMD_UNSAFE_RE since the env var approach makes character-level sanitization unnecessary. --------- Co-authored-by: Test <test@example.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
63 lines
2.3 KiB
TypeScript
63 lines
2.3 KiB
TypeScript
/**
|
|
* Unit Tests: toNativeSafePath
|
|
*
|
|
* Verifies the Windows non-ASCII path workaround that converts paths to
|
|
* 8.3 short-name form before passing them to KuzuDB's native layer.
|
|
*/
|
|
import { describe, it, expect } from 'vitest';
|
|
import { toNativeSafePath, cleanupNativePathJunctions } from '../../src/core/lbug/lbug-config.js';
|
|
|
|
describe('toNativeSafePath', () => {
|
|
it('returns ASCII paths unchanged on any platform', () => {
|
|
const p = 'C:\\Users\\test\\project\\.gitnexus\\lbug';
|
|
expect(toNativeSafePath(p)).toBe(p);
|
|
});
|
|
|
|
it('returns forward-slash ASCII paths unchanged', () => {
|
|
const p = '/home/user/project/.gitnexus/lbug';
|
|
expect(toNativeSafePath(p)).toBe(p);
|
|
});
|
|
|
|
it('returns empty string unchanged', () => {
|
|
expect(toNativeSafePath('')).toBe('');
|
|
});
|
|
|
|
if (process.platform !== 'win32') {
|
|
it('returns non-ASCII paths unchanged on non-Windows', () => {
|
|
const p = '/home/用户/project/.gitnexus/lbug';
|
|
expect(toNativeSafePath(p)).toBe(p);
|
|
});
|
|
}
|
|
|
|
if (process.platform === 'win32') {
|
|
it('converts a path with non-ASCII parent directory to an ASCII-safe form', () => {
|
|
// Real-world scenario: repo at C:\Project\中文\code, leaf is ASCII (.gitnexus/lbug).
|
|
// Create a CJK parent dir with an ASCII leaf to match.
|
|
const os = require('os');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const cjkParent = path.join(os.tmpdir(), `gn-safepath-测试-${Date.now()}`);
|
|
const asciiLeaf = path.join(cjkParent, 'lbug');
|
|
fs.mkdirSync(cjkParent, { recursive: true });
|
|
try {
|
|
const result = toNativeSafePath(asciiLeaf);
|
|
expect(typeof result).toBe('string');
|
|
expect(result.length).toBeGreaterThan(0);
|
|
// Either 8.3 short path or junction — both produce an all-ASCII result
|
|
// since the leaf ('lbug') is ASCII and the parent is resolved
|
|
if (result !== asciiLeaf) {
|
|
expect(/^[\x00-\x7F]+$/.test(result)).toBe(true);
|
|
}
|
|
} finally {
|
|
cleanupNativePathJunctions();
|
|
fs.rmSync(cjkParent, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
it('returns the original path when the target does not exist', () => {
|
|
const nonexistent = 'C:\\不存在的路径\\test';
|
|
const result = toNativeSafePath(nonexistent);
|
|
expect(result).toBe(nonexistent);
|
|
});
|
|
}
|
|
});
|