cmd

package
v0.0.0-...-68956d0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 12, 2026 License: MIT Imports: 87 Imported by: 0

Documentation

Overview

Commands `gitmap add ignore` and `gitmap add attributes`.

Both share a near-identical pipeline:

  1. Validate we are inside a Git working tree.
  2. Resolve `common.<ext>` plus each language argument from the templates package (overlay > embed).
  3. Concatenate bodies with a single dedupe pass keyed on the trimmed line — comments included, blank lines preserved.
  4. Hand the merged body to templates.Merge under a marker block tagged "<kind>/<concatenated-langs>" so re-runs are byte-stable.

The two entry points (`runAddIgnore`, `runAddAttributes`) parameterize only the kind / extension / target file / marker tag prefix and reuse the shared `addTemplateOp` body. This keeps each entry point under the 15-line cap and avoids two diverging copies of the merge dance.

Command `gitmap add lfs-install`.

Two-step operation:

  1. Run `git lfs install --local` so the current repo has the LFS pre-push / clean / smudge hooks wired up. This is itself idempotent — Git LFS treats repeat invocations as no-ops.
  2. Resolve the `lfs/common` template (overlay > embed) and merge its body into ./.gitattributes via templates.Merge, which uses a gitmap-managed marker block so the second and later runs are byte-stable no-ops when the template hasn't changed.

Why a separate command from `gitmap lfs-common`? `lfs-common` shells out to `git lfs track` per-pattern and writes whatever line format `git lfs` decides on. `add lfs-install` is the template-driven path: the bytes written to .gitattributes come from the curated, versioned `lfs/common.gitattributes` asset (audit-trailed `# source:` header) and can be overridden by a user file at ~/.gitmap/templates/lfs/common.gitattributes.

Package cmd — amend.go handles flag parsing and orchestration for the amend command.

Package cmd — amendaudit.go handles audit JSON writing and DB persistence.

Package cmd — amendexec.go handles git operations for the amend command.

Package cmd — amendexecprint.go handles output and display for amend operations.

Package cmd — amendlist.go handles the amend-list command.

Package cmd: audit-legacy scans the workspace for forbidden legacy strings (default: gitmap-v26 / gitmap-v26 / gitmap-v26) and exits 1 on // gitmap-legacy-ref-allow any hit. Designed as a regression guard for remixes / rename commits.

Package cmd: unified-diff rendering for audit-legacy --diffs.

Pure-Go: reads the source file once, rewrites every regex match to DefaultAuditLegacyReplace, and emits one single-line hunk per changed line in standard `diff --unified=0` format.

Package cmd: per-file unified-diff writer for `gitmap audit-legacy`.

When --diffs is set alongside --report, every file with at least one match gets its own `<reportDir>/diffs/<sanitized-path>.diff` artifact containing a minimal unified diff that previews the legacy → v8 substitution. The Markdown report links each diff so a reviewer can click straight from the file-counts table to the proposed change.

Package cmd: emit + report helpers for `gitmap audit-legacy`.

Package cmd: flag parsing for `gitmap audit-legacy`.

Package cmd: Markdown report writer for `gitmap audit-legacy`.

Splits per-pattern + per-file counts and the full hit list into a human-readable Markdown file. Used so CI / contributors can attach a single artifact to a PR or share an audit summary without piping JSON through a formatter.

Package cmd — `gitmap backup` ls/prune (v6.57.0).

Scans `<cwd>/.gitmap/backup/` (the tree used by fix-repo / undo) and exposes two read-only-friendly operations:

gitmap backup ls                          # group by repo, count + size
gitmap backup prune --keep=N              # keep newest N per repo
gitmap backup prune --older-than=DAYS     # drop entries older than DAYS
gitmap backup prune --dry-run             # print what would be deleted

Bounded-retention answers item #2 of the v6.55.0 suggestions list. Self-contained: walks the fix-repo timestamp layout documented in constants_undo.go, never touches release/ or release-assets/.

Package cmd — `gitmap branch <subcommand>` dispatcher.

Package cmd — cfrppriorversion.go: spec/01-app/113 §2.3.

After cfrp publishes vN, probe v(N-1), v(N-2), … on the same provider+owner. Any that are currently `public` are offered up for privatization. With `-y` we auto-confirm; otherwise prompt.

Package cmd implements the CLI commands for gitmap.

changelog_regen.go — derives CHANGELOG.md entries from the canonical per-release JSON files under `.gitmap/release/` (#18).

Until v6.60.0 the changelog was hand-edited in lockstep with the version bump, drifting easily. The release JSONs already capture `{version, tag, branch}` per release; this helper enumerates them, sorts by semver descending, and prints a freshly-rendered block that can be diffed against CHANGELOG.md (or piped in).

Invoked via `gitmap changelog regen` (read-only stdout). The existing scripts/changelog/ Go module remains the authoritative generator for CI; this helper is for ad-hoc developer use without leaving the binary.

Package cmd — chrome.go: umbrella dispatcher for the `gitmap chrome` command group (backup, restore, diff, export-bookmarks, which). Added in v6.69.0. See helptext/chrome.md.

Package cmd — chrome_backup.go: snapshot all Chrome profiles into a tar.gz under .gitmap/chrome/backup/, and restore from one.

Package cmd — chrome_bookmarks.go: export a profile's Bookmarks file to md|html|json. Defaults to md on stdout.

Package cmd — chrome_bookmarks_filter.go: --match / --title pruning. Walks the tree post-folder-filter and keeps only branches that contain at least one matching URL leaf; folders themselves are preserved as context so the rendered output retains hierarchy.

Package cmd — chrome_diff.go: extension + bookmark diff between two Chrome profiles. Lists added/removed only (not modified).

Package cmd — pure-Go Local State parser shared by chrome which/list/etc. Kept separate from chrome_which.go so it is trivially unit-testable without exec'ing Chrome or hitting the user's real profile directory.

Package cmd — chrome_manifest.go: SHA256 manifest written alongside every chrome backup tarball (`<tarball>.sha256.txt`) and verified automatically before `chrome restore` extracts anything.

Package cmd — chrome_which.go: identify which Chrome profile is currently active by reading lockfile mtimes + Local State LastUsed.

Package cmd — chromeprofile.go: entry points for the Chrome profile copy/export/import/list pipeline.

cpc : copy a profile dir (offline, no sign-in tokens)
cpe : export profile to a JSON snapshot
cpi : import a JSON snapshot back into a profile dir
cpl : list profiles discovered under Chrome User Data

Full spec: spec/04-generic-cli/40-chrome-profile-copy.md.

Package cmd — chromeprofile_copy.go: resilient Chrome profile tree copy helpers used by `gitmap chrome-profile-copy` / `gitmap cpc`.

Package cmd — chromeprofile_csv.go: CSV serialization of a Chrome profile snapshot. Companion to chromeprofile_export.go (JSON). The CSV mirrors the same curated subset so spreadsheet tooling can audit exports without parsing JSON. Schema: Category,Key,Value.

Package cmd — chromeprofile_db.go: thin glue between the chrome-profile command runners and the SQLite store helpers. Failures are non-fatal for the CLI (we still want the on-disk JSON/CSV to land) but always surface as a stderr warning so users see drift.

Package cmd — chromeprofile_delete.go: implements `gitmap chrome-profile-delete` (alias `cpd`). Removes the SQLite row and optionally rm()s the on-disk artifacts that were tracked alongside it. Refuses to run without --yes to avoid accidental destruction.

Package cmd — chromeprofile_export.go: JSON snapshot serialization. Captures bookmarks + extension IDs + preferences subset. See spec/04-generic-cli/40-chrome-profile-copy.md §4 for schema.

Package cmd — chromeprofile_import_csv.go: parses a CSV snapshot (Category,Key,Value rows produced by writeChromeExportCSV) back into a chromeExport struct. Lossy by design: bookmarks are not preserved in the CSV form, so they round-trip as empty.

Package cmd — chromeprofile_merge.go: `gitmap chrome-profile-merge` (alias `cpm`). Merges selected slices of a source Chrome profile INTO a destination profile without clobbering destination values.

Default policy (interactive): for every conflicting key/bookmark, prompt user to [k]eep, [o]verwrite, [a]ll-keep, [A]ll-overwrite, [q]uit. `--yes` auto-keeps destination on conflict; `--force` auto-overwrites destination with source.

`--what` selects the slices to merge:

all         (default) — settings + bookmarks + extensions
settings    — Preferences + Secure Preferences (top-level keys)
bookmarks   — Bookmarks file (by GUID/url under bookmark_bar/other/synced)
extensions  — Extensions/ subdir (per-extension folder add-only)

Package cmd — chromeprofile_paths.go: cross-platform Chrome User Data directory resolution. See spec/04-generic-cli/40-chrome-profile-copy.md.

Package cmd — chromeprofile_preferences.go: post-copy patcher for the destination profile's `Preferences` file. Chrome's profile picker reads BOTH `Local State` AND the per-profile `Preferences` JSON; if the destination Preferences still carries the source GAIA/signed-in fields (or a stale profile.name), Chrome may hide the new tile or silently merge it back into the source identity on next launch.

This file scrubs those fields and stamps the picker-visible name so the freshly copied dir reliably appears in chrome://settings/manageProfile.

Package cmd — chromeprofile_process.go: process guard for CPC.

Package cmd — chromeprofile_register.go: registers a freshly copied destination profile inside Chrome's `Local State` so the profile shows up in Chrome's profile picker. Without this step, copying `Profile 15` → `lv2` lands the files on disk but Chrome ignores the new directory because it's not listed in `profile.info_cache[<dir>]`.

Package cmd — chromeprofile_resolve.go: resolves user-supplied Chrome profile identifiers (directory name like "Profile 1" OR display name like "Lovable" shown in Chrome's profile picker) to an on-disk path.

Chrome stores the human-readable display name in <UserData>/Local State under profile.info_cache[<dir>].name. This file reads that index so users can pass the same name they see in Chrome instead of guessing "Profile N".

Package cmd — clonefixrepo.go: entry points for `gitmap clone-fix-repo` (alias `cfr`) and `gitmap clone-fix-repo-pub` (alias `cfrp`).

These are convenience pipelines that chain three existing commands in one shot:

cfr  : clone <url>  →  cd <folder>  →  fix-repo --all
cfrp : clone <url>  →  cd <folder>  →  fix-repo --all  →  make-public --yes

Implementation strategy: the chained commands (runFixRepo, runMakePublic) all call os.Exit at the end, which would terminate our parent process before the next step runs. To stay decoupled and side-effect-clean, we shell out to our own binary (resolved via os.Executable) for the fix-repo and make-public steps after invoking executeDirectClone in-process. This also keeps each step's exit code, stdout, and stderr semantics intact.

Package cmd — checkpoint resume for `cfrp` (and `cfr`) batches.

Mirrors the `commit-in` checkpoint contract: each batch writes a state.json sidecar after every successful clone, so re-running the same command picks up where a crash left off instead of re-cloning already-processed entries.

State file location: .gitmap/cfrp/<batch-id>/state.json

Package cmd — clonefixrepoparallel.go: comma-separated URL fan-out for `gitmap cfr` / `gitmap cfrp`. Mirrors the `visibilityparallel.go` pattern (mapub/mapri): bounded worker pool, per-worker bytes.Buffer captured stdout, mutex-guarded atomic flush so interleaved lines stay coherent.

Each worker re-execs the current binary with a single URL so the existing single-URL pipeline (chdir, fix-repo chaining, exit codes, transport persistence) stays the source of truth. Trade: each clone forks one extra process — the network/IO dwarfs it, and isolation is worth it.

Result ORDER matches input order: per-URL output buffers are flushed under the mutex in the same goroutine that finished work, so terminal interleaving is line-coherent but URL order is effectively "completion order". A pre-flight banner lists the URL set and worker count so the user can correlate finished blocks back to inputs.

Package cmd — clonenextcrossdir.go implements the cross-dir `gitmap cn <repo> <version>` form: chdir into the named repo, run the existing clone-next pipeline, then chdir back.

Backward compatibility: `gitmap cn vX.Y.Z` (single positional) keeps operating on the current directory's repo as before.

Package cmd — clonenextfolderdispatch.go implements the v3.117.0 folder-arg forms of `gitmap cn`:

gitmap cn vX <folder>     — explicit version, explicit folder
gitmap cn v+1 <folder>    — version-bump shortcut
gitmap cn <folder>        — folder only (defaults to v++)

All three chdir into the resolved folder, run the existing in-place `runCloneNext` pipeline, then chdir back via the shared `performCrossDirCloneNext` helper in clonenextcrossdir.go.

Disambiguation rules and the full test matrix are documented in spec/01-app/111-cn-folder-arg.md. The two interceptor functions here run BEFORE tryCrossDirCloneNext in runCloneNext so the path-shaped tokens win over the release-alias fallback (the alias resolver matches bare names like "gitmap" which would otherwise shadow a same-named local folder).

Package cmd — clonepmsync.go: shared helper that pushes freshly cloned repos into the alefragnani.project-manager projects.json file. Wired into every clone variant (clone, clone-next, clone-from, clone-now, clone-pick, clone-multi, cfr/cfrp) so that any command that lands a new repo on disk also makes it visible in the VS Code Project Manager sidebar without a separate `gitmap code` step.

Soft-fail policy: when the user-data root or extension dir is missing (CI / headless / no VS Code installed) the helper logs a one-line note via reportVSCodePMSoftError and returns without error. A failed sync NEVER turns a successful clone into a failed exit code.

Spec: spec/01-vscode-project-manager-sync/02-clone-sync.md Memory: mem://features/clone-vscode-pm-sync

Package cmd — clonepretty.go: shared colorful runner for every `git clone` invocation triggered by gitmap (clone, cfr, cfrp, clone-replace temp swap). Unifies the log formatting requested in the v6.49.0 spec: cyan headers, green ✓ on success with elapsed time, red panel + retry hints on failure, and a `--dry-run` short circuit that prints the exact command without executing it.

Package cmd — clonespinner.go: tiny goroutine-driven spinner used by runCloneCommandPretty to give the user visible feedback while `git clone` is doing its work. Writes to stderr with carriage returns; the stop func clears the line on exit so subsequent output (success banner, git porcelain) starts at column 0.

Package cmd — `gitmap dedupe`: detect identical repos cloned under different folders by hashing each repo's HEAD tree SHA. v6.71.0 adds parallel scanning and --format=json|csv export.

Package cmd — `gitmap doctor` command.

Doctor performs a one-shot health check of every external dependency gitmap relies on (git, ssh, chrome, PATH, sqlite, disk) and prints targeted fix recipes for each failed probe. Designed to be the first thing a user runs after an install or when a command is misbehaving.

Package cmd — additional `gitmap doctor` probes: config paths, GitHub token availability, and network/API connectivity.

Package cmd — doctor_run.go: flag-aware entry point for `gitmap doctor`.

--json   emit machine-readable JSON instead of the colorized text report
--fix    attempt safe auto-fixes (create .gitmap/, suggest exact recipes)

Exit status: 0 when every probe passes, 1 otherwise.

Package cmd — `gitmap downloader-config [path]` (shorthand: `dc`).

Slice 1 of the downloader feature. Reads / validates / persists the downloader Seedable-Config. Two modes:

  1. Path supplied → load JSON from disk, validate, save to Setting DB.
  2. No path → interactive prompt, pre-populated from current DB values (or downloaderconfig.Defaults() if none).

All actual download / install logic ships in Slice 2 (aria2c installer + engine) and Slice 3 (download / download-unzip commands). This command exists so users can pre-tune the config before those slices land.

Package cmd — glyphsflag.go: global `--glyphs` switch parser.

Mirrors stripThemeFlag exactly so the global-flag inventory stays homogeneous. Strips `--glyphs <mode>` / `--glyphs=<mode>` (and short `-glyphs` form) from os.Args, validates the value, and exports GITMAP_GLYPHS for the glyphs package and any subprocess gitmap spawns.

Package cmd — haschange.go implements `gitmap has-change (hc) <repo>`.

Prints "true" or "false" depending on whether the named repo has uncommitted changes (default), is ahead of origin, or is behind origin. Use --mode to switch dimensions; --all prints structured output covering all three.

Examples:

gitmap hc gitmap                  -> true | false   (dirty working tree)
gitmap hc gitmap --mode=ahead     -> true | false   (local commits not pushed)
gitmap hc gitmap --mode=behind    -> true | false   (remote commits not pulled)
gitmap hc gitmap --all            -> dirty=true ahead=false behind=true

Package cmd — shared helpers for `stale`, `dedupe`, `size`, `orphans`: parallel repo scanning and uniform --format=table|json|csv output. v6.71.0.

Package cmd — inject.go implements `gitmap inject` (`inj`).

Purpose: take an existing on-disk folder and "inject" it into the user's tooling — register with GitHub Desktop, open in VS Code, and (when a `git remote get-url origin` succeeds) upsert into the gitmap SQLite database so it shows up in `cd`, `list`, etc.

Forms:

gitmap inject              # operate on cwd
gitmap inject <folder>     # operate on the given folder
gitmap inj   ...           # short alias

`<folder>` accepts absolute, relative, or `~`-prefixed paths. Reuses `resolveCloneNextFolder` from clonenextfolderdispatch.go for path resolution + dir validation, so error messages stay consistent with `cn <folder>`.

Per the user's spec answer: any folder is accepted (no `.git/` required) — Desktop will silently skip non-repos and VS Code is happy to open anything. The DB upsert is conditional: if the folder has no `origin` remote, we skip the database write but still do Desktop + VS Code, so local-only sandboxes can still be injected into the editor without polluting the repo index.

Package cmd — inject_idempotency.go: shared helpers used by `gitmap inject` and `gitmap open` to skip Desktop / VS Code re-registration when the per-tool stamp on the Repo row is already set.

The `--force` (`-f`) flag bypasses both checks AND zeroes the stamps so the post-action UPDATE re-stamps to "now".

Package cmd — installlist.go renders `gitmap install --list` grouped by category with a per-tool installed-status indicator.

Package cmd — latest-branch command handler.

Package cmd — latest-branch CSV formatter.

Split out from latestbranchoutput.go to keep that file under the 200-line code-style budget. CRLF line endings are forced on every row (header + data) so output is byte-identical across platforms (RFC 4180); pinned by gitmap/cmd/csvcrlf_contract_test.go.

Package cmd — latest-branch output formatters.

Package cmd — latest-branch resolve helpers.

Package cmd — `gitmap lb --switch` checkout post-step.

Package cmd — llmdocs.go generates a consolidated LLM.md reference file.

Package cmd — llmdocscommands.go writes the command reference tables.

Package cmd — llmdocsgroups.go defines command groups for LLM doc generation.

Package cmd — llmdocsheader.go writes the header and architecture sections.

Package cmd — llmdocssections.go writes the remaining LLM.md sections.

Package cmd — migrate.go handles automatic migration of legacy directories.

Package cmd — open.go implements `gitmap open` (alias `op`).

Detects the repo for the current working directory (preferring `git rev-parse --show-toplevel` when available, falling back to cwd) and launches BOTH GitHub Desktop and VS Code on that path.

Behavior is intentionally idempotent-by-side-effect: GitHub Desktop silently skips if the repo is already registered, and VS Code happily re-opens an already-open window. The DB upsert step mirrors `inject`: best-effort, only when a remote origin exists, never aborts the user-visible side effects.

Package cmd — `gitmap orphans`: find local clones whose remote no longer exists (HTTP 404 on the origin URL) and offer bulk delete. v6.71.0 adds parallel remote probing and --format=json|csv export.

Package cmd — `gitmap pending clear` removes orphaned or illegal pending tasks so the next clone run is not blocked by a leftover entry from an earlier crash.

Modes (see helptext/pending-clear.md for the full contract):

orphans  — TargetPath is missing on disk
illegal  — TargetPath looks like a URL or contains illegal Windows
           path characters (`:` after drive letter, `?`, `*`, etc.)
all      — every pending task
<id>     — a single task by numeric ID

Default mode is `orphans` because it's the safest auto-cleanup. Confirmation is required unless --yes is passed; --dry-run previews without touching the DB.

Package cmd — projectrepos.go handles project type query commands.

Package cmd — projectreposoutput.go formats project query output.

Package cmd — projectreposrender.go is the stablejson encoder for `gitmap <type>-repos --json`. Migrated off encoding/json so wire-key order is a compile-time decision pinned by the schema, not a reflection accident on model.DetectedProject.

Schema: spec/08-json-schemas/project-repos.schema.json.

Package cmd — `gitmap pull-release-cd` (alias `prc`).

Package cmd — reclonetransport.go wires the cfr/cfrp/clone-now pipelines into the store-backed IdentifiedTransport column added by migration 008. Two halves:

  1. coerceURLToStoredTransport(url) — runs PRE-clone. If the URL pair (HttpsUrl, SshUrl) has a stored transport verdict from a prior scan/reclone, rewrite `url` to that transport so an SSH-origin repo never silently downgrades to HTTPS on reclone.
  2. persistRecloneTransport(url) — runs POST-clone. Records the transport that was actually used and emits a `gitmap history` row (Command="reclone-transport") so users can audit transport flips with `gitmap history`.

Both functions are fail-open: any store error is warned to stderr and the caller continues. The reclone is the user's primary goal; transport bookkeeping must never break it.

Package cmd implements the CLI commands for gitmap.

Package cmd — release-notes flag parsing & grouped formatting.

Supports:

--since <date|ref>   git log --since= window (e.g. "2 weeks ago", "2025-01-01")
--since-tag <tag>    shorthand for <tag>..HEAD
--format <fmt>       flat | grouped | markdown | json

A bare positional <tagA>..<tagB> is still accepted for back-compat.

Package cmd — release_tools.go: release-notes, release-dry, tag-rename.

Package cmd implements the CLI commands for gitmap.

Package cmd implements the CLI commands for gitmap.

Package cmd — releaserebase.go implements the cross-dir `gitmap r <repo> <version>` form: pull --rebase the named repo, then run the standard release pipeline, then chdir back to the original directory.

Backward compatibility: `gitmap r vX.Y.Z` (single positional arg) keeps running an in-place release of the current repo. The new behavior only triggers when TWO positional args are given AND the first does NOT look like a version string (e.g. v3.31.0, 3.31.0).

Package cmd — releaserecentclone.go: the auto-cd-into-most-recent- clone fallback for `gitmap release`.

When the user runs `gitmap r vX.Y.Z` from a parent directory that is itself NOT a git repo (typical right after `gitmap clone` / `cn` / `cfrp`), we look up the most recently cloned repo in the SQLite DB and chdir into it before delegating to the normal release pipeline. After the release returns we chdir back so the shell's working directory is unchanged.

Package cmd — `gitmap release-undo --range` extension.

Roll back several contiguous release tags at once. The range is inclusive on both ends and must be in `vX.Y.Z..vX.Y.Z` form. Each version is processed sequentially via the existing single-tag release-undo pipeline, so failures stop the run and leave earlier successes intact (idempotent — safe to re-run).

Package cmd — reporeclone.go implements the single-repo "wipe-and-re-clone" flow that overlays the existing manifest-based `gitmap reclone` command.

Triggers when `reclone` / `rec` / `rc` / `relclone` / `clone-now` is invoked AND (the sole positional arg is a path containing `.git`) OR (no positional arg + cwd is inside a git repo). In every other shape (a manifest path, --manifest flag, or no repo in sight) we fall through to runCloneNow's manifest pipeline so existing scripts keep working byte-for-byte.

Package cmd implements the CLI commands for gitmap.

Package cmd — safety_snapshot.go: full working-tree snapshot to .gitmap/snapshot/, rollback, and pre-commit guard hook installer.

Package cmd — scanbenchmark.go captures per-phase scan timings and writes them to a benchmark log so users can diagnose slow scans without us having to ask. Each scan invocation appends a fresh, timestamped block to .gitmap/output/scan-benchmark.log alongside the binary version.

Why a file (not just stdout): users routinely report "scan is slow" with no reproducible numbers. The log gives them — and us — a record of exactly which phase ate the wall clock, across every run.

Package cmd — scanprojectoutput.go writes project-specific JSON files.

Package cmd — scanprojects.go handles project detection during scan.

Package cmd — scanprojectsmeta.go handles Go and C# metadata persistence.

Package cmd — `gitmap self-update` command.

Probes the GitHub releases API for the newest tag, compares against constants.Version, and re-runs `gitmap self-install` non-interactively when a newer release is available. Honors --dry-run and --force.

Package cmd — seowrite.go handles flag parsing and orchestration for seo-write.

Package cmd — seowritecreate.go scaffolds a sample seo-templates.json.

Package cmd — seowritecsv.go handles CSV parsing for seo-write.

Package cmd — seowriteloop.go handles the commit loop, rotation, and timing.

Package cmd — seowritetemplate.go handles template loading and placeholder substitution.

Package cmd — `gitmap size`: per-repo .git size report with --prune to run `git gc --aggressive` on the worst offenders. v6.71.0 adds parallel `.git` sizing and --format=json|csv export.

Package cmd — sshexisting.go handles the case where an SSH key already exists on disk when `gitmap ssh` is invoked. Instead of forwarding the stdin "Overwrite (y/n)?" prompt to `ssh-keygen` (which fails non-interactively and confuses users), we detect the existing key UP FRONT, print the public key + fingerprint, and exit cleanly. Pass `--force` to regenerate.

Package cmd — `gitmap ssh status` subcommand (v6.57.0).

Single-screen SSH health summary: ssh-agent reachability, loaded identities (best-effort via `ssh-add -l`), and per-host probe of `ssh -T -o BatchMode=yes git@<host>`. Side-effect free; safe to run repeatedly. Exits 0 always — diagnostic, not gating.

Package cmd — `gitmap stale` (sta): list local repos with no commits in N days, with optional --archive to move them to .gitmap/archive/. v6.68.0.

Command `gitmap templates init <lang> [<lang>...] [--lfs] [--dry-run] [--force]`.

Scaffolds .gitignore and .gitattributes for one or more languages by resolving the corresponding embedded (or user-overlay) templates and merging them into the target files via templates.Merge — the same idempotent marker-block primitive that powers `add lfs-install`.

Behavior summary:

  • For each <lang>, ignore/<lang>.gitignore is REQUIRED. Missing → hard error (exit 1) with a one-liner pointing at `templates list`.
  • attributes/<lang>.gitattributes is OPTIONAL. Missing → soft skip with a dim "no attributes template for <lang>" notice. This matches the embed corpus (every lang has ignore, only some have attributes).
  • --lfs additionally merges lfs/common.gitattributes into .gitattributes. Reuses templates.Merge with tag "lfs/common" so the block is interchangeable with `gitmap add lfs-install`.
  • --dry-run prints every block that WOULD be written and exits without touching disk. Outcome verbs reflect what would happen (created / would update / would insert).
  • --force replaces any pre-existing target file outright with a fresh gitmap-managed block, discarding hand edits OUTSIDE the markers. Without --force, Merge preserves non-marker content and either updates the existing block in place or appends one — see merge.go.

Operates from CWD. Does NOT require being inside a git repo (scaffolding before `git init` is a legitimate workflow). The --lfs path also does NOT shell out to `git lfs install` — that's `add lfs-install`'s job. `templates init --lfs` is purely a template-merge operation.

Package cmd implements CLI command handlers for gitmap.

Package cmd implements CLI command handlers for gitmap.

Package cmd — themeflag.go: global `--theme` palette selector.

Strips `--theme <mode>` / `--theme=<mode>` (and the short `-theme` form) from os.Args before subcommand dispatch and exports GITMAP_THEME so gitmap/theme.Install — and any subprocess gitmap spawns — picks up the choice. Mirrors stripVSCodeSyncDisabledFlag's pattern so the global-flag inventory stays homogeneous.

Package cmd — `gitmap unzip-compact` (alias `uzc`).

Resolves an input source (local archive, HTTP(S) URL, or auto-detect a single archive in the current folder) and runs the compact-extract algorithm into either the user-supplied destination folder or the current working directory.

Listing mode (--list / -l) skips extraction and prints the archive's entry table to stderr.

Package cmd — extra cleanup passes for update-cleanup.

These complement the pattern-based pass in updatecleanup_remove.go by targeting two artifact classes that don't fit the simple-glob model:

  1. The obsolete v2.90.0 drive-root forwarding shim (e.g. E:\gitmap.exe sitting at the literal drive root, NOT inside a gitmap\ subfolder).
  2. *.gitmap-tmp-* swap directories left by interrupted clones.

Both passes follow the spec/04-generic-cli/22-data-folder-deploy-and-cleanup.md contract (DFD-6, DFD-7).

Package cmd — `--debug-windows` diagnostics for the self-update Phase 3 cleanup handoff.

The flag is opt-in and prints a structured dump to os.Stderr on every relevant lifecycle event. It propagates across the handoff boundary via two channels:

  1. Argv — `--debug-windows` is forwarded into the handoff copy (Phase 2) and the detached cleanup child (Phase 3).
  2. Env — `GITMAP_DEBUG_WINDOWS=1` is set on the cleanup child so even processes spawned without an inherited argv (e.g. future re-execs) keep printing the dump.

Either signal alone activates the dump; users can flip the env var manually to enable the dump on a single run without rebuilding.

The dump is intentionally cross-platform (works on Unix too) so the same flag can debug Linux/macOS handoffs, even though the original motivation was the Windows update-cleanup loop tracked in Issue #10.

Package cmd — JSON sink for `--debug-windows` diagnostics.

In addition to the human-readable `[debug-windows]` lines printed to stderr, every dump helper also emits a structured NDJSON event to a timestamped file under the project's output directory:

output/gitmap-debug-windows-YYYY-MM-DD_HH-MM-SS.jsonl

One event per line — easy to `jq`/`grep`, easy to ship to a log aggregator, and (crucially) survives even when stdout/stderr are swallowed by a detached Windows launcher.

Activation:

  1. `--debug-windows-json` flag (boolean, defaults the path)
  2. `--debug-windows-json=<path>` to override the file path
  3. `GITMAP_DEBUG_WINDOWS_JSON=<path>` env var (also auto-forwarded to the Phase 3 cleanup child so its events append to the same file as the parent, giving one consolidated trace per handoff)

The sink is OFF by default — `--debug-windows` alone keeps the console-only behavior from v3.86. You opt-in to the file sink because writing under the project tree has user-visible side effects.

Failure policy: file open / write errors are swallowed and degrade to console-only. Diagnostics must NEVER block or fail the update.

Package cmd — extended `--debug-windows` output that prints the exact commands and filesystem operations the update-cleanup handoff will perform, so the user can audit and reproduce them.

Two functions are exported within the package:

dumpDebugWindowsCommandPlan — renders the Phase 3 spawn command
line as a copy-pastable shell invocation (proper quoting), and
prints an explicit note that no `git` subprocess is launched.

dumpDebugWindowsCleanupPlan — enumerates the filepath.Glob
patterns the deployed binary will scan and the actual file
matches that will be passed to os.Remove / os.RemoveAll. Called
from runUpdateCleanup BEFORE any deletion happens so the output
reflects intent, not outcome.

These complement the structured-event log written by updatehandofflog.go (which is post-hoc) with a pre-flight view.

Package cmd — Phase 3 of the self-update handoff chain.

Phase 1 (update.go): active gitmap.exe → handoff copy (gitmap-update-<pid>.exe) Phase 2 (update.go): handoff copy runs build/deploy via run.ps1 Phase 3 (this file): handoff copy spawns the freshly-deployed gitmap.exe

(a different file with no lock) detached, with a small delay, to
run `update-cleanup`. Only the deployed binary can safely remove
the still-locked handoff copy and the just-renamed *.exe.old.

See spec/08-generic-update/06-cleanup.md and spec/03-general/02f-self-update-orchestration.md for the full sequence.

Package cmd — durable on-disk handoff log for the self-update Phase 3 cleanup chain.

The verbose logger (verbose.Get) only writes when --verbose is on, and stdout/stderr from a detached Windows cleanup child can be swallowed by intermediate launchers (run.ps1 wrappers, hidden process attrs, etc.). To make these failures forensically recoverable, every Phase 3 lifecycle event also goes to a small, always-on log file under the same temp directory used for the handoff copy and update script:

<TMP>/gitmap-update-handoff-YYYYMMDD.log

The file is opened in append mode (O_APPEND|O_CREATE|O_WRONLY) with line-oriented entries:

2026-04-24T12:34:56Z pid=12345 ppid=12000 phase=phase-3 event=resolve source=config target=C:\bin\gitmap.exe

We never rotate — daily filename is enough to keep the file bounded for the typical update cadence. If the file cannot be opened (read-only volume, etc.) writes degrade silently; this logger must NEVER block or fail the update flow.

Package cmd — visibility.go: entry points for `gitmap make-public` and `gitmap make-private`.

These commands toggle the current repository's visibility on the remote provider (GitHub or GitLab). They wrap the host CLI (`gh` or `glab`) so we don't have to ship OAuth tokens — if the CLI is authenticated, so are we.

Spec parity: spec-authoring/23-visibility-change/01-spec.md.

Forms:

gitmap make-public  [--yes] [--dry-run] [--verbose]
gitmap make-private        [--dry-run] [--verbose]

`--yes` is a no-op for `make-private` (no confirmation is shown when going public → private; the asymmetry matches the PowerShell reference and is intentional — exposing a private repo is the risky direction, hiding a public one is reversible).

Package cmd — visibilityallbulk.go: top-level handler for the four bulk wildcard visibility commands (make-all-public / make-all-private / MAPUB / MAPRI) plus their except-latest counterparts. Owns dispatch, flag parsing (-Y / --verbose / --parallel / --cache-ttl / --except-latest), owner resolution, repo enumeration (TTL-cached), pattern matching, optional except-latest filtering, the optional interactive prompt (-Y skips it), the parallel per-repo apply loop, and exit-code aggregation.

Heavy lifting is delegated:

  • ResolveOwnerOnly → visibilityresolveowner.go
  • listOwnerReposCached → visibilityownerlistcache.go
  • visibility.ParsePatternList / MatchOwnerRepos → gitmap/visibility
  • splitExceptLatest → visibilityexceptlatest.go
  • renderMatchedTable / promptConfirmOrExclude → visibilitybulkprompt.go
  • applyBulkLoopParallel → visibilityparallel.go

Spec: spec/01-app/116-bulk-visibility-mapub-mapri.md §plan + §parallel.

Package cmd — visibilityallbulkaudit.go: thin wiring layer that persists each `make-all-*` invocation to MakeAllVisibilityRun + MakeAllVisibilityResult via the store helpers.

All DB calls are best-effort: a missing/locked audit DB MUST NOT abort the user's bulk action. Every error is logged to os.Stderr with Code Red context (zero-swallow) but execution continues.

Spec: spec/01-app/116-bulk-visibility-mapub-mapri.md §plan steps 19-20.

Package cmd — visibilityapply.go: read / write / verify visibility via the host provider's CLI (`gh repo view --json visibility` and `gh repo edit --visibility ...`; analogous `glab` commands).

We deliberately shell out instead of speaking the REST API directly — it lets users authenticate once via their normal `gh auth login` / `glab auth login` flow and keeps gitmap free of token storage.

Package cmd — visibilityapplyone.go: non-exiting per-repo apply helper for the bulk wildcard visibility commands. Mirrors the read→skip-if-same→apply→verify pipeline of the single-repo path in visibilityapply.go, but returns a structured status instead of calling os.Exit so the outer loop can continue past per-repo failures and tally a summary.

Spec: spec/01-app/116-bulk-visibility-mapub-mapri.md §plan step 14.

Package cmd — visibilityauthstatus.go: preflight `gh auth status` / `glab auth status` gate shared by `make-all-*`, `vu`, and `vr`. Fails fast with a Code Red message BEFORE any provider mutation so an unauthenticated CLI cannot leave a half-populated audit run.

Spec: spec/01-app/116-bulk-visibility-mapub-mapri.md §preflight.

Package cmd — visibilitybulk.go: spec/01-app/113 §2.2.

Adds positional `make-public|make-private <repo-or-url> <count>` form. When count >= 1, the command flips the N most recent versions (vN, vN-1, …, vN-count+1) of the base repo on the same provider+owner as the current repo's origin.

Package cmd — visibilitybulkhelpers.go: small helpers shared by visibilitybulk.go and cfrppriorversion.go. Kept in their own file to stay under the 200-line cap.

Package cmd — visibilitybulkprompt.go: interactive renderer + confirm/exclude loop for the bulk wildcard visibility commands.

Renderer is pure (string in / string out) so it can be golden-tested. Prompt I/O is split into a thin wrapper that takes io.Reader / Writer for the same reason. -Y short-circuits BOTH prompts upstream in visibilityallbulk.go (plan step 13).

Spec: spec/01-app/116-bulk-visibility-mapub-mapri.md §4.

Package cmd — visibilitydriftguard.go: pure decision helper for the `vu` / `vr` drift guard. Extracted as a seam so the policy (force-override vs drift-skip vs proceed) is unit-testable without a real provider client.

Spec: spec/01-app/116-bulk-visibility-mapub-mapri.md §undo-redo.

Package cmd — visibilityexceptlatest.go: splits a matched repo set so the newest `-vN` sibling per base group is held out for the INVERTED visibility flip. Repos that don't carry a `-vN` suffix are left in the main (target-visibility) bucket untouched.

Behavior (v6.65.0+):

--except-latest no longer just "preserves" the latest version —
it flips it to the opposite of the requested target. Example:
  make-all-public  --except-latest → all → public, latest → PRIVATE
  make-all-private --except-latest → all → private, latest → PUBLIC

Spec: spec/01-app/116-bulk-visibility-mapub-mapri.md §except-latest.

Package cmd — visibilityhistory.go: `gitmap visibility-history` (`vh`) prints the most recent make-all-* / VisibilityUndo / VisibilityRedo runs newest-first so users can select a `--run <id>` for `vu` / `vr`.

Spec: spec/01-app/116-bulk-visibility-mapub-mapri.md §history.

Package cmd — visibilityhistoryfilters.go: step-36 post-fetch filters for `vh`. Pure helpers (no DB, no I/O) so the filter policy is unit-testable in isolation. SQL-side filtering is a follow-up if `vh` ever paginates beyond MaxFilterBacklog rows.

Spec: spec/01-app/116-bulk-visibility-mapub-mapri.md §history.

Package cmd — visibilitymakelast.go: `make-last-public` / `make-last-private` (aliases MLPUB / MLPRI). Flips visibility on exactly one repo: the highest `-vN` sibling under `<base>` for the given owner.

Resolution order:

  1. If `<base>` itself ends in `-vN`, treat it as an exact repo name and apply directly.
  2. Else consult OwnerRepoNameIndex for the highest -vN row whose BaseName == `<base>`.
  3. Else refresh the owner repo list (warming the cache + index) and retry step 2.

Honors -Y / --yes to skip confirmation. Spec follow-up to spec/01-app/116-bulk-visibility-mapub-mapri.md.

Package cmd — visibilityownerlist.go: enumerates every repo under a given owner/org via the host provider CLI.

GitHub: gh repo list <owner> --limit <N> --json name GitLab: glab repo list --group <owner> -P <N> -F json

Output JSON is parsed with a permissive `[{"name":"…"}]` scanner — no full JSON unmarshal — so we tolerate extra fields without coupling to the provider's schema version.

Pagination: the provider CLIs cap at --limit; when the returned slice length equals the cap we log a stderr WARNING per spec §plan step 26 so users with >cap repos are not silently truncated.

Spec: spec/01-app/116-bulk-visibility-mapub-mapri.md §plan step 9.

Package cmd — visibilityownerlistcache.go: TTL-bounded SQLite cache in front of listOwnerRepos. Cuts repeated `gh repo list` round-trips when users iterate on patterns within the cache window. The cache is bypassed entirely when the resolved TTL is 0.

Spec: spec/01-app/116-bulk-visibility-mapub-mapri.md §parallel.

Package cmd — visibilityparallel.go: bounded worker pool that applies the per-repo visibility flip concurrently. Per-repo stdout is captured into a bytes.Buffer per worker and flushed atomically under a mutex so the interleaved output stays line-coherent.

Audit writes (a.updateResult) are serialized through the same mutex because SQLite connections aren't safe for concurrent writers.

Spec: spec/01-app/116-bulk-visibility-mapub-mapri.md §parallel.

Package cmd — visibilityredo.go: `gitmap visibility-redo` (`vr`) reverses the most recent `VisibilityUndo` run, restoring the visibility state that the undo reverted. Pure reuse of the shared reverseRunAndExit helper from visibilityundo.go.

Accepts `--run <id>` and `--dry-run`.

Spec: spec/01-app/116-bulk-visibility-mapub-mapri.md §undo-redo.

Package cmd — visibilityresolve.go: provider/slug detection, CLI-availability checks, and the interactive confirm prompt.

Kept separate from visibility.go so each file stays well under the 200-line limit and helpers can be unit-tested in isolation without dragging in the flag-parsing surface.

Package cmd — visibilityresolveowner.go: owner-only resolver used by the bulk wildcard visibility commands (make-all-public, make-all-private, MAPUB, MAPRI). Accepts a full provider URL, a bare "host/owner" token, a folder path, or "." (origin of cwd). Returns the classified provider and the bare owner — NO repo slug, because the caller will enumerate repos under that owner.

Kept in its own file to honor the ≤200-line per-file rule and to keep the existing single-repo resolver (visibilityresolve.go) untouched. Spec: spec/01-app/116-bulk-visibility-mapub-mapri.md §2.

Package cmd — visibilityundo.go: `gitmap visibility-undo` (`vu`) reverses the most recent successful bulk make-all-* run by reading the persisted MakeAllVisibilityResult rows and re-applying each repo's PrevVisibility. The undo itself is logged as a new run with CommandKind=VisibilityUndo, so a follow-up `vu` reverses the undo (this is also how `vr` / visibility-redo is wired in step 23).

Accepts `--run <id>` to target a specific historical run instead of the latest one (step 24).

Spec: spec/01-app/116-bulk-visibility-mapub-mapri.md §undo-redo.

Package cmd — visibilityundoflags.go: flag parsing + dry-run rendering for `gitmap visibility-undo` / `visibility-redo`. Extracted from visibilityundo.go to honor the 200-line per-file cap.

Spec: spec/01-app/116-bulk-visibility-mapub-mapri.md §undo-redo.

Package cmd — visibilityundojson.go: step-37 `--json` summary renderer for `vu` / `vr`. Pure, stdlib-only, no side effects so the contract is table-testable independent of the apply loop.

Wire-format mirrors the v5.43.0+ JSON contract used by `--json` on every other gitmap CLI: stable key order, lowerCamel field names, integer counters, ISO-8601 timestamps from the caller.

Spec: spec/01-app/116-bulk-visibility-mapub-mapri.md §undo-redo.

Package cmd — vscodecustomtags.go: global CLI surface for tuning VS Code Project Manager tag detection.

Three repeatable flags (each accepting comma-lists) let users override the defaults that ship in constants.AutoTagMarkers / AutoTagOrder:

--vscode-tag <name>             always add to every entry
--vscode-tag-skip <name>        drop this auto-detected tag
--vscode-tag-marker <file>=<tag> register marker→tag rule

Like `--vscode-sync-disabled`, the flags are stripped from argv before any subcommand sees its flagset and persisted into GITMAP_VSCODE_TAG_{ADD,SKIP,MARKER} for the current process. The vscodepm.DetectTagsCustom helper consumes those env vars, so every caller that swapped DetectTags → DetectTagsCustom inherits the rules without per-call wiring.

Package cmd — vscodepmrename.go: thin wrapper around vscodepm.RenameByPath used by `gitmap as`. Soft-fails so an alias rename never aborts on a missing VS Code install.

Package cmd — vscodepmsofterror.go: shared soft-fail reporter for every code path that touches the alefragnani.project-manager projects.json file.

Soft-fail policy: a failed VS Code Project Manager interaction (missing user-data root, extension not installed, parse error on a hand-edited projects.json, transient write failure) MUST NEVER turn a successful gitmap operation into a non-zero exit code. Every caller in gitmap/cmd routes through this single function so the wording, formatting, and stderr destination stay consistent — and so future changes to the policy (e.g. demoting the line to a debug-only trace) happen in exactly one place.

The reporter intentionally writes to os.Stderr (not os.Stdout) so scripts that pipe gitmap output through `jq` / `tee` keep clean streams. Callers do not need to print anything else after invoking it — the produced line already includes the "vscode:" namespace prefix used by every other helper in gitmap/vscodepm.

Package cmd — vscodepmsync.go: implements `gitmap vscode-pm-sync` (alias `vpm`). Path defaults to vscodepm.ProjectsJSONPath but --projects-json overrides it. Per-pair tags come from vscodepm.DetectTagsCustom unless --tag was passed (in which case the user-supplied list is used verbatim — brand tag is NOT auto-prepended). --mode (union|replace|intersection) governs the reconciliation against whatever is already on disk. Soft-fails on headless / no-VS-Code boxes. Spec: spec/01-vscode-project-manager-sync/04-tag-resync.md Memory: mem://features VS Code PM Sync (v4.36.0; flags v4.37.0).

Package cmd — vscodepmsync_flags.go: flag-parsing surface for `gitmap vscode-pm-sync` (alias `vpm`).

Lives in its own file so the runner in vscodepmsync.go can stay under the 200-line strict-style budget while we keep growing the CLI. All four documented flags are parsed here:

  • --dry-run (bool) preview, no write
  • --mode <m> (string) union|replace|intersection
  • --projects-json (string) absolute override path
  • --tag <name> (repeatable) replace per-pair detected tags

`--tag` is a custom flag.Value supporting BOTH repetition AND comma-separated values, so `--tag a --tag b,c` produces {a,b,c}. The order is preserved within a single Set call but de-duplicated across calls — first occurrence wins. The `gitmap` brand tag is NOT auto-prepended in this mode (per the constants_cli.go docstring): callers in full control means callers must pass it explicitly if they want it.

Package cmd — vscodesyncdisabled.go: global kill switch for the VS Code Project Manager projects.json sync.

The per-command `--no-vscode-sync` flag opts out of a single invocation. This file adds a process-wide lever that disables the sync for the current gitmap run AND every subprocess it spawns (clone-fix-repo, reclone batches, etc.) by flipping GITMAP_VSCODE_SYNC_DISABLED=1.

Activation paths (any one is enough):

  1. Pass `--vscode-sync-disabled` (or `-vscode-sync-disabled`) anywhere on the command line. It is stripped from os.Args before subcommand dispatch so individual flag.FlagSets never see an unknown flag.
  2. Export GITMAP_VSCODE_SYNC_DISABLED=1 in the shell. Useful for CI / headless boxes that should never touch projects.json regardless of which gitmap command runs.

Honored centrally by syncClonedReposToVSCodePM in clonepmsync.go, so every present and future clone variant inherits the behavior without per-call wiring.

Package cmd — vscodeworkspace.go: implements `gitmap vscode-workspace` (alias `vsws`).

Emits a single multi-root `.code-workspace` file from the same Repo table that drives the Project Manager sync, so one click in VS Code (File → Open Workspace from File…) opens every cloned repo as a folder in one window — no manual "Add Folder to Workspace…" loop.

Distinct from the projects.json sync: the PM sync gives you a flat sidebar list of projects (each opens in its own VS Code window); the workspace file gives you ONE window with N folders, ideal for cross-repo search / refactor. Both surfaces stay in lockstep because both read the same DB.

Spec: spec/01-vscode-project-manager-sync/03-workspace-export.md

Package cmd — workflow_open_pr.go: `gitmap pull-requests` lists open PRs and `gitmap blame-stats` aggregates per-author line counts. The `open` command itself lives in open.go.

Package cmd — workflow_recent_todo.go: `gitmap recent` jumps back to recent repos via the navigation helper history; `gitmap todo` greps TODO/FIXME/XXX with blame.

Package cmd — `gitmap zip` (alias `z`).

Resolves N heterogeneous sources (folders, archive URLs, git repos) into local paths, then runs CreateArchive into the user-supplied --out path. Compression mode is chosen via mutually exclusive flags (--best / --fast / --standard, with -s as a synonym for standard).

Each invocation writes one ArchiveHistory row (in-flight at start, finalized at end) so a partial failure still leaves a forensic trace.

Index

Constants

View Source
const (
	StartupActionCreated     = "created"
	StartupActionOverwritten = "overwritten"
	StartupActionExists      = "exists"
	StartupActionRefused     = "refused"
	StartupActionBadName     = "bad_name"
	StartupActionDeleted     = "deleted"
	StartupActionNoOp        = "noop"
)

Action labels. Mirror the AddStatus / RemoveStatus enums but with snake_case strings safe for shell pipelines (jq, awk on the `.action` value). Kept as constants so the translators can't disagree on spelling.

View Source
const (
	StartupOwnerGitmap     = "gitmap"
	StartupOwnerThirdParty = "third-party"
	StartupOwnerNone       = "none"
	StartupOwnerUnknown    = "unknown"
)

Owner labels. Tells the consumer who CURRENTLY holds the on-disk entry — independent of what we did to it. "none" appears only when there's no entry at all (NoOp / BadName).

Variables

View Source
var (
	BuildCommit = ""
	BuildBranch = ""
	BuildRepo   = ""
	BuildDate   = ""
)

Build-time identity, injected via:

go build -ldflags "-X github.com/.../gitmap/cmd.BuildCommit=<sha> \
                  -X github.com/.../gitmap/cmd.BuildBranch=<branch> \
                  -X github.com/.../gitmap/cmd.BuildRepo=<origin-url> \
                  -X github.com/.../gitmap/cmd.BuildDate=<utc>"

All four default to "" so unset values fall back to a runtime git probe against `constants.RepoPath` (the source repo baked in at link time).

Functions

func AliasAsRecords

func AliasAsRecords() []store.AliasWithRepo

AliasAsRecords returns the alias as a single-element ScanRecord slice. Useful for commands that operate on a list of repos.

func ApplyTransportFlag

func ApplyTransportFlag(dir string, useSSH, useHTTPS bool) (bool, string, string, error)

ApplyTransportFlag rewrites the `remote.origin.url` of dir to the requested transport and persists it via `git remote set-url`. Returns (changed, oldURL, newURL, err).

When neither flag is set, returns immediately with changed=false. When both flags are set, --ssh wins and a one-line warning is printed to stderr (mirrors `gitmap clone` semantics).

Unrecognised origin URLs fail-open: a warning is printed but no error is returned, so the caller can still run git push/pull.

Spec: spec/01-app/111-push-pull-transport-flags.md

func CheckSequenceRange

func CheckSequenceRange(start, count, digits int) error

CheckSequenceRange validates sequence range without os.Exit.

func CheckpointPath

func CheckpointPath(repoRoot, batchID string) string

CheckpointPath returns the on-disk sidecar path for a batch.

func ConvertURLToHTTPS

func ConvertURLToHTTPS(url string) (string, bool)

ConvertURLToHTTPS rewrites a Git remote URL into its `https://host/owner/repo.git` form. Symmetric counterpart to ConvertURLToSSH; intended for callers that want to force HTTPS even when the source manifest captured an SSH URL.

func ConvertURLToSSH

func ConvertURLToSSH(url string) (string, bool)

ConvertURLToSSH rewrites a Git remote URL into its `git@host:owner/repo.git` SSH-shorthand form. Inputs that already look like SSH are normalized (`.git` suffix appended) but otherwise returned as-is. Inputs that are not a recognised Git URL shape are returned unchanged with ok=false so the caller can decide whether to abort or fall through.

Supported input shapes:

https://host/owner/repo(.git)?(/)?
http://host/owner/repo(.git)?(/)?
ssh://git@host[:port]/owner/repo(.git)?
git@host:owner/repo(.git)?

Spec: spec/01-app/110-clone-ssh-flag.md

func CountUnguardedTokenHits

func CountUnguardedTokenHits(body, token string) int

CountUnguardedTokenHits is a convenience wrapper that returns just the hit count. Equivalent to len(ScanUnguardedTokenHits(...)) but avoids the slice allocation on hot paths.

func FilterRemaining

func FilterRemaining(cp *CFRPCheckpoint, all []string) []string

FilterRemaining returns entries from `all` not present in cp.Done. Used at the start of a resumed batch to skip completed work.

func FormatSeq

func FormatSeq(seq, digits int) string

FormatSeq is an exported wrapper for testing formatSeq.

func GetAliasPath

func GetAliasPath() string

GetAliasPath returns the resolved alias path if set, or empty string.

func GetAliasSlug

func GetAliasSlug() string

GetAliasSlug returns the resolved alias slug if set, or empty string.

func HasAlias

func HasAlias() bool

HasAlias returns true if a -A flag was resolved.

func IsCloneDryRun

func IsCloneDryRun() bool

IsCloneDryRun reports the current dry-run flag state. Callers outside runCloneCommand (e.g. cfr's chained fix-repo step) can branch on it to suppress destructive follow-ups in dry-run mode.

func ParsePrettyFlag

func ParsePrettyFlag(args []string) ([]string, render.PrettyMode)

ParsePrettyFlag pulls --pretty / --no-pretty (and the --color / --no-color synonyms) out of args and returns the cleaned slice + the resolved render.PrettyMode. Accepted forms:

--pretty | --color                 → PrettyOn
--pretty=true|on|1|yes|y           → PrettyOn
--color=true|on|1|yes|y            → PrettyOn
--pretty=false|off|0|no|n          → PrettyOff
--color=false|off|0|no|n           → PrettyOff
--pretty=auto | --color=auto       → PrettyAuto (explicit reset)
--no-pretty | --no-color           → PrettyOff

When the same flag is repeated, the **last** occurrence wins (matches stdlib flag.Parse semantics) — and "same flag" spans the synonym pair, so `--pretty --no-color` resolves to PrettyOff. When neither appears, the returned mode is PrettyAuto so callers can rely on Decide()'s default ladder.

Unrecognized values fall through to PrettyAuto and the token is left in place so the downstream parser can produce a meaningful error.

func ParseVersionPatternSafe

func ParseVersionPatternSafe(pattern string) (string, int)

ParseVersionPatternSafe parses a version pattern without os.Exit.

func PrintBinaryLocations

func PrintBinaryLocations()

PrintBinaryLocations prints the Active / Deployed / Config binary triplet to stdout. Called from bare `gitmap` (no args) and from the post-update readout. The output is suppressed when --no-banner is in os.Args or when the GITMAP_QUIET env var is set to "1".

Definitions (see spec/01-app/89-deploy-layout-and-binary-readout.md):

  • Active = os.Executable() after filepath.EvalSymlinks. The file the OS actually loaded for this process.
  • Deployed = <powershell.json.deployPath>/gitmap-cli/<binaryName> if it exists on disk; "(not found)" otherwise.
  • Config = literal path the config declares, whether or not the file exists. Represents config intent.

func PrintCmdFaithfulReport

func PrintCmdFaithfulReport(w io.Writer, r CmdFaithfulReport) error

PrintCmdFaithfulReport writes the report to w. No-op when the report has no mismatches so callers can invoke it unconditionally. Returns the first write error so a closed stderr surfaces (zero- swallow policy).

Format (v4.13.0+): every line is prefixed with the severity tag `[FAIL]` so a CI log scraped one line at a time is unambiguous, and the banner ends with a hint about which flag promotes the report into a hard exit. The intent is to stop users asking "is this actually broken?" — the banner answers it inline.

func PrintCmdFaithfulReportForTest

func PrintCmdFaithfulReportForTest(w io.Writer, r CmdFaithfulReport) error

PrintCmdFaithfulReportForTest wraps PrintCmdFaithfulReport in a "--- expected mismatch ---" banner so test runs that intentionally drive a divergent input don't bury real `[FAIL]` lines in identical- looking simulated ones. Production code MUST NOT call this — only tests that deliberately exercise the mismatch print path. The banner emits even when the report is empty so the section is always paired open/close in captured output, making golden diffs and human scans deterministic.

func RegenChangelog

func RegenChangelog(releaseDir string, w io.Writer) error

RegenChangelog writes a Markdown changelog skeleton (newest first) derived from every release JSON under `releaseDir`. Each entry is a stub the developer fills in with notes; the version + tag are the source of truth so drift between files is impossible.

func ResolveOwnerOnly

func ResolveOwnerOnly(arg string) (ownerContext, error)

ResolveOwnerOnly classifies the supplied target and extracts the owner. Order of attempts: (1) explicit URL → host + first path segment; (2) bare "host/owner"; (3) folder path or "." → read origin of that folder's .git/config. Returns an error with full path/operation/reason context per Code Red rule on failure.

func ResolveTRBranchExported

func ResolveTRBranchExported(version string) string

ResolveTRBranchExported is an exported wrapper for testing resolveTRBranch.

func Run

func Run()

Run is the main entry point for the CLI.

func RunDoctor

func RunDoctor(w io.Writer) int

RunDoctor executes every check and writes a colorized report to w. Returns a non-zero exit when any check fails.

func RunReleaseUndoRange

func RunReleaseUndoRange(opts ReleaseUndoRangeOptions) int

RunReleaseUndoRange parses the range and undoes each version in order.

func RunSelfUpdate

func RunSelfUpdate(opts SelfUpdateOptions) int

RunSelfUpdate is the entry point for `gitmap self-update`.

func SaveCheckpoint

func SaveCheckpoint(path string, cp *CFRPCheckpoint) error

SaveCheckpoint atomically writes the sidecar (write-then-rename).

func ScanUnguardedTokenHits

func ScanUnguardedTokenHits(body, token string) []int

ScanUnguardedTokenHits returns every byte offset in body where token appears AND the rewriter's negative-lookahead guard would allow a substitution. The returned slice is in ascending order.

func SetCloneAssumeYes

func SetCloneAssumeYes(on bool)

SetCloneAssumeYes toggles auto-accept-new-host-key behavior for SSH clone commands when the user passes -y / --yes.

func SetCloneDryRun

func SetCloneDryRun(on bool)

SetCloneDryRun toggles the dry-run short circuit for every subsequent runCloneCommand call in this process. Exported lowercase (package-private) intentionally — only the cmd package wires it.

func SetCloneSpinnerOff

func SetCloneSpinnerOff(off bool)

SetCloneSpinnerOff disables the inline spinner. Useful in tests or CI where carriage-return updates clutter captured output.

func WriteShellHandoff

func WriteShellHandoff(targetPath string)

WriteShellHandoff records `targetPath` so the shell wrapper function can `cd` to it after the binary exits.

Mechanism: the wrapper function exports `GITMAP_HANDOFF_FILE=<tmp>` before invoking the binary. We write `targetPath` to that file. The wrapper then reads it and cds. If the env var is unset (binary called without the wrapper) this is a no-op — `cd` still prints the path to stdout for legacy capture.

Spec: spec/04-generic-cli/21-post-install-shell-activation/01-contract.md

Types

type CFRPCheckpoint

type CFRPCheckpoint struct {
	BatchID   string    `json:"batch_id"`
	StartedAt time.Time `json:"started_at"`
	UpdatedAt time.Time `json:"updated_at"`
	Total     int       `json:"total"`
	Done      []string  `json:"done"`
	Failed    []string  `json:"failed,omitempty"`
}

CFRPCheckpoint captures the in-flight state of a cfrp batch.

func LoadCheckpoint

func LoadCheckpoint(path string) (*CFRPCheckpoint, error)

LoadCheckpoint reads the sidecar; returns (nil, nil) if missing.

type ChromeLocalState

type ChromeLocalState struct {
	LastUsed   string
	LastActive []string
	Profiles   map[string]ChromeProfileEntry // dir name → entry
}

ChromeLocalState is the slice of Chrome's Local State JSON gitmap reads.

func ParseChromeLocalState

func ParseChromeLocalState(raw []byte) (ChromeLocalState, error)

ParseChromeLocalState decodes Local State JSON into a flat, test-friendly shape. Robust to: missing keys, extra keys, empty info_cache, last_used pointing at a directory not present in info_cache (returns the entry with empty display name).

func (ChromeLocalState) DisplayNameFor

func (s ChromeLocalState) DisplayNameFor(dir string) string

DisplayNameFor returns the human-readable name for a profile directory, falling back to the directory name when no entry exists.

type ChromeManifestEntry

type ChromeManifestEntry struct {
	Name string
	SHA  string
}

ChromeManifestEntry is one row of the manifest: tar member name + sha.

type ChromeProfileEntry

type ChromeProfileEntry struct {
	DirName     string
	DisplayName string
	GAIAName    string
	UserName    string
	IsActive    bool
}

ChromeProfileEntry mirrors profile.info_cache[<dir>] fields gitmap surfaces.

type CloneFlags

type CloneFlags struct {
	Source     string
	FolderName string
	TargetDir  string
	SSHKeyName string
	// DefaultBranch mirrors `gitmap scan --default-branch`: when a
	// manifest row has an unknown / empty Branch (or a non-trustworthy
	// BranchSource like "detached" or "unknown"), the cloner rebuilds
	// the clone instruction as `git clone -b <DefaultBranch> ...`
	// instead of letting the remote's default HEAD decide. Empty keeps
	// the legacy behavior. Same constant powers both flags so the help
	// wording stays byte-identical across surfaces.
	DefaultBranch  string
	Positional     []string
	SafePull       bool
	GHDesktop      bool
	NoReplace      bool
	Verbose        bool
	Audit          bool
	MaxConcurrency int
	// Output selects the per-repo summary format. Empty (default)
	// keeps the legacy terse messages; "terminal" emits the
	// standardized RepoTermBlock right before each clone runs so
	// the shape matches scan/clone-next/clone-from/probe.
	Output string
	// VerifyCmdFaithful enables the dry-run argv-vs-displayed
	// checker. See clonetermverify.go for behavior.
	VerifyCmdFaithful bool
	// VerifyCmdFaithfulExitOnMismatch upgrades the verifier into a
	// hard failure: any divergence sets a sticky bit and the run tail
	// exits with constants.CloneVerifyCmdFaithfulExitCode. Implies
	// VerifyCmdFaithful.
	VerifyCmdFaithfulExitOnMismatch bool
	// PrintCloneArgv dumps the executor's literal argv tokens to
	// stderr. See cloneprintargv.go for behavior.
	PrintCloneArgv bool
	// NoVSCodeSync suppresses the post-clone update of the
	// alefragnani.project-manager projects.json file. Mirrors the
	// flag of the same name on `gitmap scan`. Default false →
	// every successful clone is reflected in the VS Code Project
	// Manager sidebar without an extra command. See
	// spec/01-vscode-project-manager-sync/02-clone-sync.md.
	NoVSCodeSync bool
	// UseSSH forces every direct URL (and the first positional in
	// multi-URL form) to be rewritten into its `git@host:owner/repo.git`
	// SSH-shorthand form before git is invoked. HTTPS and `ssh://` URLs
	// are converted via ConvertURLToSSH; already-SSH-shorthand URLs are
	// normalized (`.git` suffix appended). See `--ssh` in clone.md.
	UseSSH bool
	// UseHTTPS is the symmetric counterpart of UseSSH — forces every
	// URL into `https://host/owner/repo.git` form. Useful in CI/headless
	// environments where the SSH agent isn't unlocked.
	UseHTTPS bool
	// DryRun short-circuits every git clone in this run: the runner
	// prints the exact command + target path but never invokes git.
	// Plumbed through cfr/cfrp as well via parseCloneFixRepoArgs.
	DryRun bool
	// AssumeYes skips the SSH first-connect host-key prompt by asking
	// OpenSSH to accept new host keys. Changed host keys still fail.
	IsAssumeYes bool
}

CloneFlags holds all parsed clone-command flags and positional args. Exposing the full positional slice (Positional) lets runClone detect the multi-URL invocation form documented in spec/01-app/104-clone-multi.md.

type CloneNextFlags

type CloneNextFlags struct {
	VersionArg   string
	Delete       bool
	Keep         bool
	NoDesktop    bool
	CreateRemote bool
	SSHKeyName   string
	Verbose      bool
	CSVPath      string
	All          bool
	// Force forces a flat clone even when the user's cwd IS the target
	// folder. Triggers a chdir-to-parent before the existence check (to
	// release Windows file locks) and DISABLES the versioned-folder
	// fallback so the user gets either a flat layout or a clear error.
	// See spec/01-app/87-clone-next-flatten.md.
	Force bool
	// MaxConcurrency is the worker-pool size for batch mode (--all / --csv).
	// 1 (the default) preserves the historical sequential behavior so
	// stdout ordering of per-repo lines is deterministic. Values >1 fan
	// repos out across a bounded pool that mirrors the main cloner's
	// pattern (see gitmap/cloner/concurrent.go). Ignored in single-repo
	// mode where there is only one unit of work.
	MaxConcurrency int
	// NoProgress suppresses the live per-repo progress line printed
	// by the batch collector as workers finish. The final summary
	// (ok/failed/skipped totals) always prints regardless. Default
	// false so users get progress feedback out-of-the-box.
	NoProgress bool
	// ReportErrors enables a JSON failure report at command exit
	// when any per-repo clone fails. Off by default; mirrors the
	// `gitmap scan --errors-report` flag for consistent UX.
	ReportErrors bool
	// DryRun, when true, prints the would-be `git clone` commands
	// (single-repo + batch) and skips ALL side effects — no actual
	// clone, no folder removal, no DB write, no GH Desktop / VS Code
	// launch, no shell handoff. See FlagCloneNextDryRun.
	DryRun bool
	// Output selects the per-repo summary format. Empty keeps the
	// legacy terse stage messages; "terminal" additionally emits
	// the standardized RepoTermBlock right before the clone, so the
	// shape matches scan/clone-from/probe.
	Output string
	// VerifyCmdFaithful enables the dry-run argv-vs-displayed checker.
	VerifyCmdFaithful bool
	// VerifyCmdFaithfulExitOnMismatch upgrades the verifier into a
	// hard failure: any divergence sets a sticky bit and the run tail
	// exits with constants.CloneVerifyCmdFaithfulExitCode. Implies
	// VerifyCmdFaithful.
	VerifyCmdFaithfulExitOnMismatch bool
	// PrintCloneArgv dumps the executor argv to stderr.
	PrintCloneArgv bool
	// NoVSCodeSync suppresses the post-clone update of the
	// alefragnani.project-manager projects.json file. Mirrors
	// `gitmap scan --no-vscode-sync`. Default false. See
	// spec/01-vscode-project-manager-sync/02-clone-sync.md.
	NoVSCodeSync bool
}

CloneNextFlags bundles every parsed flag from the clone-next command so the dispatcher in runCloneNext can branch on batch vs single mode without a 9-arg return list.

type CloneTermBlockInput

type CloneTermBlockInput struct {
	Index        int
	Name         string
	Branch       string
	BranchSource string
	OriginalURL  string
	TargetURL    string
	Dest         string
	// CmdBranch overrides which branch (if any) is rendered as `-b`
	// in the printed cmd. Empty = no `-b` flag, regardless of what
	// Branch (the display field) holds. Defaults to Branch when the
	// caller leaves both CmdBranch AND CmdExtraArgs* unset (legacy
	// fallback for clone-now / clone-pick rows).
	CmdBranch string
	// CmdExtraArgsPre are tokens between `git clone` and `-b`.
	CmdExtraArgsPre []string
	// CmdExtraArgsPost are tokens between `-b <branch>` and the
	// positional URL/dest pair.
	CmdExtraArgsPost []string
}

CloneTermBlockInput carries the per-repo data every clone command already has on hand. Branch/BranchSource may be empty — the renderer falls back to "(unknown)" so the block shape is stable.

Faithfulness contract (audited): the printed `cmd:` line MUST be byte-identical to the argv the executor passes to exec.Command. Each caller controls three override fields to achieve that:

  • CmdBranch: branch passed to `-b` in the printed cmd. Empty means "no `-b` flag".
  • CmdExtraArgsPre: literal tokens inserted between `git clone` and the `-b` slot. Used by clone-pick for `--filter=blob:none --no-checkout` and the long-form `--branch X` / `--depth N`.
  • CmdExtraArgsPost: literal tokens inserted between the `-b` slot and the positional `<url> <dest>` pair. Used by clone-from for `--depth=N` (its executor places --depth AFTER -b).

type CmdFaithfulMismatch

type CmdFaithfulMismatch struct {
	Index     int
	Displayed string
	Executed  string
	Reason    string // short tag: "differs", "missing-in-displayed", "missing-in-executed"
}

CmdFaithfulMismatch describes one position-level divergence between the displayed cmd: tokens and the executor's argv. Index is 0-based over the joined slice (git, clone, …). Either Displayed or Executed may be empty when one slice is shorter than the other.

type CmdFaithfulReport

type CmdFaithfulReport struct {
	Repo       string
	Displayed  string // exact `cmd:` string the user would see
	Executed   string // space-joined executor argv (incl. "git")
	Mismatches []CmdFaithfulMismatch
}

CmdFaithfulReport bundles the per-row verification result. Empty Mismatches means the two forms are byte-identical when joined by single spaces — which is the contract --output terminal advertises.

func VerifyCmdFaithful

func VerifyCmdFaithful(in CloneTermBlockInput, executorArgv []string) CmdFaithfulReport

VerifyCmdFaithful computes the displayed cmd: line via buildCloneCommand and compares it token-by-token to executorArgv (which the caller obtains from clonenow.BuildGitArgs / clonefrom.BuildGitArgs / clonepick.BuildGitArgs). The "git" prefix is prepended to executorArgv internally so the two forms align — the executors return argv WITHOUT the binary, matching exec.Command's convention.

Pure function: no I/O, deterministic. Caller decides where (if anywhere) to print the resulting report — see PrintCmdFaithfulReport.

func (CmdFaithfulReport) HasMismatch

func (r CmdFaithfulReport) HasMismatch() bool

HasMismatch is a convenience predicate so callers can branch without poking at the slice length directly.

type DoctorCheck

type DoctorCheck struct {
	Name    string
	Run     func() (ok bool, detail string)
	FixHint string
}

DoctorCheck is a single named probe.

type DoctorResult

type DoctorResult struct {
	Name    string `json:"name"`
	OK      bool   `json:"ok"`
	Detail  string `json:"detail,omitempty"`
	FixHint string `json:"fix_hint,omitempty"`
}

DoctorResult is the per-check outcome surfaced via text + --json.

type ReleaseMeta

type ReleaseMeta struct {
	Version string `json:"version"`
	Tag     string `json:"tag"`
	Branch  string `json:"branch"`
}

ReleaseMeta mirrors the on-disk shape of `.gitmap/release/*.json`.

type ReleaseNotesOpts

type ReleaseNotesOpts struct {
	Range    string // "vA..vB" or "" when using Since
	Since    string // git --since= value
	SinceTag string // shorthand: <tag>..HEAD
	Format   string // flat | grouped | markdown | json
}

ReleaseNotesOpts holds parsed flags for release-notes.

type ReleaseUndoRangeOptions

type ReleaseUndoRangeOptions struct {
	Range       string // e.g. "v6.60.0..v6.65.0"
	KeepRemote  bool
	KeepSidecar bool
	Yes         bool
	DryRun      bool
	Stdout      io.Writer
	UndoOne     func(version string) error // injected for testability
}

ReleaseUndoRangeOptions configures a multi-tag undo.

type ScanProbeOptions

type ScanProbeOptions struct {
	// Disable suppresses the background probe entirely. Set via --no-probe.
	Disable bool
	// NoWait makes scan return immediately after dispatching jobs;
	// the runner keeps draining in the background until process exit.
	NoWait bool
	// Concurrency overrides the worker count. 0 = use the documented
	// default; negative values disable the runner the same as --no-probe.
	Concurrency int
	// ConcurrencySet records whether the user explicitly passed
	// --probe-workers (or the deprecated --probe-concurrency alias).
	// Used to bypass the auto-trigger ceiling for power users who
	// clearly opted in.
	ConcurrencySet bool
	// Depth is the `--depth N` value forwarded to the shallow-clone
	// fallback inside the background runner. Defaults to
	// constants.ProbeDefaultDepth (1) when no flag was passed.
	Depth int
}

ScanProbeOptions bundles the flags that govern the optional background version-probe pass scan kicks off after upserting repos. Bundling them keeps parseScanFlags's return list manageable and makes the runner-wiring call site read as a single cohesive object.

type SelfUpdateOptions

type SelfUpdateOptions struct {
	DryRun bool
	Force  bool
	Stdout io.Writer
	Client *http.Client
}

SelfUpdateOptions controls a self-update run.

type Snapshot

type Snapshot struct {
	ID         string
	DevicePath string
	Volume     string
}

Snapshot is the non-Windows stub for the VSS shadow-copy helper (#8). The Windows build provides a real implementation; on other platforms callers always receive ok=false and fall back to the regular skip-list copy path.

func CreateSnapshot

func CreateSnapshot(_ string) (Snapshot, bool)

CreateSnapshot is a no-op on non-Windows builds.

func (Snapshot) Delete

func (s Snapshot) Delete()

Delete is a no-op on non-Windows builds.

func (Snapshot) TranslatePath

func (s Snapshot) TranslatePath(srcAbs string) string

TranslatePath returns srcAbs unchanged on non-Windows builds.

Source Files

Directories

Path Synopsis
Package commitin contains the typed enums and shared types for the `gitmap commit-in` (cin) command.
Package commitin contains the typed enums and shared types for the `gitmap commit-in` (cin) command.
checkpoint
Package checkpoint persists per-input progress for commit-in so a re-run after a crash or Ctrl-C skips the source SHAs that already produced a Created/Skipped outcome in the previous attempt.
Package checkpoint persists per-input progress for commit-in so a re-run after a crash or Ctrl-C skips the source SHAs that already produced a Created/Skipped outcome in the previous attempt.
e2e
Package e2e provides shared fixture builders and run helpers for the commit-in end-to-end test suites (Steps 9–12 of the commit-in implementation plan).
Package e2e provides shared fixture builders and run helpers for the commit-in end-to-end test suites (Steps 9–12 of the commit-in implementation plan).
orchestrator
Package orchestrator wires the commit-in sub-packages together.
Package orchestrator wires the commit-in sub-packages together.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL