gitdone-agent 0.8.8 → 0.8.10
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 +58 -7
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -31,7 +31,7 @@ import { randomUUID, createHash } from 'node:crypto'
|
|
|
31
31
|
// Reported to the server on every sync so the web UI can flag outdated agents.
|
|
32
32
|
// Keep in lockstep with packages/agent/package.json. The server's offline
|
|
33
33
|
// fallback is bumped only after this release has actually reached npm.
|
|
34
|
-
const AGENT_VERSION = '0.8.
|
|
34
|
+
const AGENT_VERSION = '0.8.10'
|
|
35
35
|
|
|
36
36
|
const AGENT_DIR = join(homedir(), '.gitdone-agent')
|
|
37
37
|
const CONFIG_PATH = join(AGENT_DIR, 'config.json')
|
|
@@ -775,11 +775,12 @@ function gitTry(cmd, cwd) {
|
|
|
775
775
|
// commit path swallowed that via git() + `|| 'committed'` and reported a fake
|
|
776
776
|
// success while nothing was committed (gd-445). gitDiffUntracked() already uses
|
|
777
777
|
// execFileSync for the same reason. Local calls get 2 min; pass net for 5.
|
|
778
|
-
function gitArgs(args, cwd, { net = false } = {}) {
|
|
778
|
+
function gitArgs(args, cwd, { net = false, input } = {}) {
|
|
779
779
|
try {
|
|
780
780
|
const out = execFileSync('git', args, {
|
|
781
781
|
cwd, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'],
|
|
782
782
|
maxBuffer: GIT_MAX_BUFFER, timeout: net ? GIT_NET_TIMEOUT_MS : GIT_TIMEOUT_MS, env: GIT_ENV,
|
|
783
|
+
...(input === undefined ? {} : { input }),
|
|
783
784
|
}).trim()
|
|
784
785
|
return { ok: true, out }
|
|
785
786
|
} catch (err) {
|
|
@@ -789,6 +790,32 @@ function gitArgs(args, cwd, { net = false } = {}) {
|
|
|
789
790
|
}
|
|
790
791
|
}
|
|
791
792
|
|
|
793
|
+
function nulPathList(paths) {
|
|
794
|
+
return Buffer.from(`${paths.join('\0')}\0`, 'utf8')
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
// A snapshot can become stale between rendering and Commit — most notably when
|
|
798
|
+
// the selected change also updates .gitignore. Return the selected paths that
|
|
799
|
+
// match the repo's ignore rules. Normally check-ignore omits tracked files;
|
|
800
|
+
// --no-index includes them so callers can handle the two groups differently.
|
|
801
|
+
function ignoredPaths(paths, cwd, { includeTracked = false } = {}) {
|
|
802
|
+
if (paths.length === 0) return new Set()
|
|
803
|
+
try {
|
|
804
|
+
const args = ['check-ignore', ...(includeTracked ? ['--no-index'] : []), '-z', '--stdin']
|
|
805
|
+
const out = execFileSync('git', args, {
|
|
806
|
+
cwd, encoding: 'buffer', stdio: ['pipe', 'pipe', 'pipe'], input: nulPathList(paths),
|
|
807
|
+
maxBuffer: GIT_MAX_BUFFER, timeout: GIT_TIMEOUT_MS, env: GIT_ENV,
|
|
808
|
+
})
|
|
809
|
+
return new Set(out.toString('utf8').split('\0').filter(Boolean))
|
|
810
|
+
} catch (err) {
|
|
811
|
+
// Exit 1 is check-ignore's documented "none ignored" result, not a failure.
|
|
812
|
+
if (err?.status === 1) return new Set()
|
|
813
|
+
const stderr = err?.stderr?.toString().trim()
|
|
814
|
+
const stdout = err?.stdout?.toString().trim()
|
|
815
|
+
throw new Error(`git check-ignore се провали: ${stderr || stdout || err?.message || 'unknown error'}`)
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
|
|
792
819
|
// Never let a token reach the log file or the server's command-result.
|
|
793
820
|
function redact(text, token) {
|
|
794
821
|
if (!text || !token) return text
|
|
@@ -2665,17 +2692,41 @@ async function executeCommand(cfg, cmd, repoPath) {
|
|
|
2665
2692
|
const files = Array.isArray(cmd.payload?.files)
|
|
2666
2693
|
? cmd.payload.files.filter((f) => typeof f === 'string' && f.trim())
|
|
2667
2694
|
: []
|
|
2668
|
-
const
|
|
2669
|
-
|
|
2670
|
-
|
|
2695
|
+
const ignoredUntracked = ignoredPaths(files, repoPath)
|
|
2696
|
+
const ignoredByRules = ignoredPaths(files, repoPath, { includeTracked: true })
|
|
2697
|
+
const trackedIgnored = new Set([...ignoredByRules].filter((f) => !ignoredUntracked.has(f)))
|
|
2698
|
+
const addFiles = ignoredByRules.size > 0 ? files.filter((f) => !ignoredByRules.has(f)) : files
|
|
2699
|
+
if (ignoredUntracked.size > 0) log(`↷ commit @ ${repoPath}: пропускам ${ignoredUntracked.size} игнорирани untracked файла`)
|
|
2700
|
+
// Do not put every selected path in argv: a large change set can exceed
|
|
2701
|
+
// Windows' ~32K CreateProcess command-line limit before git even starts
|
|
2702
|
+
// (`spawnSync git ENAMETOOLONG`). Git's NUL-delimited stdin pathspec mode
|
|
2703
|
+
// has no such argv limit and also preserves spaces/newlines verbatim.
|
|
2704
|
+
// `git add <path>` refuses tracked files when a newly added rule ignores
|
|
2705
|
+
// their parent directory. update-index stages those exact tracked paths
|
|
2706
|
+
// without force-adding anything untracked; the normal add below handles
|
|
2707
|
+
// all remaining (including new files and embedded repositories).
|
|
2708
|
+
const updateIgnoredTracked = trackedIgnored.size > 0
|
|
2709
|
+
? gitArgs(['update-index', '--add', '--remove', '-z', '--stdin'], repoPath, { input: nulPathList([...trackedIgnored]) })
|
|
2710
|
+
: { ok: true, out: '' }
|
|
2711
|
+
if (!updateIgnoredTracked.ok) throw new Error(`git update-index се провали: ${updateIgnoredTracked.out}`)
|
|
2712
|
+
const add = addFiles.length
|
|
2713
|
+
? gitArgs(
|
|
2714
|
+
['--literal-pathspecs', 'add', '--pathspec-from-file=-', '--pathspec-file-nul'],
|
|
2715
|
+
repoPath,
|
|
2716
|
+
{ input: nulPathList(addFiles) },
|
|
2717
|
+
)
|
|
2718
|
+
: files.length === 0
|
|
2719
|
+
? gitArgs(['add', '-A'], repoPath)
|
|
2720
|
+
: { ok: true, out: '' }
|
|
2671
2721
|
if (!add.ok) throw new Error(`git add се провали: ${add.out}`)
|
|
2672
2722
|
const commit = gitArgs(['commit', '-m', msg], repoPath)
|
|
2723
|
+
const ignoredNote = ignoredUntracked.size > 0 ? `\nпропуснати игнорирани файлове: ${ignoredUntracked.size}` : ''
|
|
2673
2724
|
if (commit.ok) {
|
|
2674
|
-
result = commit.out || 'committed'
|
|
2725
|
+
result = `${commit.out || 'committed'}${ignoredNote}`
|
|
2675
2726
|
} else if (/nothing to commit|no changes added|working tree clean/i.test(commit.out)) {
|
|
2676
2727
|
// Benign: the checked files carried no staged change (already committed or
|
|
2677
2728
|
// whitespace-only). Say so plainly instead of faking success.
|
|
2678
|
-
result =
|
|
2729
|
+
result = `няма промени за commit${ignoredNote}`
|
|
2679
2730
|
} else {
|
|
2680
2731
|
// Real failure (hook, identity, lock, corrupt path…) — surface it so the
|
|
2681
2732
|
// console shows the reason instead of the old silent fake ✓.
|