gitnexus 1.6.6-rc.49 → 1.6.6-rc.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/analyze.js +1 -0
- package/dist/cli/setup.js +2 -0
- package/dist/cli/wiki.js +3 -3
- package/dist/core/embeddings/embedder.js +5 -1
- package/dist/core/git-staleness.js +3 -0
- package/dist/core/lbug/lbug-adapter.js +106 -74
- package/dist/core/run-analyze.js +1 -0
- package/dist/core/wiki/cursor-client.js +2 -1
- package/dist/core/wiki/generator.js +8 -1
- package/dist/mcp/local/local-backend.js +2 -0
- package/dist/server/git-clone.js +2 -0
- package/dist/storage/git.js +10 -1
- package/hooks/claude/gitnexus-hook.cjs +4 -0
- package/hooks/claude/hook-db-lock-probe.cjs +3 -0
- package/package.json +1 -1
package/dist/cli/analyze.js
CHANGED
package/dist/cli/setup.js
CHANGED
|
@@ -42,6 +42,7 @@ function resolveGitnexusBin() {
|
|
|
42
42
|
encoding: 'utf-8',
|
|
43
43
|
timeout: 5000,
|
|
44
44
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
45
|
+
windowsHide: true,
|
|
45
46
|
});
|
|
46
47
|
const lines = output
|
|
47
48
|
.split('\n')
|
|
@@ -454,6 +455,7 @@ async function setupCodex(result) {
|
|
|
454
455
|
const entry = getMcpEntry();
|
|
455
456
|
await execFileAsync('codex', ['mcp', 'add', 'gitnexus', '--', entry.command, ...entry.args], {
|
|
456
457
|
shell: process.platform === 'win32',
|
|
458
|
+
windowsHide: true,
|
|
457
459
|
});
|
|
458
460
|
result.configured.push('Codex');
|
|
459
461
|
return;
|
package/dist/cli/wiki.js
CHANGED
|
@@ -442,7 +442,7 @@ const wikiCommandImpl = async (inputPath, options) => {
|
|
|
442
442
|
console.log(`\n Opening ${treeFile} in ${editor}...`);
|
|
443
443
|
console.log(' Save and close the editor when done.\n');
|
|
444
444
|
try {
|
|
445
|
-
execFileSync(editor, [treeFile], { stdio: 'inherit' });
|
|
445
|
+
execFileSync(editor, [treeFile], { stdio: 'inherit', windowsHide: true });
|
|
446
446
|
}
|
|
447
447
|
catch {
|
|
448
448
|
console.log(` Could not open editor. Please edit manually:\n ${treeFile}\n`);
|
|
@@ -556,7 +556,7 @@ const wikiCommandImpl = async (inputPath, options) => {
|
|
|
556
556
|
// ─── Gist Publishing ───────────────────────────────────────────────────
|
|
557
557
|
function hasGhCLI() {
|
|
558
558
|
try {
|
|
559
|
-
execSync('gh --version', { stdio: 'ignore' });
|
|
559
|
+
execSync('gh --version', { stdio: 'ignore', windowsHide: true });
|
|
560
560
|
return true;
|
|
561
561
|
}
|
|
562
562
|
catch {
|
|
@@ -595,7 +595,7 @@ function isGistUrl(line) {
|
|
|
595
595
|
}
|
|
596
596
|
function publishGist(htmlPath) {
|
|
597
597
|
try {
|
|
598
|
-
const output = execFileSync('gh', ['gist', 'create', htmlPath, '--desc', 'Repository Wiki — generated by GitNexus', '--public'], { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
598
|
+
const output = execFileSync('gh', ['gist', 'create', htmlPath, '--desc', 'Repository Wiki — generated by GitNexus', '--public'], { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true }).trim();
|
|
599
599
|
// `gh gist create` prints the gist URL as a line in the output. Find the
|
|
600
600
|
// first parseable Gist URL — if no line is a valid Gist URL, fail closed
|
|
601
601
|
// (do NOT fall back to lines[last]: a non-Gist last line would propagate
|
|
@@ -68,7 +68,11 @@ function isCudaAvailable() {
|
|
|
68
68
|
// Primary: query the dynamic linker cache — covers all architectures,
|
|
69
69
|
// distro layouts, and custom install paths registered with ldconfig
|
|
70
70
|
try {
|
|
71
|
-
const out = execFileSync('ldconfig', ['-p'], {
|
|
71
|
+
const out = execFileSync('ldconfig', ['-p'], {
|
|
72
|
+
timeout: 3000,
|
|
73
|
+
encoding: 'utf-8',
|
|
74
|
+
windowsHide: true,
|
|
75
|
+
});
|
|
72
76
|
if (out.includes('libcublasLt.so.12'))
|
|
73
77
|
return true;
|
|
74
78
|
}
|
|
@@ -17,6 +17,7 @@ export function checkStaleness(repoPath, lastCommit) {
|
|
|
17
17
|
cwd: repoPath,
|
|
18
18
|
encoding: 'utf-8',
|
|
19
19
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
20
|
+
windowsHide: true,
|
|
20
21
|
}).trim();
|
|
21
22
|
const commitsBehind = parseInt(result, 10) || 0;
|
|
22
23
|
if (commitsBehind > 0) {
|
|
@@ -44,6 +45,7 @@ export async function checkStalenessAsync(repoPath, lastCommit) {
|
|
|
44
45
|
const { stdout } = await execFileAsync('git', ['rev-list', '--count', `${lastCommit}..HEAD`], {
|
|
45
46
|
cwd: repoPath,
|
|
46
47
|
encoding: 'utf-8',
|
|
48
|
+
windowsHide: true,
|
|
47
49
|
});
|
|
48
50
|
const commitsBehind = parseInt(stdout.trim(), 10) || 0;
|
|
49
51
|
if (commitsBehind > 0) {
|
|
@@ -73,6 +75,7 @@ function commitsAheadOfIndexed(siblingPath, indexedCommit) {
|
|
|
73
75
|
cwd: siblingPath,
|
|
74
76
|
encoding: 'utf-8',
|
|
75
77
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
78
|
+
windowsHide: true,
|
|
76
79
|
}).trim();
|
|
77
80
|
return parseInt(result, 10) || 0;
|
|
78
81
|
}
|
|
@@ -418,6 +418,7 @@ const reopenWritableAfterMissingShadow = async (dbPath, err) => {
|
|
|
418
418
|
return await openLbugConnection(lbug, dbPath);
|
|
419
419
|
};
|
|
420
420
|
const ensureReadOnlyConnectionUsable = async (dbPath, handle) => {
|
|
421
|
+
let shadowReplayErr;
|
|
421
422
|
try {
|
|
422
423
|
await queryAndDrain(handle.conn, READ_ONLY_SHADOW_REPLAY_PROBE);
|
|
423
424
|
return handle;
|
|
@@ -431,9 +432,22 @@ const ensureReadOnlyConnectionUsable = async (dbPath, handle) => {
|
|
|
431
432
|
await closeLbugConnection(handle);
|
|
432
433
|
throw err;
|
|
433
434
|
}
|
|
435
|
+
shadowReplayErr = err;
|
|
434
436
|
}
|
|
435
437
|
await closeLbugConnection(handle);
|
|
436
|
-
|
|
438
|
+
let writable;
|
|
439
|
+
try {
|
|
440
|
+
writable = await openLbugConnection(lbug, dbPath);
|
|
441
|
+
}
|
|
442
|
+
catch (openErr) {
|
|
443
|
+
const code = extractErrnoCode(openErr);
|
|
444
|
+
if (code === 'EROFS' || code === 'EACCES' || code === 'EPERM') {
|
|
445
|
+
throw new Error(shadowSidecarRecoveryMessage(dbPath, shadowReplayErr) +
|
|
446
|
+
'\n The workspace appears to be read-only — mount it read-write to perform shadow replay recovery,' +
|
|
447
|
+
' or re-run `gitnexus analyze` on a writable filesystem to rebuild the index.');
|
|
448
|
+
}
|
|
449
|
+
throw openErr;
|
|
450
|
+
}
|
|
437
451
|
let missingShadowError;
|
|
438
452
|
try {
|
|
439
453
|
await queryAndDrain(writable.conn, READ_ONLY_SHADOW_REPLAY_PROBE);
|
|
@@ -573,89 +587,107 @@ const doInitLbug = async (dbPath, readOnly = false) => {
|
|
|
573
587
|
vectorExtensionLoaded = false;
|
|
574
588
|
ensuredFTSIndexes.clear();
|
|
575
589
|
}
|
|
576
|
-
// LadybugDB stores the database as a single file (not a directory).
|
|
577
|
-
// If the path already exists, it must be a valid LadybugDB database file.
|
|
578
|
-
// Remove stale empty directories or files from older versions.
|
|
579
|
-
try {
|
|
580
|
-
const stat = await fs.lstat(dbPath);
|
|
581
|
-
if (stat.isSymbolicLink()) {
|
|
582
|
-
// Never follow symlinks — just remove the link itself
|
|
583
|
-
await fs.unlink(dbPath);
|
|
584
|
-
}
|
|
585
|
-
else if (stat.isDirectory()) {
|
|
586
|
-
// Verify path is within expected storage directory before deleting
|
|
587
|
-
const realPath = await fs.realpath(dbPath);
|
|
588
|
-
const parentDir = path.dirname(dbPath);
|
|
589
|
-
const realParent = await fs.realpath(parentDir);
|
|
590
|
-
if (!realPath.startsWith(realParent + path.sep) && realPath !== realParent) {
|
|
591
|
-
throw new Error(`Refusing to delete ${dbPath}: resolved path ${realPath} is outside storage directory`);
|
|
592
|
-
}
|
|
593
|
-
// Old-style directory database or empty leftover - remove it
|
|
594
|
-
await fs.rm(dbPath, { recursive: true, force: true });
|
|
595
|
-
}
|
|
596
|
-
// If it's a file, assume it's an existing LadybugDB database - LadybugDB will open it
|
|
597
|
-
}
|
|
598
|
-
catch (err) {
|
|
599
|
-
if (!isMissingFileError(err)) {
|
|
600
|
-
throw err;
|
|
601
|
-
}
|
|
602
|
-
// Path doesn't exist, which is what LadybugDB wants for a new database
|
|
603
|
-
}
|
|
604
590
|
// ---------------------------------------------------------------------------
|
|
605
|
-
//
|
|
606
|
-
//
|
|
607
|
-
//
|
|
608
|
-
//
|
|
591
|
+
// Read-only fast path: skip all filesystem mutations (path cleanup, init
|
|
592
|
+
// lock, orphan sidecar removal, mkdir) so the open succeeds on read-only
|
|
593
|
+
// filesystems such as Docker `:ro` bind mounts. The init lock exists to
|
|
594
|
+
// prevent a TOCTOU race during DB *creation* — read-only opens never
|
|
595
|
+
// create databases and don't need the lock.
|
|
609
596
|
// ---------------------------------------------------------------------------
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
597
|
+
if (readOnly) {
|
|
598
|
+
await preflightLbugSidecars(dbPath, {
|
|
599
|
+
mode: 'read-only',
|
|
600
|
+
logger,
|
|
601
|
+
allowQuarantine: false,
|
|
602
|
+
});
|
|
603
|
+
const opened = await openLbugConnection(lbug, dbPath, { readOnly: true });
|
|
604
|
+
const usable = await ensureReadOnlyConnectionUsable(dbPath, opened);
|
|
605
|
+
db = usable.db;
|
|
606
|
+
conn = usable.conn;
|
|
607
|
+
currentDbReadOnly = true;
|
|
608
|
+
}
|
|
609
|
+
else {
|
|
610
|
+
// LadybugDB stores the database as a single file (not a directory).
|
|
611
|
+
// If the path already exists, it must be a valid LadybugDB database file.
|
|
612
|
+
// Remove stale empty directories or files from older versions.
|
|
614
613
|
try {
|
|
615
|
-
await fs.
|
|
614
|
+
const stat = await fs.lstat(dbPath);
|
|
615
|
+
if (stat.isSymbolicLink()) {
|
|
616
|
+
// Never follow symlinks — just remove the link itself
|
|
617
|
+
await fs.unlink(dbPath);
|
|
618
|
+
}
|
|
619
|
+
else if (stat.isDirectory()) {
|
|
620
|
+
// Verify path is within expected storage directory before deleting
|
|
621
|
+
const realPath = await fs.realpath(dbPath);
|
|
622
|
+
const parentDir = path.dirname(dbPath);
|
|
623
|
+
const realParent = await fs.realpath(parentDir);
|
|
624
|
+
if (!realPath.startsWith(realParent + path.sep) && realPath !== realParent) {
|
|
625
|
+
throw new Error(`Refusing to delete ${dbPath}: resolved path ${realPath} is outside storage directory`);
|
|
626
|
+
}
|
|
627
|
+
// Old-style directory database or empty leftover - remove it
|
|
628
|
+
await fs.rm(dbPath, { recursive: true, force: true });
|
|
629
|
+
}
|
|
630
|
+
// If it's a file, assume it's an existing LadybugDB database - LadybugDB will open it
|
|
616
631
|
}
|
|
617
632
|
catch (err) {
|
|
618
|
-
if (isMissingFileError(err)) {
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
633
|
+
if (!isMissingFileError(err)) {
|
|
634
|
+
throw err;
|
|
635
|
+
}
|
|
636
|
+
// Path doesn't exist, which is what LadybugDB wants for a new database
|
|
637
|
+
}
|
|
638
|
+
// -------------------------------------------------------------------------
|
|
639
|
+
// Cross-process critical section: acquire init lock, clean orphan sidecars,
|
|
640
|
+
// and open the database. The lock prevents a TOCTOU race where another
|
|
641
|
+
// process could create a fresh DB between our access() check and the
|
|
642
|
+
// unlink() of stale sidecars.
|
|
643
|
+
// -------------------------------------------------------------------------
|
|
644
|
+
const releaseInitLock = await acquireInitLock(dbPath);
|
|
645
|
+
try {
|
|
646
|
+
// Crash-recovery cleanup: if the main DB file is missing, stale sidecars
|
|
647
|
+
// from an interrupted run can block fresh opens indefinitely.
|
|
648
|
+
try {
|
|
649
|
+
await fs.access(dbPath);
|
|
650
|
+
}
|
|
651
|
+
catch (err) {
|
|
652
|
+
if (isMissingFileError(err)) {
|
|
653
|
+
// `.shadow` is documented by LadybugDB checkpointing and `.wal.checkpoint`
|
|
654
|
+
// was observed in the #1618 crash loop that motivated this recovery path.
|
|
655
|
+
const orphanSidecars = [`${dbPath}.shadow`, `${dbPath}.wal.checkpoint`];
|
|
656
|
+
for (const sidecar of orphanSidecars) {
|
|
657
|
+
try {
|
|
658
|
+
await fs.unlink(sidecar);
|
|
659
|
+
logger.warn(`GitNexus: removed orphan sidecar ${path.basename(sidecar)} (no main DB file present)`);
|
|
660
|
+
}
|
|
661
|
+
catch (err) {
|
|
662
|
+
if (isMissingFileError(err)) {
|
|
663
|
+
continue;
|
|
664
|
+
}
|
|
665
|
+
const code = extractErrnoCode(err);
|
|
666
|
+
logger.warn(`GitNexus: failed to remove orphan sidecar ${path.basename(sidecar)} (${code ?? 'UNKNOWN'}) while main DB file is missing; LadybugDB open may still fail: ${summarizeError(err)}`);
|
|
630
667
|
}
|
|
631
|
-
const code = extractErrnoCode(err);
|
|
632
|
-
logger.warn(`GitNexus: failed to remove orphan sidecar ${path.basename(sidecar)} (${code ?? 'UNKNOWN'}) while main DB file is missing; LadybugDB open may still fail: ${summarizeError(err)}`);
|
|
633
668
|
}
|
|
634
669
|
}
|
|
670
|
+
else {
|
|
671
|
+
const code = extractErrnoCode(err);
|
|
672
|
+
logger.warn(`GitNexus: unable to verify main DB file before orphan sidecar cleanup (${code ?? 'UNKNOWN'}); skipping cleanup: ${summarizeError(err)}`);
|
|
673
|
+
}
|
|
635
674
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
675
|
+
// Ensure parent directory exists
|
|
676
|
+
const parentDir = path.dirname(dbPath);
|
|
677
|
+
await fs.mkdir(parentDir, { recursive: true });
|
|
678
|
+
await preflightLbugSidecars(dbPath, {
|
|
679
|
+
mode: 'write',
|
|
680
|
+
logger,
|
|
681
|
+
allowQuarantine: true,
|
|
682
|
+
});
|
|
683
|
+
const opened = await openLbugConnection(lbug, dbPath);
|
|
684
|
+
db = opened.db;
|
|
685
|
+
conn = opened.conn;
|
|
686
|
+
currentDbReadOnly = false;
|
|
687
|
+
}
|
|
688
|
+
finally {
|
|
689
|
+
await releaseInitLock();
|
|
640
690
|
}
|
|
641
|
-
// Ensure parent directory exists
|
|
642
|
-
const parentDir = path.dirname(dbPath);
|
|
643
|
-
await fs.mkdir(parentDir, { recursive: true });
|
|
644
|
-
await preflightLbugSidecars(dbPath, {
|
|
645
|
-
mode: readOnly ? 'read-only' : 'write',
|
|
646
|
-
logger,
|
|
647
|
-
allowQuarantine: true,
|
|
648
|
-
});
|
|
649
|
-
const opened = readOnly
|
|
650
|
-
? await openLbugConnection(lbug, dbPath, { readOnly: true })
|
|
651
|
-
: await openLbugConnection(lbug, dbPath);
|
|
652
|
-
const usable = readOnly ? await ensureReadOnlyConnectionUsable(dbPath, opened) : opened;
|
|
653
|
-
db = usable.db;
|
|
654
|
-
conn = usable.conn;
|
|
655
|
-
currentDbReadOnly = readOnly;
|
|
656
|
-
}
|
|
657
|
-
finally {
|
|
658
|
-
await releaseInitLock();
|
|
659
691
|
}
|
|
660
692
|
if (!readOnly) {
|
|
661
693
|
const missingShadowError = await runSchemaCreationQueries(dbPath);
|
package/dist/core/run-analyze.js
CHANGED
|
@@ -26,7 +26,7 @@ export function detectCursorCLI() {
|
|
|
26
26
|
if (cachedCursorBin !== undefined)
|
|
27
27
|
return cachedCursorBin;
|
|
28
28
|
try {
|
|
29
|
-
execSync('agent --version', { stdio: 'ignore' });
|
|
29
|
+
execSync('agent --version', { stdio: 'ignore', windowsHide: true });
|
|
30
30
|
cachedCursorBin = 'agent';
|
|
31
31
|
}
|
|
32
32
|
catch {
|
|
@@ -78,6 +78,7 @@ export async function callCursorLLM(prompt, config, systemPrompt, options) {
|
|
|
78
78
|
const child = spawn(cursorBin, args, {
|
|
79
79
|
cwd: config.workingDirectory || process.cwd(),
|
|
80
80
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
81
|
+
windowsHide: true,
|
|
81
82
|
env: {
|
|
82
83
|
...process.env,
|
|
83
84
|
// Ensure non-interactive mode
|
|
@@ -675,7 +675,12 @@ export class WikiGenerator {
|
|
|
675
675
|
// ─── Helpers ────────────────────────────────────────────────────────
|
|
676
676
|
getCurrentCommit() {
|
|
677
677
|
try {
|
|
678
|
-
return execSync('git rev-parse HEAD', {
|
|
678
|
+
return execSync('git rev-parse HEAD', {
|
|
679
|
+
cwd: this.repoPath,
|
|
680
|
+
windowsHide: true,
|
|
681
|
+
})
|
|
682
|
+
.toString()
|
|
683
|
+
.trim();
|
|
679
684
|
}
|
|
680
685
|
catch {
|
|
681
686
|
return '';
|
|
@@ -690,6 +695,7 @@ export class WikiGenerator {
|
|
|
690
695
|
execFileSync('git', ['merge-base', '--is-ancestor', fromCommit, toCommit], {
|
|
691
696
|
cwd: this.repoPath,
|
|
692
697
|
stdio: 'ignore',
|
|
698
|
+
windowsHide: true,
|
|
693
699
|
});
|
|
694
700
|
return true;
|
|
695
701
|
}
|
|
@@ -706,6 +712,7 @@ export class WikiGenerator {
|
|
|
706
712
|
try {
|
|
707
713
|
const output = execFileSync('git', ['diff', `${fromCommit}..${toCommit}`, '--name-only'], {
|
|
708
714
|
cwd: this.repoPath,
|
|
715
|
+
windowsHide: true,
|
|
709
716
|
})
|
|
710
717
|
.toString()
|
|
711
718
|
.trim();
|
|
@@ -1978,6 +1978,7 @@ export class LocalBackend {
|
|
|
1978
1978
|
cwd: diffCwd,
|
|
1979
1979
|
encoding: 'utf-8',
|
|
1980
1980
|
maxBuffer: 256 * 1024 * 1024,
|
|
1981
|
+
windowsHide: true,
|
|
1981
1982
|
});
|
|
1982
1983
|
}
|
|
1983
1984
|
catch (err) {
|
|
@@ -2195,6 +2196,7 @@ export class LocalBackend {
|
|
|
2195
2196
|
timeout: 5000,
|
|
2196
2197
|
// Avoid ENOBUFS on large repos: rg -l can list many files.
|
|
2197
2198
|
maxBuffer: 256 * 1024 * 1024,
|
|
2199
|
+
windowsHide: true,
|
|
2198
2200
|
});
|
|
2199
2201
|
const files = output
|
|
2200
2202
|
.trim()
|
package/dist/server/git-clone.js
CHANGED
|
@@ -262,6 +262,7 @@ export function getRemoteOriginUrl(cwd) {
|
|
|
262
262
|
const proc = spawn('git', ['config', '--get', 'remote.origin.url'], {
|
|
263
263
|
cwd,
|
|
264
264
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
265
|
+
windowsHide: true,
|
|
265
266
|
env: { ...process.env, GIT_TERMINAL_PROMPT: '0' },
|
|
266
267
|
});
|
|
267
268
|
let stdout = '';
|
|
@@ -368,6 +369,7 @@ function runGit(args, cwd) {
|
|
|
368
369
|
const proc = spawn('git', args, {
|
|
369
370
|
cwd,
|
|
370
371
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
372
|
+
windowsHide: true,
|
|
371
373
|
env: {
|
|
372
374
|
...process.env,
|
|
373
375
|
// Prevent git from prompting for credentials (hangs the process)
|
package/dist/storage/git.js
CHANGED
|
@@ -4,7 +4,11 @@ import path from 'path';
|
|
|
4
4
|
// Git utilities for repository detection, commit tracking, and diff analysis
|
|
5
5
|
export const isGitRepo = (repoPath) => {
|
|
6
6
|
try {
|
|
7
|
-
execSync('git rev-parse --is-inside-work-tree', {
|
|
7
|
+
execSync('git rev-parse --is-inside-work-tree', {
|
|
8
|
+
cwd: repoPath,
|
|
9
|
+
stdio: 'ignore',
|
|
10
|
+
windowsHide: true,
|
|
11
|
+
});
|
|
8
12
|
return true;
|
|
9
13
|
}
|
|
10
14
|
catch {
|
|
@@ -21,6 +25,7 @@ export const getCurrentCommit = (repoPath) => {
|
|
|
21
25
|
// "fatal: not a git repository" to stderr, which leaks to the user's
|
|
22
26
|
// terminal even though the error is caught here (#1172).
|
|
23
27
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
28
|
+
windowsHide: true,
|
|
24
29
|
})
|
|
25
30
|
.toString()
|
|
26
31
|
.trim();
|
|
@@ -58,6 +63,7 @@ export const getRemoteUrl = (repoPath) => {
|
|
|
58
63
|
raw = execSync('git config --get remote.origin.url', {
|
|
59
64
|
cwd: repoPath,
|
|
60
65
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
66
|
+
windowsHide: true,
|
|
61
67
|
})
|
|
62
68
|
.toString()
|
|
63
69
|
.trim();
|
|
@@ -97,6 +103,7 @@ export const getGitRoot = (fromPath) => {
|
|
|
97
103
|
cwd: fromPath,
|
|
98
104
|
// Suppress stderr -- see getCurrentCommit comment and #1172.
|
|
99
105
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
106
|
+
windowsHide: true,
|
|
100
107
|
})
|
|
101
108
|
.toString()
|
|
102
109
|
.trim();
|
|
@@ -139,6 +146,7 @@ export const getCanonicalRepoRoot = (fromPath) => {
|
|
|
139
146
|
const commonDir = execSync('git rev-parse --path-format=absolute --git-common-dir', {
|
|
140
147
|
cwd: fromPath,
|
|
141
148
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
149
|
+
windowsHide: true,
|
|
142
150
|
})
|
|
143
151
|
.toString()
|
|
144
152
|
.trim();
|
|
@@ -247,6 +255,7 @@ export const getRemoteOriginUrl = (repoPath) => {
|
|
|
247
255
|
const url = execSync('git config --get remote.origin.url', {
|
|
248
256
|
cwd: repoPath,
|
|
249
257
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
258
|
+
windowsHide: true,
|
|
250
259
|
})
|
|
251
260
|
.toString()
|
|
252
261
|
.trim();
|
|
@@ -77,6 +77,7 @@ function findCanonicalRepoRoot(cwd) {
|
|
|
77
77
|
timeout: 2000,
|
|
78
78
|
cwd,
|
|
79
79
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
80
|
+
windowsHide: true,
|
|
80
81
|
});
|
|
81
82
|
if (result.error || result.status !== 0) return null;
|
|
82
83
|
const commonDir = (result.stdout || '').trim();
|
|
@@ -218,6 +219,7 @@ function runGitNexusCli(cliPath, args, cwd, timeout) {
|
|
|
218
219
|
timeout,
|
|
219
220
|
cwd,
|
|
220
221
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
222
|
+
windowsHide: true,
|
|
221
223
|
});
|
|
222
224
|
}
|
|
223
225
|
// On Windows, invoke npx.cmd directly (no shell needed)
|
|
@@ -226,6 +228,7 @@ function runGitNexusCli(cliPath, args, cwd, timeout) {
|
|
|
226
228
|
timeout: timeout + 5000,
|
|
227
229
|
cwd,
|
|
228
230
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
231
|
+
windowsHide: true,
|
|
229
232
|
});
|
|
230
233
|
}
|
|
231
234
|
|
|
@@ -315,6 +318,7 @@ function handlePostToolUse(input) {
|
|
|
315
318
|
timeout: 3000,
|
|
316
319
|
cwd,
|
|
317
320
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
321
|
+
windowsHide: true,
|
|
318
322
|
});
|
|
319
323
|
currentHead = (headResult.stdout || '').trim();
|
|
320
324
|
} catch {
|
|
@@ -109,6 +109,7 @@ function hasGitNexusServerOwnerWindows(dbPathAbs, myPid) {
|
|
|
109
109
|
encoding: 'utf-8',
|
|
110
110
|
timeout: 6000,
|
|
111
111
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
112
|
+
windowsHide: true,
|
|
112
113
|
env: { ...process.env, GITNEXUS_HOOK_RM_TARGET: dbPathAbs },
|
|
113
114
|
},
|
|
114
115
|
);
|
|
@@ -192,6 +193,7 @@ function unixLsofPsFindGitNexusServer(dbPathAbs, myPid) {
|
|
|
192
193
|
encoding: 'utf-8',
|
|
193
194
|
timeout: 1000,
|
|
194
195
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
196
|
+
windowsHide: true,
|
|
195
197
|
});
|
|
196
198
|
if (lsof.error) return lsof.error.code === 'ETIMEDOUT';
|
|
197
199
|
|
|
@@ -203,6 +205,7 @@ function unixLsofPsFindGitNexusServer(dbPathAbs, myPid) {
|
|
|
203
205
|
encoding: 'utf-8',
|
|
204
206
|
timeout: 500,
|
|
205
207
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
208
|
+
windowsHide: true,
|
|
206
209
|
});
|
|
207
210
|
if (ps.error) {
|
|
208
211
|
if (ps.error.code === 'ETIMEDOUT') return true;
|
package/package.json
CHANGED