@google/gemini-cli-core 0.63.0-preview.0 → 0.64.0-nightly.20261001.gc6bccb7ec
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/docs/changelogs/preview.md +54 -65
- package/dist/google-gemini-cli-core-0.64.0-nightly.20260929.gd75234cae.tgz +0 -0
- package/dist/src/generated/git-commit.d.ts +2 -2
- package/dist/src/generated/git-commit.js +2 -2
- package/dist/src/generated/git-commit.js.map +1 -1
- package/dist/src/services/fileSystemService.atomic.test.d.ts +6 -0
- package/dist/src/services/fileSystemService.atomic.test.js +92 -0
- package/dist/src/services/fileSystemService.atomic.test.js.map +1 -0
- package/dist/src/services/fileSystemService.d.ts +10 -0
- package/dist/src/services/fileSystemService.js +96 -1
- package/dist/src/services/fileSystemService.js.map +1 -1
- package/dist/src/services/fileSystemService.test.js +74 -6
- package/dist/src/services/fileSystemService.test.js.map +1 -1
- package/dist/src/services/gitService.js +27 -13
- package/dist/src/services/gitService.js.map +1 -1
- package/dist/src/services/gitService.test.js +29 -0
- package/dist/src/services/gitService.test.js.map +1 -1
- package/dist/src/tools/edit.js +40 -0
- package/dist/src/tools/edit.js.map +1 -1
- package/dist/src/tools/edit.test.js +81 -0
- package/dist/src/tools/edit.test.js.map +1 -1
- package/dist/src/tools/write-file.js +37 -0
- package/dist/src/tools/write-file.js.map +1 -1
- package/dist/src/tools/write-file.test.js +31 -0
- package/dist/src/tools/write-file.test.js.map +1 -1
- package/dist/src/utils/pathMutex.d.ts +19 -0
- package/dist/src/utils/pathMutex.js +99 -0
- package/dist/src/utils/pathMutex.js.map +1 -0
- package/dist/src/utils/pathMutex.test.d.ts +6 -0
- package/dist/src/utils/pathMutex.test.js +95 -0
- package/dist/src/utils/pathMutex.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# Preview release: v0.
|
|
1
|
+
# Preview release: v0.63.0-preview.0
|
|
2
2
|
|
|
3
|
-
Released: September
|
|
3
|
+
Released: September 29, 2026
|
|
4
4
|
|
|
5
5
|
Our preview release includes the latest, new, and experimental features. This
|
|
6
6
|
release may not be as stable as our [latest weekly release](latest.md).
|
|
@@ -13,73 +13,62 @@ npm install -g @google/gemini-cli@preview
|
|
|
13
13
|
|
|
14
14
|
## Highlights
|
|
15
15
|
|
|
16
|
-
- **
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
and
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
16
|
+
- **Autonomous Plan Execution**: Enabled autonomous plan execution in
|
|
17
|
+
non-interactive mode, allowing automated agent workflows to run multi-step
|
|
18
|
+
plans without requiring interactive user confirmation.
|
|
19
|
+
- **Memory Lifecycle & Output Bounding**: Bounded tool output sizes and
|
|
20
|
+
optimized the memory lifecycle in long-running agent loops to prevent memory
|
|
21
|
+
leaks, while ensuring full output formatting when truncation is disabled.
|
|
22
|
+
- **Authentication Resilience**: Prevented infinite authentication loops caused
|
|
23
|
+
by file contention, headless keyring environments, and supervisor state drops,
|
|
24
|
+
ensuring reliable credential handling across environments.
|
|
25
|
+
- **CLI & Connection Recovery UX**: Displayed a retry progress indicator during
|
|
26
|
+
connection recovery, restored paused stdin after capability detection, and
|
|
27
|
+
ensured automatic temporary directory cleanup upon background shell execution
|
|
28
|
+
exit.
|
|
27
29
|
|
|
28
30
|
## What's Changed
|
|
29
31
|
|
|
30
|
-
- fix(
|
|
31
|
-
|
|
32
|
-
[#
|
|
33
|
-
- Changelog for v0.61.0-preview.
|
|
34
|
-
[#
|
|
35
|
-
- Changelog for v0.
|
|
36
|
-
[#
|
|
37
|
-
- fix(
|
|
38
|
-
|
|
39
|
-
[#
|
|
40
|
-
-
|
|
32
|
+
- fix(cli): display retry progress indicator during connection recovery (#28340)
|
|
33
|
+
by @amelidev in
|
|
34
|
+
[#29468](https://github.com/google-gemini/gemini-cli/pull/29468)
|
|
35
|
+
- Changelog for v0.61.0-preview.1 by @gemini-cli-robot in
|
|
36
|
+
[#29469](https://github.com/google-gemini/gemini-cli/pull/29469)
|
|
37
|
+
- Changelog for v0.61.0 by @gemini-cli-robot in
|
|
38
|
+
[#29472](https://github.com/google-gemini/gemini-cli/pull/29472)
|
|
39
|
+
- fix(cli): distinguish missing MCP enablement config from malformed JSON by
|
|
40
|
+
@jesussamuel-byte in
|
|
41
|
+
[#29446](https://github.com/google-gemini/gemini-cli/pull/29446)
|
|
42
|
+
- fix(cli): restore paused stdin after capability detection by @ugorla-dev in
|
|
43
|
+
[#29487](https://github.com/google-gemini/gemini-cli/pull/29487)
|
|
44
|
+
- fix(core): bound tool output size and optimize memory lifecycle in
|
|
45
|
+
long-running agent loops by @diegogodinezr in
|
|
46
|
+
[#29451](https://github.com/google-gemini/gemini-cli/pull/29451)
|
|
47
|
+
- fix(core): remove invalid diff.external override by @urielefrenvirtusa in
|
|
48
|
+
[#29467](https://github.com/google-gemini/gemini-cli/pull/29467)
|
|
49
|
+
- chore(release): bump version to 0.63.0-nightly.20260923.gf50ba8608 by
|
|
41
50
|
@gemini-cli-robot in
|
|
42
|
-
[#
|
|
43
|
-
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
- fix(core): synchronize ConPTY process exit lifecycle and harden PTY output
|
|
59
|
-
finalization by @jvargassanchez-dot in
|
|
60
|
-
[#29379](https://github.com/google-gemini/gemini-cli/pull/29379)
|
|
61
|
-
- fix(cli): suppress uncaught AbortError logs during request cancellation by
|
|
62
|
-
@urielefrenvirtusa in
|
|
63
|
-
[#29343](https://github.com/google-gemini/gemini-cli/pull/29343)
|
|
64
|
-
- fix(core,cli): improve terminal buffer memory management and format Windows
|
|
65
|
-
diagnostic paths by @jesussamuel-byte in
|
|
66
|
-
[#29380](https://github.com/google-gemini/gemini-cli/pull/29380)
|
|
67
|
-
- fix(vscode-ide-companion): preserve terminal focus when closing diff tabs by
|
|
68
|
-
@amelidev in [#29378](https://github.com/google-gemini/gemini-cli/pull/29378)
|
|
69
|
-
- fix(core): update auth error documentation link to valid anchor and add
|
|
70
|
-
fallback (#26140) by @villahernandez-coder in
|
|
71
|
-
[#29377](https://github.com/google-gemini/gemini-cli/pull/29377)
|
|
72
|
-
- fix(core): normalize proxy-agent esbuild interop for environment proxy
|
|
73
|
-
resolution by @diegogodinezr in
|
|
74
|
-
[#29401](https://github.com/google-gemini/gemini-cli/pull/29401)
|
|
75
|
-
- fix(cli): emit tool_call update prior to request_permission in ACP mode by
|
|
51
|
+
[#29471](https://github.com/google-gemini/gemini-cli/pull/29471)
|
|
52
|
+
- Changelog for v0.62.0-preview.0 by @gemini-cli-robot in
|
|
53
|
+
[#29470](https://github.com/google-gemini/gemini-cli/pull/29470)
|
|
54
|
+
- fix(core): clean up temporary directory when background shell execution exits
|
|
55
|
+
by @jesussamuel-byte in
|
|
56
|
+
[#29437](https://github.com/google-gemini/gemini-cli/pull/29437)
|
|
57
|
+
- fix(acp): resolve session before config initialization and avoid same-minute
|
|
58
|
+
filename collisions by @jesussamuel-byte in
|
|
59
|
+
[#29463](https://github.com/google-gemini/gemini-cli/pull/29463)
|
|
60
|
+
- fix(core): align policy redirection gates, path validation, and workflow
|
|
61
|
+
parsing by @DavidAPierce in
|
|
62
|
+
[#29506](https://github.com/google-gemini/gemini-cli/pull/29506)
|
|
63
|
+
- fix(auth): prevent infinite auth loop from file contention, headless keyring,
|
|
64
|
+
and supervisor state drops (#28341) by @villahernandez-coder in
|
|
65
|
+
[#29448](https://github.com/google-gemini/gemini-cli/pull/29448)
|
|
66
|
+
- fix(core): enable autonomous plan execution in non-interactive mode by
|
|
76
67
|
@urielefrenvirtusa in
|
|
77
|
-
[#
|
|
78
|
-
-
|
|
79
|
-
|
|
80
|
-
-
|
|
81
|
-
@DavidAPierce in
|
|
82
|
-
[#29462](https://github.com/google-gemini/gemini-cli/pull/29462)
|
|
68
|
+
[#29539](https://github.com/google-gemini/gemini-cli/pull/29539)
|
|
69
|
+
- fix(core): disable truncation when maxChars <= 0 in formatTruncatedToolOutput
|
|
70
|
+
by @diegogodinezr in
|
|
71
|
+
[#29542](https://github.com/google-gemini/gemini-cli/pull/29542)
|
|
83
72
|
|
|
84
73
|
**Full Changelog**:
|
|
85
|
-
https://github.com/google-gemini/gemini-cli/compare/v0.
|
|
74
|
+
https://github.com/google-gemini/gemini-cli/compare/v0.62.0-preview.0...v0.63.0-preview.0
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* Copyright 2026 Google LLC
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
-
export declare const GIT_COMMIT_INFO = "
|
|
7
|
-
export declare const CLI_VERSION = "0.
|
|
6
|
+
export declare const GIT_COMMIT_INFO = "c6bccb7ec";
|
|
7
|
+
export declare const CLI_VERSION = "0.64.0-nightly.20261001.gc6bccb7ec";
|
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
*/
|
|
6
6
|
// This file is auto-generated by the build script (scripts/generate-git-commit-info.js)
|
|
7
7
|
// Do not edit this file manually.
|
|
8
|
-
export const GIT_COMMIT_INFO = '
|
|
9
|
-
export const CLI_VERSION = '0.
|
|
8
|
+
export const GIT_COMMIT_INFO = 'c6bccb7ec';
|
|
9
|
+
export const CLI_VERSION = '0.64.0-nightly.20261001.gc6bccb7ec';
|
|
10
10
|
//# sourceMappingURL=git-commit.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-commit.js","sourceRoot":"","sources":["../../../src/generated/git-commit.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,wFAAwF;AACxF,kCAAkC;AAClC,MAAM,CAAC,MAAM,eAAe,GAAG,WAAW,CAAC;AAC3C,MAAM,CAAC,MAAM,WAAW,GAAG,
|
|
1
|
+
{"version":3,"file":"git-commit.js","sourceRoot":"","sources":["../../../src/generated/git-commit.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,wFAAwF;AACxF,kCAAkC;AAClC,MAAM,CAAC,MAAM,eAAe,GAAG,WAAW,CAAC;AAC3C,MAAM,CAAC,MAAM,WAAW,GAAG,oCAAoC,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
7
|
+
import fs from 'node:fs';
|
|
8
|
+
import fsp from 'node:fs/promises';
|
|
9
|
+
import os from 'node:os';
|
|
10
|
+
import path from 'node:path';
|
|
11
|
+
import { StandardFileSystemService } from './fileSystemService.js';
|
|
12
|
+
/**
|
|
13
|
+
* These tests exercise the real filesystem on purpose: the behaviour under
|
|
14
|
+
* test is what a concurrent observer can see on disk while a write is in
|
|
15
|
+
* flight, which a mocked `fs` cannot express.
|
|
16
|
+
*/
|
|
17
|
+
describe('StandardFileSystemService atomicity', () => {
|
|
18
|
+
let dir;
|
|
19
|
+
let service;
|
|
20
|
+
beforeEach(async () => {
|
|
21
|
+
dir = await fsp.mkdtemp(path.join(os.tmpdir(), 'gemini-atomic-write-'));
|
|
22
|
+
service = new StandardFileSystemService();
|
|
23
|
+
});
|
|
24
|
+
afterEach(async () => {
|
|
25
|
+
await fsp.rm(dir, { recursive: true, force: true });
|
|
26
|
+
});
|
|
27
|
+
it('never exposes a partially written file to a concurrent observer', async () => {
|
|
28
|
+
// Large enough that the underlying write is split into several chunks;
|
|
29
|
+
// old and new are the same length so any other size is a partial state.
|
|
30
|
+
const SIZE = 16 * 1024 * 1024;
|
|
31
|
+
const filePath = path.join(dir, 'large.txt');
|
|
32
|
+
await fsp.writeFile(filePath, 'o'.repeat(SIZE), 'utf-8');
|
|
33
|
+
// The write runs on the libuv threadpool, so a *synchronous* loop on the
|
|
34
|
+
// main thread is what actually catches the destination mid-write. An
|
|
35
|
+
// async reader tends to be scheduled only before or after it.
|
|
36
|
+
const sizes = new Set();
|
|
37
|
+
let settled = false;
|
|
38
|
+
const write = service
|
|
39
|
+
.writeTextFile(filePath, 'n'.repeat(SIZE))
|
|
40
|
+
.finally(() => {
|
|
41
|
+
settled = true;
|
|
42
|
+
});
|
|
43
|
+
let spins = 0;
|
|
44
|
+
while (!settled && spins < 2_000_000) {
|
|
45
|
+
try {
|
|
46
|
+
sizes.add(fs.statSync(filePath).size);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
// The destination may briefly not exist while being replaced.
|
|
50
|
+
sizes.add(-1);
|
|
51
|
+
}
|
|
52
|
+
spins++;
|
|
53
|
+
if (spins % 200 === 0) {
|
|
54
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
await write;
|
|
58
|
+
// Guard against a vacuous pass where the observer never ran.
|
|
59
|
+
expect(sizes.size).toBeGreaterThan(0);
|
|
60
|
+
const partialStates = [...sizes].filter((size) => size !== SIZE && size !== -1);
|
|
61
|
+
expect(partialStates).toEqual([]);
|
|
62
|
+
});
|
|
63
|
+
it('writes the requested content', async () => {
|
|
64
|
+
const filePath = path.join(dir, 'content.txt');
|
|
65
|
+
await service.writeTextFile(filePath, 'hello');
|
|
66
|
+
await expect(fsp.readFile(filePath, 'utf-8')).resolves.toBe('hello');
|
|
67
|
+
});
|
|
68
|
+
it.skipIf(process.platform === 'win32')('preserves the permissions of an existing file', async () => {
|
|
69
|
+
const filePath = path.join(dir, 'secret.txt');
|
|
70
|
+
await fsp.writeFile(filePath, 'before', { mode: 0o600 });
|
|
71
|
+
await fsp.chmod(filePath, 0o600);
|
|
72
|
+
await service.writeTextFile(filePath, 'after');
|
|
73
|
+
const stats = await fsp.stat(filePath);
|
|
74
|
+
expect(stats.mode & 0o777).toBe(0o600);
|
|
75
|
+
});
|
|
76
|
+
it('leaves no temporary files behind on success', async () => {
|
|
77
|
+
const filePath = path.join(dir, 'clean.txt');
|
|
78
|
+
await service.writeTextFile(filePath, 'done');
|
|
79
|
+
await expect(fsp.readdir(dir)).resolves.toEqual(['clean.txt']);
|
|
80
|
+
});
|
|
81
|
+
it('updates the target of a symlink without replacing the symlink itself', async () => {
|
|
82
|
+
const targetPath = path.join(dir, 'target.txt');
|
|
83
|
+
const symlinkPath = path.join(dir, 'link.txt');
|
|
84
|
+
await fsp.writeFile(targetPath, 'original');
|
|
85
|
+
await fsp.symlink(targetPath, symlinkPath);
|
|
86
|
+
await service.writeTextFile(symlinkPath, 'updated');
|
|
87
|
+
await expect(fsp.readFile(targetPath, 'utf-8')).resolves.toBe('updated');
|
|
88
|
+
const lstat = await fsp.lstat(symlinkPath);
|
|
89
|
+
expect(lstat.isSymbolicLink()).toBe(true);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
//# sourceMappingURL=fileSystemService.atomic.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fileSystemService.atomic.test.js","sourceRoot":"","sources":["../../../src/services/fileSystemService.atomic.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,5 +27,15 @@ export interface FileSystemService {
|
|
|
27
27
|
*/
|
|
28
28
|
export declare class StandardFileSystemService implements FileSystemService {
|
|
29
29
|
readTextFile(filePath: string): Promise<string>;
|
|
30
|
+
/**
|
|
31
|
+
* Writes `content` to `filePath` atomically.
|
|
32
|
+
*
|
|
33
|
+
* A plain `fs.writeFile` truncates the destination and then streams the
|
|
34
|
+
* content in chunks, so anything reading the file concurrently can observe
|
|
35
|
+
* a truncated prefix. Writing to a sibling temp file and renaming it into
|
|
36
|
+
* place means an observer sees either the old file or the new one.
|
|
37
|
+
*/
|
|
30
38
|
writeTextFile(filePath: string, content: string): Promise<void>;
|
|
39
|
+
private getFileMode;
|
|
40
|
+
private renameWithRetry;
|
|
31
41
|
}
|
|
@@ -3,7 +3,13 @@
|
|
|
3
3
|
* Copyright 2025 Google LLC
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
+
import { randomUUID } from 'node:crypto';
|
|
6
7
|
import fs from 'node:fs/promises';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import { isNodeError } from '../utils/errors.js';
|
|
10
|
+
import { resolveToRealPath } from '../utils/paths.js';
|
|
11
|
+
/** Rename retries, for transient Windows lock errors. */
|
|
12
|
+
const RENAME_MAX_RETRIES = 5;
|
|
7
13
|
/**
|
|
8
14
|
* Standard file system implementation
|
|
9
15
|
*/
|
|
@@ -11,8 +17,97 @@ export class StandardFileSystemService {
|
|
|
11
17
|
async readTextFile(filePath) {
|
|
12
18
|
return fs.readFile(filePath, 'utf-8');
|
|
13
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Writes `content` to `filePath` atomically.
|
|
22
|
+
*
|
|
23
|
+
* A plain `fs.writeFile` truncates the destination and then streams the
|
|
24
|
+
* content in chunks, so anything reading the file concurrently can observe
|
|
25
|
+
* a truncated prefix. Writing to a sibling temp file and renaming it into
|
|
26
|
+
* place means an observer sees either the old file or the new one.
|
|
27
|
+
*/
|
|
14
28
|
async writeTextFile(filePath, content) {
|
|
15
|
-
|
|
29
|
+
// When filePath is a symlink, resolve to its real target path so that the
|
|
30
|
+
// rename updates the underlying target file rather than replacing the
|
|
31
|
+
// symlink itself with a regular file.
|
|
32
|
+
let realPath = filePath;
|
|
33
|
+
try {
|
|
34
|
+
realPath = resolveToRealPath(filePath);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
try {
|
|
38
|
+
const dir = path.dirname(filePath);
|
|
39
|
+
const base = path.basename(filePath);
|
|
40
|
+
realPath = path.join(resolveToRealPath(dir), base);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
realPath = filePath;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// The temp file must share a directory with the destination so that the
|
|
47
|
+
// rename stays within one filesystem, and must be uniquely named so that
|
|
48
|
+
// concurrent writers do not clobber each other's temp file.
|
|
49
|
+
const tmpPath = `${realPath}.${randomUUID()}.tmp`;
|
|
50
|
+
// A fresh temp file does not inherit the destination's permissions, so
|
|
51
|
+
// without this, replacing a 0600 file would silently widen it to the
|
|
52
|
+
// default mode.
|
|
53
|
+
const existingMode = await this.getFileMode(realPath);
|
|
54
|
+
try {
|
|
55
|
+
// Create the temp file already carrying the destination's mode, so the
|
|
56
|
+
// content is never briefly readable through a wider default mode. The
|
|
57
|
+
// mode is masked by umask, so this can only be more restrictive.
|
|
58
|
+
await fs.writeFile(tmpPath, content, {
|
|
59
|
+
encoding: 'utf-8',
|
|
60
|
+
...(existingMode !== undefined ? { mode: existingMode } : {}),
|
|
61
|
+
});
|
|
62
|
+
if (existingMode !== undefined) {
|
|
63
|
+
try {
|
|
64
|
+
// Correct any narrowing that umask applied above. Best effort: some
|
|
65
|
+
// filesystems (FAT32, exFAT, a few NFS/CIFS mounts) and restricted
|
|
66
|
+
// sandboxes reject chmod with EPERM/ENOTSUP, and permissions must
|
|
67
|
+
// not be the reason a write fails.
|
|
68
|
+
await fs.chmod(tmpPath, existingMode);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Keep whatever mode the temp file was created with.
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
await this.renameWithRetry(tmpPath, realPath);
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
await fs.rm(tmpPath, { force: true }).catch(() => {
|
|
78
|
+
// Best effort: the original error is the one worth reporting.
|
|
79
|
+
});
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async getFileMode(filePath) {
|
|
84
|
+
try {
|
|
85
|
+
const stats = await fs.stat(filePath);
|
|
86
|
+
return stats.mode & 0o777;
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// New file, or a destination we cannot stat; keep the default mode.
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async renameWithRetry(from, to) {
|
|
94
|
+
for (let attempt = 0; attempt < RENAME_MAX_RETRIES; attempt++) {
|
|
95
|
+
try {
|
|
96
|
+
await fs.rename(from, to);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
// Windows can transiently refuse a rename while another process has
|
|
101
|
+
// the destination open (antivirus, editors, watchers).
|
|
102
|
+
const code = isNodeError(error) ? error.code : '';
|
|
103
|
+
const isRetryable = code === 'EBUSY' || code === 'EPERM' || code === 'EACCES';
|
|
104
|
+
if (!isRetryable || attempt === RENAME_MAX_RETRIES - 1) {
|
|
105
|
+
throw error;
|
|
106
|
+
}
|
|
107
|
+
const delayMs = Math.pow(2, attempt) * 50;
|
|
108
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
16
111
|
}
|
|
17
112
|
}
|
|
18
113
|
//# sourceMappingURL=fileSystemService.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileSystemService.js","sourceRoot":"","sources":["../../../src/services/fileSystemService.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"fileSystemService.js","sourceRoot":"","sources":["../../../src/services/fileSystemService.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,10 +5,16 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
7
7
|
import fs from 'node:fs/promises';
|
|
8
|
+
import path from 'node:path';
|
|
8
9
|
import { StandardFileSystemService } from './fileSystemService.js';
|
|
9
10
|
vi.mock('fs/promises');
|
|
11
|
+
function escapeRegex(str) {
|
|
12
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
13
|
+
}
|
|
10
14
|
describe('StandardFileSystemService', () => {
|
|
11
15
|
let fileSystem;
|
|
16
|
+
const targetFile = path.resolve('/test/file.txt');
|
|
17
|
+
const tmpPattern = new RegExp(`^${escapeRegex(targetFile)}\\..*\\.tmp$`);
|
|
12
18
|
beforeEach(() => {
|
|
13
19
|
vi.resetAllMocks();
|
|
14
20
|
fileSystem = new StandardFileSystemService();
|
|
@@ -20,21 +26,83 @@ describe('StandardFileSystemService', () => {
|
|
|
20
26
|
it('should read file content using fs', async () => {
|
|
21
27
|
const testContent = 'Hello, World!';
|
|
22
28
|
vi.mocked(fs.readFile).mockResolvedValue(testContent);
|
|
23
|
-
const result = await fileSystem.readTextFile(
|
|
24
|
-
expect(fs.readFile).toHaveBeenCalledWith(
|
|
29
|
+
const result = await fileSystem.readTextFile(targetFile);
|
|
30
|
+
expect(fs.readFile).toHaveBeenCalledWith(targetFile, 'utf-8');
|
|
25
31
|
expect(result).toBe(testContent);
|
|
26
32
|
});
|
|
27
33
|
it('should propagate fs.readFile errors', async () => {
|
|
28
34
|
const error = new Error('ENOENT: File not found');
|
|
29
35
|
vi.mocked(fs.readFile).mockRejectedValue(error);
|
|
30
|
-
await expect(fileSystem.readTextFile(
|
|
36
|
+
await expect(fileSystem.readTextFile(targetFile)).rejects.toThrow('ENOENT: File not found');
|
|
31
37
|
});
|
|
32
38
|
});
|
|
33
39
|
describe('writeTextFile', () => {
|
|
34
|
-
it('should write file
|
|
40
|
+
it('should write to a sibling temp file and rename it into place', async () => {
|
|
35
41
|
vi.mocked(fs.writeFile).mockResolvedValue();
|
|
36
|
-
|
|
37
|
-
|
|
42
|
+
vi.mocked(fs.rename).mockResolvedValue();
|
|
43
|
+
vi.mocked(fs.stat).mockRejectedValue(new Error('ENOENT'));
|
|
44
|
+
await fileSystem.writeTextFile(targetFile, 'Hello, World!');
|
|
45
|
+
const [tmpPath, content, options] = vi.mocked(fs.writeFile).mock
|
|
46
|
+
.calls[0];
|
|
47
|
+
expect(content).toBe('Hello, World!');
|
|
48
|
+
expect(options.encoding).toBe('utf-8');
|
|
49
|
+
expect(tmpPath).toMatch(tmpPattern);
|
|
50
|
+
expect(fs.rename).toHaveBeenCalledWith(tmpPath, targetFile);
|
|
51
|
+
});
|
|
52
|
+
it('should match temp file patterns with Windows-style backslash paths', () => {
|
|
53
|
+
const winTarget = 'C:\\test\\folder\\file.txt';
|
|
54
|
+
const winTmpPattern = new RegExp(`^${escapeRegex(winTarget)}\\..*\\.tmp$`);
|
|
55
|
+
const sampleWinTmp = 'C:\\test\\folder\\file.txt.12345678-1234-1234-1234-123456789abc.tmp';
|
|
56
|
+
expect(sampleWinTmp).toMatch(winTmpPattern);
|
|
57
|
+
});
|
|
58
|
+
it('should create the temp file with the destination permissions', async () => {
|
|
59
|
+
vi.mocked(fs.writeFile).mockResolvedValue();
|
|
60
|
+
vi.mocked(fs.rename).mockResolvedValue();
|
|
61
|
+
vi.mocked(fs.chmod).mockResolvedValue();
|
|
62
|
+
vi.mocked(fs.stat).mockResolvedValue({
|
|
63
|
+
mode: 0o600,
|
|
64
|
+
});
|
|
65
|
+
const secretFile = path.resolve('/test/secret.txt');
|
|
66
|
+
await fileSystem.writeTextFile(secretFile, 'Hello, World!');
|
|
67
|
+
// Creating the temp file already restricted means the content is never
|
|
68
|
+
// briefly readable through a wider default mode.
|
|
69
|
+
const [, , options] = vi.mocked(fs.writeFile).mock.calls[0];
|
|
70
|
+
expect(options).toEqual({ encoding: 'utf-8', mode: 0o600 });
|
|
71
|
+
});
|
|
72
|
+
it('should still write the file when chmod is not permitted', async () => {
|
|
73
|
+
vi.mocked(fs.writeFile).mockResolvedValue();
|
|
74
|
+
vi.mocked(fs.rename).mockResolvedValue();
|
|
75
|
+
vi.mocked(fs.rm).mockResolvedValue();
|
|
76
|
+
vi.mocked(fs.stat).mockResolvedValue({
|
|
77
|
+
mode: 0o600,
|
|
78
|
+
});
|
|
79
|
+
// FAT32/exFAT, some NFS/CIFS mounts and restricted sandboxes reject chmod.
|
|
80
|
+
vi.mocked(fs.chmod).mockRejectedValue(Object.assign(new Error('operation not supported'), {
|
|
81
|
+
code: 'ENOTSUP',
|
|
82
|
+
}));
|
|
83
|
+
await expect(fileSystem.writeTextFile(targetFile, 'Hello, World!')).resolves.toBeUndefined();
|
|
84
|
+
expect(fs.rename).toHaveBeenCalled();
|
|
85
|
+
expect(fs.rm).not.toHaveBeenCalled();
|
|
86
|
+
});
|
|
87
|
+
it('should remove the temp file when the write fails', async () => {
|
|
88
|
+
vi.mocked(fs.writeFile).mockRejectedValue(new Error('ENOSPC'));
|
|
89
|
+
vi.mocked(fs.rm).mockResolvedValue();
|
|
90
|
+
await expect(fileSystem.writeTextFile(targetFile, 'Hello, World!')).rejects.toThrow('ENOSPC');
|
|
91
|
+
expect(fs.rename).not.toHaveBeenCalled();
|
|
92
|
+
const [removed] = vi.mocked(fs.rm).mock.calls[0];
|
|
93
|
+
expect(removed).toMatch(tmpPattern);
|
|
94
|
+
});
|
|
95
|
+
it('should retry rename when encountering EACCES', async () => {
|
|
96
|
+
vi.mocked(fs.writeFile).mockResolvedValue();
|
|
97
|
+
vi.mocked(fs.stat).mockRejectedValue(new Error('ENOENT'));
|
|
98
|
+
const eaccesError = Object.assign(new Error('permission denied'), {
|
|
99
|
+
code: 'EACCES',
|
|
100
|
+
});
|
|
101
|
+
vi.mocked(fs.rename)
|
|
102
|
+
.mockRejectedValueOnce(eaccesError)
|
|
103
|
+
.mockResolvedValueOnce();
|
|
104
|
+
await expect(fileSystem.writeTextFile(targetFile, 'Hello, World!')).resolves.toBeUndefined();
|
|
105
|
+
expect(fs.rename).toHaveBeenCalledTimes(2);
|
|
38
106
|
});
|
|
39
107
|
});
|
|
40
108
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fileSystemService.test.js","sourceRoot":"","sources":["../../../src/services/fileSystemService.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AAEnE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AAEvB,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,IAAI,UAAqC,CAAC;
|
|
1
|
+
{"version":3,"file":"fileSystemService.test.js","sourceRoot":"","sources":["../../../src/services/fileSystemService.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
import * as fs from 'node:fs/promises';
|
|
7
7
|
import * as path from 'node:path';
|
|
8
8
|
import { isNodeError } from '../utils/errors.js';
|
|
9
|
+
import { withPathLock } from '../utils/pathMutex.js';
|
|
10
|
+
import { resolveToRealPath } from '../utils/paths.js';
|
|
9
11
|
import { spawnAsync } from '../utils/shell-utils.js';
|
|
10
12
|
import { simpleGit, CheckRepoActions, } from 'simple-git';
|
|
11
13
|
import { debugLogger } from '../utils/debugLogger.js';
|
|
@@ -155,22 +157,34 @@ export class GitService {
|
|
|
155
157
|
return hash.trim();
|
|
156
158
|
}
|
|
157
159
|
async createFileSnapshot(message) {
|
|
160
|
+
// `add('.')` stages the entire working tree, so two snapshots running at
|
|
161
|
+
// once fold each other's files into whichever commit lands first. Serialize
|
|
162
|
+
// stage -> status -> commit per shadow repository.
|
|
163
|
+
let realProjectRoot = this.projectRoot;
|
|
158
164
|
try {
|
|
159
|
-
|
|
160
|
-
await repo.add('.');
|
|
161
|
-
const status = await repo.status();
|
|
162
|
-
if (status.isClean()) {
|
|
163
|
-
// If no changes are staged, return the current HEAD commit hash
|
|
164
|
-
return await this.getCurrentCommitHash();
|
|
165
|
-
}
|
|
166
|
-
const commitResult = await repo.commit(message, {
|
|
167
|
-
'--no-verify': null,
|
|
168
|
-
});
|
|
169
|
-
return commitResult.commit;
|
|
165
|
+
realProjectRoot = resolveToRealPath(this.projectRoot);
|
|
170
166
|
}
|
|
171
|
-
catch
|
|
172
|
-
|
|
167
|
+
catch {
|
|
168
|
+
// Keep unresolved
|
|
173
169
|
}
|
|
170
|
+
return withPathLock(`git-snapshot:${realProjectRoot}`, async () => {
|
|
171
|
+
try {
|
|
172
|
+
const repo = this.shadowGitRepository;
|
|
173
|
+
await repo.add('.');
|
|
174
|
+
const status = await repo.status();
|
|
175
|
+
if (status.isClean()) {
|
|
176
|
+
// If no changes are staged, return the current HEAD commit hash
|
|
177
|
+
return await this.getCurrentCommitHash();
|
|
178
|
+
}
|
|
179
|
+
const commitResult = await repo.commit(message, {
|
|
180
|
+
'--no-verify': null,
|
|
181
|
+
});
|
|
182
|
+
return commitResult.commit;
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
throw new Error(`Failed to create checkpoint snapshot: ${error instanceof Error ? error.message : 'Unknown error'}. Checkpointing may not be working properly.`);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
174
188
|
}
|
|
175
189
|
async restoreProjectFromSnapshot(commitHash) {
|
|
176
190
|
const repo = this.shadowGitRepository;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gitService.js","sourceRoot":"","sources":["../../../src/services/gitService.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"gitService.js","sourceRoot":"","sources":["../../../src/services/gitService.ts"],"names":[],"mappings":"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"}
|