@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
92 lines • 4.1 kB
JavaScript
// ========= 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 { PathSpec } from "../../../../types.js";
import { posixNormpath } from "../../../../utils/path.js";
import { CD_OPTIONS } from "./constants.js";
// Split leading -L/-P option flags (clusters like -LP, and a `--`
// terminator) from the operands. Shared by `cd` (which also takes -e -@)
// and `pwd`, so the last-wins rule -- `pwd -L -P` is physical, `pwd -P
// -L` logical -- has one implementation. A bare `-` is an operand (`cd`'s
// OLDPWD shorthand), not an option. `bad` is the first unknown character.
export function splitModeOptions(args, letters = CD_OPTIONS,
// The mode to assume when the line names neither, which is what
// `set -P` changes for the whole session.
fallback = false) {
const operands = [];
let parsing = true;
let physical = fallback;
for (const arg of args) {
const s = arg instanceof PathSpec ? arg.virtual : arg;
if (parsing) {
if (s === '--') {
parsing = false;
continue;
}
if (s !== '-' && s.length >= 2 && s.startsWith('-')) {
let bad = null;
for (const c of s.slice(1)) {
if (!letters.includes(c)) {
bad = c;
break;
}
}
if (bad !== null)
return { operands, bad, physical };
for (const c of s.slice(1)) {
if (c === 'P')
physical = true;
else if (c === 'L')
physical = false;
}
continue;
}
parsing = false;
}
operands.push(arg);
}
return { operands, bad: null, physical };
}
// Resolve a combined `cd` target following symlinks per mode. Logical (-L,
// default) simplifies `..` textually first, then follows links; physical (-P)
// follows links first so `..` acts on the target. The namespace's walk leaves
// no link in what it answers, so one walk settles either. `follow` is the
// session's link resolution, which throws CycleError on a loop (ELOOP).
// Mirrors Python's resolve_target.
export function resolveTarget(combined, follow, physical) {
return posixNormpath(follow(physical ? combined : posixNormpath(combined)));
}
// Join an operand to `cwd` WITHOUT simplifying `..`. resolvePath normalizes,
// which is what -L wants but destroys the only input -P has: bash resolves a
// link before applying the `..` after it, so `/link/..` is the link's parent
// under -L and the target's parent under -P. Collapsing the `..` first makes
// the two modes identical. resolveTarget normalizes for both modes, so
// nothing downstream sees the raw form.
export function joinRaw(path, cwd) {
if (path.startsWith('/'))
return path;
let end = cwd.length;
while (end > 0 && cwd[end - 1] === '/')
end -= 1;
return `${cwd.slice(0, end)}/${path}`;
}
// The operand as typed, which is what -P has to resolve. A relative operand
// arrives as a PathSpec whose `virtual` was already normalized against cwd
// (expand/classify/relative.ts), losing its `..` before cd is reached;
// `rawPath` keeps the spelling.
export function typedPath(val) {
if (typeof val === 'string')
return val;
return val.rawPath || val.virtual;
}
//# sourceMappingURL=dirs.js.map