Skip to content

Commit d388f1b

Browse files
committed
Restore symlink resolution logic in LocalRuntime.writeFile()
During rebase conflict resolution, symlink resolution logic was accidentally removed from LocalRuntime.writeFile(). This restores: - resolvedPath: Resolves symlinks to write through them - originalMode: Preserves file permissions across writes The abort signal parameter addition is preserved.
1 parent da4b5c4 commit d388f1b

File tree

1 file changed

+21
-3
lines changed

1 file changed

+21
-3
lines changed

src/runtime/LocalRuntime.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -243,15 +243,29 @@ export class LocalRuntime implements Runtime {
243243
// Note: _abortSignal ignored for local operations (fast, no need for cancellation)
244244
let tempPath: string;
245245
let writer: WritableStreamDefaultWriter<Uint8Array>;
246+
let resolvedPath: string;
247+
let originalMode: number | undefined;
246248

247249
return new WritableStream<Uint8Array>({
248250
async start() {
251+
// Resolve symlinks to write through them (preserves the symlink)
252+
try {
253+
resolvedPath = await fsPromises.realpath(filePath);
254+
// Save original permissions to restore after write
255+
const stat = await fsPromises.stat(resolvedPath);
256+
originalMode = stat.mode;
257+
} catch {
258+
// If file doesn't exist, use the original path and default permissions
259+
resolvedPath = filePath;
260+
originalMode = undefined;
261+
}
262+
249263
// Create parent directories if they don't exist
250-
const parentDir = path.dirname(filePath);
264+
const parentDir = path.dirname(resolvedPath);
251265
await fsPromises.mkdir(parentDir, { recursive: true });
252266

253267
// Create temp file for atomic write
254-
tempPath = `${filePath}.tmp.${Date.now()}`;
268+
tempPath = `${resolvedPath}.tmp.${Date.now()}`;
255269
const nodeStream = fs.createWriteStream(tempPath);
256270
const webStream = Writable.toWeb(nodeStream) as WritableStream<Uint8Array>;
257271
writer = webStream.getWriter();
@@ -263,7 +277,11 @@ export class LocalRuntime implements Runtime {
263277
// Close the writer and rename to final location
264278
await writer.close();
265279
try {
266-
await fsPromises.rename(tempPath, filePath);
280+
// If we have original permissions, apply them to temp file before rename
281+
if (originalMode !== undefined) {
282+
await fsPromises.chmod(tempPath, originalMode);
283+
}
284+
await fsPromises.rename(tempPath, resolvedPath);
267285
} catch (err) {
268286
throw new RuntimeErrorClass(
269287
`Failed to write file ${filePath}: ${err instanceof Error ? err.message : String(err)}`,

0 commit comments

Comments
 (0)