UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

89 lines • 3.69 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 { decodeText } from "../../../../shell/bytes.js"; import { readOptional } from "./io.js"; const MAILMAP_LINE = /^\s*([^<>]*?)\s*<([^<>]+)>(?:\s*([^<>]*?)\s*<([^<>]*)>)?/; const IDENTITY = /(.*?)\s*<([^<>]*)>/; /** * Read Git's four mailmap identity forms. * * Pinned against git 2.47.3 (Debian stable) and 2.50.1: only a `#` in the * first column starts a comment, and the second email may be empty (`<>`) * while the first may not. */ export function parseMailmap(text) { const entries = []; for (const line of text.split('\n')) { if (line.startsWith('#')) continue; const match = MAILMAP_LINE.exec(line); if (!match) continue; const [, name = '', email = '', oldName, oldEmail] = match; entries.push({ email: (oldEmail ?? email).toLowerCase(), name: oldName ? oldName.toLowerCase() : null, mappedName: name || null, mappedEmail: oldEmail === undefined ? null : email, }); } return entries; } /** * Map one `Name <email>` identity the way git's mailmap does. * * An entry naming both the recorded name and email wins outright, the last * such line replacing any earlier one. Without one, the entries naming the * email alone apply, each later line overriding the part it spells. */ export function mappedIdentity(identity, entries) { const match = IDENTITY.exec(identity); if (!match) return identity; const [, name = '', email = ''] = match; let simpleName = null; let simpleEmail = null; let specific = null; for (const entry of entries) { if (entry.email !== email.toLowerCase()) continue; if (entry.name === null) { simpleName = entry.mappedName ?? simpleName; simpleEmail = entry.mappedEmail ?? simpleEmail; } else if (entry.name === name.toLowerCase()) { specific = entry; } } if (specific !== null) { simpleName = specific.mappedName; simpleEmail = specific.mappedEmail; } return `${simpleName ?? name} <${simpleEmail ?? email}>`; } /** Read the worktree mailmap through the workspace data plane. */ export async function loadMailmap(vfs, location, exact = false) { const data = (await readOptional(vfs, location.worktree.join(`.mailmap`))) ?? new Uint8Array(); // `exact` keeps every byte, as decodeText reads object headers, so a name // that is not UTF-8 matches byte for byte as git's does; otherwise such a // byte reads as U+FFFD, as the log family reads identities. return parseMailmap(exact ? decodeText(data) : new TextDecoder().decode(data)); } /** Apply explicit mailmap switches in command-line order. */ export function useMailmap(fl, enabled) { for (const [key] of fl.occurrences('mailmap', 'use_mailmap', 'no_mailmap', 'no_use_mailmap')) enabled = !key.startsWith('no_'); return enabled; } //# sourceMappingURL=mailmap.js.map