UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

1,063 lines • 48.2 kB
import { CommandSpec } from "../../../spec/types.js"; import { CLI } from "../../types.js"; import { CLIHandler } from "../../types.js"; import { lsFiles, lsTree } from "./ls_files.js"; import { forEachRef } from "./for_each_ref.js"; import { reflog } from "./reflog.js"; import { fetch, fetchReadOnly } from "./fetch.js"; import { clone, cloneReadOnly } from "./clone.js"; import { Argument, UsageStyle } from "../../../spec/types.js"; import { add } from "./add.js"; import { init } from "./init.js"; import { fsck } from "./fsck.js"; import { grep } from "./grep.js"; import { hashObject, hashObjectReadOnly } from "./hash_object.js"; import { stashList, stashShow } from "./stash.js"; import { nodeHelp, findNode } from "../../walk.js"; import { IOResult } from "../../../../io/types.js"; import { branch, branchReadOnly } from "./branch.js"; import { catFile } from "./cat_file.js"; import { checkout, checkoutReadOnly } from "./checkout.js"; import { commit } from "./commit.js"; import { diff } from "./diff.js"; import { log } from "./log.js"; import { mv } from "./mv.js"; import { reset } from "./reset.js"; import { restore } from "./restore.js"; import { rm } from "./rm.js"; import { revParse, config, mergeBase, remote, revList, version, showRef } from "./inspect.js"; import { shortlog } from "./shortlog.js"; import { symbolicRef, symbolicRefReadOnly } from "./symbolic_ref.js"; import { indexLocked, verb } from "./session.js"; import { show, diffTree } from "./show.js"; import { status } from "./status.js"; import { switchBranch, switchReadOnly } from "./switch.js"; import { tag, tagReadOnly } from "./tag.js"; import { checkSwitches } from "./util.js"; // `-C` is git's own before-anything-else option, so it sits on the root and // every verb inherits it. The "." default is load-bearing: a PATH default lands // as if typed, so an absent -C resolves to the session cwd and the leaves need // no separate working-directory fact. The root names it its operand base, so a // later relative -C lands under the one before it. const DIRECTORY_OPTION = new Argument('-C', { type: 'path', default: '.', help: 'Run as if git was started in <path>', }); const REVISION = new Argument('text', { metavar: '', nargs: '*' }); // --pretty and --format choose the same format in git; both take git's // optional-value form, so a bare --pretty means medium and a detached next // word is a revision, never a format. A bare --format stays parseable too, // but only so prettyFormat can answer it with git's own fatal (git takes // --format in its =value form alone). const PRETTY_OPTION = new Argument('--pretty', { nargs: '?', attachedOnly: true, help: 'Commit display format: oneline, short, medium, full, fuller, or a format:/tformat:/%-string', }); const FORMAT_OPTION = new Argument('--format', { nargs: '?', attachedOnly: true, help: 'Alias of --pretty (requires =value)', }); // Free text, read by parseDateMode: git names a style it lacks in its own // fatal, and format:<strftime> is no fixed word. const DATE_OPTION = new Argument('--date', { help: 'Date display format: default, relative, local, iso, iso-strict, rfc, short, raw, unix, ' + 'human or format:<strftime>', }); const DIFF_OPTIONS = [ new Argument(['-a', '--text'], { action: 'store_true', help: 'Treat binary files as text' }), new Argument(['-W', '--function-context'], { action: 'store_true', help: 'Show whole functions as diff context', }), new Argument(['-U', '--unified'], { type: 'int', help: 'Number of context lines' }), new Argument('--name-status', { action: 'store_true', help: 'Show changed paths and status' }), new Argument('--name-only', { action: 'store_true', help: 'Show changed paths instead of the patch', }), new Argument('--stat', { action: 'store_true', help: 'Show the diffstat table instead of the patch', }), new Argument('--numstat', { action: 'store_true', help: 'Show added and deleted line counts per path', }), new Argument('--shortstat', { action: 'store_true', help: 'Show only the diffstat summary line', }), new Argument('--summary', { action: 'store_true', help: 'Summarize creations, deletions and mode changes', }), new Argument(['-p', '--patch'], { action: 'store_true', help: 'Show the patch' }), new Argument(['-s', '--no-patch'], { action: 'store_true', help: 'Suppress all diff output' }), new Argument('--no-ext-diff', { action: 'store_true', help: 'Accepted for compatibility; there are no external diff drivers to disable', }), new Argument(['-M', '--find-renames'], { nargs: '?', attachedOnly: true, help: 'Detect renames with an optional similarity threshold', }), new Argument('--no-renames', { action: 'store_true', help: 'Turn off rename detection' }), new Argument('--raw', { action: 'store_true', help: 'Show the raw diff format' }), ]; // git's optional-value form: a bare --decorate is short, and a detached next // word is a revision, never a style. const DECORATE_OPTIONS = [ new Argument('--decorate', { nargs: '?', attachedOnly: true, help: 'Print ref names on commits: short (the default), full, auto or no', }), new Argument('--no-decorate', { action: 'store_true', help: 'Print no ref names on commits' }), ]; const MERGE_OPTIONS = [ new Argument('-m', { action: 'store_true', help: 'Show merge diffs separately against each parent', }), new Argument('-c', { action: 'store_true', help: 'Show combined merge diffs' }), new Argument('--cc', { action: 'store_true', help: 'Show dense combined merge diffs' }), new Argument('--first-parent', { action: 'store_true', help: 'Follow and compare only the first parent', }), new Argument('--diff-merges', { help: 'Select merge diff mode' }), ]; const LOG_OPTIONS = [ new Argument(['-E', '--extended-regexp'], { action: 'store_true', help: 'Use extended regular expressions', }), new Argument(['-F', '--fixed-strings'], { action: 'store_true', help: 'Match patterns literally', }), new Argument(['-P', '--perl-regexp'], { action: 'store_true', help: 'Use Perl-compatible regular expressions', }), new Argument('--basic-regexp', { action: 'store_true', help: 'Use basic regular expressions' }), new Argument('--committer', { action: 'append', help: 'Limit commits to matching committers' }), new Argument('--author', { action: 'append', help: 'Limit commits to matching authors' }), new Argument('--grep', { action: 'append', help: 'Limit commits to ones with a message line that matches', }), new Argument(['-i', '--regexp-ignore-case'], { action: 'store_true', help: 'Match --grep, --author and -S without regard to case', }), ...MERGE_OPTIONS, new Argument('--after', { help: 'Commits more recent than a date, like --since' }), new Argument('--before', { help: 'Commits older than a date, like --until' }), new Argument('--max-parents', { type: 'int', help: 'Show only commits with at most this many parents', }), new Argument('--min-parents', { type: 'int', help: 'Show only commits with at least this many parents', }), new Argument('--merges', { action: 'store_true', help: 'Show only merge commits' }), new Argument('--no-merges', { action: 'store_true', help: 'Leave out merge commits' }), DATE_OPTION, ...DECORATE_OPTIONS, new Argument(['-n', '--max-count'], { type: 'int', numericShorthand: true, help: 'Limit the number of commits shown', }), new Argument('--oneline', { action: 'store_true', help: 'One abbreviated line per commit' }), new Argument('--reverse', { action: 'store_true', help: 'Print commits oldest first' }), new Argument('--graph', { action: 'store_true', help: 'Draw the commit history beside the log (implies --topo-order)', }), new Argument('--topo-order', { action: 'store_true', help: 'Show no parent before all its children, one line of history at a time', }), new Argument('--date-order', { action: 'store_true', help: 'Show no parent before all its children, otherwise newest first', }), new Argument('--all', { action: 'store_true', help: 'Start from every ref as well as the revision', }), new Argument('--boundary', { action: 'store_true', help: 'Also show the excluded commits the history stops at', }), PRETTY_OPTION, FORMAT_OPTION, // The pickaxe, and the reason `git log -S <name> --reverse` answers "which // commit introduced this": it selects commits that changed how many times the // string occurs, not commits that mention it. new Argument('-S', { help: 'Show commits that change the number of occurrences of the string' }), new Argument('-G', { help: 'Show commits whose diff adds or removes a line that matches the extended regular expression', }), new Argument('--pickaxe-regex', { action: 'store_true', help: 'Treat the -S string as an extended regular expression', }), new Argument('--pickaxe-all', { action: 'store_true', help: 'Show every file a matching commit changed, not only the files -S or -G matched', }), new Argument('--since', { help: 'Commits more recent than a date (ISO-8601 or epoch)' }), new Argument('--until', { help: 'Commits older than a date (ISO-8601 or epoch)' }), ]; const MAILMAP_OPTIONS = [ new Argument('--mailmap', { action: 'store_true', help: 'Apply mailmap to identities' }), new Argument('--use-mailmap', { action: 'store_true', help: 'Apply mailmap to identities' }), new Argument('--no-mailmap', { action: 'store_true', help: 'Use recorded identities' }), new Argument('--no-use-mailmap', { action: 'store_true', help: 'Use recorded identities' }), ]; const SHOW_OPTIONS = [ ...MAILMAP_OPTIONS, new Argument('--oneline', { action: 'store_true', help: 'One abbreviated line per commit' }), ...DIFF_OPTIONS, ...MERGE_OPTIONS, DATE_OPTION, PRETTY_OPTION, FORMAT_OPTION, ]; const STATUS_OPTIONS = [ new Argument('--ignored', { action: 'store_true', help: 'Show ignored files' }), new Argument('--porcelain', { nargs: '?', attachedOnly: true, help: 'Machine-readable output, stable across versions', }), new Argument(['-s', '--short'], { action: 'store_true', help: 'Give the output in the short format', }), new Argument(['-b', '--branch'], { action: 'store_true', help: 'Show the branch line even in short format', }), // git spells the mode attached (`-uall`) or not at all, never as a separate // token, which is what valueOptional says: a bare -u means "all" and the next // word is left alone to be an operand. new Argument(['-u', '--untracked-files'], { nargs: '?', attachedOnly: true, choices: ['no', 'normal', 'all'], help: 'Show untracked files: no, normal or all', }), ]; const PATHSPEC = new Argument('text', { metavar: '', nargs: '*' }); const ADD_OPTIONS = [ new Argument(['-A', '--all'], { action: 'store_true', help: 'Stage every change' }), new Argument(['-u', '--update'], { action: 'store_true', help: 'Stage changes to tracked files only', }), new Argument(['-f', '--force'], { action: 'store_true', help: 'Stage paths an ignore rule covers', }), new Argument(['-v', '--verbose'], { action: 'store_true', help: 'Name each path as it is added or removed', }), ]; const COMMIT_OPTIONS = [ new Argument(['-q', '--quiet'], { action: 'store_true', help: 'Suppress feedback messages' }), new Argument(['-a', '--all'], { action: 'store_true', help: 'Stage modified and deleted tracked files first', }), // Required, not defaulted: git would open an editor without it, and a mount // has none to open. new Argument(['-m', '--message'], { help: 'Commit message' }), new Argument('--author', { help: 'Override the recorded author' }), new Argument('--allow-empty', { action: 'store_true', help: 'Record a commit that changes nothing from its parent', }), ]; const CHECKOUT_OPTIONS = [ new Argument('-b', { metavar: 'branch', help: 'Create the branch and switch to it' }), new Argument('--detach', { action: 'store_true', help: 'Leave HEAD on the commit itself' }), new Argument(['-q', '--quiet'], { action: 'store_true', help: 'Suppress feedback messages' }), ]; const SWITCH_OPTIONS = [ new Argument(['-q', '--quiet'], { action: 'store_true', help: 'Suppress feedback messages' }), new Argument(['-c', '--create'], { help: 'Create the branch and switch to it' }), new Argument(['-d', '--detach'], { action: 'store_true', help: 'Detach HEAD at the named commit', }), ]; const RESTORE_OPTIONS = [ new Argument(['-S', '--staged'], { action: 'store_true', help: 'Restore the index' }), new Argument(['-W', '--worktree'], { action: 'store_true', help: 'Restore the working tree (default)', }), new Argument(['-s', '--source'], { help: 'Which tree-ish to restore from' }), ]; const RM_OPTIONS = [ new Argument('-r', { action: 'store_true', help: 'Allow recursive removal' }), new Argument('--cached', { action: 'store_true', help: 'Only remove from the index, keeping the file', }), new Argument(['-f', '--force'], { action: 'store_true', help: 'Override the up-to-date check' }), new Argument(['-q', '--quiet'], { action: 'store_true', help: 'Do not list removed files' }), new Argument('--ignore-unmatch', { action: 'store_true', help: 'Exit with a zero status even if nothing matched', }), ]; const MV_OPTIONS = [ new Argument(['-f', '--force'], { action: 'store_true', help: 'Force move/rename even if target exists', }), new Argument('-k', { action: 'store_true', help: 'Skip move/rename errors' }), new Argument(['-n', '--dry-run'], { action: 'store_true', help: 'Dry run' }), new Argument(['-v', '--verbose'], { action: 'store_true', help: 'Be verbose' }), ]; // git's ref-filter options, which `branch` and `tag` share. The four commit // filters take the next word as their commit, whatever it looks like // (`--merged --no-merged` names a commit called `--no-merged`), except as the // line's last word, where they read HEAD: parse-options' LASTARG_DEFAULT. The // spec has no word for that, so they are declared with an optional value (a // bare one is HEAD, `--merged=main` is main) and `filterWords` reattaches a // detached value from the verbatim argv. `--points-at` always takes a value. const REF_FILTER_OPTIONS = [ new Argument('--contains', { action: 'append', nargs: '?', attachedOnly: true, metavar: 'commit', help: 'List only refs that contain the commit (HEAD if omitted)', }), new Argument('--no-contains', { action: 'append', nargs: '?', attachedOnly: true, metavar: 'commit', help: "List only refs that don't contain the commit (HEAD if omitted)", }), new Argument('--merged', { action: 'append', nargs: '?', attachedOnly: true, metavar: 'commit', help: 'List only refs reachable from the commit (HEAD if omitted)', }), new Argument('--no-merged', { action: 'append', nargs: '?', attachedOnly: true, metavar: 'commit', help: 'List only refs not reachable from the commit (HEAD if omitted)', }), new Argument('--points-at', { action: 'append', metavar: 'object', help: 'List only refs that point at the object', }), ]; // git's ref-format options, which `for-each-ref`, `branch` and `tag` share. // --sort repeats, the last key given sorting first, and --no-sort drops every // key before it, the default refname included. const FORMAT_OPTION_REF = new Argument('--format', { metavar: 'format', help: 'Format each ref: %(fieldname) placeholders, as git for-each-ref', }); const SORT_OPTIONS = [ new Argument('--sort', { action: 'append', metavar: 'key', help: 'Sort on a field, - reversing it and version: comparing as versions', }), new Argument('--no-sort', { action: 'store_true', help: 'Drop the sort keys given so far' }), ]; const OMIT_EMPTY_OPTION = new Argument('--omit-empty', { action: 'store_true', help: 'Print nothing, not even a newline, for an empty row', }); const IGNORE_CASE_OPTION = new Argument(['-i', '--ignore-case'], { action: 'store_true', help: 'Sort and match patterns case-insensitively', }); const FOR_EACH_REF_OPTIONS = [ new Argument(['-s', '--shell'], { action: 'store_true', help: 'Quote fields suitably for shells', }), new Argument(['-p', '--perl'], { action: 'store_true', help: 'Quote fields suitably for perl' }), new Argument('--python', { action: 'store_true', help: 'Quote fields suitably for python' }), new Argument('--tcl', { action: 'store_true', help: 'Quote fields suitably for Tcl' }), OMIT_EMPTY_OPTION, new Argument('--count', { type: 'int', metavar: 'n', help: 'Show only the first <n> refs' }), FORMAT_OPTION_REF, new Argument('--exclude', { action: 'append', metavar: 'pattern', help: 'Leave out refs matching the pattern', }), ...SORT_OPTIONS, ...REF_FILTER_OPTIONS, new Argument('--ignore-case', { action: 'store_true', help: 'Sort and match patterns case-insensitively', }), new Argument('--stdin', { action: 'store_true', help: 'Read ref patterns from stdin' }), new Argument('--include-root-refs', { action: 'store_true', help: 'Also list HEAD and the other root refs', }), ]; const TAG_OPTIONS = [ new Argument(['-l', '--list'], { action: 'store_true', help: 'List tag names' }), // git spells the count attached (`-n2`) or not at all, never as a separate // token, which is what valueOptional says: a bare -n means one line and the // next word is left alone to be a pattern. new Argument('-n', { type: 'int', nargs: '?', attachedOnly: true, help: 'Print <n> lines of each tag message', }), new Argument(['-d', '--delete'], { action: 'store_true', help: 'Delete tags' }), new Argument(['-a', '--annotate'], { action: 'store_true', help: 'Annotated tag, needs a message', }), new Argument(['-m', '--message'], { action: 'append', help: 'Tag message (repeatable, one paragraph each)', }), new Argument(['-f', '--force'], { action: 'store_true', help: 'Replace the tag if exists' }), ...REF_FILTER_OPTIONS, ...SORT_OPTIONS, FORMAT_OPTION_REF, OMIT_EMPTY_OPTION, IGNORE_CASE_OPTION, ]; const BRANCH_OPTIONS = [ new Argument('--show-current', { action: 'store_true', help: 'Show the current branch name' }), new Argument(['-q', '--quiet'], { action: 'store_true', help: 'Suppress feedback messages' }), new Argument(['-v', '--verbose'], { action: 'count', help: 'Show commit and upstream details' }), new Argument('-a', { action: 'store_true', help: 'List local and remote-tracking branches' }), new Argument('-r', { action: 'store_true', help: 'List remote-tracking branches' }), new Argument(['-d', '--delete'], { action: 'store_true', help: 'Delete a fully merged branch' }), new Argument('-D', { action: 'store_true', help: 'Delete a branch even if not merged' }), new Argument('--delete-merged', { action: 'append', metavar: 'pattern', help: 'Delete merged branches whose upstream matches (repeatable)', }), new Argument('--dry-run', { action: 'store_true', help: 'With --delete-merged, only print what would be deleted', }), new Argument('--no-dry-run', { action: 'store_true' }), new Argument(['-l', '--list'], { action: 'store_true', help: 'List branches matching the patterns', }), ...REF_FILTER_OPTIONS, new Argument('--forked', { action: 'append', metavar: 'branch', help: 'List branches whose upstream matches (repeatable)', }), ...SORT_OPTIONS, FORMAT_OPTION_REF, OMIT_EMPTY_OPTION, IGNORE_CASE_OPTION, ]; /** * The git program tree. No configModel: local git needs no credentials, which is * what makes it installable with a bare `cli: git`. * * Lives in core rather than node because nothing here touches a runtime API: the * verbs read and write through the workspace dispatcher, and isomorphic-git * reaches the object database through the same bridge, so a repository mounted * in a browser works exactly as one mounted over disk. */ function helpCmd(_accessor, paths, texts, ctx) { checkSwitches(ctx, texts); const found = findNode(GIT.spec, texts); if (found === null) return [ null, new IOResult({ exitCode: 1, stderr: new TextEncoder().encode(`git: '${texts.join(' ')}' is not a git command. See 'git --help'.\n`), }), ]; return [ new TextEncoder().encode(nodeHelp(['git', ...found.path].join(' '), found.node, GIT.spec.usageStyle)), new IOResult(), ]; } export const GIT = new CLI({ spec: new CommandSpec({ name: 'git', description: 'Content tracker', usageStyle: UsageStyle.GIT, operandBase: '-C', arguments: [ DIRECTORY_OPTION, new Argument('--git-dir', { type: 'path', env: 'GIT_DIR', help: 'Use the repository at <path>', }), new Argument('--work-tree', { type: 'path', env: 'GIT_WORK_TREE', help: 'Use <path> as the working tree', }), ], subcommands: [ new CommandSpec({ name: 'reflog', description: 'Show reference history', arguments: [ new Argument(['-n', '--max-count'], { type: 'int', numericShorthand: true, help: 'Limit the number of entries', }), REVISION, ], }), new CommandSpec({ name: 'for-each-ref', description: 'List references with a format', arguments: [...FOR_EACH_REF_OPTIONS, REVISION], }), new CommandSpec({ name: 'cat-file', description: 'Provide contents or details of repository objects', arguments: [ new Argument('-t', { action: 'store_true', help: 'Show the object type' }), new Argument('-s', { action: 'store_true', help: 'Show the object size' }), new Argument('-e', { action: 'store_true', help: 'Check if <object> exists' }), new Argument('-p', { action: 'store_true', help: 'Pretty-print <object> content' }), new Argument('--batch', { nargs: '?', attachedOnly: true, help: 'Show full <object> or <rev> contents', }), new Argument('--batch-check', { nargs: '?', attachedOnly: true, help: "Like --batch, but don't emit <contents>", }), REVISION, ], }), new CommandSpec({ name: 'hash-object', description: 'Compute object ID and optionally create an object from a file', arguments: [ new Argument('-t', { help: 'Object type' }), new Argument('-w', { action: 'store_true', help: 'Write the object into the object database', }), new Argument('--stdin', { action: 'store_true', help: 'Read the object from stdin' }), new Argument('--stdin-paths', { action: 'store_true', help: 'Read file names from stdin', }), new Argument('--no-filters', { action: 'store_true', help: 'Store file as is without filters', }), new Argument('--literally', { action: 'store_true', help: 'Just hash any random garbage to create corrupt objects for debugging Git', }), new Argument('--path', { help: 'Process file as it were from this path' }), PATHSPEC, ], }), new CommandSpec({ name: 'grep', description: 'Search tracked files in the working tree, index or named trees', arguments: [ new Argument('--cached', { action: 'store_true', help: 'Search index blobs instead of working files', }), new Argument(['-n', '--line-number'], { action: 'store_true', help: 'Show line numbers', }), new Argument(['-i', '--ignore-case'], { action: 'store_true', help: 'Match without regard to case', }), new Argument(['-F', '--fixed-strings'], { action: 'store_true', help: 'Match literal strings', }), new Argument(['-E', '--extended-regexp'], { action: 'store_true', help: 'Use extended regular expressions', }), new Argument(['-G', '--basic-regexp'], { action: 'store_true', help: 'Use basic regular expressions', }), new Argument(['-w', '--word-regexp'], { action: 'store_true', help: 'Match at word boundaries', }), new Argument(['-v', '--invert-match'], { action: 'store_true', help: 'Select nonmatching lines', }), new Argument(['-c', '--count'], { action: 'store_true', help: 'Count selected lines in each matching file', }), new Argument(['-l', '--files-with-matches'], { action: 'store_true', help: 'Show only matching filenames', }), new Argument(['-L', '--files-without-match'], { action: 'store_true', help: 'Show only nonmatching filenames', }), new Argument(['-q', '--quiet'], { action: 'store_true', help: 'Report matches through exit status', }), new Argument('-e', { action: 'append', help: 'Match an additional pattern' }), new Argument(['-a', '--text'], { action: 'store_true', help: 'Treat binary files as text', }), new Argument('-I', { action: 'store_true', help: 'Skip binary files' }), new Argument(['-z', '--null'], { action: 'store_true', help: 'Terminate filename fields with NUL', }), new Argument('-h', { action: 'store_true', help: 'Omit filenames from matching lines' }), new Argument('-H', { action: 'store_true', help: 'Show filenames with matching lines' }), new Argument('texts', { metavar: '', nargs: 'REMAINDER' }), ], }), new CommandSpec({ name: 'ls-tree', description: 'List the contents of a tree object', arguments: [ new Argument('-r', { action: 'store_true', help: 'Recurse into subtrees' }), new Argument('-t', { action: 'store_true', help: 'Show trees when recursing' }), new Argument('-d', { action: 'store_true', help: 'Only show trees' }), new Argument('-z', { action: 'store_true', help: 'Terminate entries with NUL' }), new Argument('--name-only', { action: 'store_true', help: 'Show only filenames' }), new Argument('--name-status', { action: 'store_true', help: 'Alias of --name-only' }), new Argument('--full-name', { action: 'store_true', help: 'Show paths relative to the repository root', }), new Argument('--full-tree', { action: 'store_true', help: 'List the whole tree, ignoring the current directory', }), REVISION, ], }), new CommandSpec({ name: 'ls-files', description: 'Show files in the index', arguments: [ new Argument('-z', { action: 'store_true', help: 'Terminate paths with NUL' }), new Argument(['-s', '--stage'], { action: 'store_true', help: 'Show staged object metadata', }), new Argument(['-c', '--cached'], { action: 'store_true', help: 'Show cached files' }), REVISION, ], }), new CommandSpec({ name: 'fetch', description: 'Download objects and refs from another repository', arguments: [ new Argument(['-q', '--quiet'], { action: 'store_true', help: 'Print nothing but errors', }), new Argument(['-v', '--verbose'], { action: 'store_true', help: 'Also list unchanged refs', }), new Argument(['-p', '--prune'], { action: 'store_true', help: 'Remove remote-tracking refs the remote no longer has', }), new Argument(['-t', '--tags'], { action: 'store_true', help: 'Fetch every tag' }), new Argument(['-n', '--no-tags'], { action: 'store_true', help: 'Follow no tags' }), REVISION, ], }), new CommandSpec({ name: 'clone', description: 'Clone a repository into a new directory', arguments: [ new Argument(['-q', '--quiet'], { action: 'store_true', help: 'Print nothing but errors', }), new Argument(['-b', '--branch'], { help: 'Check out this branch or tag' }), new Argument(['-o', '--origin'], { help: 'Name the remote this instead of origin' }), new Argument(['-n', '--no-checkout'], { action: 'store_true', help: 'Leave the working tree empty', }), REVISION, ], }), new CommandSpec({ name: 'help', description: 'Show command help', arguments: [new Argument('texts', { metavar: '', nargs: '*' })], }), new CommandSpec({ name: 'init', description: 'Create an empty Git repository or reinitialize an existing one', arguments: [ new Argument(['-q', '--quiet'], { action: 'store_true' }), new Argument('--bare', { action: 'store_true' }), new Argument(['-b', '--initial-branch']), new Argument('directory', { nargs: '?' }), ], }), new CommandSpec({ name: 'fsck', description: 'Verify object hashes and connectivity', arguments: [ new Argument('--full', { action: 'store_true' }), new Argument('--no-dangling', { action: 'store_true' }), new Argument('--unreachable', { action: 'store_true' }), ], }), new CommandSpec({ name: 'stash', description: 'Inspect saved working trees', subcommands: [ new CommandSpec({ name: 'list', description: 'List stashed changes' }), new CommandSpec({ name: 'show', description: 'Show stashed changes', arguments: [...DIFF_OPTIONS, new Argument('stash', { nargs: '?' })], }), ], }), new CommandSpec({ name: 'version', aliases: ['--version', '-v'], description: 'Show the Mirage Git implementation version', }), new CommandSpec({ name: 'remote', description: 'List remotes and inspect their URLs', arguments: [ new Argument(['-v', '--verbose'], { action: 'store_true', help: 'Show remote URLs' }), new Argument('texts', { metavar: '', nargs: 'REMAINDER' }), ], }), new CommandSpec({ name: 'config', description: 'Read repository configuration', arguments: [ new Argument('--global', { action: 'store_true', help: 'Read global configuration' }), new Argument('--get', { action: 'store_true', help: 'Get a configuration value' }), new Argument(['-l', '--list'], { action: 'store_true', help: 'List every variable and value', }), new Argument('--show-origin', { action: 'store_true', help: 'Show the file each value comes from', }), new Argument('--get-regexp', { action: 'store_true', help: 'Get the variables whose names match a regular expression', }), new Argument('name', { nargs: '?' }), new Argument('value', { nargs: '?' }), new Argument('value-pattern', { nargs: '?' }), ], }), new CommandSpec({ name: 'merge-base', description: 'Find best common ancestors of commits', arguments: [ new Argument(['-a', '--all'], { action: 'store_true', help: 'Show all best common ancestors', }), new Argument('--is-ancestor', { action: 'store_true', help: 'Test whether the first commit is an ancestor of the second', }), REVISION, ], }), new CommandSpec({ name: 'show-ref', description: 'List references', arguments: [REVISION] }), // symbolic-ref has every option git's has, so its rows carry git's own // help and its usage block reads exactly as git's. new CommandSpec({ name: 'symbolic-ref', description: 'Read, change or delete a symbolic ref', arguments: [ new Argument(['-q', '--quiet'], { action: 'store_true', help: 'suppress error message for non-symbolic (detached) refs', }), new Argument('--no-quiet', { action: 'store_true', help: 'Refuse a ref that is not symbolic aloud', }), new Argument(['-d', '--delete'], { action: 'store_true', help: 'delete symbolic ref' }), new Argument('--no-delete', { action: 'store_true', help: 'Read or change the ref instead', }), new Argument('--short', { action: 'store_true', help: 'shorten ref output' }), new Argument('--no-short', { action: 'store_true', help: 'Print the full name it points at', }), new Argument('--recurse', { action: 'store_true', help: 'recursively dereference (default)', }), new Argument('--no-recurse', { action: 'store_true', help: 'Print only the ref this one points at directly', }), new Argument('-m', { metavar: 'reason', help: 'reason of the update' }), new Argument('texts', { metavar: '', nargs: '*' }), ], }), // shortlog's -n is --numbered, so the count keeps only its long spelling. new CommandSpec({ name: 'shortlog', description: 'Summarize commit history', arguments: [ ...LOG_OPTIONS.filter((opt) => !opt.names.includes('-n')), new Argument('--max-count', { type: 'int', help: 'Limit the number of commits' }), new Argument(['-s', '--summary'], { action: 'store_true', help: 'Show only commit counts', }), new Argument(['-e', '--email'], { action: 'store_true', help: 'Show author email addresses', }), new Argument(['-n', '--numbered'], { action: 'store_true', help: 'Sort by commit count', }), REVISION, ], }), new CommandSpec({ name: 'rev-parse', description: 'Resolve revisions', arguments: [ new Argument('--show-toplevel', { action: 'store_true', help: 'Show the worktree root' }), new Argument('--abbrev-ref', { nargs: '?', attachedOnly: true, help: 'Show abbreviated reference names, strict or loose', }), new Argument('--show-prefix', { action: 'store_true', help: 'Show the current directory relative to the worktree root', }), new Argument('--is-shallow-repository', { action: 'store_true', help: 'Print whether the repository is shallow', }), new Argument('--is-inside-work-tree', { action: 'store_true', help: 'Print whether the current directory is inside the work tree', }), new Argument('--verify', { action: 'store_true', help: 'Require exactly one revision that names an object', }), new Argument('--short', { nargs: '?', attachedOnly: true, help: 'Abbreviate the object name; implies --verify', }), new Argument(['-q', '--quiet'], { action: 'store_true', help: 'With --verify, exit 1 without a message', }), REVISION, ], }), new CommandSpec({ name: 'rev-list', description: 'List reachable commits', arguments: [ ...LOG_OPTIONS, new Argument('--count', { action: 'store_true', help: 'Print commit count' }), REVISION, ], }), new CommandSpec({ name: 'diff-tree', description: 'Compare a commit with its parent', arguments: [ ...SHOW_OPTIONS, new Argument('--no-commit-id', { action: 'store_true', help: 'Suppress commit ID' }), new Argument('-r', { action: 'store_true', help: 'Recurse into subtrees' }), new Argument('commit'), PATHSPEC, ], }), new CommandSpec({ name: 'status', description: 'Show the working tree status', arguments: [...STATUS_OPTIONS], }), new CommandSpec({ name: 'log', description: 'Show commit logs', arguments: [...LOG_OPTIONS, ...MAILMAP_OPTIONS, ...DIFF_OPTIONS, REVISION], }), new CommandSpec({ name: 'show', description: 'Show a commit and its diff', arguments: [...SHOW_OPTIONS, ...DECORATE_OPTIONS, REVISION], }), new CommandSpec({ name: 'diff', description: 'Show changes between commits', arguments: [ ...DIFF_OPTIONS, new Argument('--cached', { action: 'store_true', help: 'Compare the index with a commit', }), new Argument('--staged', { action: 'store_true', help: 'Alias of --cached' }), REVISION, ], }), new CommandSpec({ name: 'branch', description: 'List, create or delete branches', arguments: [...BRANCH_OPTIONS, new Argument('texts', { metavar: '', nargs: '*' })], }), new CommandSpec({ name: 'add', description: 'Stage working tree content', arguments: [...ADD_OPTIONS, PATHSPEC], }), new CommandSpec({ name: 'reset', description: 'Unstage, putting the index back to HEAD', arguments: [ new Argument(['-q', '--quiet'], { action: 'store_true', help: 'Only report errors' }), PATHSPEC, ], }), new CommandSpec({ name: 'commit', description: 'Record the index as a new commit', arguments: [...COMMIT_OPTIONS], }), new CommandSpec({ name: 'checkout', description: 'Switch branches', arguments: [...CHECKOUT_OPTIONS, REVISION], }), new CommandSpec({ name: 'switch', description: 'Switch branches', arguments: [...SWITCH_OPTIONS, REVISION], }), new CommandSpec({ name: 'restore', description: 'Restore working tree files', arguments: [...RESTORE_OPTIONS, PATHSPEC], }), new CommandSpec({ name: 'rm', description: 'Remove files from the working tree and the index', arguments: [...RM_OPTIONS, PATHSPEC], }), new CommandSpec({ name: 'mv', description: 'Move or rename a file, a directory, or a symlink', arguments: [...MV_OPTIONS, PATHSPEC], }), new CommandSpec({ name: 'tag', description: 'Create, list or delete a tag', arguments: [...TAG_OPTIONS, new Argument('texts', { metavar: '', nargs: '*' })], }), ], }), handlers: { reflog: new CLIHandler({ fn: verb(reflog) }), 'for-each-ref': new CLIHandler({ fn: verb(forEachRef) }), 'cat-file': new CLIHandler({ fn: verb(catFile) }), 'hash-object': new CLIHandler({ fn: verb(hashObject, hashObjectReadOnly), write: true }), grep: new CLIHandler({ fn: verb(grep) }), 'ls-tree': new CLIHandler({ fn: verb(lsTree) }), 'ls-files': new CLIHandler({ fn: verb(lsFiles) }), fetch: new CLIHandler({ fn: verb(fetch, fetchReadOnly), write: true }), clone: new CLIHandler({ fn: verb(clone, cloneReadOnly), write: true }), help: new CLIHandler({ fn: verb(helpCmd) }), init: new CLIHandler({ fn: verb(init), write: true }), fsck: new CLIHandler({ fn: verb(fsck) }), 'stash list': new CLIHandler({ fn: verb(stashList) }), 'stash show': new CLIHandler({ fn: verb(stashShow) }), version: new CLIHandler({ fn: verb(version) }), remote: new CLIHandler({ fn: verb(remote) }), config: new CLIHandler({ fn: verb(config) }), 'merge-base': new CLIHandler({ fn: verb(mergeBase) }), 'show-ref': new CLIHandler({ fn: verb(showRef) }), 'symbolic-ref': new CLIHandler({ fn: verb(symbolicRef, symbolicRefReadOnly), write: true }), shortlog: new CLIHandler({ fn: verb(shortlog) }), 'rev-parse': new CLIHandler({ fn: verb(revParse) }), 'rev-list': new CLIHandler({ fn: verb(revList) }), 'diff-tree': new CLIHandler({ fn: verb(diffTree) }), status: new CLIHandler({ fn: verb(status) }), log: new CLIHandler({ fn: verb(log) }), show: new CLIHandler({ fn: verb(show) }), diff: new CLIHandler({ fn: verb(diff) }), branch: new CLIHandler({ fn: verb(branch, branchReadOnly), write: true }), add: new CLIHandler({ fn: verb(add, indexLocked), write: true }), reset: new CLIHandler({ fn: verb(reset, indexLocked), write: true }), commit: new CLIHandler({ fn: verb(commit, indexLocked), write: true }), checkout: new CLIHandler({ fn: verb(checkout, checkoutReadOnly), write: true }), switch: new CLIHandler({ fn: verb(switchBranch, switchReadOnly), write: true }), restore: new CLIHandler({ fn: verb(restore, indexLocked), write: true }), rm: new CLIHandler({ fn: verb(rm, indexLocked), write: true }), mv: new CLIHandler({ fn: verb(mv, indexLocked), write: true }), tag: new CLIHandler({ fn: verb(tag, tagReadOnly), write: true }), }, }); //# sourceMappingURL=index.js.map