UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

96 lines • 3.6 kB
// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. ========= // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ========= Copyright 2026 @ Strukto.AI All Rights Reserved. ========= import { extraOperandError, missingOperandError } from "../../../spec/usage.js"; import { IOResult } from "../../../../io/types.js"; import { FileType, Follow, LineFacts } from "../../../../types.js"; import { fsStrerror, isFsError } from "../../../../errors/fs.js"; import { posixPhrase } from "../../../../errors/posix.js"; import { commandFiles } from "../files.js"; import { linksOf } from "../../utils/links.js"; const unlink = async (_accessor, paths, _texts, ctx) => { const files = commandFiles(ctx, paths); if (paths.length === 0) throw missingOperandError('unlink', null); const resolved = await files.resolveGlob(paths); if (resolved.length > 1) { const extra = resolved[1]; throw extraOperandError('unlink', extra === undefined ? '' : extra.rawPath); } const p = resolved[0]; if (p === undefined) throw missingOperandError('unlink', null); const enc = new TextEncoder(); const links = linksOf(ctx) ?? null; // unlink(2) never follows, so a trailing slash on a link operand is // refused rather than resolved: GNU answers `unlink dlink/` and // `unlink flink/` alike with ENOTDIR, where a real directory under a // slash is EISDIR. A bare link operand never reaches here at all -- // the dispatcher removes the link entry, which no backend can see. if (links !== null && p.rawPath.endsWith('/') && links.statAt(p.virtual) !== null) { return [ null, new IOResult({ exitCode: 1, stderr: enc.encode(`unlink: cannot unlink '${p.rawPath}': ${posixPhrase('ENOTDIR')}\n`), }), ]; } let isDir = false; try { const st = await files.stat(p); isDir = st.type === FileType.DIRECTORY; } catch (err) { if (!isFsError(err)) throw err; return [ null, new IOResult({ exitCode: 1, stderr: enc.encode(`unlink: cannot unlink '${p.rawPath}': ${fsStrerror(err) ?? String(err)}\n`), }), ]; } if (isDir) { return [ null, new IOResult({ exitCode: 1, stderr: enc.encode(`unlink: cannot unlink '${p.rawPath}': ${posixPhrase('EISDIR')}\n`), }), ]; } try { await files.unlink(p); } catch (err) { if (!isFsError(err)) throw err; return [ null, new IOResult({ exitCode: 1, stderr: enc.encode(`unlink: cannot unlink '${p.rawPath}': ${String(fsStrerror(err))}\n`), }), ]; } return [null, new IOResult()]; }; export const BUILDER = { name: 'unlink', facts: new LineFacts({ follows: Follow.NONE }), write: true, fn: unlink, }; //# sourceMappingURL=unlink.js.map