MCPcopy
hub / github.com/coder/mux / writeFile

Function writeFile

src/node/runtime/RemoteRuntime.ts:391–460  ·  view source on GitHub ↗

* Write file contents atomically via exec. * Uses temp file + mv for atomic write.

(filePath: string, abortSignal?: AbortSignal)

Source from the content-addressed store, hash-verified

389 * Uses temp file + mv for atomic write.
390 */
391 writeFile(filePath: string, abortSignal?: AbortSignal): WritableStream<Uint8Array> {
392 const quotedPath = this.quoteForRemote(filePath);
393 const tempPath = getAtomicWriteTempPath(filePath);
394 const quotedTempPath = this.quoteForRemote(tempPath);
395
396 // Build write command - subclasses can override buildWriteCommand for special handling
397 const writeCommand = this.buildWriteCommand(quotedPath, quotedTempPath);
398
399 let execPromise: Promise<ExecStream> | null = null;
400 const writeAbortController = new AbortController();
401 const abortWrite = () => writeAbortController.abort();
402 if (abortSignal?.aborted) {
403 writeAbortController.abort();
404 } else {
405 abortSignal?.addEventListener("abort", abortWrite, { once: true });
406 }
407 const cleanupAbortForwarder = () => {
408 abortSignal?.removeEventListener("abort", abortWrite);
409 };
410
411 const getExecStream = () => {
412 execPromise ??= this.exec(writeCommand, {
413 cwd: this.getBasePath(),
414 timeout: 300,
415 abortSignal: writeAbortController.signal,
416 });
417 return execPromise;
418 };
419
420 return new WritableStream<Uint8Array>({
421 write: async (chunk: Uint8Array) => {
422 const stream = await getExecStream();
423 const writer = stream.stdin.getWriter();
424 try {
425 await writer.write(chunk);
426 } finally {
427 writer.releaseLock();
428 }
429 },
430 close: async () => {
431 try {
432 const stream = await getExecStream();
433 await stream.stdin.close();
434 const exitCode = await stream.exitCode;
435
436 if (exitCode !== 0) {
437 const stderr = await streamToString(stream.stderr);
438 throw new RuntimeError(`Failed to write file ${filePath}: ${stderr}`, "file_io");
439 }
440 } finally {
441 cleanupAbortForwarder();
442 }
443 },
444 abort: async (reason?: unknown) => {
445 writeAbortController.abort();
446 if (execPromise) {
447 try {
448 const stream = await execPromise;

Calls 10

getAtomicWriteTempPathFunction · 0.90
streamToStringFunction · 0.90
getExecStreamFunction · 0.85
cleanupAbortForwarderFunction · 0.85
abortMethod · 0.65
writeMethod · 0.65
closeMethod · 0.65
quoteForRemoteMethod · 0.45
buildWriteCommandMethod · 0.45
addEventListenerMethod · 0.45