gitdone-agent 0.6.5 → 0.6.6
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/index.js +42 -5
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -27,7 +27,7 @@ import { randomUUID } from 'node:crypto'
|
|
|
27
27
|
// Reported to the server on every sync so the web UI can flag outdated agents.
|
|
28
28
|
// Keep in lockstep with packages/agent/package.json "version" AND
|
|
29
29
|
// src/lib/agentVersion.ts LATEST_AGENT_VERSION.
|
|
30
|
-
const AGENT_VERSION = '0.6.
|
|
30
|
+
const AGENT_VERSION = '0.6.6'
|
|
31
31
|
|
|
32
32
|
const AGENT_DIR = join(homedir(), '.gitdone-agent')
|
|
33
33
|
const CONFIG_PATH = join(AGENT_DIR, 'config.json')
|
|
@@ -403,6 +403,42 @@ function decodeDiffText(buf) {
|
|
|
403
403
|
}
|
|
404
404
|
}
|
|
405
405
|
|
|
406
|
+
// Git C-quotes paths with spaces / special chars / non-ASCII bytes, wrapping them
|
|
407
|
+
// in double quotes with backslash escapes (`"export coca_cola/x.cs"`, octal `\NNN`
|
|
408
|
+
// for raw bytes). Both `git status --porcelain` and the `diff --git` header do it.
|
|
409
|
+
// Left unhandled, files with spaces (or Cyrillic) got mis-keyed and their diff was
|
|
410
|
+
// dropped (gd-321). This reverses it back to a plain path so the diff key matches
|
|
411
|
+
// the file name shown in the list.
|
|
412
|
+
function unquoteGitPath(s) {
|
|
413
|
+
if (typeof s !== 'string' || s.length < 2 || s[0] !== '"' || s[s.length - 1] !== '"') return s
|
|
414
|
+
const body = s.slice(1, -1)
|
|
415
|
+
const bytes = []
|
|
416
|
+
for (let i = 0; i < body.length; i++) {
|
|
417
|
+
if (body[i] === '\\' && i + 1 < body.length) {
|
|
418
|
+
const n = body[i + 1]
|
|
419
|
+
if (n === 'n') { bytes.push(10); i++ }
|
|
420
|
+
else if (n === 't') { bytes.push(9); i++ }
|
|
421
|
+
else if (n === 'r') { bytes.push(13); i++ }
|
|
422
|
+
else if (n === '"') { bytes.push(34); i++ }
|
|
423
|
+
else if (n === '\\') { bytes.push(92); i++ }
|
|
424
|
+
else if (n >= '0' && n <= '7') { bytes.push(parseInt(body.substr(i + 1, 3), 8) & 0xff); i += 3 }
|
|
425
|
+
else { bytes.push(body.charCodeAt(i)) }
|
|
426
|
+
} else {
|
|
427
|
+
bytes.push(body.charCodeAt(i) & 0xff)
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
return Buffer.from(bytes).toString('utf8')
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// Read the b-side path from a `diff --git` header line, handling git's quoting
|
|
434
|
+
// of paths with spaces / special chars (gd-321).
|
|
435
|
+
function diffHeaderPath(hdr) {
|
|
436
|
+
const q = hdr.match(/ ("b\/.*")$/) // quoted: "a/x" "b/x"
|
|
437
|
+
if (q) return unquoteGitPath(q[1]).replace(/^b\//, '')
|
|
438
|
+
const u = hdr.match(/ b\/(.*)$/) // plain: a/x b/x
|
|
439
|
+
return u ? u[1] : null
|
|
440
|
+
}
|
|
441
|
+
|
|
406
442
|
function parseDiffByFile(diffBuf) {
|
|
407
443
|
const files = {}
|
|
408
444
|
if (!diffBuf || diffBuf.length === 0) return files
|
|
@@ -413,10 +449,11 @@ function parseDiffByFile(diffBuf) {
|
|
|
413
449
|
for (const section of sections) {
|
|
414
450
|
if (!section.trim()) continue
|
|
415
451
|
// Decode THIS file's bytes on their own (UTF-8 or CP1251), then read the
|
|
416
|
-
// filename from the decoded header.
|
|
452
|
+
// filename from the decoded header (quoted or not).
|
|
417
453
|
const text = decodeDiffText(Buffer.from(section, 'latin1'))
|
|
418
|
-
const
|
|
419
|
-
|
|
454
|
+
const hdr = text.match(/^diff --git (.+)$/m)
|
|
455
|
+
const name = hdr ? diffHeaderPath(hdr[1]) : null
|
|
456
|
+
if (name) files[name] = text
|
|
420
457
|
}
|
|
421
458
|
return files
|
|
422
459
|
}
|
|
@@ -430,7 +467,7 @@ function getSnapshot(repoPath) {
|
|
|
430
467
|
const statuses = {}
|
|
431
468
|
for (const line of statusLines) {
|
|
432
469
|
const xy = line.slice(0, 2)
|
|
433
|
-
const file = line.slice(3)
|
|
470
|
+
const file = unquoteGitPath(line.slice(3))
|
|
434
471
|
statuses[file] = xy
|
|
435
472
|
if (xy[0] !== ' ' && xy[0] !== '?') staged.push(file)
|
|
436
473
|
if (xy[1] !== ' ') modified.push(file)
|