Documentation
¶
Overview ¶
Package constants defines all shared constant values for gitmap. No magic strings — all literals used for comparison, defaults, formats, and file extensions live here.
Split into focused files:
constants.go — core defaults, modes, formats, permissions constants_git.go — git command and argument strings constants_cli.go — CLI command names, help text, flag descriptions constants_terminal.go — ANSI colors, terminal sections, table headers constants_messages.go — user-facing messages and error strings constants_release.go — release workflow messages and setup sections
Package constants — clone-fix-repo command IDs, messages, and exit codes for `gitmap clone-fix-repo` (cfr) and `gitmap clone-fix-repo-pub` (cfrp).
These commands chain `clone` → `fix-repo` (and optionally `make-public`) into a single invocation. See cmd/clonefixrepo.go.
Package constants centralizes every user-facing string in the CLI. This file owns the `commit-left` / `commit-right` / `commit-both` command surface (commit-transfer family).
Spec: spec/01-app/106-commit-left-right-both.md
**Status:** SCAFFOLD ONLY (v3.74.0). Constants, dispatch wiring, and helptext are in place; the actual replay engine in `gitmap/committransfer/` is deferred to its own session per the spec's phasing plan (§18). Running these commands today prints a clear "not yet implemented — see spec 106" message and exits 2.
**Alias note:** Spec §13 reserves `cl`, `cr`, `cb`. Two of those are already taken at the top-level alias namespace (`cl` → changelog, `cr` → cpp-repos), so the commit-transfer family uses the disambiguated three-letter aliases `cml`, `cmr`, `cmb`. The long-form names (`commit-left` etc.) match the spec verbatim.
Package constants centralizes every user-facing string in the CLI. This file owns the `reinstall` top-level command surface.
`reinstall` does NOT collide with `install` / `uninstall` (which are owned by the third-party tool installer in constants_install.go). It is a separate top-level verb that manages the gitmap binary itself, auto-detecting the install method:
- If a source repo is linked (constants.RepoPath != ""), shell out to run.ps1 -reinstall (Windows) or run.sh --reinstall (Unix). This preserves the user's existing build → deploy → setup pipeline.
- Otherwise, run self-uninstall + self-install back-to-back.
The auto-detect is documented in helptext/reinstall.md and overridable with --mode {auto|repo|self}.
Package constants — Linux/Unix startup-management commands and the marker convention used to scope list/remove operations to entries gitmap itself created (never third-party autostart files).
Package constants — constants_templates_cli.go: CLI identifiers for the `gitmap templates ...` discovery command and its subcommands.
Package constants — TransactionAction schema (v23+).
Spec: spec/04-generic-cli/29-reversible-actions-schema.md
TransactionAction is the typed-action layer that sits ON TOP of the existing TransactionFile byte-snapshot journal. Each row is a single reversible step with a forward+reverse JSON payload and an optional BackupRef pointer to a TransactionFile row that holds the byte payload.
Replay rules:
- Forward apply: ORDER BY Seq ASC.
- Revert: ORDER BY Seq DESC.
- Seq is dense, 1-based, unique within a TransactionId.
- Reverts are idempotent: applying a reverse to an already-reverted row is a no-op (handler returns nil, RevertedAt is left set).
Package constants — constants_v331.go centralizes the new strings introduced in v3.31.0 for: cross-dir release (`r <repo> <ver>`), cross-dir clone-next (`cn <repo> <ver>`), `has-change` (`hc`), and the SSH existing-key-on-disk fix. Kept in a single file (rather than scattered across domain files) to keep the v3.31.0 surface area easy to audit and unwind.
Package constants — visibility command IDs, flags, messages, and exit codes for `gitmap make-public` / `gitmap make-private`.
The two commands are thin wrappers around the host platform's CLI (`gh` for GitHub, `glab` for GitLab). They:
- Resolve provider + owner/repo from `git remote get-url origin`.
- Read the current visibility via the provider CLI.
- Skip if already in the target state (idempotent).
- Prompt the user when going private → public (skip with --yes).
- Apply, then verify the change took effect.
Spec parity: spec-authoring/23-visibility-change/01-spec.md (PowerShell reference: visibility-change.ps1).
Index ¶
Constants ¶
const ( ModeHTTPS = "https" ModeSSH = "ssh" )
Clone modes.
const ( OutputTerminal = "terminal" OutputCSV = "csv" OutputJSON = "json" )
Output formats.
const ( PrefixHTTPS = "https://" PrefixSSH = "git@" )
URL prefixes.
const ( ExtCSV = ".csv" ExtJSON = ".json" ExtTXT = ".txt" ExtGit = ".git" )
File extensions.
const ( ReleaseDirName = "release" OutputDirName = "output" DeployedDirName = "deployed" )
Subdirectory names within .gitmap/.
const ( LegacyOutputDir = "gitmap-output" LegacyReleaseDir = ".release" LegacyDeployedDir = ".deployed" )
Legacy directory names (pre-.gitmap migration).
const ( DefaultCSVFile = "gitmap.csv" DefaultJSONFile = "gitmap.json" DefaultTextFile = "gitmap.txt" DefaultVerboseLogDir = GitMapDir + "/output" DefaultStructureFile = "folder-structure.md" DefaultCloneScript = "clone.ps1" DefaultDirectCloneScript = "direct-clone.ps1" DefaultDirectCloneSSHScript = "direct-clone-ssh.ps1" DefaultDesktopScript = "register-desktop.ps1" DefaultScanCacheFile = "last-scan.json" DefaultConfigPath = "./data/config.json" DefaultSetupConfigPath = "./data/git-setup.json" DefaultBuildOutput = "./bin" DefaultOutputDir = ".gitmap/output" DefaultOutputFolder = "output" DefaultBranch = "main" DefaultDir = "." DefaultVersionFile = "version.json" )
Default file names.
const ( DateDisplayLayout = "02-Jan-2006 03:04 PM" DateUTCSuffix = " (UTC)" )
Date display formatting.
const ( SortByDate = "date" SortByName = "name" )
Sort orders.
const ( BumpMajor = "major" BumpMinor = "minor" BumpPatch = "patch" )
Bump levels.
const ( SafePullRetryAttempts = 4 SafePullRetryDelayMS = 600 WindowsPathWarnThreshold = 240 )
Safe-pull defaults.
const ( CmdAlias = "alias" CmdAliasShort = "a" SubCmdAliasSet = "set" SubCmdAliasRm = "remove" SubCmdAliasList = "list" SubCmdAliasShow = "show" SubCmdAliasSug = "suggest" )
gitmap:cmd top-level Alias command names.
const ( SQLInsertAlias = `INSERT INTO Alias (Alias, RepoId) VALUES (?, ?)` SQLUpdateAlias = `UPDATE Alias SET RepoId = ? WHERE Alias = ?` SQLSelectAllAliases = `SELECT a.AliasId, a.Alias, a.RepoId, a.CreatedAt FROM Alias a ORDER BY a.Alias` SQLSelectAliasByName = `SELECT a.AliasId, a.Alias, a.RepoId, a.CreatedAt FROM Alias a WHERE a.Alias = ?` SQLSelectAliasByRepoID = `SELECT a.AliasId, a.Alias, a.RepoId, a.CreatedAt FROM Alias a WHERE a.RepoId = ?` SQLDeleteAlias = `DELETE FROM Alias WHERE Alias = ?` SQLSelectAliasWithRepo = `` /* 144-byte string literal not displayed */ SQLSelectAllAliasesWithRepo = `` /* 143-byte string literal not displayed */ SQLSelectUnaliasedRepos = `` /* 132-byte string literal not displayed */ )
SQL: alias operations (v15: Alias singular, AliasId PK).
const ( SQLDropAlias = "DROP TABLE IF EXISTS Alias" SQLDropAliases = "DROP TABLE IF EXISTS Aliases" // legacy )
SQL: drop Alias table (and legacy plural for safety on Reset).
const ( FlagDescAliasApply = "Auto-accept all alias suggestions" FlagDescAliasFlag = "Target a repository by its alias" )
Alias flag descriptions.
const ( MsgAliasCreated = " ✓ Alias %q → %s\n" MsgAliasUpdated = " ✓ Updated alias %q → %s\n" MsgAliasRemoved = " ✓ Removed alias %q\n" MsgAliasResolved = " → Resolved alias %q → %s (slug: %s)\n" MsgAliasSuggest = " %-20s → %-10s Accept? (y/N): " MsgAliasSuggestDone = " ✓ Created %d alias(es).\n" MsgAliasSuggestNone = " All repos already have aliases." MsgAliasListHeader = "\n Aliases (%d):\n\n" MsgAliasListRow = " %-15s → %s\n" MsgAliasConflict = " ⚠ Alias %q already points to %s.\n" MsgAliasReassign = " → Reassign to %s? (y/N): " MsgAliasBothWarn = " ⚠ Both alias and slug provided — using alias %q.\n" )
Alias messages.
const ( ErrAliasNotFound = "no alias found: %s" ErrAliasEmpty = "alias name cannot be empty" ErrAliasInvalid = "alias must be alphanumeric with hyphens: %s" ErrAliasShadow = "alias cannot shadow command: %s" ErrAliasCreate = "failed to create alias: %v" ErrAliasQuery = "failed to query aliases: %v" ErrAliasDelete = "failed to delete alias: %v" ErrAliasRepoMissing = "repo not found for alias target: %s" )
Alias error messages.
const ( CmdAmend = "amend" CmdAmendAlias = "am" CmdAmendList = "amend-list" CmdAmendListAlias = "al" )
gitmap:cmd top-level Amend command.
const ( FlagAmendName = "name" FlagAmendEmail = "email" FlagAmendBranch = "branch" FlagAmendDryRun = "dry-run" FlagAmendForcePush = "force-push" )
Amend flag names.
const ( FlagDescAmendName = "New author name for commits" FlagDescAmendEmail = "New author email for commits" FlagDescAmendBranch = "Target branch (default: current branch)" FlagDescAmendDryRun = "Preview which commits would be amended" FlagDescAmendForcePush = "Auto-run git push --force-with-lease after amend" )
Amend flag descriptions.
const ( AmendModeAll = "all" AmendModeRange = "range" AmendModeHead = "head" )
Amend modes.
const ( AmendAuditDir = ".gitmap/amendments" AmendAuditFilePrefix = "amend-" )
Amend audit directory.
const ( MsgAmendHeader = "amend: rewriting %d commits from %s..%s (branch: %s)\n" MsgAmendHeaderAll = "amend: rewriting %d commits on branch: %s\n" MsgAmendAuthor = " author: %q -> %q\n" MsgAmendProgress = " [%d/%d] %s - %s\n" MsgAmendDone = "\nDone: %d commits amended\n" MsgAmendAuditFile = " Audit log: %s\n" MsgAmendAuditDB = " Database: 1 record saved to Amendments table\n" MsgAmendForcePush = " Force push: completed\n" MsgAmendWarnPush = "Warning: Run 'git push --force-with-lease' to update the remote\n" MsgAmendDryHeader = "amend (dry-run): %d commits would be rewritten\n" MsgAmendDryLine = " [%d] %s - %s (author: %s <%s>)\n" MsgAmendDrySkip = " No changes applied (dry-run mode)\n" MsgAmendCheckout = " Switching to branch: %s\n" MsgAmendReturn = " Returning to branch: %s\n" MsgAmendWarnRewrite = "Warning: This rewrites Git history and requires force-push.\n" )
Amend terminal messages.
const ( ErrAmendNoFlags = "error: at least one of --name or --email is required\n" ErrAmendCheckout = "error: failed to checkout branch %s: %v\n" ErrAmendListCommits = "error: failed to list commits: %v\n" ErrAmendFilter = "error: git filter-branch failed: %v\n" ErrAmendForcePush = "error: force push failed: %v\n" ErrAmendAuditWrite = "error: failed to write audit file: %v\n" ErrAmendCommitAmend = "error: git commit --amend failed: %v\n" ErrAmendNoCommits = "error: no commits found in the specified range\n" )
Amend error messages.
const ( HelpAmend = " amend (am) [hash] Rewrite author name/email on commits" HelpAmendList = " amend-list (al) Show stored amendments from database (--limit N, --json, --branch)" HelpAmendFlags = "Amend flags:" HelpAmendName = " --name <name> New author name" HelpAmendEmail = " --email <email> New author email" HelpAmendBr = " --branch <branch> Target branch (default: current)" HelpAmendDry = " --dry-run Preview which commits would be amended" HelpAmendForce = " --force-push Auto force-push after amend" )
Amend help text.
const ( MsgAmendListEmpty = "No amendments found." MsgAmendListHeader = "Amendments: %d record(s)\n" MsgAmendListSeparator = "" /* 246-byte string literal not displayed */ MsgAmendListColumns = "BRANCH MODE COMMITS PREV AUTHOR NEW AUTHOR PUSHED DATE" MsgAmendListRowFmt = "%-15s %-7s %7d %-12s %-12s %-12s %-12s %-6s %s\n" )
Amend-list terminal messages.
const ( SQLInsertAmendment = `` /* 173-byte string literal not displayed */ SQLSelectAllAmendments = `` /* 181-byte string literal not displayed */ SQLSelectAmendmentsByBranch = `` /* 198-byte string literal not displayed */ SQLDropAmendment = "DROP TABLE IF EXISTS Amendment" SQLDropAmendments = "DROP TABLE IF EXISTS Amendments" // legacy )
SQL: amendment operations (v15).
const ( CmdUnzipCompact = "unzip-compact" CmdUnzipCompactAlias = "uzc" CmdZip = "zip" )
gitmap:cmd top-level Archive CLI commands and shorthand aliases (Slice — uzc + zip family).
const ( FlagArchiveBest = "best" FlagArchiveFast = "fast" FlagArchiveStandard = "standard" FlagArchiveStdShort = "s" FlagArchiveOut = "out" FlagArchiveOutShort = "o" FlagArchiveList = "list" FlagArchiveListShrt = "l" FlagArchiveInclude = "include" FlagArchiveExclude = "exclude" FlagArchiveYes = "yes" )
Archive flag names (long + short).
const ( FlagDescArchiveBest = "Use the highest compression level (slowest, smallest)" FlagDescArchiveFast = "Use the fastest compression level (largest)" FlagDescArchiveStandard = "Use the default/standard compression level" FlagDescArchiveOut = "Output file path (extension drives format selection)" FlagDescArchiveList = "List archive contents without extracting" FlagDescArchiveInclude = "Comma-separated globs; only matching paths are processed" FlagDescArchiveExclude = "Comma-separated globs; matching paths are skipped" FlagDescArchiveYes = "Skip confirmation prompts" )
Archive flag descriptions.
const ( CompressionBest = "Best" CompressionFast = "Fast" CompressionStandard = "Standard" )
Compression mode tags persisted in ArchiveHistory.CompressionMode.
const ( ArchiveCmdUnzipCompact = "unzip-compact" ArchiveCmdZip = "zip" )
Archive command names persisted in ArchiveHistory.CommandName.
const ( ArchiveStatusSuccess = "Success" ArchiveStatusFailed = "Failed" )
ArchiveHistory.Status values.
const ( SQLInsertArchiveHistory = `` /* 213-byte string literal not displayed */ SQLUpdateArchiveHistoryFinish = `` /* 171-byte string literal not displayed */ SQLSelectArchiveHistoryRecent = `` /* 229-byte string literal not displayed */ SQLDropArchiveHistory = `DROP TABLE IF EXISTS ArchiveHistory` )
SQL: ArchiveHistory operations.
const ( MsgArchiveBanner = "▶ gitmap %s v%s" MsgArchiveResolving = " ▸ Resolving %d input source(s)…" MsgArchiveResolved = " ✓ %s → %s" MsgArchiveExtractStart = " ▸ Extracting %s → %s" MsgArchiveExtractDone = " ✓ Extracted to %s (%d entries, format=%s)" MsgArchiveCompactFlatten = " ✓ Flattened %d duplicate-name layer(s)" MsgArchiveListHeader = " Archive: %s (format=%s, %d entries)" MsgArchiveListEntry = " %s %d bytes" MsgArchiveCreateStart = " ▸ Creating %s (compression=%s, %d source(s))" MsgArchiveCreateDone = " ✓ Created %s" MsgArchiveTempCleanup = " ◦ Cleaning temporary workspace %s" MsgArchiveAutoPicked = " ✓ Auto-detected single archive in current folder: %s" MsgArchiveHistoryRecorded = " ✓ Recorded ArchiveHistory[%d] (%s)" WarnArchiveHistoryWrite = " ⚠ Could not record ArchiveHistory: %v" ErrArchiveNoSource = "%s: no input source(s) supplied and current folder has no single archive" ErrArchiveMultiInCwd = "%s: current folder has %d archives — pass one explicitly" ErrArchiveUnknownFormat = "%s: could not determine archive format for %q" ErrArchiveCreateNeedsOut = "zip: --out <path> is required (extension drives format)" ErrArchiveBadCompression = "%s: choose at most one of --best / --fast / --standard" )
User-facing archive messages.
const ( HelpUnzipCompact = " unzip-compact (uzc) [src] [dest] Extract local/URL archive into a single normalized folder" HelpZip = " zip (z) <src...> --out <file> Create archive from folders / URLs / git repos" )
HelpUnzipCompact / HelpZip strings shown by the help generator.
const ( CmdAs = "as" CmdAsAlias = "s-alias" LogPrefixAs = "[as]" FlagAsForce = "force" FlagAsForceS = "f" )
gitmap:cmd top-level `gitmap as` — register a short name (alias) for the current Git repo.
Spec: docs in helptext/as.md and README.
const ( MsgAsRegisteredFmt = " ✓ Registered repo '%s' as alias '%s' (path: %s)\n" MsgAsUpdatedFmt = " ✓ Updated alias '%s' -> repo '%s' (path: %s)\n" MsgAsDBSyncedFmt = " ✓ Database now tracks repo '%s' (slug: %s)\n" MsgAsHintNext = " Tip: run `gitmap release-alias %s <version>` from anywhere to release this repo.\n" ErrAsNotInRepoFmt = "error: not inside a Git repository (cwd: %s). Run this from inside the repo's working tree." ErrAsResolveFmt = "error: could not resolve repo metadata for %s: %v" ErrAsAliasInUseFmt = "error: alias '%s' is already mapped to a different repo (slug '%s'). Pass --force to overwrite." ErrAsUsage = "Usage: gitmap as [alias-name] [--force]\n (omit alias-name to use the repo folder's basename)" )
User-facing messages for the `as` command.
const ( AssetsStagingDir = ".gitmap/release-assets" GitHubTokenEnv = "GITHUB_TOKEN" )
Go release asset constants.
const ( FlagDescBin = "Cross-compile Go binaries and include in release assets" FlagDescTargets = "Comma-separated cross-compile targets (e.g. windows/amd64,linux/arm64)" FlagDescListTargets = "Print resolved target matrix and exit" )
Asset flag descriptions.
const ( HelpBin = " --bin, -b Cross-compile Go binaries and include in release assets" HelpTargets = " --targets <list> Cross-compile targets: windows/amd64,linux/arm64" HelpListTargets = " --list-targets Print resolved target matrix and exit" )
Asset help text.
const ( MsgListTargetsHeader = "Release targets (%d):\n" MsgListTargetsSource = "Source: %s\n\n" MsgListTargetsRow = " %s/%s\n" )
List-targets messages.
const ( MsgAssetDetected = " → Detected Go project: %s\n" MsgAssetCrossCompile = "\n Cross-compiling %d target(s)...\n" MsgAssetBuilt = " ✓ Built %s (%s/%s)\n" MsgAssetBuildSummary = " → Built %d/%d binaries successfully\n" MsgAssetUploaded = " ✓ Uploaded %s\n" MsgAssetUploadStart = "\n Uploading %d asset(s) to GitHub...\n" MsgAssetSkipped = "" MsgAssetNoMain = " → No buildable main package found, skipping binaries\n" MsgAssetNoGoProject = "" MsgAssetStagingClean = " ✓ Cleaned up staging directory\n" )
Asset messages.
const ( ScriptReleaseVersionPS1 = "release-version.ps1" ScriptReleaseVersionSh = "release-version.sh" ReleaseVersionSnapshotPS1Fmt = "release-version-%s.ps1" ReleaseVersionSnapshotShFmt = "release-version-%s.sh" MsgReleaseScriptSnapshot = " ✓ Generated release-script snapshot: %s\n" ErrReleaseScriptSnapshot = "Error: snapshot generation failed for %s: %v (operation: bake-version)\n" )
Release-version snapshot install scripts (spec 105).
The same `release-version.ps1` / `release-version.sh` source ships in two forms: the always-current generic script under gitmap/scripts/, and per-release snapshots uploaded as release assets with the version baked in. The naming convention is `release-version-<tag>.<ext>` so each release page can deep-link to a frozen, drift-proof installer.
const ( MsgAssetDryRunHeader = " [dry-run] Would cross-compile %d binaries:\n" MsgAssetDryRunBinary = " → %s\n" MsgAssetDryRunUpload = " [dry-run] Would upload %d assets\n" )
Asset dry-run messages.
const ( ErrAssetBuildFailed = "Error: build failed for %s/%s: %s (operation: compile)\n" ErrAssetUploadFinal = "Error: upload failed for asset %s: %v (operation: upload)\n" ErrAssetNoToken = "Error: GITHUB_TOKEN not set — skipping asset upload (reason: environment variable not set)\n" ErrAssetRemoteParse = "Error: could not parse remote origin: %v (operation: resolve)\n" )
Asset error messages — Code Red: all file errors include exact path and reason.
const ( RetryMaxAttempts = 3 RetryBaseDelayMs = 1000 RetryBackoffFactor = 2 )
Retry constants.
const ( HTTPTooManyRequests = 429 HTTPServerErrorMin = 500 )
Retry HTTP status codes.
const ( MsgRetryAttempt = " ⟳ Retry %d/%d for %s (waiting %s)...\n" MsgRetrySuccess = " ✓ Uploaded %s (attempt %d)\n" )
Retry messages.
const ( MsgAutoCommitScanning = "\n ■ Checking for uncommitted changes...\n" MsgAutoCommitReleaseOnly = " ✓ Release metadata committed: %s\n" MsgAutoCommitPushed = " ✓ Pushed to %s\n" MsgAutoCommitNone = " ✓ Working tree clean — nothing else to commit\n" MsgAutoCommitPrompt = " → Uncommitted changes outside .gitmap/release/:\n" MsgAutoCommitFile = " • %s\n" MsgAutoCommitAsk = " → Auto-commit these alongside the release? [y/N]: " MsgAutoCommitAll = " ✓ All changes committed: %s\n" MsgAutoCommitPartial = " ✓ Committed .gitmap/release/ changes only: %s\n" MsgAutoCommitSkipped = " → Skipped auto-commit (--no-commit)\n" MsgAutoCommitDryRun = " [dry-run] Would auto-commit release changes\n" MsgAutoCommitSyncRetry = " → Remote %s moved; rebasing and retrying push...\n" ErrAutoCommitFailed = " ✗ Auto-commit failed: %v\n" ErrAutoCommitPush = " ✗ Push failed: %v\n" AutoCommitMsgFmt = "Release %s" FlagDescNoCommit = "Skip post-release auto-commit and push" FlagDescYes = "Auto-confirm all prompts (e.g. commit)" MsgAutoCommitAutoYes = " → Auto-confirmed via -y flag\n" // Git diff arguments for detecting changes. GitDiff = "diff" GitDiffNameOnly = "--name-only" GitDiffCached = "--cached" )
Auto-commit messages for post-release commit behavior.
const ( SQLInsertBookmark = `INSERT INTO Bookmark (Name, Command, Args, Flags) VALUES (?, ?, ?, ?)` SQLSelectAllBookmarks = `SELECT BookmarkId, Name, Command, Args, Flags, CreatedAt FROM Bookmark ORDER BY Name` SQLSelectBookmarkByName = `SELECT BookmarkId, Name, Command, Args, Flags, CreatedAt FROM Bookmark WHERE Name = ?` SQLDeleteBookmark = "DELETE FROM Bookmark WHERE Name = ?" SQLDropBookmark = "DROP TABLE IF EXISTS Bookmark" SQLDropBookmarks = "DROP TABLE IF EXISTS Bookmarks" // legacy )
SQL: bookmark operations (v15).
const ( CmdBookmark = "bookmark" CmdBookmarkAlias = "bk" )
gitmap:cmd top-level Bookmark CLI commands.
const ( CmdBookmarkSave = "save" // gitmap:cmd skip CmdBookmarkList = "list" // gitmap:cmd skip CmdBookmarkRun = "run" // gitmap:cmd skip CmdBookmarkDelete = "delete" // gitmap:cmd skip )
gitmap:cmd top-level Bookmark subcommands.
const ( MsgBookmarkSaved = "Bookmark saved: %s → gitmap %s %s %s\n" MsgBookmarkDeleted = "Bookmark deleted: %s\n" MsgBookmarkEmpty = "No bookmarks saved.\n" MsgBookmarkRunning = "Running bookmark: %s → gitmap %s %s %s\n" MsgBookmarkColumns = "NAME COMMAND ARGS FLAGS" MsgBookmarkRowFmt = "%-20s %-15s %-16s %s\n" ErrBookmarkUsage = "usage: gitmap bookmark <save|list|run|delete> [args]\n" ErrBookmarkSaveUsage = "usage: gitmap bookmark save <name> <command> [args...] [--flags...]\n" ErrBookmarkRunUsage = "usage: gitmap bookmark run <name>\n" ErrBookmarkDelUsage = "usage: gitmap bookmark delete <name>\n" ErrBookmarkNotFound = "bookmark not found: %s\n" ErrBookmarkExists = "bookmark already exists: %s (delete it first)\n" ErrBookmarkQuery = "failed to query bookmarks: %v" ErrBookmarkSave = "failed to save bookmark: %v\n" ErrBookmarkDelete = "failed to delete bookmark: %v\n" )
Bookmark messages.
const ( CmdCD = "cd" CmdCDAlias = "go" )
gitmap:cmd top-level CD CLI commands.
const ( CmdCDRepos = "repos" // gitmap:cmd skip CmdCDSetDefault = "set-default" // gitmap:cmd skip CmdCDClearDefault = "clear-default" // gitmap:cmd skip )
gitmap:cmd top-level CD subcommands.
const ( MsgCDMultipleHeader = "Multiple locations found for \"%s\":\n" MsgCDMultipleRowFmt = " %d %s\n" MsgCDPickPrompt = "\nPick [1-%d]: " MsgCDReposHeader = "TRACKED REPOS\n" MsgCDReposRowFmt = " %d %s\n" MsgCDDefaultSet = "Default set for %s: %s\n" MsgCDDefaultCleared = "Default cleared for %s\n" ErrCDUsage = "usage: gitmap cd <repo-name|repos> [--group <name>] [--pick]\n" ErrCDNotFound = "no repo found matching '%s'\n" ErrCDInvalidPick = "invalid selection\n" ErrCDSetDefaultUsage = "usage: gitmap cd set-default <name> <path>\n" ErrCDClearDefaultUsage = "usage: gitmap cd clear-default <name>\n" ErrCDDefaultNotFound = "no default set for '%s'\n" )
CD messages.
const ( FlagDescCDGroup = "Filter repos list by group" FlagDescCDPick = "Force interactive picker even if a default is set" )
CD flag descriptions.
const ( EnvGitmapWrapper = "GITMAP_WRAPPER" EnvGitmapWrapperVal = "1" )
CD shell wrapper env var — set by wrappers so the binary can detect them.
const ( MsgWrapperNotLoaded = "" /* 198-byte string literal not displayed */ MsgWrapperVerifyOK = " %s✓%s Shell wrapper is active (gitmap resolves as a function)\n" MsgWrapperVerifyTip = "" /* 159-byte string literal not displayed */ )
CD wrapper verification messages.
const ( MsgCDFuncInstalled = "Installed 'gitmap'/'gcd' shell wrappers — restart your terminal or source your profile\n" MsgCDFuncAlready = "Shell wrappers for 'gitmap'/'gcd' already installed\n" )
CD function messages.
const ( CmdChangelogGen = "changelog-generate" CmdChangelogGenAlias = "cg" )
gitmap:cmd top-level Changelog generate command.
const ( FlagDescFrom = "Start tag (older). Defaults to second-latest tag" FlagDescTo = "End tag or HEAD. Defaults to latest tag" FlagDescWrite = "Prepend output to CHANGELOG.md instead of printing" )
Changelog generate flag descriptions.
const ( ChangelogGenFormat = "--format=%s" ChangelogGenNoMerges = "--no-merges" ChangelogGenSortFlag = "--sort" ChangelogGenSortVersion = "-version:refname" )
Changelog generate git arguments.
const ( MsgChangelogGenHeader = "\n Changelog: %s → %s\n\n" MsgChangelogGenEmpty = " No commits found between %s and %s.\n" MsgChangelogGenWritten = " ✓ Prepended changelog to %s\n" MsgChangelogGenPreview = " Preview (use --write to save):\n\n" )
Changelog generate messages.
const ( ErrChangelogGenCommits = "failed to list commits between %s and %s: %v" ErrChangelogGenTags = "failed to list tags: %v" ErrChangelogGenTagNotFound = "tag %s not found locally" ErrChangelogGenNoTags = "no version tags found — create a release first" ErrChangelogGenWrite = "failed to write changelog at %s: %v (operation: write)" ErrChangelogGenRead = "failed to read existing changelog at %s: %v (operation: read)" )
Changelog generate errors.
const ( MsgCleanCodeRunning = " Installing coding guidelines from %s\n" MsgCleanCodeDone = " OK Coding guidelines installed.\n" MsgCleanCodeNoPwsh = " ✗ PowerShell not found on PATH. Install PowerShell 7+ or run the one-liner manually:\n irm %s | iex\n" ErrCleanCodeFailed = " ✗ Coding guidelines install failed: %v\n" MsgCleanCodeNonWin = " Note: this installer is PowerShell-based; on non-Windows it requires PowerShell 7+ (pwsh).\n" )
Clean-code installer messages.
const ( CmdInstallCleanCode = "clean-code" CmdInstallCleanCodeGuide = "code-guide" CmdInstallCleanCodeCC = "cc" )
gitmap:cmd top-level Clean-code installer alias tokens exposed to shell tab-completion. These are not standalone top-level commands — they are argument values to `gitmap install` (e.g. `gitmap install clean-code`, `gitmap i cc`). We expose them through the completion marker block so users get tab-complete hints when typing `gitmap install <TAB>`.
NOTE: `cg` is intentionally OMITTED here because it is already owned by `CmdChangelogGenAlias` as a top-level command. Adding it twice would silently win the dedupe in the generator but mask the conflict at the dispatch layer. Users can still run `gitmap install cg` — the install command parses its own positional argument and routes it to the clean-code installer via cleanCodeAliases (see installcleancode.go).
const ( CmdScan = "scan" CmdScanAlias = "s" CmdClone = "clone" CmdCloneAlias = "c" CmdUpdate = "update" CmdUpdateRunner = "update-runner" // gitmap:cmd skip CmdUpdateCleanup = "update-cleanup" // gitmap:cmd skip CmdInstalledDir = "installed-dir" // gitmap:cmd skip CmdInstalledDirAlias = "id" CmdVersion = "version" CmdVersionAlias = "v" CmdHelp = "help" CmdDesktopSync = "desktop-sync" CmdDesktopSyncAlias = "ds" CmdGitHubDesktop = "github-desktop" CmdGitHubDesktopAlias = "gd" CmdPull = "pull" CmdPullAlias = "p" CmdRescan = "rescan" CmdRescanAlias = "rsc" // CmdRescanSubtree narrowly re-runs `gitmap scan` against the // absolutePath of an at-cap row from a previous scan output. Default // MaxDepth is bumped to RescanSubtreeDefaultMaxDepth so users get a // deeper view in one step; override with --max-depth. CmdRescanSubtree = "rescan-subtree" CmdRescanSubtreeAlias = "rss" CmdSetup = "setup" CmdStatus = "status" CmdStatusAlias = "st" CmdExec = "exec" CmdExecAlias = "x" CmdRelease = "release" CmdReleaseShort = "r" CmdReleaseBranch = "release-branch" CmdReleaseBranchAlias = "rb" CmdReleasePending = "release-pending" CmdReleasePendingAlias = "rp" CmdChangelog = "changelog" CmdChangelogAlias = "cl" CmdChangelogMD = "changelog.md" // gitmap:cmd skip CmdDoctor = "doctor" CmdLatestBranch = "latest-branch" CmdLatestBranchAlias = "lb" // `gitmap branch <subcommand>` namespaces general branch-management // helpers. First subcommand: `default` / `def` — checkout the repo's // default branch (origin/HEAD or constants.DefaultBranch fallback). // Designed for muscle-memory parity with `gitmap lb -s` (latest) so // users can flip between "freshest" and "canonical" with a single // short word. Subcommand strings live in constants_messages.go to // keep all `branch`-specific tokens together. CmdBranch = "branch" CmdBranchAlias = "b" CmdBranchSubDefault = "default" // gitmap:cmd skip CmdBranchSubDefaultAlias = "def" // gitmap:cmd skip CmdList = "list" CmdListAlias = "ls" CmdGroup = "group" CmdGroupAlias = "g" CmdGroupCreate = "create" // gitmap:cmd skip CmdGroupAdd = "add" // gitmap:cmd skip CmdGroupRemove = "remove" // gitmap:cmd skip CmdGroupList = "list" // gitmap:cmd skip CmdGroupShow = "show" // gitmap:cmd skip CmdGroupDelete = "delete" // gitmap:cmd skip CmdDBReset = "db-reset" CmdReset = "reset" CmdListVersions = "list-versions" CmdListVersionsAlias = "lv" CmdRevert = "revert" CmdRevertRunner = "revert-runner" // gitmap:cmd skip CmdListReleases = "list-releases" CmdListReleasesAlias = "lr" CmdReleases = "releases" // v3.20.0: alias of list-releases, intended for --all-repos batch view CmdCompletion = "completion" CmdCompletionAlias = "cmp" CmdClearReleaseJSON = "clear-release-json" CmdClearReleaseJSONAlias = "crj" CmdDocs = "docs" CmdDocsAlias = "d" CmdCloneNext = "clone-next" CmdCloneNextAlias = "cn" CmdReleaseSelf = "release-self" CmdReleaseSelfAlias = "rself" CmdReleaseSelfAlias2 = "rs" CmdHelpDashboard = "help-dashboard" CmdHelpDashboardAlias = "hd" CmdPending = "pending" // gitmap:cmd skip CmdDoPending = "do-pending" // gitmap:cmd skip CmdDoPendingAlias = "dp" // gitmap:cmd skip CmdLLMDocs = "llm-docs" CmdLLMDocsAlias = "ld" CmdSetSourceRepo = "set-source-repo" // gitmap:cmd skip CmdSelfInstall = "self-install" CmdSelfUninstall = "self-uninstall" CmdSf = "sf" CmdProbe = "probe" CmdCode = "code" CmdVSCodePMPath = "vscode-pm-path" CmdVSCodePMPathAlias = "vpath" // CmdVSCodeWorkspace emits a single `.code-workspace` file listing // every tracked repo as a folder, so one click in VS Code opens // them all in one window. Source is the same DB the Project // Manager sync reads (store.ListRepos), so the file always matches // the latest scan output. Help: vscode-workspace.md. CmdVSCodeWorkspace = "vscode-workspace" CmdVSCodeWorkspaceAlias = "vsws" CmdLFSCommon = "lfs-common" CmdLFSCommonAlias = "lfsc" CmdReplace = "replace" CmdReplaceAlias = "rpl" CmdInject = "inject" CmdInjectAlias = "inj" // CmdRegoldens runs `go test -run <pattern>` in two passes: pass 1 // regenerates golden fixtures with both gate env vars set; pass 2 // re-runs the same tests with the env vars unset to verify the // regenerated bytes are deterministic. Spec: // spec/05-coding-guidelines/21-golden-fixture-regeneration.md. CmdRegoldens = "regoldens" CmdRegoldensAlias = "rg" // CmdAuditLegacy scans the workspace for forbidden legacy strings // (e.g. gitmap-v16/v6/v7) and exits non-zero on any hit. Used as a // gitmap-legacy-ref-allow // regression guard for remixes / rename commits. Help: audit-legacy.md. CmdAuditLegacy = "audit-legacy" CmdAuditLegacyAlias = "aul" CmdAuditLegacyAlias2 = "audit" // CmdFixRepo rewrites prior `{base}-vN` tokens in tracked files to // the current version, mirroring fix-repo.ps1 / fix-repo.sh exit // codes and config schema. Spec: spec/04-generic-cli/27-fix-repo-command.md. CmdFixRepo = "fix-repo" CmdFixRepoAlias = "fr" // CmdReleasePull is sugar for `release` that first runs // `git pull --ff-only` in the current repo, then delegates to // the regular release pipeline. Hard-fails on non-fast-forward // so we never tag on top of a divergent tree. CmdReleasePull = "release-pull" CmdReleasePullAlias = "relp" // CmdMakePublic / CmdMakePrivate toggle the current repo's // visibility on GitHub or GitLab via `gh` / `glab`. No alias — // the long forms are the spec-mandated UX. Spec: // spec-authoring/23-visibility-change/01-spec.md. CmdMakePublic = "make-public" CmdMakePrivate = "make-private" // CmdHistoryPurge / CmdHistoryPin wrap `git filter-repo` in a // mirror-clone sandbox. Spec: spec/04-generic-cli/16-history-rewrite.md. // The user's working repo is never rewritten in place. CmdHistoryPurge = "history-purge" CmdHistoryPurgeAlias = "hp" CmdHistoryPin = "history-pin" CmdHistoryPinAlias = "hpin" // CmdCommitIn / CmdCommitInAlias — chronological multi-source // commit replay into a single destination repo. See // spec/03-commit-in/. Both tokens resolve to the same handler; // short alias is `cin`. CmdCommitIn = "commit-in" CmdCommitInAlias = "cin" )
gitmap:cmd top-level CLI commands.
const ( FlagAuditLegacyPatterns = "patterns" FlagDescAuditLegacyPatterns = "Comma-separated regex patterns to flag (default: gitmap-v[567])" FlagAuditLegacyPath = "path" FlagDescAuditLegacyPath = "Root directory to scan (default: current working directory)" FlagAuditLegacyJSON = "json" FlagDescAuditLegacyJSON = "Emit machine-readable JSON instead of human text" FlagAuditLegacyReport = "report" FlagDescAuditLegacyReport = "Write a Markdown audit report to this path (use '' for default .gitmap/audit-legacy-report.md)" FlagAuditLegacyDiffs = "diffs" FlagDescAuditLegacyDiffs = "Also write per-file unified diffs (legacy → v8) into the report's diffs/ folder and link them" DefaultAuditLegacyPatterns = "gitmap-v[567]\\b" DefaultAuditLegacyReport = ".gitmap/audit-legacy-report.md" DefaultAuditLegacyDiffsDir = "diffs" DefaultAuditLegacyReplace = "gitmap-v16" MsgAuditLegacyClean = " ✓ audit-legacy: no forbidden legacy strings found in %s\n" MsgAuditLegacyHeader = " ✗ audit-legacy: %d match(es) across %d file(s) for pattern(s) %q\n" MsgAuditLegacyHit = " %s:%d: %s\n" MsgAuditLegacyReportWrote = " 📄 audit-legacy: report written to %s\n" MsgAuditLegacyDiffsWrote = " 📎 audit-legacy: %d per-file diff(s) written to %s\n" ErrAuditLegacyWalk = "audit-legacy: walk failed for %s: %v\n" ErrAuditLegacyRegex = "audit-legacy: invalid regex %q: %v\n" ErrAuditLegacyReportWrite = "audit-legacy: failed to write report to %s: %v\n" ErrAuditLegacyDiffWrite = "audit-legacy: failed to write diff for %s: %v\n" )
Audit-legacy defaults + flag names. Patterns are comma-separated regexes. Defaults catch the gitmap-v16/v6/v7 → v8 rename regression class. // gitmap-legacy-ref-allow
const ( FlagRegoldensPattern = "pattern" FlagDescRegoldensPattern = "Test name pattern passed to `go test -run` (required)" FlagRegoldensPackage = "package" FlagDescRegoldensPackage = "Go package selector to test (default: ./...)" FlagRegoldensSkipVerify = "skip-verify" FlagDescRegoldensSkipVerify = "Skip the second verification pass that re-runs without the gate env vars" FlagRegoldensDryRun = "dry-run" FlagDescRegoldensDryRun = "Print the `go test` invocations that would run, then exit 0" FlagRegoldensDiff = "diff" FlagDescRegoldensDiff = "" /* 221-byte string literal not displayed */ FlagRegoldensDeterminism = "determinism" FlagDescRegoldensDeterminism = "" /* 323-byte string literal not displayed */ RegoldensDiffModeShort = "short" RegoldensDiffModeFull = "full" RegoldensDefaultPackageGlob = "./..." // RegoldensNonDetMarker is the substring goldenguard prints when // a writer fails AssertWriterDeterministic. The pre-check pass // scans `go test` output for this marker to distinguish a real // non-determinism failure from the EXPECTED gate-block failure. // Keep in sync with goldenguard/determinism.go nonDeterministicWriterMsgFmt. RegoldensNonDetMarker = "is non-deterministic" )
Regoldens flag names + descriptions. The two env vars driven by this command (GITMAP_UPDATE_GOLDEN, GITMAP_ALLOW_GOLDEN_UPDATE) are the canonical two-key safety gate from the goldenguard package; the values themselves live there to keep one source of truth (do NOT duplicate "1" here).
const ( MsgRegoldensPass1Header = "▸ Pass 1: regenerating goldens (GITMAP_UPDATE_GOLDEN=1 GITMAP_ALLOW_GOLDEN_UPDATE=1)\n" MsgRegoldensPass2Header = "▸ Pass 2: verifying determinism (gate env vars cleared)\n" MsgRegoldensSkipVerify = "▸ Pass 2 skipped (--skip-verify)\n" MsgRegoldensSuccess = "✓ Goldens regenerated and verified for pattern %q in package %q\n" MsgRegoldensSuccessNoVeri = "✓ Goldens regenerated for pattern %q in package %q (verification skipped)\n" MsgRegoldensDryRun = "▸ Dry run — would execute:\n %s\n %s\n" MsgRegoldensDiffHeader = "▸ Golden diff summary (testdata/**/*golden* files touched by pass 1) [mode=%s]:\n" MsgRegoldensDiffNoChanges = " (no testdata/**/*golden* files changed)\n" MsgRegoldensDiffLineShort = " %s %s\n" MsgRegoldensDiffLineFull = " %s %s (+%d / -%d)\n" MsgRegoldensDiffRenameFull = " ↳ renamed from %s\n" MsgRegoldensDiffTotals = " ─ %d file(s) changed: %d added, %d modified, %d renamed, %d deleted (+%d / -%d total)\n" MsgRegoldensDiffSkipped = "▸ Diff summary skipped: not a git working tree (or `git` not on PATH)\n" MsgRegoldensPass2NotRun = "▣ Pass 2: did NOT run — pass 1 failed (exit %d); fixtures left in partial state, determinism unverified\n" MsgRegoldensPass2NotRunSkip = "▣ Pass 2: did NOT run — --skip-verify was set; determinism unverified\n" MsgRegoldensPass2Ran = "▣ Pass 2: ran and PASSED — writer is deterministic; goldens are safe to commit\n" MsgRegoldensPrecheckHeader = "▸ Pre-check: determinism (trigger ON, allow-update gate OFF — no fixture writes)\n" MsgRegoldensPrecheckPass = "✓ Pre-check passed — no non-deterministic writers detected; proceeding to pass 1\n" ErrRegoldensMissingPat = "regoldens: --pattern is required (e.g. --pattern TestCloneFromReportJSON_Golden)" ErrRegoldensPass1Failed = "" /* 131-byte string literal not displayed */ ErrRegoldensPass2Failed = "" /* 137-byte string literal not displayed */ ErrRegoldensDiffMode = "regoldens: --diff=%q is not valid; use --diff=short or --diff=full" ErrRegoldensPrecheckFailed = "" /* 254-byte string literal not displayed */ )
Regoldens user-facing messages.
const ( HelpUsage = "Usage: gitmap <command> [flags]" HelpCommands = "Commands:" HelpScan = " scan (s) [dir] Scan directory for Git repos" HelpClone = " clone (c) <source|json|csv|text> Re-clone from file (shorthands auto-resolve)" HelpUpdate = " update Self-update from source repo" HelpUpdateCleanup = " update-cleanup Remove leftover update temp files and .old backups" HelpInstalledDir = " installed-dir (id) Show the active installed binary path" HelpVersion = " version (v) Show version number" HelpDesktopSync = " desktop-sync (ds) Sync repos to GitHub Desktop from output" HelpGitHubDesktop = " github-desktop (gd) Register current repo with GitHub Desktop (no scan needed)" HelpPull = " pull (p) <name> Pull a specific repo by its name" HelpRescan = " rescan (rsc) Re-run last scan with cached flags" HelpSetup = " setup Configure Git diff/merge tool, aliases & core settings" HelpStatus = " status (st) Show dirty/clean, ahead/behind, stash for all repos" HelpExec = " exec (x) <args...> Run any git command across all repos" HelpRelease = " release (r) [ver] Create release branch, tag, and push" HelpReleasePull = " release-pull (relp) [ver] git pull --ff-only, then release the current repo" HelpReleaseBr = " release-branch (rb) Complete release from existing release branch" HelpReleasePend = " release-pending (rp) Release all pending branches without tags" HelpFixRepo = " fix-repo (fr) Rewrite prior {base}-vN tokens (-2/-3/-5/--all/--dry-run)" HelpChangelog = " changelog (cl) [ver] Show concise release notes (use --open, --source)" HelpDoctor = " doctor [--fix-path] Diagnose PATH, deploy, and version issues" HelpLatestBr = " latest-branch (lb) Find most recently updated remote branch" HelpList = " list (ls) Show all tracked repos with slugs" HelpGroup = " group (g) <sub> Manage repo groups / activate group for batch ops" HelpMultiGroup = " multi-group (mg) Select multiple groups for batch operations" HelpSf = " sf <add|list|rm> Manage scan folders (roots that gitmap scan tracks)" HelpDBReset = " db-reset --confirm Clear all tracked repos and groups from the database" HelpCompletion = " completion (cmp) Generate shell tab-completion scripts" HelpClearReleaseJSON = " clear-release-json (crj) Remove a .gitmap/release/vX.Y.Z.json file" HelpDocs = " docs (d) Open documentation website in browser" HelpHelpDash = " help-dashboard (hd) Serve the docs site locally in your browser" HelpCloneNext = " clone-next (cn) Clone next versioned iteration of current repo" HelpReleaseSelf = " release-self (rs) Release gitmap itself from any directory" HelpHelp = " help Show this help message" HelpListVersions = " list-versions (lv) Show all release tags, highest first (--limit N, --json, --source)" HelpListReleases = " list-releases (lr) Show releases from .gitmap/release/ files or database (--limit N, --json, --source)" HelpRevert = " revert <version> Revert to a specific release version" MsgHelpLFSCommon = " lfs-common (lfsc) Track common binary file types with Git LFS in current repo" )
const ( FlagDescConfig = "Path to config file" FlagDescMode = "Clone URL style: https or ssh" FlagDescOutput = "Output format: terminal, csv, json" FlagDescOutFile = "Exact output file path" FlagDescOutputPath = "Output directory for CSV/JSON" // FlagScanManifest is a unified alias for `--output-path` on the // scan command, mirroring the same flag on `gitmap reclone` so // the scan→reclone round-trip uses one vocabulary. Resolution: // `--manifest` is honored only when `--output-path` is empty. FlagScanManifest = "manifest" FlagDescScanManifest = "Alias for --output-path: directory where the scan " + "manifest (JSON + CSV) is written. Used by `gitmap reclone --manifest`." FlagDescTargetDir = "Base directory for cloned repos" FlagDescSafePull = "If repo exists, run safe git pull with retries and unlock diagnostics" FlagDescGHDesktop = "Add discovered repos to GitHub Desktop" FlagDescOpen = "Open output folder after scan completes" FlagDescQuiet = "Suppress terminal clone help section" FlagDescVerbose = "Write detailed stdout/stderr debug log to a timestamped file" FlagScanWorkers = "workers" FlagDescScanWorkers = "Worker pool size for scan (0 = auto, capped at 16)" DefaultScanWorkers = 0 // FlagScanWorkersConcurrencyAlias is the deprecated long-form // spelling kept for muscle-memory compatibility. Mirrors the // --probe-workers / --probe-concurrency precedent in // constants_probe.go: --workers stays canonical; --concurrency // is honored but emits a one-line stderr deprecation notice. // When BOTH are passed, --workers wins (explicit canonical // flag overrides the deprecated alias) without a warning. FlagScanWorkersConcurrencyAlias = "concurrency" FlagDescScanWorkersConcurrencyAlias = "(deprecated, use --workers) Worker pool size for scan (0 = auto, capped at 16)" // MsgScanWorkersConcurrencyAlias is printed to os.Stderr when // the deprecated --concurrency flag is used. Single-line, // prefixed with two-space + middle-dot to match the rest of // gitmap's stderr advisory format (see MsgScanProbeConcurrencyAlias). MsgScanWorkersConcurrencyAlias = " · --concurrency is deprecated; use --workers instead\n" // FlagScanRelativeRoot lets the user pin the base path used to compute // each repo's RelativePath in the output (CSV/JSON/text/structure/ // clone scripts). Without it, RelativePath is derived from the scan // dir, which means running `gitmap scan .` from different cwds // produces different paths for the same repos. With --relative-root, // every output row is computed against the supplied (absolute or // relative) directory so artifacts stay byte-stable across cwds. FlagScanRelativeRoot = "relative-root" FlagDescScanRelativeRoot = "Pin the base directory used for output RelativePath (absolute or relative; must contain every scanned repo)" // FlagScanMaxDepth caps how many directory levels below the scan root // the walker may descend. Default 0 → resolves to scanner.DefaultMaxDepth // (4) inside the scanner. Negative → unbounded (legacy behavior). // Honored regardless of whether a `.git` was found on the path — // repos already stop their own subtree as before. FlagScanMaxDepth = "max-depth" FlagDescScanMaxDepth = "Max directory levels to descend below scan root (0 = default 4, negative = unlimited)" DefaultScanMaxDepth = 0 // RescanSubtreeDefaultMaxDepth is the cap `gitmap rescan-subtree` // applies when the user does not pass an explicit --max-depth. It is // deliberately deeper than DefaultScanMaxDepth (which resolves to 4 // inside the scanner) so the typical at-cap-rescan workflow finds // the previously hidden nested repos in one shot. RescanSubtreeDefaultMaxDepth = 8 // FlagScanDefaultBranch overrides the fallback branch name written // to ScanRecord.Branch when none of the live detection steps in // gitutil.DetectBranchWithDefault returned a usable name. Without // the flag, the fallback is the package-default constants.DefaultBranch // ("main"). Useful for catalogs that target legacy infra still on // "master", or for forcing a project-specific convention without // touching the binary's compiled-in default. FlagScanDefaultBranch = "default-branch" FlagDescScanDefaultBranch = "Fallback branch name when HEAD/remote-tracking detection finds nothing (default: main)" // FlagScanReportErrors enables a JSON failure report at command // exit for `gitmap scan` and `gitmap cn --all/--csv`. Bare boolean // — output path is fixed at `<binaryDir>/.gitmap/reports/errors- // <unixts>.json`. Honored by both `gitmap scan` (captures scanner // ReadDir + background ls-remote / shallow-clone failures) and // `gitmap cn --all/--csv` (captures per-repo clone failures). // Clean runs leave NO file on disk. // // NOTE: distinct from the existing `--report-errors` (with leading // dashes baked in) on the `gitmap update` command — that flag // takes a value (`json`) and writes a JSONL handoff trace. Naming // this one `--errors-report` keeps both UX surfaces intact. FlagScanReportErrors = "errors-report" FlagDescScanReportErrors = "Write per-repo failures to .gitmap/reports/errors-<unixts>.json (only emitted when failures occur)" FlagDescSetupConfig = "Path to git-setup.json config file" FlagDescDryRun = "Preview changes without applying them" FlagDescAssets = "Directory or file to attach to the release" FlagDescCommit = "Create release from a specific commit" FlagDescRelBranch = "Create release from latest commit of a branch" FlagDescBump = "Auto-increment version: major, minor, or patch" FlagDescDraft = "Create an unpublished draft release" FlagDescLatest = "Show only the latest changelog entry" FlagDescLimit = "Number of changelog versions to show" FlagDescOpenChangelog = "Open CHANGELOG.md with the default system app" FlagDescLBRemote = "Remote to filter branches against (default: origin)" FlagDescLBAllRemotes = "Include branches from all remotes" FlagDescLBContains = "Fall back to --contains if --points-at returns empty" FlagDescLBTop = "Show top N most recently updated branches" FlagDescLBJSON = "Output structured JSON instead of plain text (shorthand for --format json)" FlagDescLBFormat = "Output format: terminal, json, csv (default: terminal)" FlagDescLBNoFetch = "Skip git fetch (use existing remote refs)" FlagDescLBSort = "Sort order: date (default, descending) or name (alphabetical)" FlagDescLBFilter = "Filter branches by glob or substring pattern" // FlagDescLBSwitch / FlagDescLBSwitchShort document `gitmap lb // --switch` / `gitmap lb -s`. Both register the SAME effect: after // printing the latest-branch report, run `git checkout` against the // resolved branch name. Useful as a single-keystroke "jump to whatever // is freshest" workflow when reviewing PR work across many branches. FlagDescLBSwitch = "Checkout the resolved latest branch after printing the report" FlagDescLBSwitchShort = "Short alias for --switch" FlagDescGroup = "Filter by group name" FlagDescAll = "Run against all tracked repos from database" FlagDescListVerbose = "Show full paths and URLs" FlagDescGroupDesc = "Optional group description" FlagDescGroupColor = "Terminal color for group display" FlagDescConfirm = "Confirm destructive operation" FlagDescSource = "Filter by source: release or import" )
Flag descriptions.
const ( FlagDebugPaths = "debug-paths" FlagDescDebugPaths = "" /* 165-byte string literal not displayed */ )
FlagDebugPaths exposes the canonicalize-path tracer used by the VS Code Project Manager sync helper. When set on `gitmap clone`, the flag exports GITMAP_DEBUG_PATHS=1 for the current process so every clone variant that routes through canonicalizePMPath emits a one-line stderr trace of (raw → cleaned → resolved) rootPaths. Diagnostic-only — Windows 8.3 short-name and symlink resolution is the primary debugging target. Off by default.
const ( ProgressBeginFmt = "[%3d/%d] Cloning %s ..." ProgressDoneFmt = " done (%s)\n" ProgressSkipFmt = " skipped (cached)\n" ProgressFailFmt = " FAILED\n" ProgressSummaryFmt = "\nClone complete: %d/%d repos in %s\n" ProgressDetailFmt = " Cloned: %d | Pulled: %d | Skipped: %d | Failed: %d\n" )
Clone progress format strings.
const ( BatchProgressBeginFmt = "[%3d/%d] %s ..." BatchProgressDoneFmt = " done (%s)\n" BatchProgressFailFmt = " FAILED\n" BatchProgressSkipFmt = " skipped\n" BatchProgressSummaryFmt = "\n%s complete: %d/%d in %s\n" BatchProgressDetailFmt = " Succeeded: %d | Failed: %d | Skipped: %d\n" BatchStoppedMsg = " ⚠ Halted early (--stop-on-fail)\n" )
Batch progress format strings (generic operations).
const ( BatchFailureHeader = " ── Failed Items ──" BatchFailureEntryFmt = " %d. %s: %s\n" ExitPartialFailure = 3 )
Batch failure report format strings.
const ( FlagStopOnFail = "stop-on-fail" FlagDescStopOnFail = "Stop batch operation after first failure" )
Batch flag constants.
const ( ShorthandJSON = "json" ShorthandCSV = "csv" ShorthandText = "text" )
Clone shorthands — short aliases for `gitmap clone <source>` that expand to the default scan output files (json/csv/text).
const ( MsgCloneInvalidURLFmt = " ⚠ Skipping invalid URL: %s\n" MsgCloneSummaryMultiFmt = "\n Multi-clone summary: %d succeeded, %d failed (of %d URLs)\n" MsgCloneRegisteredInline = " ✓ Registered with GitHub Desktop: %s\n" MsgCloneMultiBegin = "\n Cloning %d repositories...\n" MsgCloneMultiItem = "\n [%d/%d] %s\n" ErrCloneAllInvalid = " ✗ All URLs were invalid — nothing to clone\n" ErrCloneMultiFailedFmt = " ✗ [%d/%d] %s failed: %v\n" )
Multi-URL clone messages (spec/01-app/104-clone-multi.md).
const ( ExitCloneMultiPartialFail = 1 ExitCloneMultiAllInvalid = 3 )
Multi-clone exit codes.
const ( MsgCloneAuditHeader = "clone audit: source=%s target=%s records=%d\n" MsgCloneAuditRow = " %s %s %s (%s) — %s\n" MsgCloneAuditCmd = " $ %s\n" MsgCloneAuditSummary = "audit summary: +clone=%d ~pull=%d =cached=%d ?conflict=%d !invalid=%d\n" )
Audit output format strings. Layout decisions:
- Header carries source path, target dir, and total record count.
- Each row begins with a single-character diff marker so the output is visually scannable and easy to grep ("^+ " for new clones, "^! " for invalid records, etc.).
- The optional command line is indented two spaces to differentiate it from the row header.
- Summary always prints, even when every count is zero.
const ( // CloneTermDetectTimeout caps how long `git ls-remote --symref // <url> HEAD` is allowed to run when previewing a clone in // `--output terminal` mode. The clone itself has no timeout — // this only protects the per-repo PREVIEW from a hung remote. CloneTermDetectTimeout = 4 * time.Second // BranchSourceRemoteHEAD is the canonical RepoTermBlock // BranchSource label used when the branch was discovered via // `git ls-remote --symref <url> HEAD` (i.e. the remote default // branch). Mirrors "HEAD" / "manifest" / "default HEAD" used by // the other clone commands so the rendered output is grep-able. BranchSourceRemoteHEAD = "remote HEAD" // FlagCloneTermOutput is the shared --output flag name used by // every clone-related command. clone-next and clone-from already // use the same string ("output") but kept as a constant so a // future rename only happens in one place. FlagCloneTermOutput = "output" // FlagDescCloneTermOutput is the shared description for clone, // clone-now, and clone-pick. clone-next and clone-from keep // their existing descriptions verbatim to avoid breaking help // snapshots; new commands use this one. Wording calls out the // stream split explicitly so users know where to redirect: // blocks go to stdout (machine-pipeable), git progress + the // human summary go to stderr. FlagDescCloneTermOutput = "Per-repo summary format: '' (legacy) or " + "'terminal' (standardized branch/from/to/command block on " + "stdout, streamed before each clone; git progress stays on stderr)" // FlagCloneVerifyCmdFaithful is the shared boolean flag name used // by every clone-related command to enable the dry-run verifier // that compares the rendered `cmd:` line against the executor's // real argv. Single constant so a future rename happens in one // place and `gitmap <cmd> --help` stays consistent across surfaces. FlagCloneVerifyCmdFaithful = "verify-cmd-faithful" // FlagDescCloneVerifyCmdFaithful explains the flag in --help. // Wording calls out that it's a SAFETY check (no execution // difference, no output unless something is wrong) so users feel // safe leaving it on in CI. FlagDescCloneVerifyCmdFaithful = "Verify the rendered cmd: line " + "matches the executor's real git argv. Prints a structured " + "mismatch report to stderr on divergence; silent on match. " + "Pure check — does not change clone behavior." // FlagCloneVerifyCmdFaithfulExitOnMismatch is the shared boolean // flag name used by every clone-related command to upgrade the // informational --verify-cmd-faithful checker into a hard failure: // when ANY mismatch is detected during the run, the process exits // with CloneVerifyCmdFaithfulExitCode after the work completes. // Single constant so a future rename happens in one place and // `gitmap <cmd> --help` stays consistent across surfaces. // // Implies --verify-cmd-faithful (the verifier must run to detect // drift). The flag is independent so users can opt into hard-fail // without re-typing both flags in CI. FlagCloneVerifyCmdFaithfulExitOnMismatch = "verify-cmd-faithful-exit-on-mismatch" // FlagDescCloneVerifyCmdFaithfulExitOnMismatch explains the flag in // --help. Wording is explicit about the exit code AND the timing // (after the run completes, not at the first mismatch) so CI logs // show the FULL list of divergences before the process dies. FlagDescCloneVerifyCmdFaithfulExitOnMismatch = "Exit non-zero (code " + "3) at the end of the run when --verify-cmd-faithful detects " + "any mismatch. Implies --verify-cmd-faithful. Mismatch reports " + "still print to stderr; the executor still finishes the work " + "so the full divergence list is logged before the non-zero exit." // CloneVerifyCmdFaithfulExitCode is the process exit code used // when --verify-cmd-faithful-exit-on-mismatch trips. Distinct from // 1 (runtime failure) and 2 (bad CLI usage) so CI scripts can // branch on "the code is wrong" vs "git failed" vs "I invoked it // wrong" without parsing stderr. CloneVerifyCmdFaithfulExitCode = 3 // FlagClonePrintArgv is the shared boolean flag name used by every // clone-related command to dump the exact argv tokens that would // be passed to exec.Command. Companion to --verify-cmd-faithful: // the verifier proves displayed==executed, this flag SHOWS the // executed form so users can paste it elsewhere or grep one token // at a time without re-quoting the cmd: string. FlagClonePrintArgv = "print-clone-argv" // FlagDescClonePrintArgv explains the flag in --help. Wording // calls out the format (one token per line, prefixed `argv[i]=`) // and the stream (stderr, not stdout) so users redirecting the // terminal block to a file aren't surprised by extra noise. FlagDescClonePrintArgv = "Print the exact git-clone argv tokens " + "to stderr (one per line, `argv[i]=<token>`) right after each " + "terminal block. Audit-only — does not change clone behavior." // MsgCloneVerifyCmdFaithfulExit is the one-line stderr summary // printed immediately before the process exits with // CloneVerifyCmdFaithfulExitCode. Phrased as a single sentence so // CI UIs that surface the LAST stderr line as the failure reason // produce a self-explanatory headline. MsgCloneVerifyCmdFaithfulExit = "verify-cmd-faithful: FAIL - " + "one or more cmd: lines did not match the executor's argv " + "(see per-row reports above); exiting with code 3 because " + "--verify-cmd-faithful-exit-on-mismatch was set" // CmdFaithfulReportSeverityTag is the severity prefix used on every // line of a mismatch report. Picked to be unambiguous in CI logs: // "[FAIL]" reads as a real failure even when the surrounding // context is missing (e.g. log truncation, single-line scrapers). // Paired with CmdFaithfulReportTestPrefix so test-emitted reports // can be visually separated from production-emitted ones. CmdFaithfulReportSeverityTag = "[FAIL]" // gitmap:cmd skip // CmdFaithfulReportHeaderFmt is the multi-arg format string for // the report banner. Order: severity tag, repo name, divergence // count, exit-flag hint. The trailing hint tells the reader which // CLI flag would turn the report into a hard failure — without it, // users routinely ask "did this fail the build?" when the answer // depends on whether --verify-cmd-faithful-exit-on-mismatch was // passed. Verb tense is past ("did not match") to match the // printed report's role as a post-hoc diagnostic. CmdFaithfulReportHeaderFmt = "%s verify-cmd-faithful: %s — " + "%d divergence(s); displayed cmd: did not match executor argv " + "(non-fatal unless --verify-cmd-faithful-exit-on-mismatch is set)\n" // CmdFaithfulReportTestPrefix wraps a mismatch report when the // caller is a Go test that INTENTIONALLY drives a divergent input // to exercise the printer. Without this banner, a successful // `go test ./...` run prints lines that look identical to a real // regression — burying genuine failures and training engineers to // ignore "[FAIL]" in test logs. The matching close-tag below makes // the bracketed region trivially grep-able and easy for humans // scanning a wall of test output. CmdFaithfulReportTestPrefix = "--- expected mismatch (test fixture; " + "not a real failure) ---\n" // CmdFaithfulReportTestSuffix closes the test-fixture banner. Kept // as a separate constant (vs. embedding both in one block) so // callers can wrap multi-line content without string surgery. CmdFaithfulReportTestSuffix = "--- end expected mismatch ---\n" // gitmap:cmd skip )
const ( CmdCloneFixRepo = "clone-fix-repo" CmdCloneFixRepoAlias = "cfr" CmdCloneFixRepoPub = "clone-fix-repo-pub" CmdCloneFixRepoPubAlias = "cfrp" )
gitmap:cmd top-level Clone-fix-repo command IDs and short aliases.
const ( HelpCloneFixRepo = " clone-fix-repo (cfr) <url> [folder] Clone, then run fix-repo --all in the new folder" HelpCloneFixRepoPub = " clone-fix-repo-pub (cfrp) <url> [folder] Clone, fix-repo --all, then make-public --yes" )
Clone-fix-repo help-line entries surfaced by `gitmap help`.
const ( MsgCloneFixRepoDone = "clone-fix-repo: pipeline completed in %s\n" ErrCloneFixRepoUsage = "" /* 139-byte string literal not displayed */ ErrCloneFixRepoChdirFmt = "clone-fix-repo: ERROR cannot cd into %q: %v\n" ErrCloneFixRepoExecFmt = "clone-fix-repo: ERROR could not run chained step: %v\n" )
Clone-fix-repo user-facing messages and errors.
const ( ExitCloneFixRepoOk = 0 ExitCloneFixRepoBadFlag = 6 ExitCloneFixRepoChdir = 9 ExitCloneFixRepoChainFailed = 10 )
Clone-fix-repo exit codes.
const ( CmdCloneFrom = "clone-from" CmdCloneFromAlias = "cf" )
CLI surface. CmdCloneFrom and CmdCloneFromAlias are referenced from the dispatcher (rootcore.go) and the completion generator (which scans the const block for the `// gitmap:cmd top-level` marker — preserve that comment when reorganizing).
const ( FlagCloneFromExecute = "execute" FlagDescCloneFromExecute = "Actually run git clone (default: dry-run only)" FlagCloneFromQuiet = "quiet" FlagDescCloneFromQuiet = "Suppress per-row progress lines (summary still prints)" FlagCloneFromNoReport = "no-report" FlagDescCloneFromNoReport = "Skip writing the .gitmap/clone-from-report-*.csv file" // FlagCloneFromOutput selects the dry-run / per-row format. // "default" preserves the legacy 4-line block (url/dest/branch/ // depth). "terminal" emits the standardized RepoTermBlock used // across scan/clone-next/probe so users get one format regardless // of which command produced the per-repo summary. Wording mirrors // FlagDescCloneTermOutput so the stdout-vs-stderr split is the // same sentence across every clone command. FlagCloneFromOutput = "output" FlagDescCloneFromOutput = "Per-row format: 'default' (legacy 4-line block) " + "or 'terminal' (standardized branch/from/to/command block on " + "stdout, streamed before each clone; git progress stays on stderr)" // FlagCloneFromCheckout sets the GLOBAL default for post-clone // working-tree behavior. Per-row `checkout` (JSON/CSV column) // overrides this. Modes: "auto" (default — git clone materializes // the working tree), "skip" (passes --no-checkout, no working // tree), "force" (explicit `git checkout <branch>` after clone, // fails the row on missing branch / detached-HEAD-with-no-target). FlagCloneFromCheckout = "checkout" FlagDescCloneFromCheckout = "Default per-row checkout mode " + "('auto' | 'skip' | 'force'). Per-row 'checkout' field " + "overrides this. 'skip' uses --no-checkout. 'force' runs " + "git checkout after clone and fails missing-branch rows." )
Flag names + descriptions. Flag names are the long form only; short flags are deliberately avoided here because `-e` could collide with future global flags (the existing flag conventions in gitmap reserve single-letter flags for very-frequent operations).
const ( CloneFromCheckoutAuto = "auto" CloneFromCheckoutSkip = "skip" CloneFromCheckoutForce = "force" // CloneFromCheckoutDefault is the project-wide default applied // when neither the global flag nor the row specifies one. CloneFromCheckoutDefault = CloneFromCheckoutAuto )
Checkout-mode enum. Stable strings — emitted in error/detail messages and accepted verbatim from the JSON/CSV `checkout` field.
const ( CloneFromStatusOK = "ok" CloneFromStatusSkipped = "skipped" CloneFromStatusFailed = "failed" )
Status enum strings. Stable: emitted to the CSV report which downstream tools may parse. Renaming any of these is a breaking change for those consumers.
const ( // %s = source path, %s = format ("json"|"csv"), %d = row count. MsgCloneFromDryHeader = "gitmap clone-from: dry-run\n" + "source: %s (%s)\n" + "%d row(s) -- pass --execute to actually clone\n\n" // %d ok, %d skipped, %d failed, %d total. MsgCloneFromSummaryHeader = "\ngitmap clone-from: %d ok, %d skipped, %d failed (%d total)\n" MsgCloneFromDestExists = "dest exists" MsgCloneFromMissingArg = "clone-from: <file> argument is required (e.g. clone-from repos.csv)" )
User-facing messages. Format strings include trailing newlines so the call site doesn't need to remember to add them. Header formats end in a blank line to visually separate from the per-row block.
const ( // %s = path, %v = err. ErrCloneFromAbsPath = "clone-from: resolve path %s: %v" ErrCloneFromOpen = "clone-from: open %s: %v" // %v = err. ErrCloneFromJSONDecode = "clone-from: decode JSON: %v" // %d = 1-indexed row, %v = err. ErrCloneFromJSONRow = "clone-from: row %d: %v" // %v = err. ErrCloneFromCSVHeader = "clone-from: read CSV header: %v" ErrCloneFromCSVNoURL = "clone-from: CSV header is missing required column 'url'" // %d = row number including header, %v = err. ErrCloneFromCSVRow = "clone-from: CSV row %d: %v" // %d = row number including header, %s = column name, %v = err. // Used when a row failure is attributable to a specific column so // the operator can jump straight to the offending cell instead of // re-reading the whole row to guess which field tripped validation. ErrCloneFromCSVRowCol = "clone-from: CSV row %d, column %q: %v" // %s = bad depth string. ErrCloneFromBadDepth = "depth %q is not a valid integer" ErrCloneFromEmptyURL = "url is empty after trim" // %s = url. ErrCloneFromBadURL = "url %q does not look like a git URL " + "(expected https://, http://, ssh://, git://, file://, or scp-style host:path)" // %d = bad depth. ErrCloneFromNegDepth = "depth %d is negative" // CloneFromDepthFlagFmt is the SINGLE source of truth for how // clone-from renders its shallow-clone flag, both in the executed // argv (clonefrom/execute.go buildGitArgs) and in every // human-facing preview (render.go cloneCommandForRow + cmd/ // clonetermrow.go printCloneFromTermBlockRow). The joined form // (`--depth=N`) is intentional — it matches what the executor // hands to exec.Command exactly, so the printed cmd: line in the // terminal block is byte-faithful and the --verify-cmd-faithful // checker has zero false positives. Do NOT switch to the split // form (`--depth N`) without updating ALL three sites + the // golden fixture in cmd/testdata/clonetermblock_clonefrom.golden // + TestCloneFromDepthFlagFormat_Locked. // %d = depth. CloneFromDepthFlagFmt = "--depth=%d" // %s = directory, %v = err. ErrCloneFromReportMkdir = "clone-from: mkdir %s: %v" // %s = file path, %v = err. ErrCloneFromReportCreate = "clone-from: create report %s: %v" // ErrCloneFromReportMissingFields is surfaced when one or more // rows in the result set are missing a field required to // produce a useful report (URL, Dest, or Status). Listing each // offending row index keeps the message actionable: the user // can correlate the index with the manifest or with the // progress lines printed during Execute. // %d = count of bad rows, %s = comma-separated row indices, // %s = comma-separated missing-field summary per row. ErrCloneFromReportMissingFields = "clone-from: refusing to write report -- " + "%d row(s) missing required fields: rows=[%s] missing=[%s]" // CloneFromReportFieldURL / Dest / Status are the canonical // names the validator emits in the missing-field summary. Kept // as constants so the integration test can assert against them // without re-hardcoding the words. CloneFromReportFieldURL = "url" CloneFromReportFieldDest = "dest" CloneFromReportFieldStatus = "status" // MsgCloneFromMkdirParentFailFmt is the per-row Detail string set // when MkdirAll on the dest's parent dir fails (permission, // read-only FS). Single source of truth so the report column and // the per-row progress line stay byte-identical. // %v = err. MsgCloneFromMkdirParentFailFmt = "mkdir parent: %v" // ErrCloneFromMkdirParent is the standardized stderr log emitted // alongside the per-row failure. Follows the project's Code Red // format: Error: ... at <path>: <err> (operation: ..., reason: ...). // %s = parent path, %v = err. ErrCloneFromMkdirParent = "Error: clone-from: failed to create dest parent at %s: %v " + "(operation: MkdirAll, reason: cannot preserve folder hierarchy)\n" // ErrCloneFromBadCheckout fires at parse time when the row's // `checkout` field is set to anything other than auto/skip/force. // %q = bad value. ErrCloneFromBadCheckout = "checkout %q is not one of 'auto', 'skip', 'force'" // MsgCloneFromBranchMissingFmt is the per-row Detail when // checkout=force is configured AND `git checkout <branch>` fails // because the branch doesn't exist on the cloned remote (typical // cause: typo in row.Branch). The string is short — full git // stderr already streamed live during the clone. // %s = branch name. MsgCloneFromBranchMissingFmt = "branch missing on remote: %s" // ErrCloneFromCheckoutFailed is the standardized stderr Code Red // log emitted alongside the per-row failure when post-clone // checkout fails. Mirrors ErrCloneFromMkdirParent format so the // stderr surface is uniform across executor failure modes. // %s = dest, %s = branch, %v = err. ErrCloneFromCheckoutFailed = "Error: clone-from: post-clone checkout failed at %s for branch %q: %v " + "(operation: git checkout, reason: branch missing on remote or detached HEAD without target)\n" // MsgCloneFromBadCheckoutFlag is the user-facing message when the // CLI --checkout flag is given an invalid value. Caller-friendly // message (vs. the parse-time ErrCloneFromBadCheckout used for // row-level errors). %s = bad value. MsgCloneFromBadCheckoutFlag = "clone-from: --checkout %q is not one of 'auto', 'skip', 'force'" // CloneFromNoCheckoutFlag is the literal git flag passed in // `--no-checkout` mode. Centralized so the executor and the // preview renderer agree byte-for-byte (preserves the // --verify-cmd-faithful invariant the depth flag set up). CloneFromNoCheckoutFlag = "--no-checkout" )
Errors. All use printf-style verbs documented inline.
const ( CSVColumnURL = "url" CSVColumnDest = "dest" CSVColumnBranch = "branch" CSVColumnDepth = "depth" CSVColumnCheckout = "checkout" // ErrCloneFromBadBranch fires at parse time for branch values // that are unambiguously invalid (leading dash → would be parsed // as a git flag; whitespace or control characters → cannot be a // real ref). Catching these at parse time surfaces the failure // with row + column context instead of as an opaque `git // checkout` error mid-clone. Stricter ref-name rules (no '..', // no '@{', etc.) are deliberately left to git itself. // %s = bad branch value. ErrCloneFromBadBranch = "branch %q is not a valid git ref name " + "(must not be empty after trim, contain whitespace, " + "start with '-', or contain control characters)" )
const ( ProvenanceStageScan = "scan" ProvenanceStageMapper = "mapper" ProvenanceStageClonefrom = "clonefrom" )
Provenance map for the JSON report envelope. Documents which pipeline stage populates each row-level field, so downstream consumers (audit dashboards, CI gates, debugging tools) can answer "where did this value come from?" without reading source.
Stages — stable strings, treat as enum:
ProvenanceStageScan — value flowed in from the user-provided
input file (JSON/CSV row); clone-from
never modifies it.
ProvenanceStageMapper — value was derived inside clonefrom's
pre-execute resolver (e.g. Dest after
DeriveDest fallback when Row.Dest is
empty).
ProvenanceStageClonefrom — value was set during execute (Status,
Detail, DurationSeconds — all written
by executeRow / runGitClone).
The map itself is a SLICE OF PAIRS (not a Go map) so the emit order is stable across runs without relying on encoding/json's alphabetical key sort. Field names match reportRowJSON's JSON tags one-for-one; a drift is caught by TestProvenance_CoversEveryReportField.
const ( // FlagCloneFromEmitSchema is the long-form flag; values are // validated against EmitSchemaKind* below. Empty string = flag // absent = normal clone-from operation. FlagCloneFromEmitSchema = "emit-schema" FlagDescCloneFromEmitSchema = "Emit a JSON Schema (draft 2020-12) " + "to stdout and exit 0. Kinds: 'report' (clone-from JSON " + "report envelope) or 'input' (accepted clone-now scan-record " + "input array). Use to validate exported manifests in CI." // EmitSchemaKindReport documents the JSON Schema for the // .gitmap/clone-from-report-<unixts>.json envelope produced by // clonefrom.WriteReportJSON. Tracks CloneFromReportSchemaVersion. EmitSchemaKindReport = "report" // EmitSchemaKindInput documents the JSON Schema for the array of // scan records accepted by `gitmap clone <file>` (the clone-now // path). Mirrors clonenow.knownScanFields. EmitSchemaKindInput = "input" // MsgCloneFromEmitSchemaUnknown is the user-facing error when an // unrecognized --emit-schema value is passed. %q = bad value. MsgCloneFromEmitSchemaUnknown = "clone-from: --emit-schema %q is not one of 'report', 'input'" // $id base for emitted schemas. Versioned URL scheme so a future // breaking change publishes under a new path. Not network-fetched // by gitmap itself; consumers may resolve it for documentation. CloneFromSchemaIDReport = "https://gitmap.dev/schema/clone-from-report-v3.json" CloneFromSchemaIDInput = "https://gitmap.dev/schema/clone-now-input-v1.json" // JSONSchemaDialect2020_12 is the canonical $schema URI emitted at // the top of every gitmap-produced JSON Schema. Centralized so a // future dialect bump is a one-line change. JSONSchemaDialect2020_12 = "https://json-schema.org/draft/2020-12/schema" )
const ( CloneFromSchemeHTTPS = "https" CloneFromSchemeHTTP = "http" CloneFromSchemeSSH = "ssh" CloneFromSchemeGit = "git" CloneFromSchemeFile = "file" CloneFromSchemeSCP = "scp" CloneFromSchemeOther = "other" )
URL scheme labels — surfaced in the per-mode tally. Stable strings: renaming would break any downstream tooling that greps the terminal summary. "scp" covers the `[user@]host:path` form that validate.go's looksLikeSCP accepts.
const ( MsgCloneNextCloning = "Cloning %s into %s...\n" MsgCloneNextCreating = "Creating GitHub repo %s...\n" MsgCloneNextCreated = "✓ Created GitHub repo %s\n" MsgCloneNextDone = "✓ Cloned %s\n" MsgCloneNextDesktop = "✓ Registered %s with GitHub Desktop\n" MsgCloneNextRemovePrompt = "Remove current folder %s? [y/N] " MsgCloneNextRemoved = "✓ Removed %s\n" MsgCloneNextMovedTo = "→ Now in %s\n" MsgFlattenFallback = "→ Falling back to versioned folder %s (current folder is locked by this shell)\n" MsgFlattenLockedHint = " Tip: 'cd ..' out of %s in your shell, then re-run to flatten — or pass -f to force.\n" // MsgForceReleasing is printed by `cn -f` BEFORE the chdir-to-parent // trick that releases the Windows file lock on the cwd. Telling the // user "I'm leaving X" up front keeps the subsequent removal log // from looking like an unrelated jump. MsgForceReleasing = " → Stepping out of %s to release the file lock\n" // Stage-banner messages emitted by `cn` to group the output into // three clear phases (PREPARE → CLONE → FINALIZE). Plain ASCII rule // glyphs so PowerShell renders them identically to bash. MsgCNStagePrepare = "\n ── 1/3 Preparing flatten (%s → %s) ──\n" MsgCNStageClone = "\n ── 2/3 Cloning %s ──\n" MsgCNStageFinalize = "\n ── 3/3 Finalizing ──\n" MsgCNDone = "\n ── ✓ Done — now in %s ──\n\n" )
Clone-next command messages.
const ( ErrCloneNextUsage = "Usage: gitmap clone-next <v++|vN> [flags]" ErrCloneNextCwd = "Error: cannot determine current directory: %v\n" ErrCloneNextNoRemote = "Error: not a git repo or no remote origin: %v\n" ErrCloneNextBadVersion = "Error: %v\n" ErrCloneNextExists = "Error: target directory already exists: %s\nUse 'cd' to switch to it.\n" ErrCloneNextFailed = "Error: clone failed for %s\n" ErrCloneNextRemoteParse = "Error: cannot parse remote URL: %v\n" ErrCloneNextRepoCheck = "Error: cannot check target repo: %v\n" ErrCloneNextRepoCreate = "Error: cannot create GitHub repo %s: %v\n" WarnCloneNextRemoveFailed = "Warning: could not remove %s: %v\n" // ErrCloneNextForceFailed fires when -f / --force was passed but // the existing flattened folder still cannot be removed (e.g. a // non-shell process holds a handle on it). We refuse the silent // versioned-folder fallback here — the user explicitly asked for // a flat layout, so a clear error beats a surprise rename. ErrCloneNextForceFailed = "Error: --force could not remove %s: %v\nClose any process holding files in %s and re-run.\n" )
Clone-next error and warning messages.
const ( FlagDescCloneNextDelete = "Auto-remove current folder after clone" FlagDescCloneNextKeep = "Keep current folder without prompting" FlagDescCloneNextNoDesktop = "Skip GitHub Desktop registration" FlagDescCloneNextCreateRemote = "Create target GitHub repo if it does not exist (requires GITHUB_TOKEN)" FlagDescCloneNextCSV = "Read repo paths from CSV file (one path per row, header optional)" FlagDescCloneNextAll = "Walk current folder and run cn on every git repo found one level deep" FlagDescCloneNextForce = "Force flatten even when cwd is the target folder (chdir to parent, no versioned fallback)" // FlagCloneNextOutput selects the human summary format. Empty // (default) keeps the legacy terse stage messages. "terminal" // additionally emits the standardized RepoTermBlock (branch, // from, to, command) right before the clone runs so users get // the same per-repo summary shape as scan/clone-from/probe. FlagCloneNextOutput = "output" FlagDescCloneNextOutput = "Per-repo summary format: '' (legacy) or 'terminal' (standardized branch/from/to/command block)" )
Clone-next flag descriptions.
const ( HelpCloneNextFlags = "Clone-Next Flags:" HelpCNDelete = " --delete Auto-remove current version folder after clone" HelpCNKeep = " --keep Keep current folder without prompting for removal" HelpCNNoDesktop = " --no-desktop Skip GitHub Desktop registration" HelpCNSSHKey = " --ssh-key, -K SSH key name to use for clone" HelpCNVerbose = " --verbose Show detailed clone-next output" HelpCNCreateRemote = " --create-remote Create target GitHub repo if missing (needs GITHUB_TOKEN)" HelpCNCSV = " --csv <path> Batch mode: read repo list from CSV (one path per row)" HelpCNAll = " --all Batch mode: cn every git repo one level under cwd" HelpCNForce = " --force, -f Force flatten when cwd IS the target folder (no versioned fallback)" HelpCNMaxConc = " --max-concurrency N Batch mode: run up to N repos in parallel (1 = sequential, default)" )
Clone-next help strings for usage output.
const ( MsgCloneNextBatchStart = "→ Batch cn over %d repo(s)\n" MsgCloneNextBatchRepo = " • %s: %s -> %s\n" MsgCloneNextBatchUpToDate = " • %s: %s (no update needed)\n" MsgCloneNextBatchSummary = "✓ Batch complete: %d ok, %d failed, %d skipped\n" MsgCloneNextBatchReport = " Report: %s\n" WarnCloneNextBatchReport = "Warning: could not write batch report: %v\n" ErrCloneNextBatchLoad = "Error: could not load batch input: %v\n" BatchStatusOK = "ok" BatchStatusFailed = "failed" BatchStatusSkipped = "skipped" // BatchDetailUpToDate is the row's `detail` field when the local // repo's version equals the highest existing remote sibling. BatchDetailUpToDate = "no update needed" // Real-time batch progress lines (v3.124.0+). Printed once per // repo as workers finish, regardless of pool size, so users get // live "X/Y done (ok=A failed=B skipped=C)" feedback during // long batch runs instead of the previous all-or-nothing // behavior where stdout went silent until every repo finished. // // Format choice: newline-per-update (no `\r` rewriting). Works // uniformly in TTY, redirected log files, and CI captures — // matches how scan's background-probe progress prints. MsgCloneNextBatchProgressFmt = " ▸ [%d/%d] %s — %s (ok=%d failed=%d skipped=%d)\n" // FlagCloneNextNoProgress and FlagDescCloneNextNoProgress // suppress the live per-repo progress line. The final summary // is always printed. FlagCloneNextNoProgress = "no-progress" FlagDescCloneNextNoProgress = "Suppress live per-repo progress lines (final summary still prints)" // FlagCloneNextDryRun, when set, prints every `git clone` command // `gitmap cn` would execute (single-repo AND batch modes) and // EXITS before any side-effect runs: no clone, no folder removal, // no GitHub Desktop registration, no VS Code launch, no shell // handoff, no DB version-history write. Intended for previewing // what `cn` will do — especially handy after `--all` / `--csv` // expansions that fan out across many repos. FlagCloneNextDryRun = "dry-run" FlagDescCloneNextDryRun = "Print the git clone commands that would run, then exit (no side effects)" // MsgCloneNextDryRunCmd is the per-clone preview line. Format: // " → <gitBin> clone <url> <dest>" — kept terse so a long --all // run stays scannable, prefixed with the same arrow other cn // stage messages use for visual consistency. MsgCloneNextDryRunCmd = " → %s %s %s %s\n" // MsgCloneNextDryRunHeader prints once at the start of dry-run // mode so users can't miss that NOTHING will actually happen. MsgCloneNextDryRunHeader = "🔍 dry-run mode — printing planned clone commands, no changes will be made:\n" // previewed commands print. Includes the count for quick sanity. MsgCloneNextDryRunFooter = "\n✓ dry-run complete — %d clone command(s) previewed. Re-run without --dry-run to execute.\n" )
Clone-next batch mode messages and statuses (v3.42.0+).
const ( CmdCloneReclone = "reclone" CmdCloneRecloneAlias = "rec" CmdCloneNow = "clone-now" CmdCloneNowAlias = "cnow" CmdCloneRel = "relclone" CmdCloneRelAlias = "rc" )
CLI surface — canonical name + backward-compat aliases.
CmdCloneReclone ("reclone") is the CANONICAL verb as of v3.x. It was renamed from clone-now so the CLI vocabulary makes the split between the two clone families unambiguous:
- `gitmap clone <url>` — fresh clone from a URL.
- `gitmap reclone <file>` — RE-clone from a scan artifact (round-trip the recorded RelativePath layout).
All four legacy spellings are kept as aliases so existing scripts keep working forever:
- clone-now / cnow — original name (v3.161.0).
- relclone / rc — earlier explicit "re-clone" alias.
The dispatcher in rootcore.go binds every spelling to runCloneNow. The completion generator picks them up via the `// gitmap:cmd top-level` marker on this const block.
const ( FlagCloneNowExecute = "execute" FlagDescCloneNowExecute = "Actually run git clone (default: dry-run only)" FlagCloneNowQuiet = "quiet" FlagDescCloneNowQuiet = "Suppress per-row progress lines (summary still prints)" // FlagCloneNowMode picks which URL column to use when the input // supplies both. Values: "https" (default) | "ssh". When the // requested mode is missing on a given row we fall back to the // other one rather than skipping the row -- the user's intent is // "clone these repos now", not "clone only the ones that have // the preferred URL shape". FlagCloneNowMode = "mode" FlagDescCloneNowMode = "URL mode to clone with: 'https' (default) or 'ssh'. " + "Falls back to the other mode if the preferred URL is missing on a row." // FlagCloneNowFormat lets the caller force the input format when // the file extension is missing or wrong (e.g., `repos.out`). // Values: "" (auto from extension) | "json" | "csv" | "text". FlagCloneNowFormat = "format" FlagDescCloneNowFormat = "Force input format: '' (auto from extension), 'json', 'csv', or 'text'." // FlagCloneNowCwd sets the working directory clones run in. // Empty (default) = the current process cwd. Honored as-is so // that scripts can re-create a tree under a fresh root with // `gitmap clone-now scan.json --cwd ./mirror --execute`. FlagCloneNowCwd = "cwd" FlagDescCloneNowCwd = "Working directory for git clone (default: current dir)." // FlagCloneNowOnExists controls re-clone behavior when the // destination already contains a git repo. Default "skip" keeps // the historical no-op behavior. "update" runs fetch + checkout // without destroying local work. "force" removes the directory // and re-clones from scratch -- destructive, opt-in only. FlagCloneNowOnExists = "on-exists" FlagDescCloneNowOnExists = "Behavior when target already exists: " + "'skip' (default, no-op when repo+branch match), " + "'update' (fetch + checkout to align with the planned URL/branch), " + "'force' (remove target and re-clone -- destructive)." // FlagCloneNowManifest is the unified, explicit-path alias for the // positional <file> argument. Accepts a JSON or CSV produced by // `gitmap scan`; format is auto-detected from the extension (use // --format to override). Precedence: // 1. --manifest <path> (explicit, highest priority) // 2. positional <file> (legacy positional form) // 3. auto-pickup (./.gitmap/output/gitmap.{json,csv}) // Passing BOTH --manifest and a positional file is a usage error // (exit 2) so the run is unambiguous. FlagCloneNowManifest = "manifest" FlagDescCloneNowManifest = "Path to a scan artifact (JSON or CSV) to consume. " + "Format auto-detected from the extension. Equivalent to the positional " + "<file> argument; when omitted, auto-pickup under ./.gitmap/output/ is used." // FlagCloneNowScanRoot redirects auto-pickup to probe // `<scan-root>/.gitmap/output/` instead of `./.gitmap/output/`. // Useful when running `reclone` from a different directory than // the one originally scanned (e.g. CI scripts, scheduled jobs). // Ignored when --manifest or a positional <file> is supplied // (those are explicit paths and don't need a root to resolve). FlagCloneNowScanRoot = "scan-root" FlagDescCloneNowScanRoot = "Directory to auto-pickup the scan manifest from " + "(probes <scan-root>/.gitmap/output/gitmap.{json,csv}). " + "Defaults to the current directory. Ignored when --manifest or a positional <file> is given." // FlagCloneNowYes bypasses the pre-flight existing-destinations // confirmation prompt. The prompt only fires on --execute when // at least one row's RelativePath already exists on disk; the // per-row --on-exists policy still decides what actually happens // to those existing dirs (skip / update / force). --yes is the // scripting / CI escape hatch and is mandatory in non-TTY runs // because there's no stdin to read a confirmation from. FlagCloneNowYes = "yes" FlagDescCloneNowYes = "Skip the pre-flight confirmation when destination folders already exist " + "(required for non-interactive / CI runs). The --on-exists policy still applies per row." // FlagCloneNowNoSummary suppresses the pre-execute summary // (totals + destination-folder tree) printed before the safety // prompt. Useful for terse CI logs where the dry-run preview // has already been printed in a previous step. FlagCloneNowNoSummary = "no-summary" FlagDescCloneNowNoSummary = "Suppress the pre-execute summary " + "(row totals + destination folder tree) shown before the safety prompt." )
Flag names + descriptions. Long-form only; short flags are reserved for very-frequent operations per the project convention.
const ( // %s = manifest path, %d = bad-row count, %d = total rows. MsgRecloneValidateHeaderFmt = "reclone: manifest validation failed for %s\n" + " %d issue(s) across %d row(s):\n" // %d = 1-based row index, %s = repo name (or "<unnamed>"), // %s = dest (or "<empty>"), %s = reason phrase. MsgRecloneValidateRowFmt = " - row %d repo=%s dest=%s -- %s\n" // the run was aborted before any side effects occurred. MsgRecloneValidateFooter = "reclone: aborted; fix the manifest and re-run " + "(no clones were attempted)\n" // Per-row reason phrases. Stable identifiers — do not rephrase // without bumping the test fixtures and CHANGELOG. MsgRecloneValidateMissingRepoName = "missing RepoName" MsgRecloneValidateNoURL = "no HTTPSUrl or SSHUrl set" MsgRecloneValidateMalformedURL = "URL is not a valid git URL " + "(expected scheme://host/path or user@host:path)" MsgRecloneValidateMissingDest = "missing RelativePath" MsgRecloneValidateAbsoluteDest = "RelativePath must be relative, not absolute" MsgRecloneValidateTraversalDest = "RelativePath escapes the working dir via '..'" // Placeholders for empty fields in the report table. MsgRecloneValidateUnnamedRepo = "<unnamed>" MsgRecloneValidateEmptyDest = "<empty>" )
Manifest validation messages. All printed to stderr by the pre-flight validator in reclone_validate.go. Phrases are stable so tests + shell scripts can grep them, and short so the row table stays scannable in an 80-column terminal.
const ( CloneNowOnExistsSkip = "skip" CloneNowOnExistsUpdate = "update" CloneNowOnExistsForce = "force" )
On-exists policy enum strings. Stable: surfaced in --on-exists, the dry-run header, and the per-row Result.Detail field. Renaming is a breaking change for shell scripts that grep these values.
const ( CloneNowModeHTTPS = "https" CloneNowModeSSH = "ssh" )
Mode enum strings. Stable: surfaced in the dry-run header and the per-row progress lines.
const ( CloneNowFormatJSON = "json" CloneNowFormatCSV = "csv" CloneNowFormatText = "text" )
Format enum strings. The "auto" empty value is intentionally not exported because callers detect it via len(format)==0.
const ( CloneNowStatusOK = "ok" CloneNowStatusSkipped = "skipped" CloneNowStatusFailed = "failed" )
Status enum strings. Mirrors clone-from for cross-tool grep-ability: downstream pipelines that already filter on "ok"/"skipped"/"failed" keep working without a status-name translation table.
const ( // %s = source path, %s = format, %s = mode, %d = row count. MsgCloneNowDryHeader = "gitmap clone-now: dry-run\n" + "source: %s (%s, mode=%s)\n" + "%d row(s) -- pass --execute to actually clone\n\n" // %d ok, %d skipped, %d failed, %d total. MsgCloneNowSummaryHeader = "\ngitmap clone-now: %d ok, %d skipped, %d failed (%d total)\n" MsgCloneNowDestExists = "dest exists" MsgCloneNowMissingArg = "reclone: <file> argument is required and " + "no scan artifact was found under ./.gitmap/output/ " + "(looked for gitmap.json then gitmap.csv). " + "Run `gitmap scan` first, or pass an explicit path " + "(e.g. reclone .gitmap/output/gitmap.json)." // %s = scan-root value. Variant of MsgCloneNowMissingArg used // when the user explicitly requested auto-pickup from a custom // root via --scan-root and that root yielded no artifact — // echoing the path back makes the typo / wrong-dir case obvious. MsgCloneNowMissingArgScanRoot = "reclone: no scan artifact was found under " + "%s/.gitmap/output/ (looked for gitmap.json then gitmap.csv). " + "Run `gitmap scan` against that root first, or pass --manifest / a positional <file>." // %s = auto-discovered manifest path. Printed to stderr when // reclone is invoked with no <file> arg and a scan artifact is // found in the conventional location. Lets users see exactly // which file fed the run instead of guessing. MsgCloneNowAutoPickup = "reclone: using scan artifact %s (auto-discovered; pass an explicit path to override)\n" // %s = positional file, %s = --manifest value. Printed when the // caller supplies BOTH forms — refusing is safer than silently // preferring one and having the run consume the wrong artifact. MsgCloneNowManifestConflict = "reclone: cannot combine positional <file> %q with --manifest %q; pass only one\n" // %d = total existing dirs, %s = on-exists policy. Header // printed before the bullet list of existing destinations. // %s = source path, %s = format, %s = mode, %s = on-exists, // %s = resolved cwd. Top banner of the pre-execute summary. MsgCloneNowSummaryHeaderFmt = "\nreclone: pre-execute summary\n" + " source : %s (%s)\n" + " mode : %s\n" + " on-exists : %s\n" + " cwd : %s\n" // %d = total rows, %d = new dirs, %d = existing dirs. MsgCloneNowSummaryCountsFmt = " rows : %d total (%d new, %d already exist)\n" // Section title for the destination folder tree. MsgCloneNowSummaryTreeTitle = " destinations:\n" // %s = tree-formatted line (already includes the leading // indent + branch glyph). One line per visible destination. MsgCloneNowSummaryTreeLineFmt = " %s\n" // %d = number of dirs not shown. MsgCloneNowSummaryTreeTruncFmt = " ... and %d more\n" MsgCloneNowConfirmHeader = "reclone: %d destination folder(s) already exist on disk " + "(--on-exists=%s will be applied to each):\n" // %s = relative path. One bullet per existing destination, up // to CloneNowExistingPreviewLimit rows. MsgCloneNowConfirmBullet = " - %s\n" // %d = number of dirs not shown. MsgCloneNowConfirmTruncated = " ... and %d more\n" // Final prompt line. The trailing space (no newline) keeps the // cursor on the prompt line for the user's response. MsgCloneNowConfirmPrompt = "Proceed with `git clone` against these destinations? [y/N]: " // Printed (stderr) when the user declines. Exit code follows. MsgCloneNowConfirmAborted = "reclone: aborted by user; no clones were performed\n" // Printed (stderr) when --execute lands in a non-TTY context // with existing destinations and no --yes. Tells the user // exactly which flag would unblock the run. MsgCloneNowConfirmNonTTY = "reclone: refusing to proceed -- destinations already exist " + "and stdin is not a TTY; pass --yes to confirm non-interactively\n" MsgCloneNowNoURL = "no url for selected mode" // Idempotency / re-clone messages. Each lands in Result.Detail // so the per-row summary tells the user exactly which branch // of the on-exists policy fired. The mismatch + fail messages // take printf args -- documented per-line. MsgCloneNowAlreadyMatches = "already matches (url + branch)" MsgCloneNowNotARepo = "dest exists but is not a git repo" // %s = current remote, %s = expected remote. MsgCloneNowURLMismatch = "skipped: remote url differs (have=%s, want=%s)" // %s = current branch, %s = expected branch. MsgCloneNowBranchMismatch = "skipped: branch differs (have=%s, want=%s)" MsgCloneNowUpdated = "updated (fetch + checkout)" MsgCloneNowForceRecloned = "force-recloned (previous dir removed)" // %s = path, %v = err. MsgCloneNowForceRemoveFail = "force: remove %s: %v" // %s = trimmed git stderr. MsgCloneNowFetchFail = "update: git fetch failed: %s" // %s = branch, %s = trimmed git stderr. MsgCloneNowCheckoutFail = "update: git checkout %s failed: %s" )
User-facing messages. Trailing newlines are baked in so call sites don't need to remember them.
const ( // %s = path, %v = err. ErrCloneNowAbsPath = "clone-now: resolve path %s: %v" ErrCloneNowOpen = "clone-now: open %s: %v" // %v = err. ErrCloneNowJSONDecode = "clone-now: decode JSON: %v" ErrCloneNowCSVRead = "clone-now: read CSV: %v" ErrCloneNowTextRead = "clone-now: read text: %v" // %s = bad value. ErrCloneNowBadMode = "clone-now: --mode must be 'https' or 'ssh', got %q" ErrCloneNowBadFormat = "clone-now: --format must be 'json', 'csv', or 'text', got %q" ErrCloneNowBadOnExists = "clone-now: --on-exists must be 'skip', 'update', or 'force', got %q" // %s = file extension (with leading dot, or "" when missing), // %s = path. Emitted when auto-detect cannot map the file // extension to a supported format. Use --format to override. ErrCloneNowUnsupportedExt = "clone-now: unsupported file extension %q for %s; " + "supported extensions are .json, .csv, .txt (or pass --format json|csv|text)" // %s = path. ErrCloneNowEmpty = "clone-now: %s contains zero clonable rows" // Schema validation errors. Run BEFORE the tolerant // formatter.ParseJSON / formatter.ParseCSV so a typo'd field // name or a wrong-shape input fails loudly instead of producing // silently-empty Rows downstream. Phrases are stable so tests // and shell scripts can grep them. // // %v = decode error from json.Decoder. ErrCloneNowJSONShape = "clone-now: JSON input must be an array of objects: %v" // %d = 1-based row index, %s = actual JSON kind ("string", // "number", "array", "null", etc.). Emitted when the top-level // array is well-formed but one of its elements is not an object. ErrCloneNowJSONRowNotObject = "clone-now: JSON row %d must be an object, got %s" // %d = 1-based row index, %s = unknown field name, %s = sorted // list of all known field names. ErrCloneNowUnknownJSONField = "clone-now: JSON row %d has unknown field %q; " + "known fields: %s" // %d = 1-based row index. Emitted when a row has neither // httpsUrl nor sshUrl set to a non-empty string. ErrCloneNowMissingURL = "clone-now: JSON row %d has neither httpsUrl nor sshUrl set" // Emitted when the CSV file is completely empty (no header). ErrCloneNowEmptyCSV = "clone-now: CSV input is empty (no header row found)" // %s = unknown column name, %s = sorted list of known fields. ErrCloneNowUnknownCSVField = "clone-now: CSV header has unknown column %q; " + "known columns: %s" // Emitted when the CSV header has neither httpsUrl nor sshUrl. ErrCloneNowCSVMissingURLCol = "clone-now: CSV header must include 'httpsUrl' or 'sshUrl'" // %d = 1-based data row number (header is NOT counted; data row // 1 is the first row after the header — matches what a user // inspecting the file in a spreadsheet sees as "row 2"). %v = // underlying csv.Reader error. ErrCloneNowCSVRowRead = "clone-now: CSV data row %d failed to parse: %v" // %d = 1-based data row number. Emitted when a CSV data row has // neither httpsUrl nor sshUrl set to a non-empty value. ErrCloneNowCSVRowMissingURL = "clone-now: CSV data row %d has neither httpsUrl nor sshUrl set" // MsgCloneNowMkdirParentFailFmt is the per-row Detail set when // pre-creating the destination's parent directory fails. Mirrors // the clonefrom equivalent so summary tables read consistently. // %v = err. MsgCloneNowMkdirParentFailFmt = "mkdir parent: %v" // ErrCloneNowMkdirParent is the standardized stderr log emitted // alongside MsgCloneNowMkdirParentFailFmt (Code Red zero-swallow). // %s = parent path, %v = err. ErrCloneNowMkdirParent = "Error: clone-now: failed to create dest parent at %s: %v " + "(check permissions / disk space)\n" )
Errors. All use printf-style verbs documented inline.
const ( CmdClonePick = "clone-pick" CmdClonePickAlias = "cpk" )
gitmap:cmd top-level CLI surface. Both names are referenced by rootcore.go's dispatcher and indirectly by the AST parity test (which requires every Cmd* constant declared under a `gitmap:cmd top-level` block to also appear in topLevelCmds()).
const ( FlagClonePickAsk = "ask" FlagDescClonePickAsk = "Open an interactive tree picker before fetching. " + "Paths supplied on the command line are pre-checked." FlagClonePickName = "name" FlagDescClonePickName = "Optional human label saved with this selection. " + "Reuse later with --replay <name>." FlagClonePickReplay = "replay" FlagDescClonePickReplay = "Re-run a previously saved selection by id or name. " + "When set, <paths> is not required." FlagClonePickBranch = "branch" FlagDescClonePickBranch = "Branch to check out (passed to git clone --branch). " + "Empty (default) lets git use the remote's HEAD." FlagClonePickMode = "mode" FlagDescClonePickMode = "URL form to use when <repo-url> is shorthand " + "(owner/repo): 'https' (default) or 'ssh'." FlagClonePickDepth = "depth" FlagDescClonePickDepth = "Shallow clone depth. 0 = full history (default: 1)." FlagClonePickCone = "cone" FlagDescClonePickCone = "Use sparse-checkout cone mode (faster, folder-only). " + "Auto-disabled when any path looks like a glob or a file." FlagClonePickDest = "dest" FlagDescClonePickDest = "Destination directory. Created if missing. " + "Default: '.' (current directory)." FlagClonePickKeepGit = "keep-git" FlagDescClonePickKeepGit = "Leave the .git directory in <dest>. " + "Set --keep-git=false for a files-only checkout." FlagClonePickDryRun = "dry-run" FlagDescClonePickDryRun = "Print the plan and the git commands without executing. " + "No DB write happens in dry-run mode." FlagClonePickQuiet = "quiet" FlagDescClonePickQuiet = "Suppress per-step progress on stderr." FlagClonePickForce = "force" FlagDescClonePickForce = "Allow non-empty <dest>. Default refuses to clobber." )
Flag names + descriptions. Long-form only; short flags are reserved for very-frequent operations per the project convention.
const ( ClonePickModeHTTPS = "https" ClonePickModeSSH = "ssh" )
Mode enum. Stable: surfaced in dry-run header + DB rows.
const ( // %s = repo url, %s = dest, %s = mode, %s = branch-or-(default), // %d = depth, %s = "cone"/"non-cone", %d = path count. MsgClonePickDryHeader = "gitmap clone-pick: dry-run\n" + "repo: %s\n" + "dest: %s\n" + "mode: %s branch: %s depth: %d sparse: %s\n" + "%d path(s) -- pass without --dry-run to actually clone\n\n" // %s = canonical repo id, %d = selection id, %s = name (or "(unnamed)"). MsgClonePickSaved = "saved selection #%d for %s (%s)\n" // %s = canonical repo id, %d = selection id, %s = name. MsgClonePickReplayed = "replayed selection #%d for %s (%s)\n" MsgClonePickMissingURL = "clone-pick: <repo-url> argument is required" MsgClonePickMissingPaths = "clone-pick: <paths> argument is required " + "(or pass --replay <id|name>)" // %s = bad path. MsgClonePickPathEmpty = "clone-pick: empty path entry in --paths list" MsgClonePickPathAbsolute = "clone-pick: absolute paths are not allowed (%s)" MsgClonePickPathTraversal = "clone-pick: '..' path traversal not allowed (%s)" MsgClonePickPathTooLong = "clone-pick: path exceeds 4096 bytes (%s)" MsgClonePickDestDirty = "clone-pick: <dest> is not empty (use --force to override)" // %s = lookup key. MsgClonePickReplayNotFound = "clone-pick: --replay: no saved selection matches %q" MsgClonePickReplayAmbiguous = "clone-pick: --replay: multiple selections match %q; " + "use --replay <id> to disambiguate" MsgClonePickUserCancelled = "clone-pick: canceled by user" )
User-facing messages. Trailing newlines are baked in so call sites don't need to remember them.
const ( // %s = bad value. ErrClonePickBadMode = "clone-pick: --mode must be 'https' or 'ssh', got %q" // %d = bad value. ErrClonePickBadDepth = "clone-pick: --depth must be >= 0, got %d" // %v = err. ErrClonePickGitClone = "clone-pick: git clone failed: %v" ErrClonePickGitSparseInit = "clone-pick: git sparse-checkout init failed: %v" ErrClonePickGitSparseSet = "clone-pick: git sparse-checkout set failed: %v" ErrClonePickGitCheckout = "clone-pick: git checkout failed: %v" ErrClonePickGitLsTree = "clone-pick: git ls-tree failed: %v" ErrClonePickFsCreateDest = "clone-pick: create dest dir: %v" ErrClonePickFsRemoveDotGit = "clone-pick: remove .git: %v" ErrClonePickDBInsert = "clone-pick: save selection: %v" ErrClonePickDBLookup = "clone-pick: lookup selection: %v" ErrClonePickPickerLaunch = "clone-pick: launch picker: %v" )
Errors. printf-style verbs documented inline.
const ( SQLInsertClonePickSelection = `` /* 179-byte string literal not displayed */ SQLSelectClonePickByID = `` /* 182-byte string literal not displayed */ SQLSelectClonePickByName = `` /* 201-byte string literal not displayed */ SQLTouchClonePickCreatedAt = `UPDATE CloneInteractiveSelection SET CreatedAt = CURRENT_TIMESTAMP WHERE SelectionId = ?` )
CRUD statements. All column lists are spelled out (no SELECT *) so future column adds don't silently break the row scanner.
const ( CommitInFlagDefault = "default" CommitInFlagDefaultShort = "d" CommitInFlagProfile = "profile" CommitInFlagSaveProfile = "save-profile" CommitInFlagSaveProfileOverwrite = "save-profile-overwrite" CommitInFlagSetDefault = "set-default" CommitInFlagAuthorName = "author-name" CommitInFlagAuthorEmail = "author-email" CommitInFlagConflict = "conflict" CommitInFlagExclude = "exclude" CommitInFlagMessageExclude = "message-exclude" CommitInFlagMessagePrefix = "message-prefix" CommitInFlagMessageSuffix = "message-suffix" CommitInFlagTitlePrefix = "title-prefix" CommitInFlagTitleSuffix = "title-suffix" CommitInFlagOverrideMessages = "override-messages" CommitInFlagOverrideOnlyWeak = "override-only-weak" CommitInFlagWeakWords = "weak-words" CommitInFlagFunctionIntel = "function-intel" CommitInFlagLanguages = "languages" CommitInFlagNoPrompt = "no-prompt" CommitInFlagDryRun = "dry-run" CommitInFlagKeepTemp = "keep-temp" )
---- Flag long names (kebab-case as parsed from argv) -------------
const ( CommitInDescDefault = "Load the default profile bound to <source>" CommitInDescProfile = "Load a named profile from .gitmap/commit-in/profiles/<name>.json" CommitInDescSaveProfile = "Persist this run's resolved answers as a named profile" CommitInDescSaveProfileOverwrite = "Allow --save-profile to overwrite an existing same-named profile" CommitInDescSetDefault = "Mark the saved profile as the default for <source>" CommitInDescAuthorName = "Override author identity (Name); requires --author-email" CommitInDescAuthorEmail = "Override author identity (Email); requires --author-name" CommitInDescConflict = "Conflict mode when replaying commits: ForceMerge | Prompt" CommitInDescExclude = "CSV of relative paths to exclude (trailing / => folder)" CommitInDescMessageExclude = "CSV of Kind:Value rules (StartsWith:|EndsWith:|Contains:)" CommitInDescMessagePrefix = "CSV pool prepended to every commit body (random pick per commit)" CommitInDescMessageSuffix = "CSV pool appended to every commit body (random pick per commit)" CommitInDescTitlePrefix = "String prepended to the first line of every commit message" CommitInDescTitleSuffix = "String appended to the first line of every commit message" CommitInDescOverrideMessages = "CSV pool that replaces the entire message (random pick per commit)" CommitInDescOverrideOnlyWeak = "Only apply --override-messages when the title's first word is weak" CommitInDescWeakWords = "CSV of weak first-words triggering override (default: change,update,updates)" CommitInDescFunctionIntel = "Toggle per-language new-function detection block: on | off" CommitInDescLanguages = "CSV of languages to scan when --function-intel on" CommitInDescNoPrompt = "Refuse interactive prompts; exit MissingAnswer when a value is unset" CommitInDescDryRun = "Walk and plan only; never run git commit (DB rows logged as Skipped)" CommitInDescKeepTemp = "Don't delete <.gitmap>/temp/<runId>/ on exit" )
---- Flag descriptions (rendered in --help) -----------------------
const ( CommitInExitOk = 0 CommitInExitPartiallyFailed = 1 CommitInExitBadArgs = 2 CommitInExitSourceUnusable = 3 CommitInExitInputUnusable = 4 CommitInExitDbFailed = 5 CommitInExitProfileMissing = 6 CommitInExitMissingAnswer = 7 CommitInExitConflictAborted = 8 CommitInExitLockBusy = 9 CommitInExitFunctionIntel = 10 )
---- Exit codes (spec §2.7) ---------------------------------------
const ( CommitInConflictModeForceMerge = "ForceMerge" CommitInConflictModePrompt = "Prompt" )
---- Enum: ConflictMode -------------------------------------------
const ( CommitInInputKeywordAll = "all" CommitInInputKeywordTailDash = "-" // followed by digits, e.g. "-5" )
---- Enum: InputKeyword (spec §2.4) -------------------------------
const ( CommitInInputKindLocalFolder = "LocalFolder" CommitInInputKindGitUrl = "GitUrl" CommitInInputKindVersionedSibling = "VersionedSibling" )
---- Enum: InputKind ----------------------------------------------
const ( CommitInRunStatusPending = "Pending" CommitInRunStatusRunning = "Running" CommitInRunStatusCompleted = "Completed" CommitInRunStatusFailed = "Failed" CommitInRunStatusPartiallyFailed = "PartiallyFailed" )
---- Enum: RunStatus ----------------------------------------------
const ( CommitInOutcomeCreated = "Created" CommitInOutcomeSkipped = "Skipped" CommitInOutcomeFailed = "Failed" )
---- Enum: CommitOutcome ------------------------------------------
const ( CommitInSkipReasonDuplicateSourceSha = "DuplicateSourceSha" CommitInSkipReasonExcludedAllFiles = "ExcludedAllFiles" CommitInSkipReasonEmptyAfterMessageRules = "EmptyAfterMessageRules" CommitInSkipReasonDryRun = "DryRun" )
---- Enum: SkipReason ---------------------------------------------
const ( CommitInExclusionKindPathFolder = "PathFolder" CommitInExclusionKindPathFile = "PathFile" )
---- Enum: ExclusionKind ------------------------------------------
const ( CommitInMessageRuleKindStartsWith = "StartsWith" CommitInMessageRuleKindEndsWith = "EndsWith" CommitInMessageRuleKindContains = "Contains" )
---- Enum: MessageRuleKind ----------------------------------------
const ( CommitInLanguageGo = "Go" CommitInLanguageJavaScript = "JavaScript" CommitInLanguageTypeScript = "TypeScript" CommitInLanguageRust = "Rust" CommitInLanguagePython = "Python" CommitInLanguagePhp = "Php" CommitInLanguageJava = "Java" CommitInLanguageCSharp = "CSharp" )
---- Enum: FunctionIntelLanguage ----------------------------------
const ( CommitInDefaultConflictMode = CommitInConflictModeForceMerge CommitInDefaultFunctionIntel = "off" CommitInDefaultLanguagesCsv = CommitInLanguageGo CommitInDefaultWeakWordsCsv = "change,update,updates" CommitInFunctionIntelOn = "on" CommitInFunctionIntelOff = "off" CommitInMessageRuleKindSep = ":" CommitInPathFolderSep = "/" CommitInCsvSep = "," )
---- Defaults ------------------------------------------------------
const ( CommitInDirRoot = "commit-in" CommitInDirProfiles = "commit-in/profiles" CommitInDirTemp = "temp" CommitInProfileFileExt = ".json" CommitInLockFileName = "commit-in.lock" CommitInTempInputFormat = "%d-%s" // <orderIndex>-<basename> )
---- Filesystem layout (under <.gitmap>/) -------------------------
const ( CommitInUrlPrefixHttps = "https://" CommitInUrlPrefixHttp = "http://" CommitInUrlPrefixSshAt = "git@" CommitInUrlPrefixSsh = "ssh://" CommitInUrlPrefixGit = "git://" CommitInUrlSuffixGit = ".git" )
---- URL detection (spec §2.3 step 1) -----------------------------
const ( CommitInMsgPhaseResolveSource = "▸ commit-in: resolving <source> %q\n" CommitInMsgPhaseInitSource = "▸ commit-in: git init in %s\n" CommitInMsgPhaseCloneSource = "▸ commit-in: cloning %s into %s\n" CommitInMsgPhaseDiscoverAll = "▸ commit-in: discovering versioned siblings of %s\n" CommitInMsgPhaseStageInputs = "▸ commit-in: staging %d input(s) under %s\n" CommitInMsgPhaseWalk = "▸ commit-in: walking %d commit(s) chronologically\n" CommitInMsgPhaseReplay = "▸ commit-in: replaying into %s\n" CommitInMsgPhaseSaveProfile = "▸ commit-in: saving profile %q\n" CommitInMsgCommitOk = "✓ commit-in: %s -> %s %s\n" CommitInMsgCommitSkip = "▣ commit-in: skip %s reason=%s\n" CommitInMsgCommitFail = "✗ commit-in: %s %v\n" CommitInMsgSummaryLine = "commit-in: run=%d created=%d skipped=%d failed=%d\n" )
---- Phase banners (STDERR) ---------------------------------------
const ( CommitInErrBadArgs = "commit-in: bad args: %s\n" CommitInErrSourceClone = "commit-in: source: clone failed: %v\n" CommitInErrSourceInit = "commit-in: source: git init failed: %v\n" CommitInErrSourceMkdir = "commit-in: source: mkdir failed: %v\n" CommitInErrInputClone = "commit-in: input %q: clone failed: %v\n" CommitInErrInputOpen = "commit-in: input %q: open failed: %v\n" CommitInErrInputMixedKeyword = "commit-in: keyword %q must appear alone" CommitInErrDbMigrate = "commit-in: db: migration failed: %v\n" CommitInErrDbWrite = "commit-in: db: write failed: %v\n" CommitInErrProfileMissing = "commit-in: profile %q not found\n" CommitInErrProfileBadJson = "commit-in: profile %q: invalid json: %v\n" CommitInErrMissingAnswer = "commit-in: --no-prompt set but %s is unset\n" CommitInErrConflictAborted = "commit-in: conflict aborted by user at commit %s\n" CommitInErrLockBusy = "commit-in: another commit-in run is in progress (lock at %s)\n" CommitInErrFunctionIntel = "commit-in: function-intel: %s parser failed on %s: %v\n" CommitInErrAuthorPair = "commit-in: --author-name and --author-email must be set together" CommitInErrConflictMode = "commit-in: --conflict must be ForceMerge or Prompt, got %q" CommitInErrFunctionIntelArg = "commit-in: --function-intel must be on or off, got %q" CommitInErrUnknownLanguage = "commit-in: unknown language %q (supported: Go,JavaScript,TypeScript,Rust,Python,Php,Java,CSharp)" CommitInErrMessageRuleShape = "commit-in: message rule %q: expected Kind:Value with Kind in StartsWith|EndsWith|Contains" CommitInErrSaveProfileExists = "commit-in: profile %q already exists; pass --save-profile-overwrite to replace" CommitInErrInputKeyword = "commit-in: keyword %q invalid (use 'all' or '-N' where N>=1)" )
---- Errors (one line per error path; zero-swallow rule) ----------
const ( TableCommitInRun = "CommitInRun" TableCommitInRunStatus = "RunStatus" TableCommitInInputRepo = "InputRepo" TableCommitInInputKind = "InputKind" TableCommitInSrcCommit = "SourceCommit" TableCommitInSrcFile = "SourceCommitFile" TableCommitInRewritten = "RewrittenCommit" TableCommitInOutcome = "CommitOutcome" TableCommitInSkipLog = "SkipLog" TableCommitInSkipReason = "SkipReason" TableCommitInShaMap = "ShaMap" TableCommitInProfile = "Profile" TableCommitInProfileExc = "ProfileExclusion" TableCommitInExcKind = "ExclusionKind" TableCommitInProfileMsg = "ProfileMessageRule" TableCommitInMsgKind = "MessageRuleKind" TableCommitInLanguage = "FunctionIntelLanguage" TableCommitInConflict = "ConflictMode" )
---- Table-name constants -----------------------------------------
const ( SQLSeedCommitInRunStatus = `INSERT OR IGNORE INTO RunStatus (Name) VALUES ('Pending'), ('Running'), ('Completed'), ('Failed'), ('PartiallyFailed')` SQLSeedCommitInInputKind = `INSERT OR IGNORE INTO InputKind (Name) VALUES ('LocalFolder'), ('GitUrl'), ('VersionedSibling')` SQLSeedCommitInOutcome = `INSERT OR IGNORE INTO CommitOutcome (Name) VALUES ('Created'), ('Skipped'), ('Failed')` SQLSeedCommitInSkipReason = `` /* 135-byte string literal not displayed */ SQLSeedCommitInExclusionKind = `INSERT OR IGNORE INTO ExclusionKind (Name) VALUES ('PathFolder'), ('PathFile')` SQLSeedCommitInMessageRuleKind = `INSERT OR IGNORE INTO MessageRuleKind (Name) VALUES ('StartsWith'), ('EndsWith'), ('Contains')` SQLSeedCommitInLanguage = `` /* 153-byte string literal not displayed */ SQLSeedCommitInConflictMode = `INSERT OR IGNORE INTO ConflictMode (Name) VALUES ('ForceMerge'), ('Prompt')` )
---- Enum-mirror seed inserts ------------------------------------- Seed Names MUST match the Go enum String() exactly (parity test in gitmap/cmd/commitin/enums_test.go locks the Go side; another test in gitmap/store/migrate_commitin_test.go locks the SQL side).
const ( CmdCommitLeft = "commit-left" CmdCommitLeftA = "cml" CmdCommitRight = "commit-right" CmdCommitRightA = "cmr" CmdCommitBoth = "commit-both" CmdCommitBothA = "cmb" )
gitmap:cmd top-level Commit-transfer commands.
const ( LogPrefixCommitLeft = "[commit-left]" LogPrefixCommitRight = "[commit-right]" LogPrefixCommitBoth = "[commit-both]" )
Commit-transfer log prefixes (matches merge-* style).
const ( FlagCTMirror = "mirror" FlagCTIncludeMerges = "include-merges" FlagCTLimit = "limit" FlagCTSince = "since" FlagCTStrip = "strip" FlagCTNoStrip = "no-strip" FlagCTDrop = "drop" FlagCTNoDrop = "no-drop" FlagCTConventional = "conventional" FlagCTNoConventional = "no-conventional" FlagCTProvenance = "provenance" FlagCTNoProvenance = "no-provenance" FlagCTPreferSource = "prefer-source" FlagCTPreferTarget = "prefer-target" FlagCTForceReplay = "force-replay" FlagCTDryRun = "dry-run" FlagCTYes = "yes" FlagCTNoPush = "no-push" FlagCTNoCommit = "no-commit" FlagCTInterleave = "interleave" )
Commit-transfer flag names. See spec §8 for semantics.
const ( FlagDescCTMirror = "Delete target files not present in source commit (true mirror)" FlagDescCTIncludeMerges = "Include merge commits in the replay set" FlagDescCTLimit = "Replay at most N source commits (oldest first); 0 = no limit" FlagDescCTSince = "Override the divergence base (sha or ISO date)" FlagDescCTStrip = "Add a strip pattern (regex, repeatable)" FlagDescCTNoStrip = "Disable all strip patterns" FlagDescCTDrop = "Add a drop pattern (regex, repeatable)" FlagDescCTNoDrop = "Replay every commit (disable drop filter)" FlagDescCTConventional = "Force conventional-commit normalization on" FlagDescCTNoConventional = "Disable conventional-commit normalization" FlagDescCTProvenance = "Append provenance footer (default true)" FlagDescCTNoProvenance = "Skip provenance footer" FlagDescCTPreferSource = "Source side wins file conflicts" FlagDescCTPreferTarget = "Target side wins file conflicts" FlagDescCTForceReplay = "Replay even commits that already carry a gitmap-replay footer" FlagDescCTDryRun = "Print the full plan + cleaned messages; perform no writes" FlagDescCTYes = "Skip the confirmation prompt" FlagDescCTNoPush = "Stop after the local commit (skip git push)" FlagDescCTNoCommit = "Copy files but skip both commit and push" FlagDescCTInterleave = "commit-both only: replay both sides in author-date order (instead of sequential L→R then R→L)" )
Commit-transfer flag descriptions.
const ( MsgCTUsageFmt = "Usage: gitmap %s LEFT RIGHT [flags]\n\nSee 'gitmap help %s' for the full flag table.\n" ErrCTNotImplementedFmt = "" /* 186-byte string literal not displayed */ ErrCTArgCountFmt = "Error: %s requires exactly two endpoints (LEFT and RIGHT). Got %d.\n" ErrCTSourceCheckoutFmt = "Error: failed to checkout %s in source: %v (operation: git checkout)\n" ErrCTReplayFailedFmt = "Error: replay failed at source commit %s: %v (operation: %s)\n" MsgCTReplayPlanFmt = "%s replaying %d commits from %s onto %s:\n" MsgCTReplayStepFmt = "%s [%d/%d] %s → %s %s\n" MsgCTReplaySkipFmt = "%s [%d/%d] %s → - skipped: %s\n" MsgCTSummaryFmt = "%s done: replayed %d, skipped %d (%s)\n" MsgCTPushedFmt = "%s pushed %d commits to %s\n" MsgCTConfirmProceedFmt = "%s proceed? [y/N] " )
Commit-transfer messages and errors.
const ( HelpCommitRight = " commit-right (cmr) Replay LEFT's commits onto RIGHT (cleaned, idempotent) [LIVE]" HelpCommitLeft = " commit-left (cml) Replay RIGHT's commits onto LEFT (cleaned, idempotent) [LIVE]" HelpCommitBoth = " commit-both (cmb) Bidirectional replay (sequential by default; --interleave for author-date) [LIVE]" )
Top-level help-listing lines. Surfaced by `gitmap help` under the "Commit Transfer" group so users can discover the family + aliases without already knowing it exists. Long-form name first, alias in parens — matches the merge-* convention.
const ( ShellPowerShell = "powershell" ShellBash = "bash" ShellZsh = "zsh" )
Completion shells.
const ( CompListRepos = "--list-repos" CompListGroups = "--list-groups" CompListCommands = "--list-commands" CompListAliases = "--list-aliases" CompListZipGroups = "--list-zip-groups" CompListHelpGroups = "--list-help-groups" )
Completion list flags.
const ( CompFilePS = "completions.ps1" CompFileBash = "completions.bash" CompFileZsh = "completions.zsh" CompDirName = "gitmap" )
Completion file names.
const ( MsgCompInstalled = "Shell completion installed for %s\n" MsgCompAlreadyDone = "Shell completion already configured for %s\n" MsgCompProfileWrite = "Added source line to %s\n" ErrCompUsage = "" /* 145-byte string literal not displayed */ ErrCompUnknownShell = "unknown shell: %s (use powershell, bash, or zsh)\n" ErrCompProfileWrite = "failed to update profile at %s: %v (operation: write)\n" )
Completion messages.
const ( FlagDescCompListRepos = "Print repo slugs one per line" FlagDescCompListGroups = "Print group names one per line" FlagDescCompListCommands = "Print all command names one per line" FlagDescCompListAliases = "Print alias names one per line" FlagDescCompListZipGroups = "Print zip group names one per line" FlagDescCompListHelpGroups = "Print help group names one per line" )
Completion flag descriptions.
const ( MsgCompressArchive = " ✓ Compressed %s → %s\n" ErrCompressFailed = " ✗ Failed to compress %s: %v\n" FlagDescCompress = "Wrap release assets in .zip (Windows) or .tar.gz (Linux/macOS)" MsgChecksumGenerated = " ✓ Generated %s (SHA256)\n" ErrChecksumFailed = " ✗ Failed to hash %s: %v\n" FlagDescChecksums = "Generate SHA256 checksums.txt for release assets" ChecksumsFile = "checksums.txt" )
Compress and checksum messages.
const ( CmdDashboard = "dashboard" CmdDashboardAlias = "db" )
gitmap:cmd top-level Dashboard CLI commands.
const ( FlagDescDashLimit = "Maximum number of commits to include" FlagDescDashSince = "Only include commits after this date (YYYY-MM-DD)" FlagDescDashOpen = "Open the generated dashboard in the default browser" FlagDescNoMerges = "Exclude merge commits from the output" FlagDescDashOutDir = "Output directory for dashboard files" )
Dashboard flag descriptions.
const ( DashboardJSONFile = "dashboard.json" DashboardHTMLFile = "dashboard.html" DashboardOutDir = ".gitmap/output" )
Dashboard output filenames.
const ( MsgDashCollecting = "Collecting repository data..." MsgDashWriteJSON = "Wrote %s (%d commits, %d authors)\n" MsgDashWriteHTML = "Wrote %s\n" MsgDashGenerated = "Dashboard generated in %s\n" MsgDashOpening = "Opening dashboard in browser..." )
Dashboard terminal messages.
const ( ErrDashNotRepo = "Current directory is not a Git repository." ErrDashWriteJSON = "Failed to write dashboard JSON at %s: %v (operation: write)\n" ErrDashWriteHTML = "Failed to write dashboard HTML at %s: %v (operation: write)\n" ErrDashCollect = "Failed to collect repository data: %v\n" )
Dashboard error messages.
const ( CmdDBMigrate = "db-migrate" CmdDBMigrateAlias = "dbm" HelpDBMigrate = " db-migrate (dbm) Run pending database schema migrations (safe, idempotent)" FlagDBMigrateVerbose = "verbose" FlagDescDBMigrateV = "Print every migration step (otherwise summary only)" MsgDBMigrateRunning = "▸ Running gitmap database migrations...\n" MsgDBMigrateDoneFmt = " ✓ Migrations complete (%d tables ensured, %d steps applied, %d warnings).\n" MsgDBMigrateStepFmt = " • %s\n" MsgDBMigrateNoWork = " ✓ Database schema is already up to date — nothing to migrate.\n" ErrDBMigrateFailFmt = "Error: gitmap db-migrate failed: %v\n" // Auto-run hook for the post-update flow. MsgDBMigratePostUpdate = "▸ Running database migrations after update...\n" WarnDBMigratePostFail = " ⚠ Post-update migration failed: %v\n Run `gitmap db-migrate --verbose` to retry.\n" )
gitmap:cmd top-level `gitmap db-migrate` (alias `dbm`) — explicitly run database schema migrations. Safe to invoke at any time; designed to be run automatically after `gitmap update` and on first launch after a fresh install.
const ( CmdDiff = "diff" CmdDiffAlias = "df" )
gitmap:cmd top-level Diff command identifiers and flag names.
Spec: companion to spec/01-app/97-move-and-merge.md
const ( FlagDiffJSON = "json" FlagDiffOnlyConflicts = "only-conflicts" FlagDiffOnlyMissing = "only-missing" FlagDiffIncludeIdentical = "include-identical" FlagDiffIncludeVCS = "include-vcs" FlagDiffIncludeNodeMods = "include-node-modules" FlagDiffNoColor = "no-color" )
Diff flag names.
const ( LogPrefixDiff = "[diff]" DiffSectionMissingRight = "Missing on RIGHT (would be added by merge-right / merge-both):" DiffSectionMissingLeft = "Missing on LEFT (would be added by merge-left / merge-both):" DiffSectionConflicts = "Conflicts (different content on both sides):" DiffSectionIdentical = "Identical files (skipped by merge-*):" DiffSummaryFmt = "%s summary: %d missing-on-left, %d missing-on-right, %d conflicts, %d identical\n" DiffNothingFmt = "%s no differences detected.\n" )
Diff log prefix and section headers.
const ( ErrDiffUsageFmt = "Usage: gitmap diff LEFT RIGHT [flags]\n" ErrDiffSameFolder = "error: LEFT and RIGHT resolve to the same folder: %s" ErrDiffNotFolderFmt = "error: %q is not a directory (gitmap diff requires local folder endpoints; clone URLs first via `gitmap clone`)" ErrDiffMissingFmt = "error: %q does not exist" )
Diff error messages.
const ( CmdDiffProfiles = "diff-profiles" CmdDiffProfilesAlias = "dp" )
gitmap:cmd top-level Diff-profiles CLI commands.
const ( MsgDPHeader = "Comparing profiles: %s ↔ %s\n" MsgDPOnlyInHeader = "\nONLY IN %s:" MsgDPOnlyInRowFmt = " %-20s %s\n" MsgDPDiffHeader = "\nDIFFERENT:" MsgDPDiffNameFmt = " %s\n" MsgDPDiffDetailFmt = " %-10s %s\n" MsgDPSameFmt = "\nSAME: %d repos (use --all to show)\n" MsgDPSameAllHeader = "\nSAME:" MsgDPSameRowFmt = " %-20s %s\n" MsgDPSummaryFmt = "\nSummary: %d only-left | %d only-right | %d different | %d same\n" MsgDPEmpty = "Both profiles have no repos." ErrDPUsage = "usage: gitmap diff-profiles <profileA> <profileB> [--all] [--json]\n" ErrDPProfileMissing = "profile not found: %s\n" ErrDPOpenFailed = "failed to open profile database '%s': %v\n" )
Diff-profiles messages.
const ( DoctorBannerFmt = "\n gitmap doctor (v%s)\n" DoctorBannerRule = "" /* 128-byte string literal not displayed */ DoctorIssuesFmt = " Found %d issue(s). See recommendations above.\n" DoctorFixPathTip = " Tip: run 'gitmap doctor --fix-path' to auto-sync the PATH binary.\n\n" DoctorAllPassed = " All checks passed." DoctorFixBannerFmt = "\n gitmap doctor --fix-path (v%s)\n" DoctorActivePathFmt = " Active PATH: %s (%s)\n" DoctorDeployedFmt = " Deployed: %s (%s)\n" DoctorSyncingFmt = " Syncing %s -> %s...\n" DoctorRetryFmt = " [%d/%d] File in use, retrying...\n" DoctorRenamedMsg = " Renamed locked binary to .old, copying fresh..." DoctorKillingMsg = " Attempting to stop stale gitmap processes..." DoctorKilledFmt = " Stopped process(es): %s\n" DoctorSyncFailTitle = "Could not sync PATH binary after all fallback attempts" DoctorSyncFailDetail = "The file is still locked by another process." DoctorSyncFailFix1 = "Close all terminals and apps using gitmap, then run:" DoctorSyncFailFix2Fmt = " Copy-Item \"%s\" \"%s\" -Force" DoctorFixFlagDesc = "Sync the active PATH binary from the deployed binary" DoctorOKPathFmt = "PATH binary synced successfully: %s" DoctorWarnSyncFmt = "Synced but version mismatch: got %s, expected %s" DoctorNotOnPath = "gitmap not found on PATH" DoctorNoSync = "Cannot sync — no active binary to replace." DoctorAddPathFix = "Add your deploy directory to PATH first." DoctorCannotResolve = "Cannot resolve deployed binary" DoctorAlreadySynced = "PATH already points to the deployed binary. Nothing to sync." DoctorVersionsMatch = "Versions already match (%s). No sync needed." DoctorRepoPathMissing = "RepoPath not embedded" DoctorRepoPathDetail = "Binary was not built with run.ps1. Self-update will not work." DoctorRepoPathFix = "Rebuild with: .\\run.ps1" DoctorRepoPathOKFmt = "RepoPath: %s" DoctorPathBinaryFmt = "PATH binary: %s (%s)" DoctorPathMissTitle = "gitmap not found on PATH" DoctorPathMissDetail = "The gitmap binary is not accessible from your terminal." DoctorPathMissFix = "Add your deploy directory to PATH (check deployPath in powershell.json or run 'gitmap installed-dir')" DoctorDeployReadFail = "Cannot read powershell.json" DoctorDeployReadDet = "Deploy path detection unavailable." DoctorNoDeployPath = "No deployPath in powershell.json" DoctorNoDeployDet = "Deploy target not configured." DoctorDeployNotFound = "Deployed binary not found" DoctorDeployRunFix = "Run: .\\run.ps1" DoctorDeployOKFmt = "Deployed binary: %s (%s)" DoctorGitMissTitle = "git not found on PATH" DoctorGitMissDetail = "Git is required for most gitmap commands." DoctorGitOKFmt = "Git: %s (%s)" DoctorGitOKPathFmt = "Git: %s (version unknown)" DoctorGoWarn = "Go not found on PATH (needed only for building from source)" DoctorGoOKFmt = "Go: %s" DoctorGoOKPathFmt = "Go: %s (version unknown)" DoctorChangelogWarn = "CHANGELOG.md not found (changelog command will not work)" DoctorChangelogOK = "CHANGELOG.md present" DoctorVersionMismatch = "PATH binary version mismatch" DoctorVMismatchFmt = "PATH: %s, Source: %s" DoctorVMismatchFix = "Run: gitmap update or gitmap doctor --fix-path" DoctorDeployMismatch = "Deployed binary version mismatch" DoctorDMismatchFmt = "Deployed: %s, Source: %s" DoctorDMismatchFix = "Run: .\\run.ps1 -NoPull" DoctorBinariesDiffer = "PATH and deployed binaries differ" DoctorBDifferFmt = "PATH: %s (%s), Deployed: %s (%s)" DoctorBDifferFix = "Run: gitmap doctor --fix-path" DoctorSourceOKFmt = "Source version: %s (all binaries match)" DoctorResolveNoRepo = "RepoPath not embedded — rebuild with run.ps1" DoctorResolveNoRead = "cannot read powershell.json: %v" DoctorResolveNoDeploy = "no deployPath in powershell.json" DoctorResolveNotFound = "deployed binary not found: %s" DoctorDefaultBinary = "gitmap.exe" )
Doctor command messages.
const ( GitMapBin = "gitmap" GoBin = "go" GoVersionArg = "version" PowershellConfigFile = "powershell.json" JSONKeyDeployPath = "deployPath" JSONKeyBuildOutput = "buildOutput" JSONKeyBinaryName = "binaryName" BackupSuffix = ".old" )
Doctor binary and tool lookup names.
const ( FlagNoBanner = "--no-banner" EnvGitMapQuiet = "GITMAP_QUIET" EnvGitMapQuietTrue = "1" )
Bare-invocation banner suppression (v3.6.0+).
const ( BinaryReadoutActive = " Active binary: %s\n" BinaryReadoutDeployed = " Deployed binary: %s\n" BinaryReadoutConfig = " Config binary: %s\n" BinaryReadoutMissing = "(not found)" )
Bare-invocation binary readout labels (v3.6.0+).
const ( DoctorOKFmt = " %s[OK]%s %s\n" DoctorIssueFmt = " %s[!!]%s %s\n" DoctorFixFmt = " %sFix:%s %s\n" DoctorWarnFmt = " %s[--]%s %s\n" DoctorDetail = " %s\n" )
Doctor format markers.
const ( DoctorConfigMissing = "config.json not found (using defaults)" DoctorConfigInvalid = "config.json is not valid JSON" DoctorConfigOKFmt = "Config: %s" )
Doctor config validation messages.
const ( DoctorDBOpenFail = "Database cannot be opened" DoctorDBMigrateFail = "Database migration failed" DoctorDBOK = "Database: %s" )
Doctor database validation messages.
const ( DoctorLockNone = "No stale lock file" DoctorLockExists = "Lock file exists — another gitmap may be running (or stale)" )
Doctor lock file messages.
const ( DoctorNetworkOK = "Network: github.com reachable" DoctorNetworkOffline = "Network: github.com unreachable (offline mode)" )
Doctor network messages.
const ( DoctorSignTitle = "Digital signature" DoctorSignOKFmt = "Signed: %s (%s)" DoctorSignUnsigned = "Binary is not digitally signed" DoctorSignUnsignDet = "Users will see SmartScreen warnings on Windows." DoctorSignUnsignFix = "See spec/03-general/05-code-signing.md for SignPath.io setup" DoctorSignSkipUnix = "Signature check: skipped (not Windows)" DoctorSignNoPath = "Signature check: skipped (binary not on PATH)" DoctorSignCheckFail = "Signature check: could not verify (PowerShell unavailable)" DoctorSignInvalidFmt = "Signature invalid: %s" DoctorSignInvalidDet = "The binary's signature is present but not valid." )
Doctor digital signature messages.
const ( DoctorDupBinOK = "Single gitmap binary on PATH" DoctorDupBinTitle = "Multiple gitmap binaries on PATH" )
Doctor duplicate binary messages.
const ( DoctorNoOrphans = "Release↔Repo integrity: no orphaned rows" DoctorOrphanedReleases = "%d orphaned Release row(s) with invalid RepoId" DoctorOrphanedDetail = "These releases reference a Repo that no longer exists in the database." DoctorOrphanedFix = "Run: gitmap list-releases (re-imports from .gitmap/release/v*.json with valid RepoId)" DoctorReposNoReleases = "%d repo(s) have no releases (run 'gitmap list-releases' in each repo to populate)" DoctorIntegrityFail = "Release↔Repo integrity check failed: %v" )
Doctor Release↔Repo integrity messages.
const ( DoctorSetupConfigMissing = "git-setup.json not found (setup will fail without --config)" DoctorSetupConfigOKFmt = "Setup config: %s" )
Doctor setup config messages.
const ( DoctorWrapperOK = "Shell wrapper active (gitmap cd will change directory)" DoctorWrapperNotLoaded = "Shell wrapper not loaded — gitmap cd prints path but cannot change directory" DoctorWrapperFix = "Run: gitmap setup, then restart terminal or reload profile (. $PROFILE / source ~/.bashrc / source ~/.zshrc)" )
Doctor shell wrapper messages.
const ( DoctorVSCodePMOKFmt = "VS Code Project Manager: %s" DoctorVSCodePMNoVSCode = "" /* 128-byte string literal not displayed */ DoctorVSCodePMNoExtension = "alefragnani.project-manager extension not installed — projects.json sync will be skipped (install the extension and re-run)" DoctorVSCodePMUnknownTitle = "VS Code Project Manager check failed" )
Doctor VS Code Project Manager check messages (v3.41.0+).
const ( CmdDownloaderConfig = "downloader-config" CmdDownloaderConfigAlias = "dc" // Reserved for Slice 3 — kept here so the dispatch table grows in // one file and shorthand collisions can be detected by the existing // constants-collision check. CmdDownload = "download" // gitmap:cmd skip CmdDownloadAlias = "dl" // gitmap:cmd skip CmdDownloadUnzip = "download-unzip" // gitmap:cmd skip CmdDownloadUnzipAlias = "du" // gitmap:cmd skip )
gitmap:cmd top-level Downloader CLI commands and shorthand aliases.
Slice 1 of the downloader feature only wires `downloader-config` (and its `dc` shorthand). The `download` / `download-unzip` / `dl` / `du` aliases are reserved here so a later slice can add them without touching the constants surface twice.
const ( SettingDownloaderConfig = "DownloaderConfig" SettingDownloaderConfigSeedHash = "DownloaderConfigSeedHash" SettingDatabaseVersion = "DatabaseVersion" )
Settings keys for the downloader feature.
SettingDownloaderConfig holds the full PascalCase JSON blob produced by the Seedable-Config (data/downloader-config.json). Stored as TEXT so the existing Setting upsert path is reused unchanged.
SettingDownloaderConfigSeedHash holds the SHA-256 of the seed file the last time it was applied, so the seeder can detect upstream changes without overwriting user-customized configs (unless OverwriteUserConfig is enabled in the seed).
const ( DownloaderDefaultParallel = 15 DownloaderDefaultSplits = 15 DownloaderDefaultSplitSize = "800K" DownloaderDefaultLargeSplitSize = "2M" DownloaderDefaultLargeThreshold = "100M" DownloaderDefaultTinyThreshold = "2M" DownloaderDefaultTinySplitSize = "100K" DownloaderDefaultTinySplits = 8 DownloaderDefaultPreferred = "Aria2C" DownloaderDefaultFallback = "GoDownloader" DownloaderDefaultAllowFallback = true DownloaderDefaultOverwriteUser = false )
Downloader hard-coded fallbacks. Only used when both the DB and the seed file are unavailable (e.g., first-run race before Migrate completes). Numbers mirror the spec: 15 parallel / 15 splits / 800KB normal / 2MB large / 100MB threshold. Tiny-file profile (<2MB → 8 splits @ 100KB) matches the user clarification.
const ( MsgDownloaderConfigBanner = "▶ gitmap downloader-config v%s" MsgDownloaderConfigLoaded = " ✓ Loaded downloader config from %s" MsgDownloaderConfigSaved = " ✓ Saved downloader config to Setting[%s]" MsgDownloaderConfigPromptHeader = " ▸ No file path supplied — entering interactive mode. Press <Enter> to keep the shown default." MsgDownloaderConfigSeeded = " ✓ Seeded downloader defaults (seed hash %s)" MsgDownloaderConfigSeedSkip = " ◦ Downloader config already customized (OverwriteUserConfig=false) — skipping seed" MsgDownloaderConfigDBVersion = " ✓ Recorded LastKnownVersion=%s" WarnDownloaderSeedRead = " ⚠ Could not read downloader seed at %s: %v" WarnDownloaderSeedParse = " ⚠ Could not parse downloader seed: %v" ErrDownloaderConfigPathRequired = "downloader-config: file path %q does not exist" ErrDownloaderConfigInvalidJSON = "downloader-config: invalid JSON: %w" ErrDownloaderConfigMissingKey = "downloader-config: missing required PascalCase key %q" ErrDownloaderConfigBadParallel = "downloader-config: ParallelDownloads must be 1..64, got %d" ErrDownloaderConfigBadSplits = "downloader-config: SplitConnections must be 1..64, got %d" )
User-facing messages for downloader-config (Slice 1).
const ( CmdEnv = "env" CmdEnvAlias = "ev" )
gitmap:cmd top-level Env CLI commands.
const ( CmdEnvSet = "set" // gitmap:cmd skip CmdEnvGet = "get" // gitmap:cmd skip CmdEnvDelete = "delete" // gitmap:cmd skip CmdEnvList = "list" // gitmap:cmd skip CmdEnvPathAdd = "path" // gitmap:cmd skip CmdEnvPathSub = "add" // gitmap:cmd skip CmdEnvPathRemove = "remove" // gitmap:cmd skip CmdEnvPathList = "list" // gitmap:cmd skip )
gitmap:cmd top-level Env subcommands.
const ( EnvRegistryFileName = "env-registry.json" EnvRegistryFilePath = GitMapDir + "/" + EnvRegistryFileName )
Env registry file.
const ( FlagEnvSystem = "system" FlagEnvShell = "shell" FlagEnvVerbose = "verbose" FlagEnvDryRun = "dry-run" )
Env flag names.
const ( FlagDescEnvSystem = "Target system-level variables (Windows, requires admin)" FlagDescEnvShell = "Target shell profile: bash, zsh (Unix only)" FlagDescEnvVerbose = "Show detailed operation output" FlagDescEnvDryRun = "Preview changes without applying" )
Env flag descriptions.
const ( EnvProfileBashRC = ".bashrc" EnvProfileZshRC = ".zshrc" EnvProfileBash = ".bash_profile" EnvExportPrefix = "export " EnvExportFmt = "export %s=\"%s\"" EnvPathExportFmt = "export PATH=\"$PATH:%s\"" EnvManagedComment = "# managed by gitmap" )
Env shell profile paths.
const ( MsgEnvSet = "Set %s=%s\n" MsgEnvDeleted = "Removed %s\n" MsgEnvPathAdded = "Added to PATH: %s\n" MsgEnvPathRemoved = "Removed from PATH: %s\n" MsgEnvListHeader = "Managed variables:\n" MsgEnvListRow = " %s = %s\n" MsgEnvListEmpty = "No managed variables. Use 'gitmap env set' to add one.\n" MsgEnvPathHeader = "Managed PATH entries:\n" MsgEnvPathRow = " %s\n" MsgEnvPathEmpty = "No managed PATH entries.\n" MsgEnvDrySet = "[dry-run] Would set %s=%s\n" MsgEnvDryPath = "[dry-run] Would add to PATH: %s\n" MsgEnvDryDelete = "[dry-run] Would remove %s\n" MsgEnvGetFmt = "%s=%s\n" )
Env terminal messages.
const ( ErrEnvNameRequired = "Variable name is required." ErrEnvValueRequired = "Variable value is required." ErrEnvPathRequired = "PATH entry is required." ErrEnvNotFound = "Variable '%s' is not managed by gitmap.\n" ErrEnvPathNotExist = "Error: directory does not exist at %s (operation: resolve, reason: file does not exist)\n" ErrEnvInvalidName = "Invalid variable name: %s (must be alphanumeric and underscore only)\n" ErrEnvProfileWrite = "Error: failed to write shell profile at %s: %v (operation: write)\n" ErrEnvRegistryLoad = "Error: failed to load env registry at %s: %v (operation: read)\n" ErrEnvRegistrySave = "Error: failed to save env registry at %s: %v (operation: write)\n" ErrEnvSubcommand = "Unknown env subcommand: %s\n" ErrEnvSystemWindows = "System-level variables require administrator privileges." ErrEnvPathDuplicate = "PATH entry already exists: %s\n" )
Env error messages.
const ( CmdExport = "export" CmdExportAlias = "ex" )
gitmap:cmd top-level Export CLI commands.
const ( MsgExportDone = "Database exported to %s (%d repos, %d groups, %d releases, %d history, %d bookmarks)\n" MsgExportFailed = "export failed: %v\n" )
Export messages.
const ( MsgFindNextEmpty = "No repos with available updates. Run `gitmap probe --all` first.\n" MsgFindNextHeaderFmt = "Available updates (%d):\n" MsgFindNextRowFmt = " %s → %s [method=%s, probed=%s]\n %s\n" MsgFindNextDoneFmt = "Hint: run `gitmap pull` or `gitmap cn next all` to apply.\n" // ErrFindNextQuery is the bare wrap-string used by store-side // fmt.Errorf calls. No trailing \n because errors are returned, // not printed. The cmd-layer counterpart (ErrFindNextQueryFmt) // adds the project's standard "Error: ... (operation: ..., // reason: ...)\n" framing for stderr. ErrFindNextQuery = "find-next: failed to query: %w" // ErrFindNextScanRow — same convention, used by store/find_next.go // when a per-row Scan fails. ErrFindNextScanRow = "find-next: failed to scan row: %w" // ErrFindNextQueryFmt wraps any DB-side failure surfaced by // store.DB.FindNext. Trailing \n so callers can Fprintf directly // to os.Stderr — matches the ErrScan* family in // constants_messages.go. ErrFindNextQueryFmt = "Error: find-next failed to query database: %v (operation: select, reason: db error)\n" // ErrFindNextScanRowFmt is the stderr-formatted counterpart of // ErrFindNextScanRow, kept for symmetry should a future caller // need to print a row-scan failure directly. ErrFindNextScanRowFmt = "Error: find-next failed to scan row: %v (operation: row-scan, reason: db error)\n" // ErrFindNextJSONEncodeFmt fires when json.Encoder.Encode fails // while writing the result array to stdout. Vanishingly rare // (stdout broken pipe), but still routed through stderr with // the standard format so scripts can detect it. ErrFindNextJSONEncodeFmt = "Error: find-next failed to encode JSON output: %v (operation: encode, reason: io error)\n" MsgFindNextUsageHeader = "Usage: gitmap find-next [--scan-folder <id>] [--json]" )
find-next user-facing strings.
const ( // ErrFindNextUnknownFlagFmt fires on tokens like `--jsno` or // `--scanfolder` that don't match any known flag. The %q wraps // the offending token so embedded whitespace stays visible. ErrFindNextUnknownFlagFmt = "find-next: unknown flag %q\n" // ErrFindNextUnknownFlagSuggestFmt is the same as above but // includes a "did you mean" hint when the unknown token is one // edit away from a known flag. ErrFindNextUnknownFlagSuggestFmt = "find-next: unknown flag %q (did you mean %q?)\n" // ErrFindNextBoolTakesNoValueFmt fires on `--json=true` and // friends. --json is a pure boolean flag; accepting `=true` // would imply `=false` is also valid, and silently ignoring // the value would let `--json=fasle` do the wrong thing. ErrFindNextBoolTakesNoValueFmt = "find-next: %s does not take a value (got %q)\n" // ErrFindNextMissingValueFmt fires when `--scan-folder` is the // last token or is followed by another flag. ErrFindNextMissingValueFmt = "find-next: %s requires an integer scan-folder ID\n" // ErrFindNextBadIntFmt replaces the previous silent ignore for // non-integer scan-folder IDs (e.g. `--scan-folder abc`). ErrFindNextBadIntFmt = "find-next: %s expects an integer, got %q\n" // ErrFindNextUnexpectedArgFmt fires on bare positional tokens. // find-next takes flags only; a stray positional is almost // always a quoting bug worth surfacing. ErrFindNextUnexpectedArgFmt = "find-next: unexpected positional argument %q\n" )
find-next flag-validation errors. Each one is printed to stderr with the usage header before the process exits 2 (the conventional exit code for CLI usage errors — distinct from the exit-1 used for I/O or DB failures so scripts can branch on the cause).
const ( FindNextFlagScanFolder = "--scan-folder" FindNextFlagJSON = "--json" )
find-next CLI flag tokens.
const ( CmdFindNext = "find-next" CmdFindNextAlias = "fn" )
gitmap:cmd top-level find-next CLI commands.
const ( FixRepoExitOk = 0 FixRepoExitNotARepo = 2 FixRepoExitNoRemote = 3 FixRepoExitNoVersionSuffix = 4 FixRepoExitBadVersion = 5 FixRepoExitBadFlag = 6 FixRepoExitWriteFailed = 7 FixRepoExitBadConfig = 8 // FixRepoExitTestsFailed is the exit code emitted by --strict when // `go test` on the touched packages reports failure. Distinct from // 7 (write-failed) so CI can branch on "the rewrite produced // semantically broken code" vs "the file system rejected the // write". Picked as 9 (next free code) so the existing 0/2..8 // matrix stays stable for downstream parsers; the help block // documents the new value verbatim. FixRepoExitTestsFailed = 9 )
Fix-repo exit codes. These match fix-repo.ps1 and fix-repo.sh 1:1 so CI scripts that branch on the exit code keep working when they switch from invoking the script to invoking the binary.
const ( FixRepoFlagAll = "all" FixRepoFlagDryRun = "dry-run" FixRepoFlagVerbose = "verbose" FixRepoFlagConfig = "config" // FixRepoFlagStrict gates the post-rewrite `go test` step that // catches semantic desyncs the byte-level rewriter cannot see // (e.g. a v9→v10 bump that desynced a hard-coded sibling literal // from the same file's `-vN` token — exactly the failure mode // closed by v4.12.0). Off by default so `gitmap fix-repo` stays a // pure rewriter for non-Go repos and for users without a Go // toolchain on PATH; opt-in via --strict / -Strict for Go repos // in CI. FixRepoFlagStrict = "strict" FixRepoModeFlag2 = "-2" FixRepoModeFlag3 = "-3" FixRepoModeFlag5 = "-5" FixRepoConfigFileName = "fix-repo.config.json" )
Fix-repo flag names. Both GNU long-form (`--dry-run`) and the PowerShell single-dash forms (`-DryRun`) are accepted as aliases.
const ( FixRepoDefaultSpan = 2 FixRepoMaxFileBytes = int64(5 * 1024 * 1024) FixRepoBinarySniffMax = 8192 )
Fix-repo defaults.
const ( FixRepoMsgHeaderFmt = "fix-repo base=%s current=v%d mode=%s\n" FixRepoMsgTargetsFmt = "targets: %s\n" FixRepoMsgIdentityFmt = "host: %s owner=%s\n" FixRepoMsgScannedFmt = "scanned: %d files\n" FixRepoMsgChangedFmt = "changed: %d files (%d replacements)\n" FixRepoMsgModeFmt = "mode: %s\n" FixRepoMsgModified = "modified: %s (%d replacements)\n" FixRepoMsgNothing = "fix-repo: nothing to replace\n" FixRepoTargetsNone = "(none)" FixRepoModeWrite = "write" FixRepoModeDryRun = "dry-run" FixRepoErrNotARepo = "fix-repo: ERROR not a git repository (E_NOT_A_REPO)\n" FixRepoErrNoRemote = "fix-repo: ERROR no remote URL found (E_NO_REMOTE)\n" FixRepoErrParseURLFmt = "fix-repo: ERROR cannot parse remote URL %q (E_NO_REMOTE)\n" FixRepoErrNoVerSuffFmt = "fix-repo: ERROR no -vN suffix on repo name %q (E_NO_VERSION_SUFFIX)\n" FixRepoErrBadVersion = "fix-repo: ERROR version <= 0 (E_BAD_VERSION)\n" FixRepoErrBadFlagFmt = "fix-repo: ERROR %s (E_BAD_FLAG)\n" FixRepoErrBadConfigFmt = "fix-repo: ERROR %s (E_BAD_CONFIG)\n" FixRepoErrWriteFmt = "fix-repo: ERROR write failed for %s: %v\n" FixRepoMsgGofmtFmt = "gofmt: %d .go file(s) reformatted\n" FixRepoMsgGofmtSkip = "gofmt: skipped (dry-run)\n" FixRepoMsgGofmtNoneFmt = "gofmt: no .go files modified\n" FixRepoErrGofmtFmt = "fix-repo: ERROR gofmt failed: %v\n%s" FixRepoErrGofmtMissing = "fix-repo: WARN gofmt not found on PATH; skipping post-rewrite formatting\n" // Strict-mode (post-rewrite `go test`) message family. Phrased to // mirror the gofmt block so a user reading the trailing summary // can tell at a glance which post-step ran, what it did, and // (on failure) which exit code maps to which root cause. FixRepoMsgStrictSkipDryRun = "strict: skipped (dry-run)\n" FixRepoMsgStrictNoGoFiles = "strict: no .go files modified; skipping go test\n" FixRepoMsgStrictNoPackages = "strict: no Go packages derived from modified files; skipping go test\n" FixRepoMsgStrictRunFmt = "strict: running go test on %d package(s): %s\n" FixRepoMsgStrictPassFmt = "strict: go test passed (%d package(s))\n" FixRepoErrStrictMissing = "fix-repo: WARN go not found on PATH; --strict skipped\n" FixRepoErrStrictFailFmt = "fix-repo: ERROR strict mode: go test failed (E_TESTS_FAILED): %v\n%s" )
Fix-repo user-facing messages and error formats. All literals printed by the command live here so the no-magic-strings rule is honored and script-vs-binary parity stays explicit.
const ( HelpFixRepoFlags = "Fix-repo flags:" HelpFRMode2 = " -2 (default) Rewrite the last 2 prior versions (v(K-2)..v(K-1) -> vK)" HelpFRMode3 = " -3 Widen window to last 3 prior versions" HelpFRMode5 = " -5 Widen window to last 5 prior versions" HelpFRAll = " --all Rewrite every prior version v1..v(K-1) -> vK" HelpFRDryRun = " --dry-run Preview only; no file is written (PowerShell alias: -DryRun)" HelpFRVerbose = " --verbose Print every modified file with replacement count (alias: -Verbose)" HelpFRConfig = " --config <path> Override fix-repo.config.json location (alias: -Config <path>)" HelpFRStrict = "" /* 127-byte string literal not displayed */ HelpFixRepoExitCodes = "" /* 150-byte string literal not displayed */ )
Fix-repo flags help section. Rendered by cmd.printUsageFixRepoFlags as part of `gitmap help` so the -2/-3/-5/--all family is discoverable from the top-level helpline (not just from `gitmap help fix-repo`).
const ( GitBin = "git" GitClone = "clone" GitPull = "pull" GitRebase = "rebase" GitBranchFlag = "-b" GitDirFlag = "-C" GitFFOnlyFlag = "--ff-only" GitPullRebaseFlag = "--rebase" GitNoRebaseFlag = "--no-rebase" GitRebaseAbortFlag = "--abort" GitConfigCmd = "config" GitGetFlag = "--get" GitRemoteOrigin = "remote.origin.url" GitRevParse = "rev-parse" GitAbbrevRef = "--abbrev-ref" GitHEAD = "HEAD" GitTag = "tag" GitCheckout = "checkout" GitPush = "push" GitLsRemote = "ls-remote" GitLsRemoteTags = "--tags" GitOrigin = "origin" GitOriginPrefix = "origin/" GitCommitPrefix = "commit:" GitTagAnnotateFlag = "-a" GitTagMessageFlag = "-m" GitTagListFlag = "--list" GitBranchListFlag = "--list" GitCatFile = "cat-file" GitCatFileTypeFlag = "-t" GitCommitType = "commit" GitTagGlob = "v*" // GitSymbolicRef + GitRefsRemotesOriginHEAD power // gitutil.ResolveDefaultBranchName, which backs `gitmap branch // default` / `b def`. We ask `git symbolic-ref refs/remotes/origin/HEAD` // to learn the upstream's chosen default (commonly main, sometimes // master, occasionally trunk/develop) instead of guessing. GitSymbolicRef = "symbolic-ref" GitRefsRemotesOriginHEAD = "refs/remotes/origin/HEAD" )
Git commands and arguments.
const ( GitFetch = "fetch" GitBranch = "branch" GitLog = "log" GitForEachRef = "for-each-ref" GitArgAll = "--all" GitArgPrune = "--prune" GitArgRemote = "-r" GitArgContains = "--contains" GitArgInsideWorkTree = "--is-inside-work-tree" GitLogTipFormat = "--format=%cI|%H|%s" GitLogDelimiter = "|" GitLogFieldCount = 3 GitPointsAtFmt = "--points-at=%s" GitRefsRemotesFmt = "refs/remotes/%s" GitFormatRefnameShort = "--format=%(refname:short)" GitForEachRefTagFmt = "--format=%(refname:short)|%(creatordate:iso-strict)" GitRefsTagsPrefix = "refs/tags/" HeadPointer = " -> " ShaDisplayLength = 7 )
Git arguments for latest-branch operations.
const ( CloneInstructionFmt = "git clone -b %s %s %s" HTTPSFromSSHFmt = "https://%s/%s" SSHFromHTTPSFmt = "git@%s:%s" )
Clone instruction format.
const ( FlagOpenValue = "--open" FlagJSON = "--json" FlagLimit = "--limit" FlagSource = "--source" FlagAllRepos = "--all-repos" // v3.20.0: list-releases multi-repo batch view FlagCompact = "--compact" FlagGroups = "--groups" )
Cross-command CLI flag values.
Each command parses its own `flag.NewFlagSet`, so these strings are reused safely (e.g. --json appears for `list-versions`, `list-releases`, `amend-list`, etc.). Centralized here so renames stay consistent.
const ( CmdGoMod = "gomod" CmdGoModAlias = "gm" )
gitmap:cmd top-level GoMod CLI commands.
const ( HelpGoMod = " gomod (gm) <path> Rename Go module path across repo with branch safety" HelpGoModFlags = "GoMod flags:" HelpGoModDry = " --dry-run Preview changes without modifying files or branches" HelpGoModNoMrg = " --no-merge Commit on feature branch but do not merge back" HelpGoModNoTdy = " --no-tidy Skip go mod tidy after replacement" HelpGoModVerb = " --verbose Print each file path as it is modified" HelpGoModExt = " --ext <exts> Comma-separated extensions to filter (e.g. *.go,*.md); default: all files" )
GoMod help text.
const ( FlagGoModDryRun = "dry-run" FlagGoModNoMerge = "no-merge" FlagGoModNoTidy = "no-tidy" FlagGoModExt = "ext" )
GoMod flag names.
const ( FlagDescGoModDryRun = "Preview changes without modifying files or branches" FlagDescGoModNoMerge = "Commit on feature branch but do not merge back" FlagDescGoModNoTidy = "Skip go mod tidy after replacement" FlagDescGoModExt = "Comma-separated file extensions to filter (e.g. *.go,*.md); default: all files" )
GoMod flag descriptions.
const ( GoModFile = "go.mod" GoModModuleLine = "module " GoFileExt = ".go" )
GoMod file and directory constants.
const ( GoModFeaturePrefix = "feature/replace-" GoModBackupPrefix = "backup/before-replace-" )
GoMod branch prefixes.
const ( MsgGoModSummary = "✔ Module path renamed\n" MsgGoModOld = " Old: %s\n" MsgGoModNew = " New: %s\n" MsgGoModFiles = " Files updated: %d\n" MsgGoModBackupBranch = " Backup branch: %s\n" MsgGoModFeatureBranch = " Feature branch: %s\n" MsgGoModMergedInto = " Merged into: %s\n" MsgGoModLeftOn = " Left on branch: %s\n" MsgGoModVerboseFile = " replaced: %s\n" MsgGoModDryHeader = "gomod (dry-run): would rename module path\n" MsgGoModDryOld = " Old: %s\n" MsgGoModDryNew = " New: %s\n" MsgGoModDryFiles = " Files that would change: %d\n" MsgGoModDryFile = " %s\n" MsgGoModNoImports = "Warning: no files found containing the old path to replace (only go.mod updated)\n" MsgGoModTidyWarn = "Warning: go mod tidy failed: %v (continuing)\n" MsgGoModNothingRename = "module path is already %s, nothing to rename\n" )
GoMod terminal messages.
const ( ErrGoModUsage = "usage: gitmap gomod <new-module-path> [--ext *.go,*.md] [--dry-run] [--no-merge] [--no-tidy] [--verbose]\n" ErrGoModNoFile = "error: go.mod not found in current directory\n" ErrGoModNoModule = "error: no module directive found in go.mod\n" ErrGoModNotRepo = "error: not inside a git repository\n" ErrGoModDirtyTree = "error: working tree has uncommitted changes, commit or stash first\n" ErrGoModBranchExists = "error: branch %s already exists, aborting\n" ErrGoModMergeConflict = "error: merge conflict — resolve manually on %s\n" ErrGoModReadFailed = "error: failed to read %s: %v (operation: read)\n" ErrGoModWriteFailed = "error: failed to write %s: %v (operation: write)\n" ErrGoModCommitFailed = "error: git commit failed: %v\n" )
GoMod error messages.
const ( GitAdd = "add" GitAddAll = "-A" GitCommit = "commit" GitCommitMsg = "-m" GitMerge = "merge" GitMergeNoFF = "--no-ff" GitStatusShort = "--porcelain" GitStatus = "status" )
GoMod git arguments.
const ( CmdHasAnyUpdates = "has-any-updates" CmdHasAnyUpdatesAlias = "hau" CmdHasAnyChanges = "has-any-changes" CmdHasAnyChangesAlias = "hac" )
gitmap:cmd top-level Has-any-updates command.
const ( MsgHAUChecking = " Checking for updates...\n" MsgHAUYes = "\n ✓ Yes, you have %d new update(s) from remote.\n Run 'git pull' to sync.\n" MsgHAUNo = "\n ✓ You are up to date. No new changes.\n" MsgHAUAhead = "\n ✓ You are %d commit(s) ahead of remote. No incoming changes.\n" MsgHAUDiverged = "\n ⚠ Branch has diverged: %d ahead, %d behind remote.\n Run 'git pull --rebase' or 'git pull' to reconcile.\n" MsgHAUNoUpstream = "\n ⚠ No upstream tracking branch configured.\n Run 'git branch --set-upstream-to=origin/<branch>' first.\n" ErrHAUNotRepo = "Error: not inside a Git repository.\n" ErrHAUFetchFailed = " Warning: fetch failed, using cached refs: %v\n" )
Has-any-updates messages.
const ( HDDefaultPort = 5173 HDDistDir = "dist" HDDocsDir = "docs-site" DocsSiteArchive = "docs-site.zip" )
Help-dashboard defaults.
const ( MsgHDServingStatic = " Serving docs from %s on http://localhost:%d\n" MsgHDStartingDev = " Starting dev server from %s...\n" MsgHDRunningNPM = " Running npm install...\n" MsgHDOpening = " Opening http://localhost:%d in browser...\n" MsgHDNoDistFallback = " No pre-built dist/ found, falling back to npm run dev\n" MsgHDStopped = "\n Server stopped.\n" )
Help-dashboard terminal messages.
const ( ErrHDNoDocsDir = " ✗ Docs site directory not found at %s (operation: resolve, reason: directory does not exist)\n" ErrHDNPMInstall = " ✗ npm install failed: %v\n" ErrHDDevServer = " ✗ Dev server failed: %v\n" ErrHDServe = " ✗ Failed to start server: %v\n" ErrHDNPMNotFound = " ✗ npm not found — install Node.js to use dev mode\n" ErrDocsSiteBundle = " ✗ Failed to bundle docs-site: %v\n" )
Help-dashboard error messages.
const ( MsgDocsSiteBundling = " Bundling docs-site from %s...\n" MsgDocsSiteBundled = " ✓ Docs site bundled: %s\n" )
Docs-site release messages.
const ( HelpGroupScanning = " Scanning & Discovery:" HelpGroupCloning = " Cloning & Sync:" HelpGroupGitOps = " Git Operations:" HelpGroupRelease = " Release & Versioning:" HelpGroupReleaseInfo = " Release History & Info:" HelpGroupData = " Data, Profiles & Bookmarks:" HelpGroupHistory = " History & Stats:" HelpGroupAmendGroup = " Author Amendment:" HelpGroupProject = " Project Detection:" HelpGroupSSH = " SSH Key Management:" HelpGroupZip = " Zip Groups (Release Archives):" HelpGroupEnvTools = " Environment & Tools:" HelpGroupTasks = " File-Sync Tasks:" HelpGroupUtilities = " Utilities:" HelpGroupVisualize = " Visualization:" HelpGroupCommitXfer = " Commit Transfer (replay between repos):" HelpGroupHint = " Run any command with --help or -h for detailed usage and examples." HelpGroupExample = " Quick start:" HelpExampleScan = " $ gitmap scan ~/projects" HelpExampleList = " $ gitmap ls" HelpExamplePull = " $ gitmap pull my-api" HelpExampleCD = " $ gitmap cd my-api" HelpCompactHint = " Use --compact for a minimal command list without descriptions." HelpAlias = " alias (a) <sub> Assign short names to repos (set, remove, list, show, suggest)" HelpSSH = " ssh <sub> Generate, list, and manage SSH keys for Git authentication" HelpZipGroup = " zip-group (z) <sub> Manage named file collections for release ZIP archives" // Compact-mode lines: command (alias) only. CompactScanning = " scan (s), rescan (rsc), rescan-subtree (rss), list (ls)" CompactCloning = " clone (c), clone-next (cn), desktop-sync (ds), github-desktop (gd)" CompactGitOps = " pull (p), exec (x), status (st), watch (w), has-any-updates, latest-branch (lb)" CompactRelease = " release (r), release-pull (relp), release-self (rs), release-branch (rb), temp-release" CompactRelInfo = "" /* 139-byte string literal not displayed */ CompactData = " export (ex), import (im), profile (pf), bookmark (bk), db-reset" CompactHistory = " history (hi), history-reset (hr), stats (ss)" CompactAmend = " amend (am), amend-list (al)" CompactProject = " go-repos (gr), node-repos (nr), react-repos (rr), cpp-repos (cr), csharp-repos (csr)" CompactSSH = " ssh" CompactZip = " zip-group (z)" CompactEnvTools = " env, install (in), uninstall (un)" CompactTasks = " task" CompactVisualize = " dashboard (db)" CompactCommitXfer = " commit-right (cmr) — LIVE, commit-left (cml), commit-both (cmb) — scaffolds" CompactUtilities = "" /* 243-byte string literal not displayed */ CompactNoMatchFmt = " No group matching '%s'. Showing all groups:\n" )
Help group headers.
const ( // Scan flags help section. HelpScanFlags = "Scan flags:" HelpConfig = " --config <path> Config file (default: ./data/config.json)" HelpMode = " --mode ssh|https Clone URL style (default: https)" HelpOutput = " --output csv|json|terminal Output format (default: terminal)" HelpOutputPath = " --output-path <dir> Output directory (default: .gitmap/output)" HelpOutFile = " --out-file <path> Exact output file path" HelpScanFlagGitHubDesktop = " --github-desktop Add repos to GitHub Desktop" HelpOpen = " --open Open output folder after scan" HelpQuiet = " --quiet Suppress clone help section (for CI/scripted use)" // Clone flags help section. HelpCloneFlags = "Clone flags:" HelpTargetDir = " --target-dir <dir> Base directory for clones (default: .)" HelpSafePull = " --safe-pull Pull existing repos with retry + unlock diagnostics (auto-enabled)" HelpVerbose = " --verbose Write detailed debug log to a timestamped file" // Release flags help section. HelpReleaseFlags = "Release flags:" HelpAssets = " --assets <path> Directory or file to attach to the release" HelpCommit = " --commit <sha> Create release from a specific commit" HelpRelBranch = " --branch <name> Create release from latest commit of a branch" HelpBump = " --bump major|minor|patch Auto-increment from latest released version" HelpDraft = " --draft Create an unpublished draft release" HelpDryRun = " --dry-run Preview release steps without executing" HelpCompressFlag = " --compress Wrap assets in .zip (Windows) or .tar.gz archives" HelpChecksumsFlag = " --checksums Generate SHA256 checksums.txt for assets" )
Help section headers and flag-line help strings, grouped by command domain. Extracted from constants_cli.go to keep that file under the 200-line guideline.
const ( HintCDRepo = "gitmap cd <repo-name>" HintCDRepoDesc = "Navigate to a repo" HintGroupCreate = "gitmap g create <name>" HintGroupCreateDesc = "Create a group" HintLsType = "gitmap ls go" HintLsTypeDesc = "List only Go projects" HintGroupAdd = "gitmap g add <group> <slug>" HintGroupAddDesc = "Add repos to a group" HintPullGroup = "gitmap g pull" HintPullGroupDesc = "Pull repos in active group" HintGroupShow = "gitmap g show <name>" HintGroupShowDesc = "Show repos in a group" HintGroupDelete = "gitmap g delete <name>" HintGroupDeleteDesc = "Delete a group" HintLsGroups = "gitmap ls groups" HintLsGroupsDesc = "List all groups" HintGPull = "gitmap g pull" HintGPullDesc = "Pull active group repos" HintGStatus = "gitmap g status" HintGStatusDesc = "Show active group status" HintGExec = "gitmap g exec <cmd>" HintGExecDesc = "Run git across active group" HintGClear = "gitmap g clear" HintGClearDesc = "Clear active group" HintCDSetDefault = "gitmap cd set-default <name> <path>" HintCDSetDefaultDesc = "Set a default repo path" HintCDRepos = "gitmap cd repos" HintCDReposDesc = "Browse all repos interactively" HintMGUsage = "gitmap mg g1,g2" HintMGUsageDesc = "Select multiple groups" HintZGCreate = "gitmap z create <name>" HintZGCreateDesc = "Create a zip group" HintZGAdd = "gitmap z add <group> <path>" HintZGAddDesc = "Add files to a zip group" HintZGShow = "gitmap z show <name>" HintZGShowDesc = "Show items in a zip group" HintZGDelete = "gitmap z delete <name>" HintZGDeleteDesc = "Delete a zip group" HintZGRelease = "gitmap r v1.0.0 --zip-group <name>" HintZGReleaseDesc = "Include zip group in release" HintAliasSet = "gitmap a set <alias> <slug>" HintAliasSetDesc = "Create a repo alias" HintAliasList = "gitmap a list" HintAliasListDesc = "List all aliases" HintAliasSuggest = "gitmap a suggest" HintAliasSuggestDesc = "Auto-suggest aliases" HintAliasUse = "gitmap pull -A <alias>" HintAliasUseDesc = "Use alias with any command" HintAliasRemove = "gitmap a remove <alias>" HintAliasRemoveDesc = "Remove an alias" )
Hint messages for project-repos commands (go-repos, node-repos, etc.).
const ( SQLInsertHistory = `` /* 163-byte string literal not displayed */ SQLUpdateHistory = `` /* 129-byte string literal not displayed */ SQLSelectAllHistory = `` /* 176-byte string literal not displayed */ SQLSelectHistoryByCommand = `` /* 194-byte string literal not displayed */ SQLDeleteAllHistory = "DELETE FROM CommandHistory" SQLDropCommandHistory = "DROP TABLE IF EXISTS CommandHistory" )
SQL: command history operations (v15: CommandHistoryId PK).
const ( CmdHistory = "history" CmdHistoryAlias = "hi" CmdHistoryReset = "history-reset" CmdHistoryResetAlias = "hr" )
gitmap:cmd top-level History CLI commands.
const ( HelpHistory = " history (hi) Show command execution audit log (--limit N, --json, --command, --detail)" HelpHistoryReset = " history-reset (hr) Clear command history (--confirm required)" )
History help text.
const ( FlagDescDetail = "Detail level: basic, standard, or detailed (default: standard)" FlagDescCommand = "Filter by command name" )
History flag descriptions.
const ( DetailBasic = "basic" DetailStandard = "standard" DetailDetailed = "detailed" )
History detail levels.
const ( MsgHistoryColumnsBasic = "COMMAND TIMESTAMP STATUS" MsgHistoryColumnsStandard = "COMMAND TIMESTAMP FLAGS STATUS DURATION" MsgHistoryColumnsDetailed = "COMMAND TIMESTAMP ARGS FLAGS STATUS DURATION REPOS SUMMARY" MsgHistoryRowBasicFmt = "%-15s %-24s %s\n" MsgHistoryRowStdFmt = "%-15s %-24s %-24s %-7s %s\n" MsgHistoryRowDetailFmt = "%-15s %-24s %-16s %-24s %-7s %-9s %-6s %s\n" )
History terminal columns.
const ( MsgHistoryEmpty = "No command history found.\n" MsgHistoryResetDone = "Command history cleared.\n" ErrHistoryResetFailed = "failed to reset command history: %v\n" ErrHistoryResetNoConfirm = "history-reset requires --confirm flag\n" ErrHistoryQuery = "failed to query command history: %v" MsgHistoryStatusOK = "OK" MsgHistoryStatusFail = "FAIL" )
History messages.
const ( HistoryFlagYes = "yes" HistoryFlagYesShort = "y" HistoryFlagNoPush = "no-push" HistoryFlagDryRun = "dry-run" HistoryFlagMessage = "message" HistoryFlagKeepSandbox = "keep-sandbox" HistoryFlagQuiet = "quiet" HistoryFlagQuietShort = "q" HistoryPathSep = "," HistorySandboxPrefix = "gitmap-history-rewrite-" HistoryFilterRepoBin = "git-filter-repo" HistoryGitBin = "git" HistoryRemoteOrigin = "origin" HistoryPushRefSpec = "--mirror" HistoryForceWithLease = "--force-with-lease" )
History-rewrite (`history-purge` / `history-pin`) flag names. See spec/04-generic-cli/16-history-rewrite.md.
const ( HistoryDescYes = "Skip the push confirmation prompt; force-push immediately on success" HistoryDescNoPush = "Stop after verification; print the manual git push command" HistoryDescDryRun = "Run the rewrite + verification in the sandbox, then exit without pushing" HistoryDescMessage = "Rewrite the commit message of ONLY commits that touch a requested path; other commit messages are left unchanged" HistoryDescKeepSandbox = "Don't delete the temp mirror-clone on exit" HistoryDescQuiet = "Suppress per-phase progress lines; only print errors and the final summary" )
History-rewrite flag descriptions (rendered in --help).
const ( HistoryExitOk = 0 HistoryExitNotInRepo = 2 HistoryExitNoFilterRepo = 3 HistoryExitBadArgs = 4 HistoryExitFilterFailed = 5 HistoryExitVerifyFailed = 6 HistoryExitPushFailed = 7 )
History-rewrite exit codes. Match spec §6 exactly.
const ( HistoryMsgPhaseIdentify = "▸ history-rewrite: identifying origin remote\n" HistoryMsgPhaseClone = "▸ history-rewrite: mirror-cloning %s into %s\n" HistoryMsgPhaseFilterPurge = "▸ history-rewrite: running filter-repo (purge) for %d path(s)\n" HistoryMsgPhaseFilterPin = "▸ history-rewrite: running filter-repo (pin) for %d path(s)\n" HistoryMsgPhaseVerify = "▸ history-rewrite: verifying sandbox\n" HistoryMsgPhasePush = "▸ history-rewrite: pushing to %s with --force-with-lease\n" HistoryMsgVerifyOk = "✓ history-rewrite: verification passed\n" HistoryMsgPushOk = "✓ history-rewrite: push complete\n" HistoryMsgDryRunDone = "✓ history-rewrite: dry-run complete; sandbox at %s\n" HistoryMsgKeepSandbox = "▣ history-rewrite: sandbox kept at %s\n" HistoryMsgManualPush = "▣ history-rewrite: to push manually, run:\n git -C %s push --force-with-lease --mirror %s\n" HistoryMsgConfirmBanner = "" /* 635-byte string literal not displayed */ HistoryMsgConfirmPush = "Type 'yes' to force-push to %s (anything else aborts): " HistoryMsgUserAborted = "▣ history-rewrite: aborted by user; sandbox at %s\n" HistoryMsgInstallHintLinux = "history-rewrite: install with: pip install --user git-filter-repo\n" HistoryMsgInstallHintMac = "history-rewrite: install with: brew install git-filter-repo\n" HistoryMsgInstallHintWin = "history-rewrite: install with: scoop install git-filter-repo (or pip install --user git-filter-repo)\n" HistoryMsgSummary = "history-rewrite: %d path(s), %d commit(s) rewritten, repo size %s -> %s\n" )
History-rewrite user-facing messages. All literals live here (no magic strings rule).
const ( HistoryErrNotInRepo = "history-rewrite: not inside a git repository: %v\n" HistoryErrNoOrigin = "history-rewrite: cannot read origin remote: %v\n" HistoryErrNoFilterRepo = "history-rewrite: `git filter-repo` is not installed.\n" HistoryErrBadArgs = "history-rewrite: %s\n" HistoryErrNoPaths = "expected at least one path argument" HistoryErrConflictFlags = "--yes and --no-push are mutually exclusive" HistoryErrPathNotReadable = "pin: cannot read %s from working tree: %v" HistoryErrMirrorClone = "history-rewrite: mirror-clone failed: %v\n" HistoryErrFilterRepo = "history-rewrite: filter-repo failed (exit %d): %s\n" HistoryErrVerifyPurge = "history-rewrite: verification failed: path %s still has %d commit(s) in history\n" HistoryErrVerifyPin = "history-rewrite: verification failed: path %s has %d distinct content hashes across history (expected 1)\n" HistoryErrPush = "history-rewrite: push failed: %v\n" HistoryErrSandbox = "history-rewrite: cannot create sandbox: %v\n" HistoryErrManifest = "history-rewrite: cannot write blob manifest: %v\n" )
History-rewrite errors.
const ( CmdImport = "import" CmdImportAlias = "im" )
gitmap:cmd top-level Import CLI commands.
const ( MsgImportDone = "Database imported from %s (%d repos, %d groups, %d releases, %d history, %d bookmarks)\n" MsgImportFailed = "import failed: %v\n" MsgImportReadFailed = "failed to read import file: %v\n" MsgImportParseFailed = "failed to parse import file: %v\n" ErrImportNoConfirm = "import requires --confirm flag (existing data will be merged)\n" MsgImportSkipGroup = "skipped group %q: missing member repos\n" )
Import messages.
const ( CmdInstall = "install" CmdInstallAlias = "in" CmdUninstall = "uninstall" CmdUninstallAlias = "un" )
gitmap:cmd top-level Install CLI commands.
const ( HelpInstall = " install (in) <tool> Install a developer tool by name" HelpUninstall = " uninstall (un) <tool> Remove a previously installed tool" )
Install help text.
const ( ToolVSCode = "vscode" ToolNodeJS = "node" ToolYarn = "yarn" ToolBun = "bun" ToolPnpm = "pnpm" ToolPython = "python" ToolGo = "go" ToolGit = "git" ToolGitLFS = "git-lfs" ToolGHCLI = "gh" ToolGitHubDesktop = "github-desktop" ToolCPP = "cpp" ToolPHP = "php" ToolPowerShell = "powershell" ToolChocolatey = "chocolatey" ToolWinget = "winget" ToolNpp = "npp" ToolNppSettings = "npp-settings" ToolNppInstall = "install-npp" ToolVSCodeSync = "vscode-settings" ToolOBSSync = "obs-settings" ToolWTSync = "wt-settings" ToolScripts = "scripts" ToolDbeaver = "dbeaver" ToolStickyNotes = "sticky-notes" ToolLiteDB = "litedb" ToolVSCodeCtx = "vscode-ctx" ToolPwshCtx = "pwsh-ctx" ToolOBS = "obs" ToolAllDevTools = "all" )
Supported tool names — Core.
const ( ToolMySQL = "mysql" ToolMariaDB = "mariadb" ToolPostgreSQL = "postgresql" ToolSQLite = "sqlite" ToolMongoDB = "mongodb" ToolCouchDB = "couchdb" ToolRedis = "redis" ToolCassandra = "cassandra" ToolNeo4j = "neo4j" ToolElasticsearch = "elasticsearch" ToolDuckDB = "duckdb" )
Supported tool names — Databases.
const ( PkgMgrChocolatey = "choco" PkgMgrWinget = "winget" PkgMgrApt = "apt" PkgMgrBrew = "brew" PkgMgrSnap = "snap" PkgMgrDnf = "dnf" PkgMgrPacman = "pacman" )
Package manager names.
const ( FlagInstallManager = "manager" FlagInstallVersion = "version" FlagInstallVerbose = "verbose" FlagInstallDryRun = "dry-run" FlagInstallCheck = "check" FlagInstallList = "list" FlagInstallStatus = "status" FlagInstallUpgrade = "upgrade" FlagInstallYes = "yes" )
Install flag names.
const ( FlagDescInstallManager = "Force package manager (choco, winget, apt, brew, snap)" FlagDescInstallVersion = "Install a specific version" FlagDescInstallVerbose = "Show full installer output" FlagDescInstallDryRun = "Show install command without executing" FlagDescInstallCheck = "Only check if tool is installed" FlagDescInstallList = "List all supported tools" FlagDescInstallStatus = "Show installed tools from database" FlagDescInstallUpgrade = "Upgrade an already-installed tool" FlagDescInstallYes = "Auto-confirm install without prompting" )
Install flag descriptions.
const ( FlagUninstallDryRun = "dry-run" FlagUninstallForce = "force" FlagUninstallPurge = "purge" )
Uninstall flag names.
const ( FlagDescUninstallDryRun = "Show uninstall command without executing" FlagDescUninstallForce = "Skip confirmation prompt" FlagDescUninstallPurge = "Remove config files too" )
Uninstall flag descriptions.
const ( ChocoPkgVSCode = "vscode" ChocoPkgNodeJS = "nodejs" ChocoPkgYarn = "yarn" ChocoPkgBun = "bun" ChocoPkgPnpm = "pnpm" ChocoPkgPython = "python" ChocoPkgGo = "golang" ChocoPkgGit = "git" ChocoPkgGitLFS = "git-lfs" ChocoPkgGHCLI = "gh" ChocoPkgGitHubDesktop = "github-desktop" ChocoPkgCPP = "mingw" ChocoPkgPHP = "php" ChocoPkgMySQL = "mysql" ChocoPkgMariaDB = "mariadb" ChocoPkgPostgreSQL = "postgresql" ChocoPkgSQLite = "sqlite" ChocoPkgMongoDB = "mongodb" ChocoPkgCouchDB = "couchdb" ChocoPkgRedis = "redis-64" ChocoPkgNeo4j = "neo4j-community" ChocoPkgElasticsearch = "elasticsearch" ChocoPkgDuckDB = "duckdb" ChocoPkgNpp = "notepadplusplus" ChocoPkgDbeaver = "dbeaver" ChocoPkgOBS = "obs-studio" ChocoPkgPowerShell = "powershell-core" ChocoPkgStickyNotes = "microsoft-windows-terminal" // sticky notes is a Windows Store app )
Chocolatey package IDs.
const ( WingetPkgVSCode = "Microsoft.VisualStudioCode" WingetPkgPowerShell = "Microsoft.PowerShell" WingetPkgDbeaver = "dbeaver.DBeaverCommunity" WingetPkgOBS = "OBSProject.OBSStudio" WingetPkgStickyNotes = "9NBLGGH4QGHW" // Microsoft Sticky Notes Store ID WingetPkgGitHubDesktop = "GitHub.GitHubDesktop" )
Winget package IDs.
const ( AptPkgNodeJS = "nodejs" AptPkgPython = "python3" AptPkgGo = "golang" AptPkgGit = "git" AptPkgGitLFS = "git-lfs" AptPkgCPP = "g++" AptPkgPHP = "php" AptPkgMySQL = "mysql-server" AptPkgMariaDB = "mariadb-server" AptPkgPostgreSQL = "postgresql" AptPkgSQLite = "sqlite3" AptPkgMongoDB = "mongod" AptPkgCouchDB = "couchdb" AptPkgRedis = "redis-server" AptPkgCassandra = "cassandra" AptPkgElasticsearch = "elasticsearch" )
Apt package IDs.
const ( BrewPkgNodeJS = "node" BrewPkgPython = "python" BrewPkgGo = "go" BrewPkgGit = "git" BrewPkgGitLFS = "git-lfs" BrewPkgGHCLI = "gh" BrewPkgCPP = "gcc" BrewPkgPHP = "php" BrewPkgMySQL = "mysql" BrewPkgMariaDB = "mariadb" BrewPkgPostgreSQL = "postgresql" BrewPkgSQLite = "sqlite" BrewPkgMongoDB = "mongodb-community" BrewPkgCouchDB = "couchdb" BrewPkgRedis = "redis" BrewPkgNeo4j = "neo4j" BrewPkgElasticsearch = "elasticsearch" BrewPkgDuckDB = "duckdb" BrewPkgDbeaver = "dbeaver-community" BrewPkgOBS = "obs" )
Brew package IDs.
const ( SnapPkgCouchDB = "couchdb" SnapPkgRedis = "redis" )
Snap package IDs.
const ( MsgInstallChecking = "\n Checking if %s is installed...\n" MsgInstallFound = " ✓ %s is already installed (version: %s)\n" MsgInstallNotFound = " ✗ %s is not installed.\n" MsgInstallInstalling = "\n Installing %s...\n" MsgInstallSuccess = " ✓ %s installed successfully.\n" MsgInstallDryCmd = " [dry-run] Would run: %s\n" MsgInstallVerifying = "\n Verifying %s installation...\n" MsgInstallListHeader = "Supported tools:\n\n" MsgInstallListRow = " %-20s %s\n" MsgInstallRecorded = " ✓ Recorded %s v%s in database.\n" MsgInstallStatusHdr = "Installed tools:\n\n" MsgInstallStatusRow = " %-20s %-12s %-8s %s\n" MsgInstallListCategory = "\n%s\n%s\n" MsgInstallListGrouped = " %s %-22s %-10s %s\n" MsgInstallListLegend = "\nLegend: ● installed ○ not installed ? unknown\n" StatusInstalled = "●" StatusNotInstalled = "○" StatusUnknown = "?" MsgInstallExeVerify = " Verifying %s binary at: %s\n" MsgInstallExeFound = " ✓ Binary confirmed: %s\n" MsgInstallNppSettings = "Syncing Notepad++ settings...\n" MsgInstallNppSkipBin = "Skipping Notepad++ installation (settings-only mode)\n" MsgInstallNppSkipSet = "Skipping Notepad++ settings (install-only mode)\n" MsgInstallNppExtract = "Extracting Notepad++ settings to %s...\n" MsgInstallPrompt = "\n → Install %s %s using %s? (y/N): " MsgInstallPromptNoVer = "\n → Install %s (latest) using %s? (y/N): " MsgInstallAborted = "\n Installation canceled by user.\n" MsgInstallVersion = " → Version: %s\n" MsgInstallVersionLabel = " → Version: latest\n" MsgInstallManager = " → Package manager: %s\n" )
Install terminal messages.
const ( ErrInstallToolRequired = "Tool name is required. Use --list to see available tools." ErrInstallUnknownTool = "Unknown tool: %s. Use --list to see available tools.\n" ErrInstallNoPkgMgr = "No package manager found. Install Chocolatey or Winget first." ErrInstallFailed = "\n ✗ Installation failed for %s.\n" ErrInstallFailedReason = " → Reason: %v\n" ErrInstallFailedVersion = " → Attempted version: %s\n" ErrInstallFailedManager = " → Package manager: %s\n" ErrInstallFailedCmd = " → Command: %s\n" ErrInstallFailedLog = " → Error log: %s\n" ErrInstallFailedHint = " → Share the log file with an AI or support to diagnose the issue.\n" ErrInstallVerifyFailed = "\n ✗ Post-install verification failed for %s.\n" ErrInstallAdminRequired = "%s requires administrator privileges to install.\n" ErrInstallNetworkRequired = "Network connection required for installation." ErrInstallExeNotFound = " Error: post-install binary not found at %s (operation: verify, reason: file does not exist)\n" )
Install error messages.
const ( MsgInstallAptUpdate = "\n Updating package index (apt-get update)...\n" MsgInstallAptUpdateDone = " ✓ Package index updated.\n" ErrInstallAptUpdateFailed = " ⚠ apt-get update failed (continuing anyway): %v\n" )
Apt-specific messages.
const ( ErrNppZipNotFound = "Error: settings zip not found at %s: %v (operation: extract, reason: file does not exist)\n" ErrNppSourceDir = "Error: settings source directory not found at %s: %v (operation: read, reason: directory does not exist)\n" ErrNppDirCreate = "Error: failed to create directory %s: %v (operation: mkdir, reason: path is inaccessible)\n" ErrNppExtractEntry = "Error: failed to open zip entry '%s' for extraction to %s: %v (operation: extract)\n" ErrNppFileCreate = "Error: failed to create file at %s: %v (operation: write, reason: path is inaccessible)\n" ErrNppFileCopy = "Error: failed to copy zip entry '%s' to %s: %v (operation: extract)\n" ErrNppFileRead = "Error: failed to read settings file at %s: %v (operation: read)\n" ErrNppFileWrite = "Error: failed to write settings file to %s: %v (operation: write)\n" ErrNppWindowsOnly = "Error: Notepad++ settings sync is only supported on Windows (current OS: %s)\n" ErrNppNoAppData = "Error: APPDATA environment variable not set (operation: resolve, reason: environment variable not set)\n" MsgNppSettingsSynced = "Settings synced to %s\n" MsgNppSettingsFallback = "Settings synced to %s (fallback — zip was missing)\n" )
NPP error messages — Code Red: all file errors include exact path and reason.
const ( MsgUninstallRemoving = "Removing %s...\n" MsgUninstallSuccess = "%s uninstalled successfully.\n" MsgUninstallDryCmd = "[dry-run] Would run: %s\n" MsgUninstallConfirm = "Uninstall %s? (y/N): " ErrUninstallFailed = "Uninstall failed for %s: %v\n" ErrUninstallNotFound = "%s is not tracked in the database. Use --force to try anyway.\n" ErrUninstallDBRemove = "Warning: could not remove %s from database: %v\n" )
Uninstall messages.
const ( MsgScriptsTarget = " → Scripts target: %s\n" MsgScriptsCloning = " Cloning gitmap repo for scripts...\n %s\n" MsgScriptsSkip = " ⚠ Skipped (not found): %s\n" MsgScriptsCopied = " ✓ Copied: %s\n" MsgScriptsDone = "\n ✅ %d scripts installed to %s\n" ErrScriptsMkdir = " ✗ Could not create target directory %s: %v\n" ErrScriptsTemp = " ✗ Could not create temp directory: %v\n" ErrScriptsClone = " ✗ Clone failed: %v\n" ErrScriptsCopy = " ✗ Failed to copy %s: %v\n" )
Scripts install messages.
const ( ToolCategoryCore = "Core Tools" ToolCategoryDatabase = "Databases" )
Tool categories.
const ( SQLInsertInstalledTool = `` /* 237-byte string literal not displayed */ SQLSelectInstalledTool = `` /* 186-byte string literal not displayed */ SQLSelectAllInstalled = `` /* 185-byte string literal not displayed */ SQLDeleteInstalledTool = `DELETE FROM InstalledTool WHERE Tool = ?` SQLExistsInstalledTool = `SELECT COUNT(*) FROM InstalledTool WHERE Tool = ?` SQLDropInstalledTool = `DROP TABLE IF EXISTS InstalledTool` SQLDropInstalledTools = `DROP TABLE IF EXISTS InstalledTools` // legacy )
SQL: InstalledTool queries (v15).
const ( MsgLLMDocsWritten = " ✓ LLM.md written to %s\n" MsgLLMDocsGenning = " ↻ Generating LLM.md from command registry...\n" ErrLLMDocsWrite = " ✗ Could not write LLM.md: %v\n" HelpLLMDocs = " llm-docs (ld) Generate LLM.md reference for AI assistants" )
llm-docs messages.
const ( FlagLLMDocsStdout = "stdout" FlagDescLLMDocsStdout = "Print to stdout instead of writing LLM.md file" FlagLLMDocsFormat = "format" FlagDescLLMDocsFormat = "Output format: markdown (default) or json" ErrLLMDocsFormat = " ✗ Unknown format %q — use markdown or json\n" FlagLLMDocsSections = "sections" FlagDescLLMDocsSections = "Comma-separated sections to include (default: all)" ErrLLMDocsSections = " ✗ Unknown section %q — valid: commands,architecture,flags,conventions,structure,database,installation,patterns\n" LLMDocsValidSections = "commands,architecture,flags,conventions,structure,database,installation,patterns" )
llm-docs flags.
const ( MsgLockCheckScanning = "Checking for processes locking %s...\n" MsgLockCheckFound = "The following processes are using this folder:\n%s\n" MsgLockCheckKillPrompt = "Terminate these processes to allow deletion? [y/N] " MsgLockCheckKilling = "Terminating %s (PID %d)...\n" MsgLockCheckKilled = "✓ Terminated %s\n" MsgLockCheckRetrying = "Retrying folder removal...\n" WarnLockCheckKillFailed = "Warning: could not terminate %s (PID %d): %v\n" WarnLockCheckScanFailed = "Warning: could not scan for locking processes: %v\n" MsgLockCheckNoneFound = "No locking processes detected.\n" )
Lock-check messages.
const ( NoteNoRemote = "no remote configured" UnknownRepoName = "unknown" )
Notes.
const ( GitHubDesktopBin = "github" OSWindows = "windows" MsgDesktopNotFound = "GitHub Desktop CLI not found — skipping." MsgDesktopAdded = " ✓ Added to GitHub Desktop: %s\n" MsgDesktopFailed = " ✗ Failed to add %s: %v\n" MsgDesktopSummary = "GitHub Desktop: %d added, %d failed\n" MsgGHDesktopRegister = " Registering with GitHub Desktop: %s\n" MsgGHDesktopDone = " ✓ Registered with GitHub Desktop: %s\n" ErrGHDesktopCwd = " ✗ Could not determine current directory: %v\n" ErrGHDesktopNotRepo = " ✗ Not a git repository: %s\n (run `gitmap gd <path>` to register a different folder)\n" ErrGHDesktopInvoke = " ✗ GitHub Desktop CLI failed: %v\n%s\n" )
GitHub Desktop.
const ( MsgLatestBranchFetching = " Fetching remotes..." MsgLatestBranchFetchWarning = " Warning: fetch failed: %v\n" LBUnknownBranch = "<unknown>" // `lb --switch` / `-s` and `branch default` post-report messages. MsgLatestBranchSwitching = " ▶ Switching to %s...\n" ErrLatestBranchSwitchNoTarget = " ✗ No usable branch name to switch to (try --contains-fallback)" ErrLatestBranchSwitchFailed = " ✗ Failed to checkout %s: %v\n" MsgBranchDefaultSwitching = " ▶ Switching to default branch %s...\n" ErrBranchDefaultFailed = " ✗ Failed to checkout default branch %s: %v\n" ErrBranchUnknownSubcommand = " ✗ Unknown branch subcommand: %q (expected: default | def)\n" ErrBranchMissingSubcommand = " ✗ Missing subcommand for `gitmap branch` (expected: default | def)\n" ErrBranchNotRepo = " ✗ Not inside a git work tree\n" )
Latest-branch display messages.
const ( ErrGenericFmt = "Error: %v\n" ErrBareFmt = "%v\n" )
Generic error formats.
const ( CmdExplorer = "explorer" // gitmap:cmd skip CmdOpen = "open" // gitmap:cmd skip CmdXdgOpen = "xdg-open" // gitmap:cmd skip CmdWindowsShell = "cmd" // gitmap:cmd skip CmdArgSlashC = "/c" // gitmap:cmd skip CmdArgStart = "start" // gitmap:cmd skip CmdArgEmpty = "" // gitmap:cmd skip )
gitmap:cmd top-level OS file-explorer commands.
const ( ErrDesktopReadFailed = "Error reading %s: %v\n" ErrDesktopParseFailed = "Error parsing JSON from %s: %v\n" ErrNoAbsPath = "no absolute path" )
Desktop sync error messages.
const ( ErrUnknownCommand = "Unknown command: %s\n" ErrUnknownCommandURLHint = "Unknown command: %s\n" + "\n" + " This looks like a git URL. Newer gitmap versions auto-redirect\n" + " bare-URL invocations to `gitmap clone`. Your installed binary\n" + " appears to predate that shortcut (added in v3.81.0).\n" + "\n" + " Fix one of two ways:\n" + " 1. Use the explicit form right now:\n" + " gitmap clone %[1]s\n" + " 2. Update gitmap so the shortcut is built in:\n" + " gitmap update\n" + " (then re-open your terminal so PATH picks up the new binary)\n\n" ErrUnknownGroupSub = "Unknown group subcommand: %s\n" )
Command dispatch errors.
const ( DocsURL = "https://gitmap.dev/docs" MsgDocsOpened = " ✓ Opened %s\n" ErrDocsOpen = " ✗ Failed to open browser: %v\n" )
Docs command.
const ( MsgFoundRepos = "Found %d repositories.\n" MsgCSVWritten = " 📊 CSV %s\n" MsgJSONWritten = " 🧬 JSON %s\n" MsgTextWritten = " 📝 Text list %s\n" MsgStructureWritten = " 🌳 Structure %s\n" MsgCloneScript = " 🪄 Clone PS1 %s\n" MsgDirectClone = " ⚡ HTTPS PS1 %s\n" MsgDirectCloneSSH = " 🔐 SSH PS1 %s\n" MsgDesktopScript = " 🖥️ Desktop PS1 %s\n" MsgCloneComplete = "\nClone complete: %d succeeded, %d failed\n" MsgAutoSafePull = "Existing repos detected — safe-pull enabled automatically.\n" MsgOpenedFolder = "Opened output folder: %s\n" MsgVerboseLogFile = "Verbose log: %s\n" MsgDesktopSyncStart = "\n Syncing repos to GitHub Desktop from %s...\n" MsgDesktopSyncSkipped = " ⊘ Skipped (already exists): %s\n" MsgDesktopSyncAdded = " ✓ Added to GitHub Desktop: %s\n" MsgDesktopSyncFailed = " ✗ Failed: %s — %v\n" MsgDesktopSyncDone = "\n GitHub Desktop sync: %d added, %d skipped, %d failed\n" MsgNoOutputDir = "Error: .gitmap/output/ not found in current directory.\nRun 'gitmap scan' first to generate output files." MsgNoJSONFile = "Error: %s not found.\nRun 'gitmap scan' first to generate the JSON output." MsgFailedClones = "\nFailed clones:" MsgFailedEntry = " - %s (%s): %s\n" MsgPullStarting = "\n Pulling %s (%s)...\n" MsgPullSuccess = " ✓ %s is up to date.\n" MsgPullFailed = " ✗ Pull failed for %s: %s\n" MsgPullAvailable = "\nAvailable repos:" MsgPullListEntry = " - %s\n" WarnVerboseLogFailed = "Warning: could not create verbose log: %v\n" MsgRescanReplay = "\n Rescanning with cached flags (dir: %s)...\n" MsgScanCacheSaved = " 💾 Cache %s\n" MsgDBUpsertDone = " ✅ %d repositories upserted into database\n" MsgDBUpsertFailed = "Warning: database upsert failed: %v\n" // Section headers for the post-scan summary. // MsgSectionArtifacts takes the common output base directory so it can be // printed once instead of repeated on every file line. MsgSectionArtifacts = "\n📦 Output Artifacts\n" + MsgSectionRule + "\n📂 Base: %s\n\n" MsgSectionDatabase = "\n🗄️ Database\n" + MsgSectionRule + "\n" MsgSectionProjects = "\n🔍 Project Detection\n" + MsgSectionRule + "\n" MsgSectionDone = "\n🎉 Scan complete.\n" MsgSectionRule = "" /* 132-byte string literal not displayed */ MsgScanFolderTagged = " 🏷️ Tagged %d repo(s) with scan folder #%d\n" MsgUpdateStarting = "\n Updating gitmap from source repo...\n" MsgUpdateRepoPath = " → Repo path: %s\n" MsgUpdateVersion = "\n ✓ Updated to gitmap v%s\n" )
CLI messages.
const ( MsgListHeader = "SLUG REPO NAME" MsgListSeparator = "" /* 126-byte string literal not displayed */ MsgListRowFmt = "%-20s %s\n" MsgListVerboseFmt = "%-20s %-20s %s\n" MsgListEmpty = "No repos tracked. Run 'gitmap scan' first." MsgListDBPath = " → Database: %s\n" MsgGroupCreated = "Group created: %s\n" MsgGroupDeleted = "Group deleted: %s\n" MsgGroupAdded = "Added %s to group %s\n" MsgGroupRemoved = "Removed %s from group %s\n" MsgGroupHeader = "GROUP REPOS DESCRIPTION" MsgGroupRowFmt = "%-15s %-7d %s\n" MsgGroupShowHeader = "Group: %s (%d repos)\n" MsgGroupShowRowFmt = " %-16s %s\n" MsgGroupEmpty = "No groups defined. Use 'gitmap group create <name>' to create one." MsgGroupActivated = "Active group set: %s\n" MsgGroupActiveShow = "Active group: %s\n" MsgGroupNoActive = "No active group. Use 'gitmap g <name>' to set one." MsgGroupCleared = "Active group cleared." ErrGroupNameReq = "Error: group name is required" ErrGroupUsage = "Usage: gitmap group <create|add|remove|list|show|delete> [args]" ErrGroupSlugReq = "Error: at least one slug is required" ErrListDBFailed = "Error: could not open database: %v\nRun 'gitmap scan' first.\n" ErrNoDatabase = "No database found. Run 'gitmap scan' first." MsgDBResetDone = "Database reset: all repos and groups cleared.\n" ErrDBResetFailed = "Error: database reset failed: %v\n" ErrDBResetNoConfirm = "Error: this will delete all tracked repos and groups.\nRun with --confirm to proceed: gitmap db-reset --confirm" MsgResetFileRemoved = "Removed database file: %s\n" MsgResetReseeded = "Reseeded %s\n" MsgResetDone = "Reset complete: database file deleted, schema rebuilt, seeds reapplied.\n" ErrResetNoConfirm = "" /* 137-byte string literal not displayed */ ErrResetRemoveFile = "Error: could not delete database file %s: %v\n" ErrResetReinit = "Error: could not reinitialize database: %v\n" )
List and group messages.
const ( ErrLatestBranchNotRepo = "Error: not inside a Git repository." ErrLatestBranchNoRefs = "Error: no remote-tracking branches found for remote '%s'.\n" ErrLatestBranchNoRefsAll = "Error: no remote-tracking branches found on any remote." ErrLatestBranchNoCommits = "Error: could not read commit info for remote branches." ErrLatestBranchNoMatch = "Error: no branches matching filter '%s'.\n" )
Latest-branch error messages.
const ( ErrSourceRequired = "Error: source file or URL is required" ErrCloneUsage = "Usage: gitmap clone <url|source|json|csv|text> [folder] [--target-dir <dir>] [--safe-pull]" ErrShorthandNotFound = "Error: %s not found.\nRun 'gitmap scan' first to generate output files.\n" ErrConfigLoad = "Error: failed to load config from %s: %v (operation: read)\n" ErrScanFailed = "Error: scan failed on directory %s: %v (operation: resolve)\n" ErrScanDirNotFound = "Error: scan target %s does not exist (resolved to %s)\n" ErrScanDirNotDir = "Error: scan target %s is not a directory (resolved to %s)\n" // ErrScanRelativeRootInvalid is emitted when --relative-root cannot be // resolved to an existing directory or is not a parent of the scan dir. // Operation tag mirrors ErrScanFailed style for log-grep consistency. ErrScanRelativeRootInvalid = "Error: --relative-root %s is invalid: %v (operation: resolve)\n" // ErrScanRelativeRootNotAncestor fires when the user-supplied root // does not contain a discovered repo, which would yield a "../" // path in the output and break clone-script reproducibility. ErrScanRelativeRootNotAncestor = "Error: --relative-root %s is not an ancestor of repo %s (would produce %q)\n" MsgScanResolvedDir = " ↳ Resolved %q → %s\n" // MsgScanRelativeRoot announces the pinned RelativePath base when it // differs from the scan dir, so the user sees that output paths // will be computed against this directory rather than [dir]. MsgScanRelativeRoot = " ↳ RelativePath root pinned to %s\n" ErrCloneFailed = "Error: clone failed for source file %s: %v (operation: read)\n" ErrOutputFailed = "Error: output generation failed: %v\n" ErrCreateDir = "Error: cannot create directory at %s: %v (operation: mkdir)\n" ErrCreateFile = "Error: cannot create file at %s: %v (operation: write)\n" ErrNoRepoPath = `` /* 709-byte string literal not displayed */ ErrUpdateFailed = "Update error: %v\n" ErrPullSlugRequired = "Error: repo name is required" ErrPullUsage = "Usage: gitmap pull <repo-name> [--verbose]" ErrPullLoadFailed = "Error: could not load gitmap.json at %s: %v (operation: read)\n" ErrPullNotFound = "Error: no repo found matching '%s'\n" ErrPullNotRepo = "Error: %s is not a git repository\n" ErrRescanNoCache = "Error: no previous scan found. Run 'gitmap scan' first.\n%v\n" ErrSetupLoadFailed = "Error: could not load git-setup.json at %s: %v (operation: read)\n" ErrStatusLoadFailed = "Error: could not load gitmap.json at %s for status: %v (operation: read)\nRun 'gitmap scan' first.\n" MsgStatusNoData = "" /* 139-byte string literal not displayed */ ErrExecUsage = "Usage: gitmap exec <git-args...>\nExample: gitmap exec fetch --prune" ErrExecLoadFailed = "Error: could not load gitmap.json at %s: %v (operation: read)\nRun 'gitmap scan' first.\n" ErrReleaseVersionRequired = "Error: version is required.\nProvide a version argument, use --bump, or create a version.json file." ErrReleaseUsage = "" /* 133-byte string literal not displayed */ ErrReleaseBranchUsage = "Usage: gitmap release-branch <release/vX.Y.Z> [--assets <path>] [--draft]" ErrReleaseAlreadyExists = "Error: version %s is already released. See .gitmap/release/%s.json for details.\n" ErrReleaseTagExists = "Error: tag %s already exists.\n" ErrReleaseBranchNotFound = "Error: branch %s does not exist.\n" ErrReleaseCommitNotFound = "Error: commit %s not found.\n" ErrReleaseInvalidVersion = "Error: '%s' is not a valid version.\n" ErrReleaseBumpNoLatest = "Error: no previous release found. Create an initial release before using --bump.\n" ErrReleaseBumpConflict = "Error: --bump cannot be used with an explicit version argument.\n" ErrReleaseCommitBranch = "Error: --commit and --branch are mutually exclusive.\n" ErrReleasePushFailed = "Error: failed to push to remote: %v\n" ErrReleaseVersionLoad = "Error: could not read version.json at %s: %v (operation: read)\n" ErrReleaseMetaWrite = "Error: could not write release metadata at %s: %v (operation: write)\n" ErrChangelogRead = "Error: could not read CHANGELOG.md at %s: %v (operation: read)\n" ErrChangelogVersionNotFound = "Error: version %s not found in CHANGELOG.md\n" ErrChangelogOpen = "Error: could not open CHANGELOG.md at %s: %v (operation: open)\n" )
CLI error messages.
const ( MsgListReleasesEmpty = "No releases found." MsgListReleasesHeader = "Releases (%d found)\n" MsgListReleasesSeparator = "" /* 216-byte string literal not displayed */ MsgListReleasesColumns = " VERSION TAG BRANCH DRAFT LATEST SOURCE DATE" MsgListReleasesRowFmt = " %-10s %-12s %-19s %-6s %-7s %-8s %s\n" ErrListReleasesFailed = "Error: failed to load releases: %v\n" MsgYes = "yes" MsgNo = "no" )
List-releases messages.
const ( MsgListReleasesAllReposEmpty = "No releases recorded across any repo. Run `gitmap release` in any repo first." MsgListReleasesAllReposHeader = "Releases across all repos (%d found)\n" MsgListReleasesAllReposSeparator = "" /* 252-byte string literal not displayed */ MsgListReleasesAllReposColumns = " REPO VERSION TAG BRANCH LATEST SOURCE DATE" MsgListReleasesAllReposRowFmt = " %-20s %-10s %-12s %-19s %-7s %-8s %s\n" )
List-releases --all-repos messages (v3.20.0). Wider table — adds REPO column.
const ( MsgReleasesImported = "Releases imported: %d from .gitmap/release/\n" WarnReleaseImportSkip = "Warning: skipping %s: %v\n" ReleaseGlob = "v*.json" )
Release import messages.
const ( MsgPendingMetaFound = " → Found %d unreleased version(s) from .gitmap/release/ metadata\n" MsgPendingMetaRelease = " → Creating release from metadata: %s (commit: %s)\n" WarnPendingMetaNoCommit = " ⚠ Skipping %s: commit %s not found in repository\n" WarnPendingMetaNoSHA = " ⚠ Skipping %s: no commit SHA in metadata\n" )
Pending metadata discovery messages.
const ( MsgClearReleaseDone = " ✓ Removed .gitmap/release/%s.json\n" MsgClearReleaseDryRun = " [dry-run] Would remove %s\n" ErrClearReleaseUsage = "Usage: gitmap clear-release-json <version> [--dry-run]\nExample: gitmap clear-release-json v2.20.0" ErrClearReleaseNotFound = "Error: no release file found for %s\n" ErrClearReleaseFailed = "Error: could not remove release file at %s: %v (operation: delete)\n" )
Clear release JSON messages.
const ( MsgRevertCheckout = " → Checking out %s...\n" MsgRevertStarting = "\n Building reverted version...\n" MsgRevertDone = "\n ✓ Revert complete.\n" ErrRevertUsage = "Usage: gitmap revert <version>\nExample: gitmap revert v2.9.0" ErrRevertTagNotFound = "Error: tag %s not found locally. Run 'git fetch --tags' first.\n" ErrRevertCheckoutFailed = "Error: git checkout failed: %v\n" ErrRevertFailed = "Revert error: %v\n" RevertScriptLogExec = "executing revert script: %s" RevertScriptLogExit = "revert script exited: err=%v" )
Revert messages.
const ( NetworkProto = "tcp" NetworkCheckHost = "github.com:443" NetworkTimeoutSec = 5 ErrOffline = "network unavailable — cannot reach github.com" MsgOfflineWarning = "\n ⚠ Network unavailable — cannot reach github.com.\n" MsgOfflineHint = " Offline operations (scan, list, status, group) still work.\n" )
Network / offline detection.
const ( MsgMigrated = "Migrated %s/ -> %s/\n" MsgMergedAndRemoved = "Merged %s/ into %s/ (%d files copied, %d skipped) and removed legacy folder\n" ErrMigrationFailed = "Error: failed to migrate directory %s: %v (operation: move, reason: path is inaccessible)\n" )
Legacy directory migration messages.
const ( MsgLegacyIDMigrationStart = "Migrating database from legacy UUID IDs to integer IDs..." MsgLegacyIDMigrationDone = "Database migration complete. Group-repo associations have been reset." )
Legacy ID migration messages.
const ( MsgCloneURLCloning = "Cloning %s into %s...\n" MsgCloneURLDone = "Cloned %s successfully.\n" ErrCloneURLFailed = "Error: clone failed for %s: %v (operation: git-clone)\n" MsgCloneDesktopPrompt = "Add to GitHub Desktop? (y/n): " ErrCloneURLExists = "Error: target folder already exists: %s\n" )
Direct URL clone messages.
const ( MsgCloneReplaceFree = " [clone] target free, cloning directly into %s\n" MsgCloneReplaceExists = " [clone] target exists: %s\n" MsgCloneReplaceStrategy1 = " [clone] strategy 1/2 — direct remove + clone" MsgCloneReplaceStrat1Fail = " [clone] strategy 1/2 failed: %v\n" MsgCloneReplaceStrategy2 = " [clone] strategy 2/2 — temp-clone then swap-in-place" MsgCloneReplaceTempClone = " [clone] cloning into %s\n" MsgCloneReplaceEmptying = " [clone] emptying target contents (%d entries) in %s\n" MsgCloneReplaceMoving = " [clone] moving %d entries from temp into target\n" MsgCloneReplaceSwapDone = " [clone] swap complete; target now points at fresh clone" WarnCloneReplaceEntryFail = " [clone] could not remove %s: %v\n" FlagDescCloneNoReplace = "Abort if the target folder already exists (disables replace)" )
Clone replace-existing-folder flow (spec/01-app/96-clone-replace-existing-folder.md).
const ( VSCodeBin = "code" VSCodeFlagReuseWindow = "--reuse-window" VSCodeFlagNewWindow = "--new-window" MsgVSCodeOpening = " Opening %s in VS Code...\n" MsgVSCodeOpened = " VS Code opened." MsgVSCodeNotFound = " VS Code not found on PATH — skipping editor open.\n" ErrVSCodeOpenFailed = " Warning: could not open VS Code: %v\n" ErrVSCodeAdminLock = " Warning: VS Code may be running as administrator — could not open automatically.\n" )
VS Code integration messages.
const ( CmdMv = "mv" CmdMove = "move" CmdMergeBoth = "merge-both" CmdMergeBothA = "mb" CmdMergeLeft = "merge-left" CmdMergeLeftA = "ml" CmdMergeRight = "merge-right" CmdMergeRgtA = "mr" )
gitmap:cmd top-level Move/merge command IDs and aliases.
Spec: spec/01-app/97-move-and-merge.md
const ( FlagMMYes = "yes" FlagMMYesShort = "y" FlagMMAccept = "accept-all" FlagMMAcceptShrt = "a" FlagMMPreferL = "prefer-left" FlagMMPreferR = "prefer-right" FlagMMPreferNew = "prefer-newer" FlagMMPreferSkip = "prefer-skip" FlagMMNoPush = "no-push" FlagMMNoCommit = "no-commit" FlagMMForceFold = "force-folder" FlagMMPullFold = "pull" FlagMMInit = "init" FlagMMDryRun = "dry-run" FlagMMIncludeVCS = "include-vcs" FlagMMIncludeNM = "include-node-modules" )
Move/merge flag names.
const ( LogPrefixMv = "[mv]" LogPrefixMergeBoth = "[merge-both]" LogPrefixMergeLeft = "[merge-left]" LogPrefixMergeRight = "[merge-right]" )
Log prefixes per command.
const ( CommitMsgMv = "gitmap mv from %s" CommitMsgMergeBoth = "gitmap merge-both with %s" CommitMsgMergeLeft = "gitmap merge-left from %s" CommitMsgMergeRight = "gitmap merge-right from %s" )
Commit message templates.
const ( GitAddCmd = "add" GitAddAllArg = "-A" GitCommitCmd = "commit" GitMessageArg = "-m" )
Git argument tokens used by movemerge finalize.
const ( ConflictPromptLine = " [L]eft [R]ight [S]kip [A]ll-left [B]all-right [Q]uit" ConflictPromptCue = " > " ErrMMUsageFmt = "Usage: gitmap %s LEFT RIGHT [flags]\n" ErrMMSameFolderFmt = "error: LEFT and RIGHT resolve to the same folder: %s" ErrMMNestedFmt = "error: RIGHT is nested inside LEFT (or vice versa): LEFT=%s RIGHT=%s" ErrMMOriginFmt = "error: folder '%s' exists but its remote is '%s', not '%s'. Pass --force-folder to overwrite, or rename it." ErrMMSrcMissingFmt = "error: source '%s' does not exist" ErrMMQuit = "user pressed Q (quit)" ErrMMPushFailFmt = "Push failed. Local commit is preserved at %s. Resolve manually or re-run with --no-push to skip." )
Conflict prompt and error messages.
const ( CmdMultiGroup = "multi-group" CmdMultiGroupAlias = "mg" )
gitmap:cmd top-level Multi-group CLI commands.
const ( CmdMGClear = "clear" // gitmap:cmd skip CmdMGPull = "pull" // gitmap:cmd skip CmdMGStatus = "status" // gitmap:cmd skip CmdMGExec = "exec" // gitmap:cmd skip )
gitmap:cmd top-level Multi-group subcommands.
const ( MsgMGActive = "Active multi-group: %s\n" MsgMGSet = "Multi-group set: %s\n" MsgMGCleared = "Multi-group selection cleared.\n" MsgMGNone = "No multi-group set. Use 'gitmap mg g1,g2' to select groups.\n" ErrMGUsage = "Usage: gitmap multi-group <group1,group2,...|clear|pull|status|exec>\n" ErrMGGroupMissing = "Group not found: %s\n" )
Multi-group messages.
const ( PathSnippetMarkerOpenFmt = "# gitmap shell wrapper v2 - managed by %s. Do not edit manually." PathSnippetMarkerClose = "# gitmap shell wrapper v2 end" )
PathSnippet marker lines (do not change without bumping snippet version).
const ( PathSnippetBashFmt = `` /* 194-byte string literal not displayed */ PathSnippetZshFmt = `` /* 194-byte string literal not displayed */ PathSnippetFishFmt = `` /* 142-byte string literal not displayed */ PathSnippetPwshFmt = `` /* 238-byte string literal not displayed */ )
PathSnippet body templates per shell. Each MUST start with the marker open line and end with the marker close line so awk/sed-based rewriters in run.sh and install.sh can locate the block.
const ( PathSnippetShellBash = "bash" PathSnippetShellZsh = "zsh" PathSnippetShellFish = "fish" PathSnippetShellPwsh = "pwsh" )
Shell identifiers accepted by `gitmap setup print-path-snippet --shell`.
const ( FlagDescPathSnippetShell = "Target shell: bash | zsh | fish | pwsh" FlagDescPathSnippetDir = "Resolved deploy directory to inject into the snippet" FlagDescPathSnippetManager = "Manager string shown in the snippet header (e.g. run.sh, installer)" )
CLI flag descriptions for the print-path-snippet subcommand.
const ( ErrPathSnippetUnknownShell = "unknown shell %q (expected bash | zsh | fish | pwsh)" ErrPathSnippetDirRequired = "--dir is required" )
Errors.
const ( TableTaskType = "TaskType" TablePendingTask = "PendingTask" TableCompletedTask = "CompletedTask" )
Pending task table names (v15: singular; PK renamed to {Table}Id).
const ( TaskTypeDelete = "Delete" TaskTypeRemove = "Remove" TaskTypeScan = "Scan" TaskTypeClone = "Clone" TaskTypePull = "Pull" TaskTypeExec = "Exec" )
Pending task type seed values.
const ( SQLDropCompletedTask = "DROP TABLE IF EXISTS CompletedTask" SQLDropPendingTask = "DROP TABLE IF EXISTS PendingTask" SQLDropTaskType = "DROP TABLE IF EXISTS TaskType" )
SQL: drop pending task tables.
const ( SQLMigratePendingWorkDir = "ALTER TABLE PendingTask ADD COLUMN WorkingDirectory TEXT DEFAULT ''" SQLMigratePendingCmdArgs = "ALTER TABLE PendingTask ADD COLUMN CommandArgs TEXT DEFAULT ''" SQLMigrateCompletedWorkDir = "ALTER TABLE CompletedTask ADD COLUMN WorkingDirectory TEXT DEFAULT ''" SQLMigrateCompletedCmdArgs = "ALTER TABLE CompletedTask ADD COLUMN CommandArgs TEXT DEFAULT ''" )
SQL: legacy ALTERs to add WorkingDirectory/CommandArgs columns. Idempotent. Run BEFORE the v15 rebuild copies these columns by name.
const ( ErrPendingTaskInsert = "failed to insert pending task: %v (operation: insert)" ErrPendingTaskQuery = "failed to query pending tasks: %v (operation: query)" ErrPendingTaskComplete = "failed to complete task: %v (operation: complete)" ErrPendingTaskFail = "failed to update task failure: %v (operation: update)" ErrPendingTaskNotFound = "pending task not found: %d\n" ErrTaskTypeNotFound = "task type not found: %s" ErrPendingTaskExists = "pending task already exists for %s at %s (Id %d)\n" ErrPendingReplayFailed = "failed to replay command: %v (operation: exec)" )
Pending task error messages.
const ( WarnPendingDBOpen = "Warning: could not open DB for task tracking: %v\n" WarnPendingTypeLookup = "Warning: task type lookup failed: %v\n" WarnPendingInsertFailed = "Warning: could not record pending task: %v\n" WarnPendingCompleteFail = "Warning: could not mark task #%d complete: %v\n" WarnPendingFailUpdate = "Warning: could not update task #%d failure: %v\n" )
Pending task warning messages.
const ( ReasonLockScanFailed = "lock scan failed: %v" ReasonNoLockingProcs = "removal failed, no locking processes found: %v" ReasonUserDeclined = "user declined to terminate locking processes" ReasonRetryFailed = "retry removal failed: %v" ReasonReplayFailed = "command replay failed: %v" ReasonTargetNotFound = "target path does not exist: %s (operation: stat, reason: file does not exist)" ReasonWorkDirNotFound = "working directory does not exist: %s (operation: stat, reason: directory does not exist)" ReasonPermissionDenied = "permission denied at path: %s (operation: %s, reason: %v)" )
Pending task failure reasons for FailureReason field.
const ( HelpPending = " pending List all pending tasks" HelpDoPending = " do-pending (dp) Retry pending tasks (all or by ID)" )
Pending task help text.
const ( MsgPendingTaskCreated = "Task #%d created: %s %s\n" MsgPendingTaskCompleted = "Task #%d completed: %s\n" MsgPendingTaskFailed = "Task #%d failed: %s\n" MsgPendingListHeader = "Pending Tasks:\n" MsgPendingListRow = " #%-6d %-8s %-40s %s\n" MsgPendingListEmpty = "No pending tasks.\n" MsgPendingRetryAll = "Retrying %d pending task(s)...\n" MsgPendingRetryOne = "Retrying task #%d...\n" MsgPendingReplaying = "Replaying: gitmap %s\n" MsgPendingSkipNotExist = "Task #%d skipped: target path no longer exists, marking complete\n" )
Pending task terminal messages.
const ( MsgPendingClearHeader = "" /* 300-byte string literal not displayed */ MsgPendingClearMode = " → Mode: %s\n" MsgPendingClearScanned = " → Scanned %d pending task(s)\n" MsgPendingClearCandidate = " • #%d type=%-8s reason=%-18s target=%s\n" MsgPendingClearDryRun = "\n (dry-run) — re-run without --dry-run to actually delete %d task(s).\n\n" MsgPendingClearConfirm = " → Delete the %d task(s) above? (yes/N): " MsgPendingClearAborted = " ✗ Cleared canceled by user. No tasks deleted.\n" MsgPendingClearDeleted = " ✓ Deleted task #%d (%s)\n" MsgPendingClearDone = "\n ✓ Cleared %d/%d pending task(s).\n\n" MsgPendingClearNoMatches = " ✓ No %s tasks found — nothing to clear.\n" MsgPendingClearReasonURL = "url-shaped-target" MsgPendingClearReasonChar = "illegal-path-char" MsgPendingClearReasonOrph = "orphan-target-missing" MsgPendingClearReasonAll = "user-requested" MsgPendingClearReasonByID = "id-match" )
`gitmap pending clear` messages.
const ( ErrPendingClearUnknownMode = "Error: unknown clear mode %q (allowed: orphans|illegal|all|<id>)\n" ErrPendingClearBadID = "Error: invalid task id %q (operation: parse, reason: must be a positive integer)\n" ErrPendingClearDeleteFail = "Error: failed to delete task #%d: %v\n" )
`gitmap pending clear` errors.
const ( SQLInsertPendingTask = `INSERT INTO PendingTask (TaskTypeId, TargetPath, WorkingDirectory, SourceCommand, CommandArgs) VALUES (?, ?, ?, ?, ?)` SQLSelectAllPendingTasks = `` /* 252-byte string literal not displayed */ SQLSelectPendingTaskByID = `` /* 253-byte string literal not displayed */ SQLSelectPendingTaskByTypePath = `SELECT p.PendingTaskId FROM PendingTask p WHERE p.TaskTypeId = ? AND p.TargetPath = ?` SQLSelectPendingTaskByTypePathCmd = `SELECT p.PendingTaskId FROM PendingTask p WHERE p.TaskTypeId = ? AND p.TargetPath = ? AND p.CommandArgs = ?` SQLUpdatePendingTaskFailure = `UPDATE PendingTask SET FailureReason = ?, UpdatedAt = CURRENT_TIMESTAMP WHERE PendingTaskId = ?` SQLDeletePendingTask = `DELETE FROM PendingTask WHERE PendingTaskId = ?` )
SQL: pending task operations (v15: PendingTaskId / CompletedTaskId / TaskTypeId PKs).
const ( SQLInsertCompletedTask = `` /* 159-byte string literal not displayed */ SQLSelectAllCompletedTasks = `` /* 262-byte string literal not displayed */ )
SQL: completed task operations (v15: CompletedTaskId PK).
const ( ProbeMethodLsRemote = "ls-remote" ProbeMethodShallowClone = "shallow-clone" ProbeMethodNone = "none" )
Probe method tokens (stored in VersionProbe.Method).
const ( ErrProbeOpenDB = "version probe: failed to open database: %v" ErrProbeMissingURL = "version probe: repo %q has no clone URL" ErrProbeLsRemoteFail = "ls-remote failed: %v" ErrProbeCloneFail = "shallow clone failed: %v" ErrProbeRecord = "version probe: failed to record result for repo %d: %v" ErrProbeNoRepo = "version probe: no repo found at %q" ErrProbeTagFail = "scan: failed to tag repos with scan folder %d: %v" )
VersionProbe error/message strings.
const ( MsgProbeStartFmt = "→ Probing %d repo(s)...\n" MsgProbeOkFmt = " ✓ %s → %s (method=%s)\n" MsgProbeNoneFmt = " · %s → no new version (method=%s)\n" MsgProbeFailFmt = " ✗ %s → %s\n" MsgProbeDoneFmt = "✓ Probe complete: %d available, %d unchanged, %d failed.\n" MsgProbeUsageHeader = "Usage: gitmap probe [<repo-path>|--all] [--json] [--probe-workers N] [--probe-depth N]" MsgProbeNoTargets = "No repos to probe. Pass a path or --all.\n" )
VersionProbe user-facing CLI strings.
const ( ProbeFlagAll = "--all" ProbeFlagJSON = "--json" ProbeFlagWorkers = "--workers" ProbeFlagProbeWorkers = "--probe-workers" ProbeFlagDepth = "--probe-depth" // ProbeFlagOutput selects an alternative human-output mode. // Currently only "terminal" is recognized — it emits the // standardized RepoTermBlock per repo (branch, from, to, // command) so the per-probe summary matches the shape used // by scan, clone-from, and clone-next. Mutually exclusive // with --json (terminal beats JSON when both are passed // because explicit terminal opts in to the human format). ProbeFlagOutput = "--output" )
VersionProbe CLI tokens.
`--workers` is the legacy spelling kept as a deprecated alias for `--probe-workers`; the foreground probe accepts both, but the new name is preferred (and is the same string scan accepts, which keeps muscle memory consistent across the two commands).
const ( ProbeDefaultWorkers = 2 ProbeMaxWorkers = 3 ProbeDefaultDepth = 1 )
Foreground probe pool sizing (v3.134.0+) and clone-depth (v3.135.0+).
`gitmap probe` runs a small capped worker pool so a probe of N repos completes in ~N/2 round-trips instead of N. The cap is intentionally tight — git hosting providers (GitHub in particular) throttle bursts of unauthenticated ls-remote calls, and going above 3 workers produces more 429s than throughput gains. The default of 2 is the sweet spot for laptops on residential bandwidth.
ProbeDefaultDepth is the `--depth N` value passed to the shallow-clone fallback. 1 is enough for the vast majority of repos because the fallback only runs when ls-remote returned nothing — at which point even one commit of history is sufficient to surface the tag list. Bump it (e.g. via `--probe-depth 25`) for repos whose latest tag lives further back than the first refs page exposes.
const ( ErrProbeWorkersValue = "version probe: --probe-workers requires a positive integer, got %q" ErrProbeWorkersMissing = "version probe: --probe-workers requires a value" ErrProbeDepthValue = "version probe: --probe-depth requires a positive integer, got %q" ErrProbeDepthMissing = "version probe: --probe-depth requires a value" MsgProbeWorkersClamped = " · --probe-workers %d exceeds cap, clamping to %d\n" MsgProbeWorkersAlias = " · --workers is deprecated; use --probe-workers instead\n" )
Probe worker- and depth-flag messages.
const ( // ScanProbeFlagDisable disables the background probe entirely. ScanProbeFlagDisable = "no-probe" // ScanProbeFlagNoWait makes scan return immediately after kicking // off probes (they keep running in background until completion or // process exit). ScanProbeFlagNoWait = "no-probe-wait" // ScanProbeFlagConcurrency sets the worker-pool size for the // background probe runner. Deprecated alias for ScanProbeFlagProbeWorkers. ScanProbeFlagConcurrency = "probe-concurrency" // ScanProbeFlagProbeWorkers is the unified spelling shared with // `gitmap probe --probe-workers`. Same semantics as // ScanProbeFlagConcurrency; either is accepted. ScanProbeFlagProbeWorkers = "probe-workers" // ScanProbeFlagProbeDepth controls the `git clone --depth N` // passed to the shallow-clone fallback (v3.135.0+). ScanProbeFlagProbeDepth = "probe-depth" // ScanProbeDefaultConcurrency caps the background pool. Three // workers is the documented sweet spot: parallel enough to // finish 50 probes in ~ten seconds, low enough that GitHub's // abuse detection doesn't kick in. ScanProbeDefaultConcurrency = 3 // ScanProbeAutoTriggerCeiling is the repo-count threshold under // which background probing fires automatically. Above it the // user must opt in by passing --probe-workers explicitly. ScanProbeAutoTriggerCeiling = 50 // FlagDescScanProbeDisable, FlagDescScanProbeNoWait, // FlagDescScanProbeConcurrency, FlagDescScanProbeProbeWorkers, and // FlagDescScanProbeProbeDepth are the help strings shown by // `gitmap help scan`. FlagDescScanProbeDisable = "Skip the background version probe entirely (offline / air-gapped runs)" FlagDescScanProbeNoWait = "Return as soon as scan finishes; let probes keep running in the background" FlagDescScanProbeConcurrency = "(deprecated, use --probe-workers) Worker count for the background probe pool" FlagDescScanProbeProbeWorkers = "Worker count for the background probe pool (default 3, 0 = disable)" FlagDescScanProbeProbeDepth = "Shallow-clone depth used by the probe fallback (default 1)" // MsgScanProbeConcurrencyAlias warns when the deprecated // --probe-concurrency spelling is used at the scan command line. MsgScanProbeConcurrencyAlias = " · --probe-concurrency is deprecated; use --probe-workers instead\n" )
Background probe tuning for `gitmap scan` (v3.123.0+).
When scan finds a small repo set we eagerly kick off a probe pass in the background so the next `gitmap find-next` call already has fresh data. The defaults are intentionally gentle: 3 workers max so we do not hammer GitHub's rate limit, and the auto-trigger only fires for scans of <50 repos so a directory full of vendored sources doesn't suddenly fan out 500 ls-remote calls. Power users can override or disable any of this with flags below.
const ( // MsgScanProbeStartFmt fires once when scan kicks off the // background runner. The %d is the number of repos queued. MsgScanProbeStartFmt = " ↪ background probe queued for %d repo(s) (workers=%d)\n" // MsgScanProbeWaitingFmt is printed at scan-end while we block // on the runner's Wait. Includes the count remaining so users // can gauge how long they'll be waiting. MsgScanProbeWaitingFmt = " ⏳ Waiting for background probes to finish (%d remaining)...\n" // MsgScanProbeDoneFmt prints the per-bucket tally once Wait // returns. Mirrors the foreground probe summary line. MsgScanProbeDoneFmt = " ✓ Background probe done: %d available, %d unchanged, %d failed.\n" // MsgScanProbeDetached prints when --no-probe-wait was passed // and we're returning before the pool drains. MsgScanProbeDetached = " ↪ Background probe detached; results will land in the DB asynchronously.\n" // MsgScanProbeSkippedAutoFmt prints when the auto-trigger // declined to start (repo count above the ceiling) so users // understand why no probe ran. MsgScanProbeSkippedAutoFmt = " · Background probe skipped: %d repos exceeds auto-trigger ceiling (%d). Pass --probe-workers to force.\n" )
Background probe runtime messages.
const ( CmdProfile = "profile" CmdProfileAlias = "pf" )
gitmap:cmd top-level Profile CLI commands.
const ( CmdProfileCreate = "create" // gitmap:cmd skip CmdProfileList = "list" // gitmap:cmd skip CmdProfileSwitch = "switch" // gitmap:cmd skip CmdProfileDelete = "delete" // gitmap:cmd skip CmdProfileShow = "show" // gitmap:cmd skip )
gitmap:cmd top-level Profile subcommands.
const ( ProfileConfigFile = "profiles.json" DefaultProfileName = "default" ProfileDBPrefix = "gitmap-" )
Profile file and defaults.
const ( MsgProfileCreated = "Profile created: %s\n" MsgProfileSwitched = "Switched to profile: %s\n" MsgProfileDeleted = "Profile deleted: %s\n" MsgProfileActive = "Active profile: %s\n" MsgProfileColumns = "PROFILE STATUS" MsgProfileRowFmt = "%-20s %s\n" MsgProfileActiveTag = "(active)" MsgProfileEmpty = "No profiles found.\n" ErrProfileUsage = "usage: gitmap profile <create|list|switch|delete|show> [name]\n" ErrProfileCreateUsage = "usage: gitmap profile create <name>\n" ErrProfileSwitchUsage = "usage: gitmap profile switch <name>\n" ErrProfileDeleteUsage = "usage: gitmap profile delete <name>\n" ErrProfileNotFound = "profile not found: %s\n" ErrProfileExists = "profile already exists: %s\n" ErrProfileDeleteActive = "cannot delete the active profile (switch first)\n" ErrProfileDeleteDefault = "cannot delete the default profile\n" ErrProfileConfig = "failed to manage profile config: %v\n" )
Profile messages.
const ( ProjectTypeGoID int64 = 1 ProjectTypeNodeID int64 = 2 ProjectTypeReactID int64 = 3 ProjectTypeCppID int64 = 4 ProjectTypeCsharpID int64 = 5 )
Project type IDs matching seed order in SQLSeedProjectTypes.
const ( ProjectKeyGo = "go" ProjectKeyNode = "node" ProjectKeyReact = "react" ProjectKeyCpp = "cpp" ProjectKeyCsharp = "csharp" )
Project type keys.
const ( TableProjectType = "ProjectType" TableDetectedProject = "DetectedProject" TableGoProjectMetadata = "GoProjectMetadata" TableGoRunnableFile = "GoRunnableFile" TableCsharpProjectMeta = "CsharpProjectMetadata" TableCsharpProjectFile = "CsharpProjectFile" TableCsharpKeyFile = "CsharpKeyFile" )
Project detection table names (v15: PascalCase singular + {Table}Id PK).
const ( LegacyTableProjectTypes = "ProjectTypes" LegacyTableDetectedProjects = "DetectedProjects" LegacyTableGoRunnableFiles = "GoRunnableFiles" LegacyTableCsharpProjectMeta = "CSharpProjectMetadata" // pre-Csharp spelling LegacyTableCsharpProjectFiles = "CSharpProjectFiles" // pre-Csharp spelling + plural LegacyTableCsharpKeyFiles = "CSharpKeyFiles" // pre-Csharp spelling + plural )
Legacy project detection table names retained ONLY for migration detection (do not use in new SQL). Includes both pre-v15 plurals and the pre-Csharp-rename "CSharp*" spellings.
const ( JSONFileGoProjects = "go-projects.json" JSONFileNodeProjects = "node-projects.json" JSONFileReactProjects = "react-projects.json" JSONFileCppProjects = "cpp-projects.json" JSONFileCsharpProjects = "csharp-projects.json" )
Project JSON output filenames.
const ( IndicatorGoMod = "go.mod" IndicatorPackageJSON = "package.json" IndicatorCMakeLists = "CMakeLists.txt" IndicatorMesonBuild = "meson.build" )
Detection indicator files.
const ( ExtCsproj = ".csproj" ExtFsproj = ".fsproj" ExtVcxproj = ".vcxproj" ExtSln = ".sln" )
Detection file extensions.
const ( GoCmdDir = "cmd" GoMainFile = "main.go" GoSumFile = "go.sum" CMakeBuildPfx = "cmake-build-" )
Go structural indicators.
const ( CmdGoRepos = "go-repos" CmdGoReposAlias = "gr" CmdNodeRepos = "node-repos" CmdNodeReposAlias = "nr" CmdReactRepos = "react-repos" CmdReactReposAlias = "rr" CmdCppRepos = "cpp-repos" CmdCppReposAlias = "cr" CmdCsharpRepos = "csharp-repos" CmdCsharpAlias = "csr" )
gitmap:cmd top-level Project query commands.
const ( FlagProjectJSON = "json" FlagProjectCount = "count" )
Project query flags.
const ( HelpGoRepos = " go-repos (gr) List repositories containing Go projects" HelpNodeRepos = " node-repos (nr) List repositories containing Node.js projects" HelpReactRepos = " react-repos (rr) List repositories containing React projects" HelpCppRepos = " cpp-repos (cr) List repositories containing C++ projects" HelpCsharpRepos = " csharp-repos (csr) List repositories containing C# projects" )
Project query help text.
const ( MsgProjectDetectDone = " 🧭 Detected %d project(s) across %d repo(s)\n" MsgProjectUpsertDone = " ✅ Saved %d detected project(s) to database\n" MsgProjectJSONWritten = " 📄 %-22s %d record(s)\n" MsgProjectNoDB = "No database found. Run 'gitmap scan' first.\n" MsgProjectNoneFound = "No %s projects found.\n" MsgProjectCount = "%d\n" MsgProjectCleanedStale = "Cleaned %d stale project records\n" MsgProjectListCount = "\n%d projects found.\n" )
Project detection messages.
const ( ErrProjectDetect = "failed to detect projects in %s: %v\n" ErrProjectUpsert = "failed to upsert detected project: %v" ErrProjectQuery = "failed to query projects: %v" ErrProjectJSONWrite = "failed to write %s: %v (operation: write)\n" ErrProjectParseMod = "failed to parse go.mod in %s: %v\n" ErrProjectParsePkgJSON = "failed to parse package.json in %s: %v\n" ErrProjectParseCsproj = "failed to parse .csproj in %s: %v\n" ErrProjectCleanup = "failed to clean stale projects for repo %d: %v\n" ErrGoMetadataUpsert = "failed to upsert Go metadata: %v" ErrGoRunnableUpsert = "failed to upsert Go runnable: %v" ErrCsharpMetaUpsert = "failed to upsert C# metadata: %v" ErrCsharpFileUpsert = "failed to upsert C# project file: %v" ErrCsharpKeyUpsert = "failed to upsert C# key file: %v" )
Project detection error messages.
const ( SQLDeleteStaleProjects = "DELETE FROM DetectedProject WHERE RepoId = ? AND DetectedProjectId NOT IN (%s)" SQLDeleteStaleGoRunnables = "DELETE FROM GoRunnableFile WHERE GoMetadataId = ? AND GoRunnableFileId NOT IN (%s)" SQLDeleteStaleCsharpFiles = "DELETE FROM CsharpProjectFile WHERE CsharpMetadataId = ? AND CsharpProjectFileId NOT IN (%s)" SQLDeleteStaleCsharpKeyFiles = "DELETE FROM CsharpKeyFile WHERE CsharpMetadataId = ? AND CsharpKeyFileId NOT IN (%s)" )
SQL: stale cleanup (v15 singular tables, {Table}Id PKs in WHERE/IN clauses).
const ( SQLDropGoRunnableFile = "DROP TABLE IF EXISTS GoRunnableFile" SQLDropGoRunnableFiles = "DROP TABLE IF EXISTS GoRunnableFiles" // legacy SQLDropGoProjectMetadata = "DROP TABLE IF EXISTS GoProjectMetadata" SQLDropCsharpKeyFile = "DROP TABLE IF EXISTS CsharpKeyFile" SQLDropCsharpKeyFiles = "DROP TABLE IF EXISTS CSharpKeyFiles" // legacy (pre-Csharp + plural) SQLDropCsharpProjectFile = "DROP TABLE IF EXISTS CsharpProjectFile" SQLDropCsharpProjectFiles = "DROP TABLE IF EXISTS CSharpProjectFiles" // legacy SQLDropCsharpProjectMeta = "DROP TABLE IF EXISTS CsharpProjectMetadata" SQLDropCsharpProjectMetaLegacy = "DROP TABLE IF EXISTS CSharpProjectMetadata" // legacy SQLDropDetectedProject = "DROP TABLE IF EXISTS DetectedProject" SQLDropDetectedProjects = "DROP TABLE IF EXISTS DetectedProjects" // legacy SQLDropProjectType = "DROP TABLE IF EXISTS ProjectType" SQLDropProjectTypes = "DROP TABLE IF EXISTS ProjectTypes" // legacy )
SQL: drop project detection tables (v15 names + legacy retained for Reset).
const ( CmdPrune = "prune" CmdPruneAlias = "pr" )
gitmap:cmd top-level Prune command names.
const ( PruneFlagDryRun = "dry-run" PruneFlagConfirm = "confirm" PruneFlagRemote = "remote" )
Prune flag names.
const ( MsgPruneStaleHeader = "\n Stale release branches (%d):\n" MsgPruneStaleItem = " %s → tag %s exists\n" MsgPruneDryRunHint = "\n Use --confirm to delete, or run without --dry-run for interactive mode.\n" MsgPruneDeleting = "\n Pruning stale release branches...\n" MsgPruneDeleted = " ✓ Deleted %s\n" MsgPruneRemoteDelete = " ✓ Deleted remote %s\n" MsgPruneRemoteWarn = " ⚠ Failed to delete remote %s: %v\n" MsgPruneSummary = "\n Summary: %d deleted, %d kept.\n" MsgPruneNone = " No stale release branches found.\n" MsgPrunePrompt = " Delete %d stale branch(es)? (y/N): " MsgPruneAborted = " Prune aborted.\n" )
Prune messages.
const ( ErrPruneListBranches = "failed to list branches: %v\n" ErrPruneDeleteBranch = " ✗ Failed to delete %s: %v\n" )
Prune errors.
const ( GitBranchDeleteFlag = "-D" GitPushDeleteFlag = "--delete" )
Prune git arguments.
const ( FlagDescPullParallel = "Run up to N pulls concurrently (default 1; serial)" FlagDescPullOnlyAvailable = "Skip repos whose latest probe reports no new tag (run `gitmap probe --all` first)" )
CLI flag descriptions (used by flag.NewFlagSet).
const ( MsgPullNoAvailable = "No repos with available updates. Run `gitmap probe --all` first.\n" WarnPullFilterFallback = " ⚠ --only-available filter unavailable (probe DB unreadable); falling back to full target set" )
User-facing pull messages (Phase 2.5).
const ( FlagReinstallMode = "mode" FlagReinstallYes = "yes" )
Reinstall flag names.
const ( FlagDescReinstallMode = "Override auto-detect: 'auto' (default), 'repo' (force run.ps1/sh), 'self' (force self-uninstall+self-install)" FlagDescReinstallYes = "Auto-confirm without prompting" )
Reinstall flag descriptions.
const ( ReinstallModeAuto = "auto" ReinstallModeRepo = "repo" ReinstallModeSelf = "self" )
Reinstall mode values.
const ( MsgReinstallHeader = "" /* 300-byte string literal not displayed */ MsgReinstallModeAuto = " → Mode: auto (detected: %s)\n" MsgReinstallModeForced = " → Mode: %s (forced via --mode)\n" MsgReinstallRepoPath = " → Source repo: %s\n" MsgReinstallRunningRepo = " → Running %s -reinstall ...\n" MsgReinstallRunningSelf = " → Running self-uninstall, then self-install ...\n" MsgReinstallStepUninst = "\n [1/2] self-uninstall\n" MsgReinstallStepInst = "\n [2/2] self-install\n" MsgReinstallDone = "\n ✓ Reinstall complete.\n\n" MsgReinstallConfirm = " → Proceed with reinstall? (yes/N): " )
Reinstall messages.
const ( ErrReinstallUnknownMode = "Error: unknown --mode value %q (allowed: auto|repo|self)\n" ErrReinstallNoRepoLinked = "" /* 132-byte string literal not displayed */ ErrReinstallScriptNotFound = "Error: reinstall script %s not found at %s (operation: stat, reason: file does not exist)\n" ErrReinstallScriptFailed = "Error: reinstall script %s exited with code %d\n" ErrReinstallSelfUninstall = "Error: self-uninstall step failed: %v\n" ErrReinstallSelfInstall = "Error: self-install step failed: %v\n" ErrReinstallAborted = " ✗ Reinstall canceled by user.\n" )
Reinstall errors.
const ( SetupSectionDiff = "Diff Tool" SetupSectionMerge = "Merge Tool" SetupSectionAlias = "Aliases" SetupSectionCred = "Credential Helper" SetupSectionCore = "Core Settings" SetupSectionComp = "■ Shell Completion —" SetupGlobalFlag = "--global" )
Setup section headers.
const ( MsgReleaseStart = "\n Creating release %s...\n" MsgReleaseBranch = " ✓ Created branch %s\n" MsgReleaseTag = " ✓ Created tag %s\n" MsgReleasePushed = " ✓ Pushed branch and tag to origin\n" MsgReleaseMeta = " ✓ Release metadata written to %s\n" MsgReleaseMetaCommitted = " ✓ Committed release metadata on %s\n" MsgReleaseLatest = " ✓ Marked %s as latest release\n" MsgReleaseAttach = " ✓ Attached %s\n" MsgReleaseChangelog = " ✓ Using CHANGELOG.md as release body\n" MsgReleaseReadme = " ✓ Attached README.md\n" MsgReleaseDryRun = " [dry-run] %s\n" MsgReleaseComplete = "\n ── Release %s complete ──\n" MsgReleaseBranchStart = "\n Completing release from %s...\n" MsgReleaseBranchPending = "\n → On release branch %s with no tag — completing pending release...\n" MsgReleaseVersionRead = " → Version from %s: %s\n" MsgReleaseBumpResult = " → Bumped %s → %s\n" MsgReleaseNotes = " → Release notes: %s\n" MsgReleaseSwitchedBack = " ✓ Switched back to %s\n" MsgReleasePendingNone = " No pending release branches found." MsgReleasePendingFound = "\n Found %d pending release branch(es).\n" MsgReleasePendingFailed = " ✗ Failed to release %s: %v\n" ReleaseBranchPrefix = "release/" ChangelogFile = "CHANGELOG.md" ReadmeFile = "README.md" ReleaseTagPrefix = "Release " FlagDescNotes = "Release notes or title for the release" )
Release messages.
const ( MsgReleaseAutoBumpHeader = "\n Auto-bump: %s → %s (minor)\n" MsgReleaseAutoBumpPrompt = " Proceed with this release? [y/N]: " MsgReleaseAutoBumpYes = " → -y supplied; proceeding without prompt.\n" MsgReleaseAutoBumpAborted = " ✗ Auto-bump aborted by user.\n" )
Bare-release auto-bump messages (v3.19.0).
When `gitmap release` / `gitmap r` is run with no version and no --bump, gitmap reads the last release from .gitmap/release/latest.json, bumps the MINOR segment, and prompts the user. -y skips the prompt.
const ( MsgReleaseScanHeader = "\n Auto-bump %d repo(s) with prior releases:\n" MsgReleaseScanRow = " • %s %s → %s\n" MsgReleaseScanPrompt = "\n Proceed with all releases? [y/N]: " MsgReleaseScanYes = "\n → -y supplied; proceeding without prompt.\n" MsgReleaseScanAborted = " ✗ Multi-repo release aborted by user.\n" MsgReleaseScanRunning = "\n ── Releasing %s → %s ──\n" MsgReleaseScanFail = " ✗ Release failed for %s: %v\n" MsgReleaseScanPartial = "\n ⚠ %d of %d release(s) failed.\n" MsgReleaseScanDone = "\n ✓ All %d release(s) complete.\n" )
Multi-repo scan-dir release messages (v3.19.0).
When `gitmap r` is run from a directory containing many git repos (the cwd itself is NOT a git repo), gitmap walks the tree, keeps only repos that have a prior release manifest, computes a minor bump per repo, and prompts ONCE before releasing them all.
const ( MsgReleaseOrphanedMeta = " ⚠ Release metadata exists for %s but no tag or branch was found.\n" MsgReleaseOrphanedPrompt = " → Do you want to remove the release JSON and proceed? (y/N): " MsgReleaseOrphanedRemoved = " ✓ Removed orphaned release metadata for %s\n" ErrReleaseOrphanedRemove = "failed to remove release metadata at %s: %w (operation: delete)" ErrReleaseAborted = "release aborted by user" )
Release orphaned metadata messages.
const ( MsgSelfReleaseSwitch = "\n → Self-release: switching to %s\n" MsgSelfReleaseReturn = " ✓ Returned to %s\n" MsgSelfReleaseSameDir = "\n → Self-release: already in source repo %s\n" MsgSelfReleasePromptPath = " → Enter gitmap source repo path: " MsgSelfReleaseSavedPath = " ✓ Saved gitmap source repo path: %s\n" MsgSelfReleaseInvalidPath = " ✗ Invalid gitmap source repo path: %s\n" ErrSelfReleaseExec = "could not resolve executable path at %s: %w (operation: resolve)" ErrSelfReleaseNoRepo = "could not locate gitmap source repository" )
Self-release messages.
const ( GitmapRepoPrefix = "github.com/alimtvnetwork/gitmap-v16" GitmapRepoOwner = "github.com/alimtvnetwork/" GitmapRepoNamePrefix = "gitmap-v" MsgInstallHintHeader = ` 📦 Install gitmap %s ───────────────────── ` MsgInstallHintWindows = `` /* 137-byte string literal not displayed */ // Trailing blank line (the second \n after the curl command) ensures // the shell prompt (PS1) lands on its own visually-separated line // instead of sitting flush under the install one-liner. Matches the // auto-register message convention (releaseautoregister.go line 48). MsgInstallHintUnix = `` /* 135-byte string literal not displayed */ )
Install hint constants (printed after release for gitmap repos).
const ( ReleaseSnippetMarker = "<!-- gitmap-pinned-install-snippet:%s -->" ReleaseSnippetTemplate = "<!-- gitmap-pinned-install-snippet:%s -->\n" + "## Install this exact version (%s)\n\n" + "Copy-paste these snippets to install **this exact tag**. " + "They skip the GitHub `latest` lookup and the versioned-repo discovery probe.\n\n" + "**Windows (PowerShell)**\n" + "```powershell\n" + "$ver = '%s'\n" + "$installer = irm https://raw.githubusercontent.com/alimtvnetwork/gitmap-v16/main/gitmap/scripts/install.ps1\n" + "& ([scriptblock]::Create($installer)) -Version $ver -NoDiscovery\n" + "```\n\n" + "**Linux / macOS (bash)**\n" + "```bash\n" + "curl -fsSL https://raw.githubusercontent.com/alimtvnetwork/gitmap-v16/main/gitmap/scripts/install.sh \\\n" + " | bash -s -- --version %s --no-discovery\n" + "```\n" )
Release-body pinned-install snippet.
AppendPinnedInstallSnippet renders this block into the GitHub release body so anyone copying from the release page installs EXACTLY that tag — no "latest" lookup, no -v<N> sibling-repo discovery.
Spec: spec/07-generic-release/08-pinned-version-install-snippet.md
const ( MsgRollbackStart = "\n ⚠ Push failed — rolling back local branch and tag...\n" MsgRollbackBranch = " ✓ Deleted local branch %s\n" MsgRollbackTag = " ✓ Deleted local tag %s\n" MsgRollbackDone = " ✓ Rollback complete. No changes remain.\n" MsgRollbackWarn = " ⚠ Rollback warning (%s): %v\n" )
Release rollback messages.
const ( CmdReleaseAlias = "release-alias" CmdReleaseAliasShort = "ra" CmdReleaseAliasPull = "release-alias-pull" CmdReleaseAliasPullShort = "rap" LogPrefixReleaseAlias = "[release-alias]" FlagRAPull = "pull" FlagRANoStash = "no-stash" FlagRADryRun = "dry-run" )
gitmap:cmd top-level `gitmap release-alias` and `gitmap release-alias-pull` — release a repo by its registered alias from anywhere on disk.
Spec: docs in helptext/release-alias.md and README.
const ( RAStashMessageFmt = "gitmap-release-alias autostash %s" MsgRAStashCreatedFmt = " ✓ Auto-stashed dirty changes (label: %s)\n" MsgRAStashPoppedFmt = " ✓ Restored auto-stashed changes (label: %s)\n" MsgRAPullingFmt = " ↻ Pulling latest from origin in %s\n" MsgRAReleasingFmt = " ▸ Releasing repo '%s' (path: %s) version=%s\n" WarnRAStashPopFailed = " ⚠ Auto-stash pop failed; your changes remain in `git stash`. Resolve manually." ErrRAUsage = "Usage: gitmap release-alias <alias> <version> [--pull] [--no-stash] [--dry-run]" ErrRAUnknownAliasFmt = "error: alias '%s' is not registered. Run `gitmap as %s` from the repo first." ErrRAChdirFailedFmt = "error: could not change directory to '%s': %v" ErrRAPullFailedFmt = "error: git pull failed in %s: %v" ErrRAStashFailedFmt = "error: auto-stash failed in %s: %v" )
Auto-stash bookkeeping.
const ( FlagRPFFOnly = "ff-only" FlagRPRebase = "rebase" FlagRPMerge = "merge" FlagRPDryRun = "dry-run" FlagRPVerbose = "verbose" FlagDescRPFFOnly = "Pull mode: fast-forward only (default). Hard-fails on divergent history." FlagDescRPRebase = "Pull mode: rebase local commits onto upstream. Aborts the rebase on conflict." FlagDescRPMerge = "Pull mode: classic merge (passes --no-rebase). Creates a merge commit on divergence." FlagDescRPDryRun = "Show the git pull command that would run, then skip the pull and forward to release." FlagDescRPVerbose = "Echo every git invocation to stderr before running it." RPModeFFOnly = "ff-only" RPModeRebase = "rebase" RPModeMerge = "merge" ErrRPNotInRepo = "release-pull: must be run inside a git repository\n" ErrRPCwdFailedFmt = "release-pull: cannot resolve cwd: %v\n" ErrRPModeConflictFmt = "release-pull: --ff-only, --rebase, and --merge are mutually exclusive (got %s)\n" ErrRPPullFailedFmt = "release-pull: git pull %s failed in %s: %v\n" ErrRPRebaseAbortFmt = "release-pull: rebase failed in %s: %v (attempted git rebase --abort)\n" MsgRPPullingFmt = "[release-pull] git pull %s in %s\n" MsgRPDryRunFmt = "[release-pull] dry-run: would run `git pull %s` in %s\n" )
release-pull mode flags and messages. Mode flags are mutually exclusive; --ff-only is the safe default. The --merge mode passes `--no-rebase` to git so it overrides any user-level `pull.rebase=true` setting.
const ( ReplaceFlagYes = "yes" ReplaceFlagYesS = "y" ReplaceFlagDryRun = "dry-run" ReplaceFlagQuiet = "quiet" ReplaceFlagQuietS = "q" ReplaceFlagExt = "ext" ReplaceFlagExtCase = "ext-case" ReplaceSubcmdAudit = "--audit" ReplaceSubcmdAll = "all" )
Replace command flag names (see spec/04-generic-cli/15-replace-command.md).
const ( FlagDescReplaceExt = "Comma-separated extension allow-list (e.g. \".go,.md\"). Leading dot optional." FlagDescReplaceExtCase = "Extension match casing: sensitive | insensitive (default insensitive)." ReplaceExtSep = "," )
Replace --ext flag description and value separator.
const ( ReplaceExtCaseSensitive = "sensitive" ReplaceExtCaseInsensitive = "insensitive" ReplaceExtCaseDefault = ReplaceExtCaseInsensitive )
Allowed values for --ext-case. The default is `insensitive` so the historical behavior is preserved when the flag is omitted.
const ( MsgReplaceScanning = "replace: scanning %d files in %s\n" MsgReplaceFileMatch = "replace: %s: %d matches (%s -> %s)\n" MsgReplaceFileMatchOne = "replace: %s: 1 match (%s -> %s)\n" MsgReplaceSummary = "replace: %d files, %d replacements\n" MsgReplaceConfirmLit = "Apply %d replacements across %d files? [y/N]: " MsgReplaceConfirmVer = "Apply replacements for versions v%d..v%d -> v%d? [y/N]: " MsgReplaceApplied = "replace: applied %d replacements across %d files\n" MsgReplaceAborted = "replace: aborted by user\n" MsgReplaceAlreadyAtV1 = "replace: already at v1, nothing to upgrade\n" MsgReplaceAuditMatch = "%s:%d: %s\n" MsgReplaceAuditClean = "replace: no older version references found\n" MsgReplaceNoMatches = "replace: no matches found\n" ErrReplaceNeedsArgs = "replace: expected two quoted strings, -N, all, or --audit\n" ErrReplaceEmptyOld = "replace: old text must not be empty\n" ErrReplaceBadN = "replace: -N must be a positive integer (got %q)\n" ErrReplaceNoRemote = "replace: cannot read git remote: %v\n" ErrReplaceVersionParse = "replace: cannot detect version from remote: %q (expected suffix -vN)\n" ErrReplaceWrite = "replace: %s: %v\n" ErrReplaceWalk = "replace: walk error: %v\n" ErrReplaceNotInRepo = "replace: not inside a git repository: %v\n" )
Replace command messages and errors. All user-facing text lives here to honor the no-magic-strings rule.
const ( TableScanFolder = "ScanFolder" TableVersionProbe = "VersionProbe" )
const ( SQLUpsertScanFolder = `` /* 319-byte string literal not displayed */ SQLSelectAllScanFolders = `` /* 137-byte string literal not displayed */ SQLSelectScanFolderByPath = `SELECT ScanFolderId, AbsolutePath, Label, Notes, LastScannedAt, CreatedAt FROM ScanFolder WHERE AbsolutePath = ?` SQLSelectScanFolderByID = `SELECT ScanFolderId, AbsolutePath, Label, Notes, LastScannedAt, CreatedAt FROM ScanFolder WHERE ScanFolderId = ?` SQLCountReposInScanFolder = `SELECT COUNT(*) FROM Repo WHERE ScanFolderId = ?` SQLDeleteScanFolderByID = `DELETE FROM ScanFolder WHERE ScanFolderId = ?` SQLDeleteScanFolderByPath = `DELETE FROM ScanFolder WHERE AbsolutePath = ?` // Detach: set Repo.ScanFolderId = NULL for any repos pointing at the // scan folder being removed. Run BEFORE DELETE to avoid orphan FK ids. SQLDetachReposFromScanFolder = `UPDATE Repo SET ScanFolderId = NULL WHERE ScanFolderId = ?` )
SQL: ScanFolder operations.
const ( SQLDropScanFolder = "DROP TABLE IF EXISTS ScanFolder" SQLDropVersionProbe = "DROP TABLE IF EXISTS VersionProbe" )
SQL: drop statements for Reset() ordering.
const ( ErrSFEnsure = "failed to ensure scan folder %q: %v" ErrSFList = "failed to list scan folders: %v" ErrSFFindByPath = "no scan folder registered for path: %s" ErrSFFindByID = "no scan folder with id: %d" ErrSFRemove = "failed to remove scan folder: %v" ErrSFDetachRepos = "failed to detach repos from scan folder: %v" ErrSFAbsResolve = "failed to resolve absolute path for %q: %v" ErrSFInvalidID = "invalid scan folder id %q: %v" ErrSFMissingArg = "missing required argument: %s" )
ScanFolder error messages (Code Red zero-swallow policy).
const ( MsgSFAddedFmt = "✓ Registered scan folder: %s (id=%d)\n" MsgSFAddedExistsFmt = "✓ Scan folder already registered: %s (id=%d, last scanned %s)\n" MsgSFRemovedFmt = "✓ Removed scan folder: %s (id=%d, %d repos detached)\n" MsgSFListEmpty = "No scan folders registered. Run `gitmap scan <dir>` or `gitmap sf add <dir>`.\n" MsgSFListHeaderFmt = "Scan folders (%d):\n" MsgSFListRowFmt = " [%d] %s\n label: %s | repos: %d | last scanned: %s\n" MsgSFUsageHeader = "Usage: gitmap sf <add|list|rm> [args]" MsgSFUsageAdd = " gitmap sf add <absolute-path> [--label <text>] [--notes <text>]" MsgSFUsageList = " gitmap sf list" MsgSFUsageRm = " gitmap sf rm <absolute-path|id>" )
ScanFolder user-facing CLI strings.
const ( SFSubAdd = "add" SFSubList = "list" SFSubListAlias = "ls" SFSubRm = "rm" SFSubRmAlias = "remove" SFFlagLabel = "--label" SFFlagNotes = "--notes" )
ScanFolder CLI tokens (avoid magic strings).
const ( SelfInstallDefaultWindows = "D:\\gitmap" SelfInstallDefaultUnix = ".local/bin/gitmap" // joined under $HOME at runtime )
Default install directories per platform.
const ( SelfInstallScriptPwsh = "install.ps1" SelfInstallScriptBash = "install.sh" )
Embedded script names.
const ( SelfInstallRemotePwsh = "https://raw.githubusercontent.com/" + "alimtvnetwork/gitmap-v16/main/gitmap/scripts/install.ps1" SelfInstallRemoteBash = "https://raw.githubusercontent.com/" + "alimtvnetwork/gitmap-v16/main/gitmap/scripts/install.sh" )
Remote installer URLs (fallback when embedded scripts are missing).
const ( MsgSelfInstallHeader = "\n gitmap self-install\n\n" MsgSelfInstallPrompt = " Install directory [%s]: " MsgSelfInstallUsing = " Using install directory: %s\n" MsgSelfInstallEmbedded = " Running embedded installer (%s)...\n" MsgSelfInstallRemote = " Embedded installer unavailable; downloading from %s\n" MsgSelfInstallDone = " ✓ Install completed.\n" MsgSelfInstallReminder = " Open a new terminal (or reload your profile) to pick up PATH changes.\n" )
Self-install messages.
const ( ErrSelfInstallScriptWrite = "Error: write installer to temp: %v\n" ErrSelfInstallScriptRun = "Error: run installer: %v\n" ErrSelfInstallDownload = "Error: download installer from %s: %v\n" ErrSelfInstallNoShell = "Error: no supported shell found (need PowerShell on Windows or bash on Unix)\n" ErrSelfInstallReadStdin = "Error: read install dir from stdin: %v\n" )
Self-install errors.
const ( MsgSelfUninstallHeader = "\n gitmap self-uninstall\n\n" MsgSelfUninstallTargets = " The following will be removed:\n" MsgSelfUninstallTargetBin = " - Binary + deploy dir: %s\n" MsgSelfUninstallTargetData = " - Data dir: %s\n" MsgSelfUninstallTargetSnippet = " - PATH snippet from: %s\n" MsgSelfUninstallTargetCompl = " - Completion files in: %s\n" MsgSelfUninstallConfirmPrompt = "\n Type 'yes' to proceed: " MsgSelfUninstallSkipBin = " ⚠ Could not resolve own binary location: %v\n" MsgSelfUninstallRemovedBin = " ✓ Removed binary: %s\n" MsgSelfUninstallRemovedDir = " ✓ Removed dir: %s\n" MsgSelfUninstallSnippetGone = " ✓ PATH snippet removed from %s\n" MsgSelfUninstallSnippetMiss = " - No PATH snippet found in %s\n" MsgSelfUninstallDone = "\n ✓ gitmap has been uninstalled. Restart your terminal to clear $env:Path.\n\n" MsgSelfUninstallHandoffActive = " Handing off to %s so the original binary can self-delete...\n" )
Self-uninstall messages.
const ( ErrSelfUninstallNoConfirm = "Error: refusing to run without --confirm or interactive 'yes'.\n" ErrSelfUninstallRemove = "Error: remove %s: %v\n" ErrSelfUninstallSnippetRead = "Error: read profile %s: %v\n" ErrSelfUninstallSnippetWrite = "Error: rewrite profile %s: %v\n" ErrSelfUninstallHandoffCopy = "Error: create handoff copy: %v\n" )
Self-uninstall errors.
const ( FlagSelfDir = "--dir" FlagSelfYes = "--yes" FlagSelfConfirm = "--confirm" FlagSelfKeepData = "--keep-data" FlagSelfKeepSnippet = "--keep-snippet" FlagSelfFromVersion = "--version" FlagSelfShellMode = "--shell-mode" // canonical (v3.48.0+) FlagSelfProfile = "--profile" // hidden alias (v3.46.0+) FlagSelfDualShell = "--dual-shell" // hidden alias (v3.43.0+) FlagSelfShowPath = "--show-path" FlagSelfForceLock = "--force-lock" )
Flag names shared by self-install / self-uninstall.
FlagSelfShellMode is the canonical name as of v3.48.0. FlagSelfProfile (introduced in v3.46.0) and FlagSelfDualShell (v3.43.0) are kept as hidden aliases so existing scripts and CI continue to work — the Go parser collapses all three onto opts.ShellMode (formerly opts.Profile).
const ( ShellModeAuto = "auto" ShellModeBoth = "both" ShellModeZsh = "zsh" ShellModeBash = "bash" ShellModePwsh = "pwsh" ShellModeFish = "fish" // Back-compat alias names — same values, different identifiers. ProfileModeAuto = ShellModeAuto ProfileModeBoth = ShellModeBoth ProfileModeZsh = ShellModeZsh ProfileModeBash = ShellModeBash ProfileModePwsh = ShellModePwsh ProfileModeFish = ShellModeFish // ShellModeComboSep is the delimiter for combo modes like "zsh+pwsh". ShellModeComboSep = "+" )
ShellMode values accepted by --shell-mode. `auto` is the default (run detect_active_pwsh + $SHELL heuristics). `both` writes PATH to every supported shell's profile file. Singletons restrict writes to exactly one family.
Combos: any `+`-joined combination of the singletons (e.g. `zsh+pwsh`, `bash+fish`, `zsh+bash+pwsh`) is also accepted. Combos are STRICT — only the listed families receive the PATH snippet; ~/.profile and any undeclared family are skipped. This is the difference from `both`, which writes everything detected.
Aliases retained for back-compat:
ProfileMode* names mirror ShellMode* names — both are still exported so old code referencing ProfileModeBoth keeps compiling.
const ( FlagDescSelfDir = "Install directory (prompted with default if omitted)" FlagDescSelfYes = "Skip the install-directory prompt and accept the default" FlagDescSelfConfirm = "Required for self-uninstall to actually remove files" FlagDescSelfKeepData = "Preserve the .gitmap data dir during self-uninstall" FlagDescSelfKeepSnippet = "Leave the PATH snippet in shell profile during self-uninstall" FlagDescSelfFromVersion = "Pin a specific gitmap version to install (e.g. v3.0.0)" FlagDescSelfShellMode = "Which shell profile(s) to write PATH into: auto|both|zsh|bash|pwsh|fish " + "or any '+'-joined combo such as zsh+pwsh (default: auto)" FlagDescSelfProfile = "Deprecated alias for --shell-mode (hidden; still works)" FlagDescSelfDualShell = "Deprecated alias for --shell-mode both (hidden; still works)" FlagDescSelfShowPath = "Print detected shell, chosen PATH target, and every profile file written" FlagDescSelfForceLock = "Bypass the duplicate-install guard (recover from a stale lock left by a crashed installer)" )
Flag descriptions.
const ( // SelfInstallLockName is the suffix passed to lockfile.Acquire. The // resulting file is os.TempDir()/gitmap-selfinstall.lock and prevents // two `gitmap self-install` processes from racing each other. SelfInstallLockName = "selfinstall" // ErrSelfInstallLockHeld is shown when another live gitmap self-install // process holds the lock. Includes its PID so the user can investigate. ErrSelfInstallLockHeld = "Error: another gitmap self-install is already running (pid=%d).\n" + " Wait for it to finish, or pass --force-lock if it crashed.\n" // ErrSelfInstallLock is the catch-all for lock filesystem failures // (permission denied, disk full, etc.). ErrSelfInstallLock = "Error: could not acquire self-install lock: %v\n" )
Self-install duplicate-install guard.
const ( CmdSEOWrite = "seo-write" CmdSEOWriteAlias = "sw" CmdCreateTemplate = "ct" // gitmap:cmd skip )
gitmap:cmd top-level SEO-write command constants.
const ( FlagSEOCSV = "csv" FlagSEOURL = "url" FlagSEOService = "service" FlagSEOArea = "area" FlagSEOCompany = "company" FlagSEOPhone = "phone" FlagSEOEmail = "email" FlagSEOAddress = "address" FlagSEOMaxCommits = "max-commits" FlagSEOInterval = "interval" FlagSEOFiles = "files" FlagSEORotateFile = "rotate-file" FlagSEODryRun = "dry-run" FlagSEOTemplate = "template" FlagSEOCreateTemplate = "create-template" FlagSEOAuthorName = "author-name" FlagSEOAuthorEmail = "author-email" )
SEO-write flag names.
const ( FlagDescSEOCSV = "CSV file with title,description columns" FlagDescSEOURL = "Website URL to glorify in commit messages" FlagDescSEOService = "Service name for template placeholders" FlagDescSEOArea = "Geographic area for template placeholders" FlagDescSEOCompany = "Company name for template placeholders" FlagDescSEOPhone = "Phone number for template placeholders" FlagDescSEOEmail = "Email address for template placeholders" FlagDescSEOAddress = "Physical address for template placeholders" FlagDescSEOMaxCommits = "Stop after N commits (0 = run until Ctrl+C)" FlagDescSEOInterval = "Random delay range in seconds (min-max)" FlagDescSEOFiles = "Glob pattern to select files for staging" FlagDescSEORotateFile = "File to modify during rotation mode" FlagDescSEODryRun = "Preview commit messages without executing" FlagDescSEOTemplate = "Load templates from a custom JSON file" FlagDescSEOCreateTemplate = "Generate a sample seo-templates.json and exit" FlagDescSEOAuthorName = "Git author name for commits" FlagDescSEOAuthorEmail = "Git author email for commits" )
SEO-write flag descriptions.
const ( SEODefaultIntervalMin = 60 SEODefaultIntervalMax = 120 SEODefaultInterval = "60-120" SEOSeedFile = "data/seo-templates.json" SEOTemplateOutputFile = "seo-templates.json" )
SEO-write defaults.
const ( PlaceholderService = "{service}" PlaceholderArea = "{area}" PlaceholderURL = "{url}" PlaceholderCompany = "{company}" PlaceholderPhone = "{phone}" PlaceholderEmail = "{email}" PlaceholderAddress = "{address}" )
SEO-write placeholder tokens.
const ( MsgSEOHeader = "seo-write: %d commits planned (interval: %d-%ds)\n" MsgSEOHeaderUnlimited = "seo-write: unlimited commits (interval: %d-%ds)\n" MsgSEOCommit = " [%d/%d] ✓ %q → pushed (file: %s)\n" MsgSEOCommitOpen = " [%d] ✓ %q → pushed (file: %s)\n" MsgSEORotation = " [%d/%d] ↻ rotation: %s (append → commit → revert → commit)\n" MsgSEORotationOpen = " [%d] ↻ rotation: %s (append → commit → revert → commit)\n" MsgSEODone = " Done: %d commits pushed in %s\n" MsgSEODryTitle = " [%d] title: %s\n" MsgSEODryDesc = " desc: %s\n" MsgSEODryAuthor = " author: %s\n" MsgSEOCreated = "Created %s with sample templates\n" MsgSEOSeeded = "Seeded %d templates into database\n" MsgSEOGraceful = "\nGraceful shutdown: finishing current commit...\n" MsgSEOWaiting = " waiting %ds before next commit...\n" )
SEO-write terminal messages.
const ( ErrSEOURLRequired = "error: --url is required in template mode\n" ErrSEOCSVRead = "error: failed to read CSV file at %s: %v (operation: read)\n" ErrSEOCSVEmpty = "error: CSV file contains no rows\n" ErrSEOTemplateRead = "error: failed to read template file at %s: %v (operation: read)\n" ErrSEOTemplateEmpty = "error: no templates found\n" ErrSEOIntervalFmt = "error: invalid --interval format, expected min-max (e.g. 60-120)\n" ErrSEONoFiles = "error: no files found matching pattern\n" ErrSEORotateNotFound = "error: rotate file not found at %s (operation: resolve, reason: file does not exist)\n" ErrSEOGitStage = "error: git add failed: %v\n" ErrSEOGitCommit = "error: git commit failed: %v\n" ErrSEOGitPush = "error: git push failed: %v\n" ErrSEOSeedRead = "error: failed to read seed file at %s: %v (operation: read)\n" ErrSEOCreateWrite = "error: failed to write template file at %s: %v (operation: write)\n" ErrSEODBInsert = "error: failed to insert template: %v\n" )
SEO-write error messages.
const ( HelpSEOWrite = " seo-write (sw) Automated SEO commit scheduler with templates" HelpSEOWriteFlags = "SEO-write flags:" HelpSEOCSV = " --csv <path> CSV file with title,description columns" HelpSEOURL = " --url <url> Website URL to glorify in commit messages (required)" HelpSEOService = " --service <name> Service name for template placeholders" HelpSEOArea = " --area <name> Geographic area for template placeholders" HelpSEOCompany = " --company <name> Company name for template placeholders" HelpSEOPhone = " --phone <number> Phone number for template placeholders" HelpSEOEmail = " --email <addr> Email address for template placeholders" HelpSEOAddress = " --address <addr> Physical address for template placeholders" HelpSEOMaxCommits = " --max-commits <N> Stop after N commits (0 = unlimited, default: 0)" HelpSEOInterval = " --interval <min-max> Random delay in seconds (default: 60-120)" HelpSEOFilesFlag = " --files <glob> Glob pattern to select files for staging" HelpSEORotate = " --rotate-file <f> File to modify in rotation mode" HelpSEODryRunFlag = " --dry-run Preview commit messages without executing" HelpSEOTemplateF = " --template <path> Load templates from a custom JSON file" HelpSEOCreateTpl = " --create-template Generate sample seo-templates.json (alias: ct)" HelpSEOAuthorName = " --author-name <n> Git author name for commits" HelpSEOAuthorEmail = " --author-email <e> Git author email for commits" )
SEO-write help text.
const ( SQLInsertTemplate = "INSERT INTO CommitTemplate (Kind, Template) VALUES (?, ?)" SQLSelectTemplatesByKind = "SELECT CommitTemplateId, Kind, Template, CreatedAt FROM CommitTemplate WHERE Kind = ? ORDER BY CreatedAt" SQLCountTemplates = "SELECT COUNT(*) FROM CommitTemplate" SQLDropCommitTemplate = "DROP TABLE IF EXISTS CommitTemplate" SQLDropCommitTemplates = "DROP TABLE IF EXISTS CommitTemplates" // legacy )
SQL: commit-template operations (v15).
const ( TemplateKindTitle = "title" TemplateKindDescription = "description" )
Template kinds.
const ( SQLUpsertSetting = `INSERT INTO Setting (Key, Value) VALUES (?, ?) ON CONFLICT(Key) DO UPDATE SET Value=excluded.Value` SQLSelectSetting = "SELECT Value FROM Setting WHERE Key = ?" SQLDeleteSetting = "DELETE FROM Setting WHERE Key = ?" )
SQL: setting operations (v15).
const ( SQLDropSetting = "DROP TABLE IF EXISTS Setting" SQLDropSettings = "DROP TABLE IF EXISTS Settings" // legacy )
SQL: reset (v15 + legacy).
const ( SettingActiveGroup = "active_group" SettingActiveMultiGroup = "active_multi_group" SettingSourceRepoPath = "source_repo_path" SettingSchemaVersion = "schema_version" )
Settings keys.
const ( MsgSchemaVersionUpToDateFmt = " ✓ Schema version %d is current — skipping migration pipeline.\n" MsgSchemaVersionAdvanceFmt = " ▸ Schema version %d → %d — running migration pipeline...\n" WarnSchemaVersionWriteFmt = " ⚠ Could not record schema version %d: %v\n" )
Schema-version log strings.
const ( ErrDBSettingUpsert = "failed to save setting: %v" ErrDBSettingQuery = "failed to read setting: %v" )
Settings error messages.
const ( CmdSSH = "ssh" SubCmdSSHCat = "cat" SubCmdSSHList = "list" SubCmdSSHListS = "ls" SubCmdSSHDelete = "delete" SubCmdSSHDeleteS = "rm" SubCmdSSHConfig = "config" )
gitmap:cmd top-level SSH command names.
const ( SQLInsertSSHKey = `INSERT INTO SshKey (Name, PrivatePath, PublicKey, Fingerprint, Email) VALUES (?, ?, ?, ?, ?)` SQLUpdateSSHKey = `UPDATE SshKey SET PrivatePath = ?, PublicKey = ?, Fingerprint = ?, Email = ? WHERE Name = ?` SQLSelectAllSSHKeys = `SELECT SshKeyId, Name, PrivatePath, PublicKey, Fingerprint, Email, CreatedAt FROM SshKey ORDER BY Name` SQLSelectSSHKeyByName = `SELECT SshKeyId, Name, PrivatePath, PublicKey, Fingerprint, Email, CreatedAt FROM SshKey WHERE Name = ?` SQLDeleteSSHKeyByName = `DELETE FROM SshKey WHERE Name = ?` )
SQL: SshKey operations (v15). Constant names retain SSH for callsite stability.
const ( SQLDropSshKey = "DROP TABLE IF EXISTS SshKey" SQLDropSSHKeys = "DROP TABLE IF EXISTS SSHKeys" // legacy )
SQL: drop SshKey table (and legacy plural).
const ( SSHKeyType = "rsa" SSHKeyBits = "4096" DefaultSSHKeyName = "default" SSHKeygenBin = "ssh-keygen" )
SSH key generation defaults.
const ( FlagSSHName = "--name" FlagSSHNameS = "-n" FlagSSHPath = "--path" FlagSSHPathS = "-p" FlagSSHEmail = "--email" FlagSSHEmailS = "-e" FlagSSHForce = "--force" FlagSSHForceS = "-f" FlagSSHFiles = "--files" FlagSSHKey = "--ssh-key" FlagSSHKeyS = "-K" FlagSSHHost = "--host" FlagSSHHostS = "-H" FlagSSHJSON = "--json" FlagSSHConfirm = "--confirm" )
SSH key generation flags.
const ( SSHConfigMarkerStart = "# --- gitmap managed (do not edit) ---" SSHConfigMarkerEnd = "# --- end gitmap managed ---" )
SSH config markers.
const ( MsgSSHGenerated = " \u2713 SSH key %q generated\n" MsgSSHPath = " Path: %s\n" MsgSSHFingerprint = " Fingerprint: %s\n" MsgSSHPubLabel = " Public key:\n\n" MsgSSHCopyHint = "\n \u2139 Copy the public key above and add it to your Git provider.\n" MsgSSHExists = " Key %q already exists at %s\n" MsgSSHExistsFP = " Fingerprint: %s\n" MsgSSHPromptAction = " [R]egenerate / [N]ew path / [C]ancel: " MsgSSHRegenerated = " \u2713 SSH key %q regenerated\n" MsgSSHDeleted = " \u2713 SSH key %q deleted\n" MsgSSHDeletedFiles = " \u2713 Key files removed from disk\n" MsgSSHDeleteConfirm = " Delete SSH key %q? (y/N): " MsgSSHListHeader = "\n SSH Keys (%d):\n\n" MsgSSHListRow = " %-15s %-30s %-25s %s\n" MsgSSHListColumns = " %-15s %-30s %-25s %s\n" MsgSSHConfigDone = " \u2713 SSH config updated\n" MsgSSHConfigShow = "\n Managed SSH config:\n\n" MsgSSHNewPathPrompt = " Enter new key path: " MsgSSHCloneUsing = " \u2192 Cloning with SSH key %q (%s)\n" MsgSSHMultiKeyHint = `` /* 127-byte string literal not displayed */ MsgSSHConfirmPrompt = " Generate SSH key %q at %s? (y/N): " MsgSSHCanceled = " Canceled.\n" MsgSSHHostUsed = " Host: %s\n" )
SSH messages.
const ( ErrSSHKeygen = "Error: SSH key generation failed at %s: %v (operation: write)\n" ErrSSHReadPub = "Error: failed to read public key at %s: %v (operation: read, reason: file does not exist)\n" ErrSSHNotFound = "Error: SSH key not found: %s\n" ErrSSHAvailable = " Available keys: %s\n" ErrSSHNameEmpty = "SSH key name cannot be empty" ErrSSHCreate = "failed to create SSH key record: %v" ErrSSHQuery = "failed to query SSH keys: %v" ErrSSHDelete = "failed to delete SSH key: %v" ErrSSHConfig = "Error: failed to update SSH config at %s: %v (operation: write)\n" ErrSSHKeygenMissing = "Error: ssh-keygen not found on PATH (operation: resolve, reason: file does not exist)\n" ErrSSHEmailResolve = "could not resolve email; use --email flag\n" ErrSSHFingerprint = "Error: failed to read key fingerprint at %s: %v (operation: read)\n" )
SSH error messages — Code Red: all file errors include exact path and reason.
const ( CmdStartupAdd = "startup-add" CmdStartupAddAlias = "sa" CmdStartupList = "startup-list" CmdStartupListAlias = "sl" CmdStartupRemove = "startup-remove" CmdStartupRemoveAlias = "sr" )
gitmap:cmd top-level Startup CLI commands. The pair `startup-list` / `startup-remove` is intentionally limited in scope on Linux/Unix: it ONLY enumerates and deletes entries gitmap created itself, identified by the `X-Gitmap-Managed=true` key inside the .desktop file. This matches the user requirement that no third-party autostart entry is ever touched, even if its filename happens to start with "gitmap".
Aliases mirror the install/uninstall short-form pattern so users who already know `in`/`un` can guess `sl`/`sr` without lookup.
const ( HelpStartupAdd = " startup-add (sa) Create a Linux/Unix or macOS autostart entry pointing at gitmap" HelpStartupList = " startup-list (sl) List Linux/Unix autostart entries created by gitmap" HelpStartupRemove = " startup-remove (sr) <name> Remove a gitmap-managed autostart entry by name" )
Startup help text. Format mirrors HelpInstall / HelpUninstall so the rendered `gitmap help` table stays visually consistent.
const ( StartupDesktopExt = ".desktop" StartupMarkerKey = "X-Gitmap-Managed" StartupMarkerVal = "true" StartupFilePrefix = "gitmap-" )
Startup .desktop file convention.
StartupDesktopExt is the file extension XDG autostart entries MUST use; the directory scanner only considers files ending in this suffix to avoid matching swap / backup files.
StartupMarkerKey is the .desktop key whose presence with value "true" marks an entry as gitmap-managed. We deliberately use a custom `X-` namespaced key (per the freedesktop.org spec — keys prefixed with `X-` are reserved for application-specific use) so a future tool with the same key cannot collide with us.
StartupFilePrefix is the filename prefix every gitmap-created .desktop file gets. It's a SECONDARY safeguard — list/remove still require StartupMarkerKey to be present, so renaming a third-party file to start with "gitmap-" does NOT make us touch it.
const ( StartupPlistExt = ".plist" StartupPlistMarker = "XGitmapManaged" StartupPlistPrefix = "gitmap." )
macOS LaunchAgent convention. The marker uses a hyphen-free key (`XGitmapManaged`) because plist keys are XML element text and keeping them simple avoids any escaping ambiguity in tests / hand edits. The on-disk filename prefix is `gitmap.` (reverse-DNS-ish) so .plist files match the LaunchAgent convention while still being cheap to pre-filter — same two-gate safety as Linux: the filename prefix is a hint, the in-file marker is the proof.
const ( MsgStartupListHeader = "Linux/Unix autostart entries managed by gitmap (%s):\n" MsgStartupListEmpty = " (none — no gitmap-managed autostart entries found)\n" MsgStartupListRow = " • %s → %s\n" MsgStartupRemoveOK = "✓ Removed gitmap-managed autostart entry: %s\n" MsgStartupRemoveNoOp = " (no-op) no gitmap-managed entry named %q found\n" MsgStartupRemoveNotOurs = " (refused) %q exists but was NOT created by gitmap — skipping\n" MsgStartupRemoveBadName = " (refused) name %q is empty or contains a path separator\n" // startup-remove --dry-run mirror messages. Same four outcomes, // each prefixed with `(dry-run)` so log-scrapers can tell a // preview from a real action without parsing flags. MsgStartupRemoveDryOK = " (dry-run) would remove gitmap-managed autostart entry: %s\n" MsgStartupRemoveDryNoOp = " (dry-run) no gitmap-managed entry named %q found — nothing to remove\n" MsgStartupRemoveDryNotOurs = " (dry-run) %q exists but was NOT created by gitmap — would refuse\n" MsgStartupRemoveDryBadName = " (dry-run) name %q is empty or contains a path separator — would refuse\n" // startup-add result messages. One line per outcome so log // scrapers can grep on the leading symbol/prefix. MsgStartupAddCreated = "✓ Created gitmap-managed autostart entry: %s\n" MsgStartupAddOverwritten = "✓ Overwrote gitmap-managed autostart entry: %s\n" MsgStartupAddExists = " (exists) gitmap-managed entry already at %s — pass --force to overwrite\n" MsgStartupAddRefused = " (refused) %q exists but was NOT created by gitmap — refusing to overwrite\n" MsgStartupAddBadName = " (refused) name %q is empty or contains a path separator\n" ErrStartupResolveDir = "could not resolve autostart directory: %v" ErrStartupReadDir = "could not read autostart directory %s: %v" ErrStartupRemoveUsage = "usage: gitmap startup-remove <name>" ErrStartupAddMissingExec = "startup-add: --exec is required " + "(or run from an installed gitmap binary so we can auto-detect it)" ErrStartupUnsupportedOS = "startup commands are not supported on this OS " + "(Linux/Unix XDG autostart and macOS LaunchAgents are supported; " + "on Windows use the Windows startup commands)" ErrStartupAddDarwinTODO = "startup-add is not yet implemented for macOS " + "(use list/remove for existing LaunchAgents; add support is tracked " + "in the OS-agnostic startup roadmap)" )
Startup user-visible messages. Plain ASCII arrows / glyphs to stay safe across terminals that don't render Unicode (matches the PowerShell-encoding constraint documented in mem://constraints/ powershell-encoding even though this is a Linux command — keeps the message style uniform across the whole CLI).
const ( FlagStartupAddName = "name" FlagStartupAddExec = "exec" FlagStartupAddDisplay = "display-name" FlagStartupAddComment = "comment" FlagStartupAddNoDisplay = "no-display" FlagStartupAddForce = "force" FlagStartupAddWorkingDir = "working-dir" FlagDescStartupAddName = "Logical name for the entry (filename becomes gitmap-<name>.desktop). Required." FlagDescStartupAddExec = "Command to run at login (default: path to the running gitmap binary)" FlagDescStartupAddDisplay = "Override the Name= field shown in desktop session managers" FlagDescStartupAddComment = "Optional Comment= field text" FlagDescStartupAddNoDisplay = "Set NoDisplay=true so the entry stays out of app menus" FlagDescStartupAddForce = "Overwrite an existing gitmap-managed entry (never overwrites third-party files)" FlagDescStartupAddWorkingDir = "Working directory the entry runs in " + "(Linux Path=, macOS WorkingDirectory, Windows tracking-subkey WorkingDir)" )
startup-add CLI flag descriptions. Kept here (not in constants_cli.go) so all startup-related strings live together and the flag parser file imports just one constants block.
const ( FlagStartupOutput = "output" FlagDescStartupOutput = "Output mode: terminal (default human lines) or json (status object)" ErrStartupBadOutput = "%s: unknown --output %q (expected: terminal, json)" FlagStartupJSONIndent = "json-indent" FlagDescStartupJSONIndent = "Spaces per indent level for --output=json (0 = minified, default 2). Ignored for --output=terminal." )
startup-add / startup-remove --output flag. Shared so both commands accept the same value set ("terminal" preserves the legacy human-readable lines; "json" emits the consistent startupStatus object — see cmd/startupstatusjson.go for the full schema). Default is "terminal" so existing scripts keep working byte-for-byte.
const ( FlagStartupListFormat = "format" FlagDescStartupListFormat = "Output format: table (default), json, jsonl, or csv" StartupListFormatTable = "table" // StartupListFormatJSONL is the jq/fluentd/BigQuery-friendly // line-oriented variant of --format=json: one compact object // per line, no array wrapper, empty list emits zero bytes. // Stable key order within each object is guaranteed via // stablejson.WriteJSONLines (same Field-slice contract as JSON). StartupListFormatJSONL = "jsonl" ErrStartupListBadFormat = "startup-list: unknown --format %q (expected: table, json, jsonl, csv)" // CSV header row for `--format csv`. Kept here so the column // order is centralized and tests can reference it. StartupListCSVHeader = "name,path,exec" // Filter flags. --backend scopes the listing to one Windows // backend (registry or startup-folder) — Linux/macOS callers // can pass either value but only entries that came from that // backend will appear, which is always zero on those OSes // (their single canonical backend is neither). --name matches // against the entry's logical name (the same value passed to // startup-add --name) so a user can verify a specific entry // without grepping table output. FlagStartupListBackend = "backend" FlagDescStartupListBackend = "Filter by backend: registry, registry-hklm, " + "or startup-folder (default: all backends)" FlagStartupListName = "name" FlagDescStartupListName = "Filter by logical entry name (same form as " + "`startup-add --name`); exact match" ErrStartupListBadBackend = "startup-list: unknown --backend %q " + "(expected: registry, registry-hklm, startup-folder)" )
startup-list CLI flag. Reuses the project-wide OutputTerminal/CSV/ JSON constants for values; "table" is accepted as an alias for the default human-readable rendering ("terminal" works too).
const ( FlagStartupListJSONIndent = "json-indent" FlagDescStartupListJSONIndent = "Spaces per indent level for --format=json (0 = minified, default 2). Ignored for non-json formats." StartupListJSONIndentDefault = 2 StartupListJSONIndentMax = 8 ErrStartupListBadJSONIndent = "startup-list: --json-indent %d out of range (expected: 0..8)" )
startup-list --json-indent flag. Controls whitespace in `--format=json` output without ever changing key order. Accepted values: integers 0..8 (0 = minified single-line; 2 = the long- standing pretty-printed default; 4/8 for editors that prefer wider indents). Negative or >8 values are rejected at parse time.
Silently IGNORED for `--format=table`, `--format=csv`, and `--format=jsonl` (which is line-oriented and minified by design). Silent rather than error so shell scripts that always pass `--json-indent=N --format=$F` for varying $F don't have to branch.
const ( FlagStartupRemoveDryRun = "dry-run" FlagDescStartupRemoveDryRun = "Show what would be deleted (or refused/no-op) without touching the filesystem" FlagStartupRemoveBackend = "backend" FlagDescStartupRemoveBackend = "Windows backend to remove from: registry, " + "registry-hklm (requires admin), or startup-folder " + "(default: try all — registry, then registry-hklm, then startup-folder)" )
startup-remove CLI flags. --backend mirrors the same flag on startup-add so a user can scope a removal to one Windows backend (registry or startup-folder) instead of the legacy dual-backend fallback. Linux/macOS callers ignore --backend — there's only one autostart backend per OS.
const ( // StartupBackendRegistry writes ONE direct value to HKCU\ // Software\Microsoft\Windows\CurrentVersion\Run and tracks // ownership in a SEPARATE scope under HKCU\Software\Gitmap\ // StartupRegistry\<name>. The Run key never carries a sibling // marker — Windows would dispatch it as an autostart command // at every login. StartupBackendRegistry = "registry" // StartupBackendStartupFolder writes a .lnk file into // %APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup, // with a sibling tracking subkey under HKCU\Software\Gitmap\ // StartupFolder\<name>. StartupBackendStartupFolder = "startup-folder" // StartupBackendRegistryHKLM mirrors StartupBackendRegistry but // targets the MACHINE-WIDE Run key under HKEY_LOCAL_MACHINE // instead of the per-user HKEY_CURRENT_USER. The autostart value // fires for EVERY interactive user that logs into the machine, // so writes require administrator privileges (UAC elevation). // Tracking metadata is stored under // HKLM\Software\Gitmap\StartupRegistry\<name> so a non-admin // reader can still discover ownership without touching HKCU. // Reads (list) work without elevation; add/remove require admin // and surface ErrStartupHKLMNotAdmin up-front when the current // process token is not elevated. StartupBackendRegistryHKLM = "registry-hklm" )
Windows backends. The user picks one via `--backend=<value>` on `gitmap startup-add` (default: registry). `gitmap startup-list` and `gitmap startup-remove` enumerate / search BOTH backends so users don't have to remember which one a given entry lives in.
const ( // RegRunKeyPath is the canonical autostart Run key, used under // HKCU for the default registry backend AND under HKLM for the // machine-wide registry-hklm backend. Values placed here // execute once at the next interactive login. We deliberately // avoid RunOnce (single-execution) and RunOnceEx (chained // execution) — both have surprising auto-deletion semantics // that conflict with idempotent `gitmap startup-add` re-runs. RegRunKeyPath = `Software\Microsoft\Windows\CurrentVersion\Run` // RegGitmapRoot is the parent for all gitmap tracking metadata // (registry-backend AND startup-folder-backend). The same // relative path is used under HKCU and HKLM. Two leaf subkeys // live underneath each hive: // StartupRegistry\<name> → tracks Run-key entries // StartupFolder\<name> → tracks .lnk Startup-folder entries // Each leaf carries metadata values (CreatedAt, Exec, Source) // that the Linux marker line and macOS plist key encode inline. RegGitmapRoot = `Software\Gitmap` RegGitmapRegistrySub = `Software\Gitmap\StartupRegistry` RegGitmapStartupFolder = `Software\Gitmap\StartupFolder` // RegMarkerSiblingSuffix is DEPRECATED and no longer written. // The direct-value Run-key model (gitmap v3.175.0+) keeps the // ownership marker out-of-band under <hive>\Software\Gitmap so // the Run key contains only real autostart commands. Kept as // a constant so external cleanup scripts that historically // removed `<name>.gitmap-managed` companions can still // reference the suffix without code drift. RegMarkerSiblingSuffix = `.gitmap-managed` // Tracking-subkey value names. Stored as REG_SZ so `reg query` // shows them readable; CreatedAt is RFC3339 UTC. WorkingDir is // only written when the user passed --working-dir; an empty // value is omitted entirely so `reg query` output stays tidy // for the common no-cwd case. RegTrackKeyExec = "Exec" RegTrackKeyCreatedAt = "CreatedAt" RegTrackKeySource = "Source" // "registry" | "registry-hklm" | "startup-folder" RegTrackKeyWorkingDir = "WorkingDir" )
Registry paths. The same RUN-key relative path (`Software\Microsoft\Windows\CurrentVersion\Run`) is used under BOTH HKCU (per-user, default) and HKLM (machine-wide, opt-in via `--backend=registry-hklm`). Tracking metadata mirrors the same shape under both hives so a non-admin reader can discover ownership of HKCU entries without touching HKLM and vice versa.
const ( StartupWinValuePrefix = "gitmap-" StartupLnkExt = ".lnk" )
Windows file naming. The Run-key value name and the .lnk filename both use the same `gitmap-<name>` form so List can recognize them from the name alone (cheap pre-filter), then re-check the tracking subkey for definitive ownership. Same two-gate model as Linux/macOS.
const ( FlagStartupAddBackend = "backend" FlagDescStartupAddBackend = "Windows backend: registry (default, HKCU per-user), " + "registry-hklm (HKLM machine-wide; requires admin), or startup-folder" ErrStartupAddBadBackend = "startup-add: unknown --backend %q " + "(expected: registry, registry-hklm, startup-folder)" )
Flag values + descriptions for the --backend flag on `gitmap startup-add` / `startup-remove` / `startup-list`. Listed at the package's existing flag block for discoverability via `gitmap startup-add --help`.
const ( MsgStartupListHeaderWindows = "Windows autostart entries managed by gitmap:\n" MsgStartupListBackendSection = " [%s]\n" ErrStartupRegistryOpen = "open registry key %s: %v" ErrStartupRegistryWrite = "write registry value %s: %v" ErrStartupRegistryRead = "read registry value %s: %v" ErrStartupShortcutCreate = "create shortcut %s: %v" ErrStartupPowerShellMissing = "powershell.exe not found on PATH " + "(required for --backend=startup-folder; install Windows " + "PowerShell or use --backend=registry)" // ErrStartupHKLMNotAdmin is surfaced BEFORE any registry write // attempt when --backend=registry-hklm is requested but the // current process token is not elevated. Keeping the check // up-front (instead of relying on the registry ACL to refuse // SET_VALUE) means the user sees a friendly, actionable // message instead of a raw "Access is denied" Win32 error and // no half-written tracking metadata is ever left behind. ErrStartupHKLMNotAdmin = "startup-add: --backend=registry-hklm requires " + "administrator privileges (re-run from an elevated shell, e.g. " + "`Run as administrator` from the Start menu, or use the per-user " + "`--backend=registry` default)" StartupFolderRelative = `Microsoft\Windows\Start Menu\Programs\Startup` )
Windows user-visible messages. Plain ASCII glyphs to match the existing PowerShell-encoding constraint (mem://constraints/ powershell-encoding) and the bullet/arrow style from constants_startup.go.
const ( CmdStats = "stats" CmdStatsAlias = "ss" )
gitmap:cmd top-level Stats CLI commands.
const ( SQLStatsPerCommand = `` /* 498-byte string literal not displayed */ SQLStatsForCommand = `` /* 492-byte string literal not displayed */ SQLStatsOverall = `` /* 384-byte string literal not displayed */ )
Stats SQL queries.
const ( MsgStatsHeader = "Command Usage Statistics" MsgStatsSeparator = "" /* 210-byte string literal not displayed */ MsgStatsOverallFmt = "Total: %d executions (%d unique commands) | Success: %d | Fail: %d (%.1f%%) | Avg: %dms\n" MsgStatsColumns = "COMMAND RUNS SUCCESS FAIL FAIL%% AVG(ms) MIN(ms) MAX(ms) LAST USED" MsgStatsRowFmt = "%-15s %-6d %-8d %-5d %-7.1f %-8d %-8d %-8d %s\n" MsgStatsEmpty = "No command history found. Run some commands first.\n" ErrStatsQuery = "failed to query stats: %v" )
Stats terminal formatting.
const ( DBDir = "data" DBFile = "gitmap.db" )
Database location.
const ( LockFileName = "gitmap.lock" LockFilePermission = 0o644 ErrLockHeld = "another gitmap process is running (PID %d).\n If incorrect, delete: %s" )
Lock file.
const ( TableRepo = "Repo" TableGroup = "Group" TableGroupRepo = "GroupRepo" TableRelease = "Release" )
Table names (v15: PascalCase + singular + {Table}Id PK).
const ( LegacyTableRepos = "Repos" LegacyTableGroups = "Groups" LegacyTableGroupRepos = "GroupRepos" LegacyTableReleases = "Releases" )
Legacy table names retained only for migration detection (do not use in new SQL).
const ( SQLUpsertRepo = `` /* 454-byte string literal not displayed */ SQLSelectAllRepos = "" /* 132-byte string literal not displayed */ SQLSelectRepoBySlug = "" /* 133-byte string literal not displayed */ SQLSelectRepoByPath = "" /* 141-byte string literal not displayed */ )
SQL: repo operations (v15: Repo table, RepoId PK).
const ( SQLInsertGroup = `INSERT INTO "Group" (Name, Description, Color) VALUES (?, ?, ?)` SQLSelectAllGroups = `SELECT GroupId, Name, Description, Color, CreatedAt FROM "Group" ORDER BY Name` SQLSelectGroupByName = `SELECT GroupId, Name, Description, Color, CreatedAt FROM "Group" WHERE Name = ?` SQLDeleteGroup = `DELETE FROM "Group" WHERE Name = ?` SQLInsertGroupRepo = "INSERT OR IGNORE INTO GroupRepo (GroupId, RepoId) VALUES (?, ?)" SQLDeleteGroupRepo = "DELETE FROM GroupRepo WHERE GroupId = ? AND RepoId = ?" SQLSelectGroupRepos = `` /* 223-byte string literal not displayed */ SQLCountGroupRepos = "SELECT COUNT(*) FROM GroupRepo WHERE GroupId = ?" )
SQL: group operations (v15: "Group" singular, GroupId PK).
const ( SQLUpsertRelease = `` /* 528-byte string literal not displayed */ SQLSelectAllReleases = `` /* 180-byte string literal not displayed */ // SQLSelectAllReleasesAcrossRepos powers `gitmap releases --all-repos`. // The JOIN on Repo.RepoId = Release.RepoId is what exercises (and // pre-pays) the IdxRelease_RepoId secondary index added in v17. SQLSelectAllReleasesAcrossRepos = `` /* 255-byte string literal not displayed */ SQLSelectReleaseByTag = `` /* 170-byte string literal not displayed */ SQLClearLatestRelease = "UPDATE Release SET IsLatest = 0 WHERE IsLatest = 1 AND RepoId = ?" SQLAddNotesColumn = "ALTER TABLE Release ADD COLUMN Notes TEXT DEFAULT ''" )
SQL: release operations (v17: composite UNIQUE(RepoId, Tag), RepoId FK).
const ( SQLDropGroupRepo = "DROP TABLE IF EXISTS GroupRepo" SQLDropGroupRepos = "DROP TABLE IF EXISTS GroupRepos" // legacy SQLDropGroup = `DROP TABLE IF EXISTS "Group"` SQLDropGroups = "DROP TABLE IF EXISTS Groups" // legacy SQLDropRepo = "DROP TABLE IF EXISTS Repo" SQLDropRepos = "DROP TABLE IF EXISTS Repos" // legacy, kept for migrateLegacyIDs SQLDropRelease = "DROP TABLE IF EXISTS Release" SQLDropReleases = "DROP TABLE IF EXISTS Releases" // legacy )
SQL: reset operations (v15 names + legacy plurals kept for safe drop on upgraded DBs).
const ( ErrDBOpen = "failed to open database at %s: %v (operation: open)" ErrDBMigrate = "failed to initialize tables: %v" ErrDBUpsert = "failed to upsert repo: %v" ErrDBQuery = "failed to query repos: %v" ErrDBNoMatch = "no repo matches slug: %s\n" ErrDBCreateDir = "failed to create database directory at %s: %v (operation: mkdir)" ErrDBGroupCreate = "failed to create group: %v" ErrDBGroupQuery = "failed to query groups: %v" ErrDBGroupAdd = "failed to add repo to group: %v" ErrDBGroupRemove = "failed to remove repo from group: %v" ErrDBGroupDelete = "failed to delete group: %v" ErrDBGroupNone = "no group found: %s" ErrDBGroupExists = "group already exists: %s" ErrDBReleaseUpsert = "failed to upsert release: %v" ErrDBReleaseQuery = "failed to query releases: %v" )
Store error messages.
const ( MsgV15RepoMigrationStart = "→ Migrating database to v15 schema (Repos → Repo)..." MsgV15RepoMigrationDone = "✓ Migrated Repos → Repo (RepoId PK). Existing data preserved." ErrV15RepoMigration = "v15 Repo migration failed: %v" ErrV15RepoCountMismatch = "v15 Repo migration count mismatch: old=%d new=%d" ErrV15Phase2Migration = "v15 Phase 1.2 migration failed: %v" ErrV15Phase3Migration = "v15 Phase 1.3 migration failed: %v" ErrV15Phase4Migration = "v15 Phase 1.4 migration failed: %v" ErrV15Phase5Migration = "v15 Phase 1.5 migration failed: %v" ErrV15Phase6Migration = "v15 Phase 1.6 migration failed: %v" )
Phase 1 v15 migration messages.
const ( MsgV15Phase6Start = "→ Migrating Release table: adding RepoId FK to Repo (v3.17.0 schema)..." MsgV15Phase6Wipe = " Existing Release rows will be wiped and re-imported from .gitmap/release/v*.json on next list-releases." MsgV15Phase6Done = "✓ Release table dropped — will be recreated with RepoId FK on next CREATE pass." ErrReleaseNoRepo = "cannot persist release: no repo registered for path %q. Run `gitmap scan` first to register the repo, then retry." )
Phase 1.6 (v17) Release.RepoId FK migration messages.
const ( CmdTask = "task" CmdTaskAlias = "tk" )
gitmap:cmd top-level Task CLI commands.
const ( CmdTaskCreate = "create" // gitmap:cmd skip CmdTaskList = "list" // gitmap:cmd skip CmdTaskRun = "run" // gitmap:cmd skip CmdTaskShow = "show" // gitmap:cmd skip CmdTaskDelete = "delete" // gitmap:cmd skip )
gitmap:cmd top-level Task subcommands.
const ( TaskDefaultInterval = 5 TaskMinInterval = 2 TaskMaxGoroutines = 64 TaskCopyBufferSize = 32768 TasksFileName = "tasks.json" )
Task defaults.
const ( FlagTaskSrc = "src" FlagTaskDest = "dest" FlagTaskInterval = "interval" FlagTaskVerbose = "verbose" FlagTaskDryRun = "dry-run" )
Task flag names.
const ( FlagDescTaskSrc = "Source directory path" FlagDescTaskDest = "Destination directory path" FlagDescTaskInterval = "Sync interval in seconds (minimum 2)" FlagDescTaskVerbose = "Show detailed sync output" FlagDescTaskDryRun = "Preview sync actions without copying" )
Task flag descriptions.
const ( MsgTaskCreated = "Task '%s' created.\n" MsgTaskDeleted = "Task '%s' deleted.\n" MsgTaskRunning = "Task '%s' running — syncing every %ds (Ctrl+C to stop)\n" MsgTaskSynced = "Synced: %s\n" MsgTaskUpToDate = "All files up to date.\n" MsgTaskDrySync = "[dry-run] Would sync: %s\n" MsgTaskListHeader = "Tasks:\n" MsgTaskListRow = " %-20s %s → %s\n" MsgTaskListEmpty = "No tasks defined. Use 'gitmap task create' to add one.\n" MsgTaskShowFmt = "Name: %s\nSource: %s\nDest: %s\n" MsgTaskStopped = "\nTask '%s' stopped.\n" )
Task terminal messages.
const ( ErrTaskNameRequired = "Task name is required." ErrTaskSrcRequired = "Source directory (--src) is required." ErrTaskDestRequired = "Destination directory (--dest) is required." ErrTaskNotFound = "Task '%s' not found.\n" ErrTaskAlreadyExists = "Task '%s' already exists.\n" ErrTaskSrcNotExist = "Error: source directory does not exist at %s (operation: resolve, reason: file does not exist)\n" ErrTaskDestCreate = "Error: failed to create destination directory at %s: %v (operation: mkdir)\n" ErrTaskLoadFile = "Error: failed to load tasks file at %s: %v (operation: read)\n" ErrTaskSaveFile = "Error: failed to save tasks file at %s: %v (operation: write)\n" ErrTaskSyncFailed = "Sync failed for %s: %v\n" ErrTaskSubcommand = "Unknown task subcommand: %s\n" )
Task error messages.
const ( CmdTemplates = "templates" CmdTemplatesAlias = "tpl" )
Top-level command. // gitmap:cmd top-level
const ( CmdTemplatesDiff = "diff" // gitmap:cmd skip CmdTemplatesDiffAlias = "td" CmdTemplatesInit = "init" // gitmap:cmd skip CmdTemplatesInitAlias = "ti" )
Templates subcommand aliases that should appear in shell tab-completion alongside the top-level `templates` / `tpl` commands. Users frequently type the alias directly after `templates` (e.g. `gitmap tpl td --lang go`), so surfacing them in completion makes the alias discoverable.
The full subcommand IDs (`diff`, `init`) are intentionally skipped via `// gitmap:cmd skip` because:
- `diff` is already registered as a top-level command (folder-tree diff via gitmap/cmd/diff.go); re-listing it here would be a no-op for the union but conceptually incorrect.
- `init` is not a top-level gitmap command at all; surfacing it standalone would mislead users into typing `gitmap init`.
gitmap:cmd top-level
const ( CmdTempRelease = "temp-release" CmdTempReleaseShort = "tr" SubCmdTRList = "list" SubCmdTRRemove = "remove" )
gitmap:cmd top-level Temp-release command names.
const ( SQLInsertTempRelease = `INSERT INTO TempRelease (Branch, VersionPrefix, SequenceNumber, CommitSha, CommitMessage) VALUES (?, ?, ?, ?, ?)` SQLSelectAllTempReleases = `` /* 139-byte string literal not displayed */ SQLSelectMaxSeqByPrefix = `SELECT COALESCE(MAX(SequenceNumber), 0) FROM TempRelease WHERE VersionPrefix = ?` SQLDeleteTempRelease = `DELETE FROM TempRelease WHERE Branch = ?` SQLDeleteAllTempReleases = `DELETE FROM TempRelease` SQLCountTempReleases = `SELECT COUNT(*) FROM TempRelease` )
SQL: temp-release operations (v15).
const ( SQLDropTempRelease = "DROP TABLE IF EXISTS TempRelease" SQLDropTempReleases = "DROP TABLE IF EXISTS TempReleases" // legacy )
SQL: drop TempRelease table (and legacy plural).
const ( FlagDescTRStart = "Starting sequence number (default: auto-increment)" FlagDescTRDryRun = "Preview branch names without creating" FlagDescTRJSON = "Output structured JSON" FlagDescTRVerbose = "Detailed logging" )
Temp-release flag descriptions.
const ( MsgTRCreating = " Creating %d temp-release branch(es)...\n" MsgTRCreated = " ✓ Created %s from %s\n" MsgTRPushing = " Pushing %d branch(es) to origin...\n" MsgTRPushed = " ✓ Pushed %d branch(es) to origin\n" MsgTRSeqStart = " → Starting sequence: %d\n" MsgTRSeqAuto = " → Starting sequence: %d (auto-detected)\n" MsgTRDryRunHeader = " Dry-run: would create %d temp-release branch(es):\n" MsgTRDryRunEntry = " %s %s %s\n" MsgTRListHeader = "\n Temp-release branches (%d):\n\n" MsgTRListRow = " %-35s %s %-50s %s\n" MsgTRListEmpty = " No temp-release branches found.\n" MsgTRRemovePrompt = " Remove %s? (y/N): " MsgTRRemoveRange = " Remove %d temp-release branch(es):\n" MsgTRRemoveAll = " Remove ALL %d temp-release branch(es):\n" MsgTRRemoveBranch = " %s\n" MsgTRRemoveConfirm = " Proceed? (y/N): " MsgTRRemoved = " ✓ Removed %d temp-release branch(es) (local + remote)\n" MsgTRRemovedOne = " ✓ Removed %s (local + remote)\n" MsgTRSkipExists = " ⚠ Branch already exists, skipping: %s\n" MsgTRSkipMissing = " ⚠ Branch not found, skipping: %s\n" MsgTRComplete = " Temp-release complete.\n" MsgTRNoneToRemove = " No temp-release branches to remove.\n" )
Temp-release messages.
const ( ErrTRUsage = "Usage: gitmap temp-release <count> <version-pattern> [-s N]" ErrTRInvalidCount = "count must be between 1 and %d" ErrTRNoPlaceholder = "version pattern must contain at least one '$' placeholder (e.g., v1.$$)" ErrTROverflow = "sequence %d exceeds %d-digit format (max %d)" ErrTRNotEnough = " ⚠ Only %d commit(s) available (requested %d)\n" ErrTRCreate = "failed to create temp-release: %v" ErrTRQuery = "failed to query temp-releases: %v" ErrTRDelete = "failed to delete temp-release: %v" ErrTRRemoveUsage = "Usage: gitmap tr remove <version> | <v1> to <v2> | all" )
Temp-release error messages.
const ( ColorReset = "\033[0m" ColorGreen = "\033[32m" ColorRed = "\033[31m" ColorYellow = "\033[33m" ColorCyan = "\033[36m" ColorWhite = "\033[97m" ColorDim = "\033[90m" )
ANSI color codes.
const ( StatusBannerTop = "╔══════════════════════════════════════╗" StatusBannerTitle = "║ gitmap status ║" StatusBannerBottom = "╚══════════════════════════════════════╝" StatusRepoCountFmt = "%d repos from .gitmap/output/gitmap.json" )
Status banner box-drawing.
const ( StatusIconClean = "✓ clean" StatusIconDirty = "● dirty" StatusDash = "—" StatusSyncDash = " —" StatusStashFmt = "📦 %d" StatusSyncUpFmt = "↑%d" StatusSyncDownFmt = "↓%d" StatusSyncBothFmt = "↑%d ↓%d" StatusStagedFmt = "+%d" StatusModifiedFmt = "~%d" StatusUntrackedFmt = "?%d" )
Status indicator strings.
const ( StatusRowFmt = " %-22s %s %s %s %s %s\n" StatusMissingFmt = " %s%-22s %s⊘ not found%s\n" StatusHeaderFmt = " %s%-22s %-12s %-8s %-10s %-8s %-6s%s\n" )
Status row format strings.
const ( SummaryJoinSep = " · " SummaryReposFmt = "%d repos" SummaryCleanFmt = "%d clean" SummaryDirtyFmt = "%d dirty" SummaryAheadFmt = "%d ahead" SummaryBehindFmt = "%d behind" SummaryStashedFmt = "%d stashed" SummaryMissingFmt = "%d missing" SummarySucceededFmt = "%d succeeded" SummaryFailedFmt = "%d failed" StatusFileCountSep = " " TruncateEllipsis = "…" )
Summary format strings.
const ( SetupBannerTop = "╔══════════════════════════════════════╗" SetupBannerTitle = "║ gitmap setup ║" SetupBannerBottom = "╚══════════════════════════════════════╝" SetupDryRunFmt = "[DRY RUN] No changes will be made" SetupAppliedFmt = "✓ %d settings applied" SetupSkippedFmt = "⊘ %d settings unchanged" SetupFailedFmt = "✗ %d settings failed" SetupErrorEntryFmt = "- %s" )
Setup banner box-drawing.
const ( ChangelogVersionFmt = "\n%s" ChangelogNoteFmt = " - %s" )
Changelog entry format strings (legacy — used by tests and any caller that still wants the bare layout). The pretty console renderer in gitmap/cmd/changelogprint.go ignores these.
const ( ChangelogPrettyRule = "" /* 210-byte string literal not displayed */ ChangelogPrettyHeaderFmt = " %s%s%s%s %s%s%s\n" // dim, version, reset, dim-bullet, white, title, reset ChangelogPrettyHeaderBare = " %s%s%s\n" // version only when no title parsed ChangelogPrettyBulletFmt = " %s%s%s %s\n" // indent, color marker, reset, text ChangelogPrettyBoldOpen = "\033[1m" ChangelogPrettyBoldClose = "\033[22m" ChangelogPrettyCodeOpen = "\033[36m" ChangelogPrettyCodeClose = "\033[39m" ChangelogPrettyMarkerL0 = "•" ChangelogPrettyMarkerL1 = "◦" ChangelogPrettyMarkerLN = "·" ChangelogPrettyIndentUnit = " " ChangelogPrettyWrapDefault = 100 ChangelogPrettyWrapMin = 60 ChangelogPrettyWrapMax = 140 ChangelogPrettyEnvColumns = "COLUMNS" )
Changelog pretty-print constants. Centralized here so future tweaks to colors, indent widths, or rule glyphs don't require code changes in the cmd package.
const ( ExecBannerTop = "╔══════════════════════════════════════╗" ExecBannerTitle = "║ gitmap exec ║" ExecBannerBottom = "╚══════════════════════════════════════╝" ExecCommandFmt = "Command: git %s" ExecRepoCountFmt = "%d repos from .gitmap/output/gitmap.json" ExecSuccessFmt = " %s✓ %-22s%s\n" ExecFailFmt = " %s✗ %-22s%s\n" ExecMissingFmt = " %s⊘ %-22s %snot found%s\n" ExecOutputLineFmt = " %s%s%s\n" ExecSummaryRule = "" /* 150-byte string literal not displayed */ )
Exec banner box-drawing.
const ( TermBannerTop = " ╔══════════════════════════════════════╗" TermBannerTitle = " ║ gitmap v%s ║" TermBannerBottom = " ╚══════════════════════════════════════╝" TermFoundFmt = " ✓ Found %d repositories" TermReposHeader = " ■ Repositories" TermTreeHeader = " ■ Folder Structure" TermCloneHeader = " ■ How to Clone on Another Machine" TermSeparator = "" /* 128-byte string literal not displayed */ TermTableRule = "" /* 210-byte string literal not displayed */ )
Terminal output sections.
const ( ScanProgressPrefix = " ⟳ Scanning" // ScanProgressLineFmt: prefix, dirs walked, repos found. // Trailing spaces overwrite any leftover wider previous frame; the // emitter then re-issues "\r" before the next frame. ScanProgressLineFmt = "\r%s%s%s — %s%d dirs%s · %s%d repos%s " ScanProgressClearLine = "\r \r" ScanProgressDoneFmt = " %s✓ Walked %d directories · found %d repositories%s\n" )
Scan live progress indicator. Rendered to stderr on a single CR-prefixed line (so stdout / output files stay clean). The "Scanning" prefix uses dim+cyan to set it apart from the boxed banner that follows.
const ( TermRepoIcon = " 📦 %s\n" TermPathLine = " Path: %s\n" TermCloneLine = " Clone: %s\n" )
Terminal repo entry formats.
const ( TermCloneStep1 = " 1. Copy the output files to the target machine:" TermCloneCmd1 = " .gitmap/output/gitmap.json (or .csv / .txt)" TermCloneStep2 = " 2. Clone via JSON (shorthand):" TermCloneCmd2 = " gitmap clone json --target-dir ./projects" TermCloneCmd2Alt = " gitmap c json # alias" TermCloneStep3 = " 3. Clone via CSV (shorthand):" TermCloneCmd3 = " gitmap clone csv --target-dir ./projects" TermCloneCmd3Alt = " gitmap c csv # alias" TermCloneStep3t = " 4. Clone via text (shorthand):" TermCloneCmd3t = " gitmap clone text --target-dir ./projects" TermCloneCmd3tAlt = " gitmap c text # alias" TermCloneStep3b = " 5. Or specify a file path directly:" TermCloneCmd3b = " gitmap clone .gitmap/output/gitmap.json --target-dir ./projects" TermCloneStep4 = " 6. Or run the PowerShell script directly:" TermCloneCmd4HTTPS = " .\\direct-clone.ps1 # HTTPS clone commands" TermCloneCmd4SSH = " .\\direct-clone-ssh.ps1 # SSH clone commands" TermCloneStep5 = " 7. Full clone script with progress & error handling:" TermCloneCmd5 = " .\\clone.ps1 -TargetDir .\\projects" TermCloneStep6 = " 8. Sync repos to GitHub Desktop:" TermCloneCmd6 = " gitmap desktop-sync # or: gitmap ds" TermCloneNote = " Note: safe-pull is auto-enabled when existing repos are detected." )
Terminal clone help text.
const ( StructureTitle = "# Folder Structure" StructureDescription = "Git repositories discovered by gitmap." StructureRepoFmt = "📦 **%s** (`%s`) — %s" TreeBranch = "├──" TreeCorner = "└──" TreePipe = "│ " TreeSpace = " " )
Folder structure Markdown.
const ( ScanTransportSSH = "ssh" ScanTransportHTTPS = "https" ScanTransportOther = "other" )
Transport-bucket labels emitted in the new "transport" CSV column and the matching JSON field. Kept here so the CSV writer, the classifier in mapper, and any downstream filter share one source of truth — renaming would silently break every grep/jq pipeline that keys on these strings.
const ( LBTermLatestFmt = " Latest branch: %s\n" LBTermRemoteFmt = " Remote: %s\n" LBTermSHAFmt = " SHA: %s\n" LBTermDateFmt = " Commit date: %s\n" LBTermSubjectFmt = " Subject: %s\n" LBTermRefFmt = " Ref: %s\n" LBTermTopHdrFmt = " Top %d most recently updated remote branches (%s):\n" LBTermRowFmt = " %-30s %-30s %-9s %s\n" )
Latest-branch terminal display format strings.
const ( // SQLCreateTransaction defines the master journal row. Status moves // pending → committed → reverted (or pending → aborted on failure). // "Transaction" is a SQL reserved word in some dialects, so the // table name is double-quoted everywhere it appears. SQLCreateTransaction = `` /* 406-byte string literal not displayed */ // SQLCreateTransactionFile records every file gitmap snapshotted // before mutating. ON DELETE CASCADE keeps the child rows in sync // when PruneOldest drops a parent transaction. SQLCreateTransactionFile = `` /* 401-byte string literal not displayed */ SQLCreateTransactionStatusIndex = `CREATE INDEX IF NOT EXISTS IdxTransactionStatus ON "Transaction"(Status, TransactionId DESC)` SQLInsertTransaction = `` /* 128-byte string literal not displayed */ SQLUpdateTransactionStatus = `UPDATE "Transaction" SET Status = ?, CommittedAt = ?, RevertedAt = ? WHERE TransactionId = ?` SQLSelectTransactionByID = `` /* 158-byte string literal not displayed */ SQLSelectTransactionsRecent = `` /* 170-byte string literal not displayed */ SQLSelectLastCommittedTransaction = `SELECT TransactionId FROM "Transaction" WHERE Status = 'committed' ORDER BY TransactionId DESC LIMIT 1` SQLSelectExcessTransactionIDs = `SELECT TransactionId FROM "Transaction" ORDER BY TransactionId DESC LIMIT -1 OFFSET ?` SQLDeleteTransaction = `DELETE FROM "Transaction" WHERE TransactionId = ?` SQLInsertTransactionFile = `` /* 128-byte string literal not displayed */ SQLSelectTransactionFiles = `` /* 167-byte string literal not displayed */ )
const ( TxnStatusPending = "pending" TxnStatusCommitted = "committed" TxnStatusAborted = "aborted" TxnStatusReverted = "reverted" TxnKindClone = "clone" TxnKindMv = "mv" TxnKindMerge = "merge" TxnKindFixRepo = "fix-repo" TxnKindHistoryPurge = "history-purge" TxnKindHistoryPin = "history-pin" TxnActionDelete = "delete" TxnActionEdit = "edit" TxnActionRename = "rename" TxnRetentionCap = 50 TxnBackupDirName = "txn" TxnBackupDataDir = "data" TxnBackupFilesDir = "files" TxnUnknownGitShaMarker = "_unknown" TxnReplaceModeWarning = "replace mode — file contents NOT recoverable, re-run fix-repo with the prior version" )
Status / kind / action enums — strings on the wire, constants in code.
const ( FlagRevertListTxn = "list-txn" FlagDescRevertListTxn = "list the last 50 transactions and exit" FlagRevertShowTxn = "show-txn" FlagDescRevertShowTxn = "print one transaction (including every captured file) by id, then exit" FlagRevertTxn = "txn" FlagDescRevertTxn = "revert the named transaction id" FlagRevertLastTxn = "last-txn" FlagDescRevertLastTxn = "revert the most recent committed transaction" FlagRevertLastN = "last-n-txn" FlagDescRevertLastN = "revert the most recent N committed transactions, newest first" FlagRevertPruneTxn = "prune-txn" FlagDescRevertPruneTxn = "force a transaction prune cycle now (drops everything beyond the 50-row cap)" FlagRevertForce = "force" FlagDescRevertForce = "skip the confirm prompt before reverting" )
CLI flags for the extended `gitmap revert` surface.
const ( MsgTxnPruned = " ✓ pruned %d old transaction(s)\n" MsgTxnReverted = " ✓ reverted transaction #%d (%s)\n" MsgTxnNoCommitted = " • no committed transactions found\n" MsgTxnConfirmRevert = "About to revert transaction #%d (%s, %d file(s)).\n" MsgTxnConfirmPrompt = "Type 'yes' to continue: " MsgTxnAbortedByUser = " • revert canceled by user\n" MsgTxnReplaceModeNote = " • transaction #%d ran in fix-repo --replace mode and cannot restore file bytes\n" MsgTxnLastNHeader = "About to revert %d transaction(s), newest first:\n" MsgTxnLastNRow = " #%-4d %-10s %s %s\n" MsgTxnLastNDone = " ✓ reverted %d transaction(s)\n" MsgTxnLastNNoneFound = " • no committed transactions to revert\n" ErrRevertLastNBadCount = "revert: --%s requires a positive integer, got %q\n" ErrTxnRowNotFound = "transaction #%d not found\n" ErrTxnNotCommitted = "transaction #%d status is %q, only committed transactions can be reverted\n" ErrTxnBackupMissing = "transaction #%d backup file missing on disk: %q\n" ErrTxnBackupShaDrift = "" /* 130-byte string literal not displayed */ ErrTxnDBOpen = "transaction journal: failed to open database: %v\n" ErrTxnDBWrite = "transaction journal: write failed: %v\n" )
User-facing messages.
const ( // SQLCreateTransactionAction is the typed action layer. // BackupRef is the TransactionFileId of the byte-snapshot row that // holds the pre-mutation payload, or 0 when the action does not need // one (rename, db row ops, tag flips, workspace writes that the // reverse JSON can fully reconstruct). SQLCreateTransactionAction = `` /* 504-byte string literal not displayed */ // SQLCreateTransactionActionTxnSeqIndex is the primary replay index: // every revert pass scans (TransactionId ASC|DESC, Seq DESC) so the // composite covers both ListByTransaction and the seq-ordered walk. SQLCreateTransactionActionTxnSeqIndex = `CREATE INDEX IF NOT EXISTS IdxTransactionActionTxnSeq ON TransactionAction(TransactionId, Seq DESC)` // SQLCreateTransactionActionKindIndex covers analytical queries that // filter by Kind across many transactions (e.g. "show every // clone_repo action in the last week"). SQLCreateTransactionActionKindIndex = `CREATE INDEX IF NOT EXISTS IdxTransactionActionKind ON TransactionAction(Kind, TransactionId DESC)` SQLInsertTransactionAction = `` /* 133-byte string literal not displayed */ SQLSelectTransactionActions = `` /* 176-byte string literal not displayed */ SQLSelectTransactionActionsReverse = `` /* 177-byte string literal not displayed */ SQLSelectMaxActionSeq = `SELECT COALESCE(MAX(Seq), 0) FROM TransactionAction WHERE TransactionId = ?` SQLMarkTransactionActionReverted = `UPDATE TransactionAction SET RevertedAt = ? WHERE TransactionActionId = ?` )
const ( ActionKindCreatePath = "create_path" ActionKindDeletePath = "delete_path" ActionKindEditFile = "edit_file" ActionKindRenamePath = "rename_path" ActionKindCloneRepo = "clone_repo" ActionKindDBUpsertRepo = "db_upsert_repo" ActionKindDBDeleteRepo = "db_delete_repo" ActionKindTagSet = "tag_set" ActionKindWorkspaceWrite = "workspace_write" )
ActionKind enum — the closed set of typed reversible actions. Every gitmap mutating command must decompose into a sequence of these.
const ( ErrActionUnknownKind = "transaction action #%d: unknown kind %q" ErrActionSeqGap = "transaction action: seq gap detected for txn #%d (expected %d, got %d)" ErrActionInsert = "transaction action insert: %w" ErrActionList = "transaction action list: %w" ErrActionMarkReverted = "transaction action mark reverted: %w" ErrActionPayloadDecode = "transaction action #%d: payload decode failed: %w" ErrActionLiveConflict = "transaction action #%d (%s): live state diverged from forward payload" )
Action error messages — typed for errors.Is dispatch by callers.
const ( CmdInteractive = "interactive" CmdInteractiveAlias = "i" )
gitmap:cmd top-level TUI command.
const ( FlagRefresh = "refresh" FlagDescRefresh = "Dashboard auto-refresh interval in seconds" )
TUI flag constants.
const ( HelpInteractive = " interactive (i) Launch interactive TUI with repo browser and batch actions" HelpInteractiveFlags = "Interactive Flags:" HelpRefresh = " --refresh <seconds> Dashboard auto-refresh interval (default: config or 30s)" )
TUI help text.
const ( TUIViewBrowser = "Repos" TUIViewActions = "Actions" TUIViewGroups = "Groups" TUIViewDashboard = "Status" TUIViewReleases = "Releases" TUIViewTempReleases = "Temp" TUIViewZipGroups = "Zip Groups" TUIViewAliases = "Aliases" TUIViewLogs = "Logs" )
TUI view labels.
const ( TUITitle = "gitmap interactive" TUISearchPrompt = "Search: " TUINoRepos = "No repositories found. Run 'gitmap scan' first." TUINoGroups = "No groups found. Press 'c' to create one." TUINoSelection = "No repos selected. Use Space to select." TUIConfirmDelete = "Delete group '%s'? (y/n)" TUIGroupCreated = "Group '%s' created" TUIGroupDeleted = "Group '%s' deleted" TUIActionPull = "Pulling %d repo(s)..." TUIActionExec = "Executing across %d repo(s)..." TUIActionStatus = "Checking status of %d repo(s)..." TUIActionComplete = "Action complete: %d success, %d failed" TUIRefreshing = "Refreshing..." TUIQuitHint = "q/esc: quit" TUITabHint = "tab: switch view" TUISelectHint = "space: select enter: detail /: search" TUIBatchHint = "p: pull x: exec s: status g: add to group" TUIGroupHint = "c: create d: delete enter: show members" TUIDashHint = "r: refresh" TUIZGHint = "enter: show items r: refresh c: create d: delete" TUIAliasHint = "r: refresh c: set alias d: remove" )
TUI status messages.
const ( TUIZGEmpty = "No zip groups defined. Use 'gitmap z create <name>' to create one." TUIZGRefreshed = "Zip groups refreshed." TUIZGCreateHint = "Use CLI: gitmap z create <name>" )
TUI zip group messages.
const ( TUIAliasEmpty = "No aliases defined. Use 'gitmap alias set <alias> <slug>' to create one." TUIAliasRefreshed = "Aliases refreshed." TUIAliasCreateHint = "Use CLI: gitmap alias set <alias> <slug>" TUIAliasDeleteHint = "Remove alias '%s'? Use CLI: gitmap alias remove %s" )
TUI alias messages.
const ( TUIColSlug = "Slug" TUIColBranch = "Branch" TUIColPath = "Path" TUIColType = "Type" TUIColStatus = "Status" TUIColAhead = "Ahead" TUIColBehind = "Behind" TUIColStash = "Stash" TUIColGroup = "Group" TUIColMembers = "Members" TUIColVersion = "Version" TUIColTag = "Tag" TUIColDraft = "Draft" TUIColLatest = "Latest" TUIColSource = "Source" TUIColDate = "Date" TUIColCommand = "Command" TUIColAlias = "Alias" TUIColArgs = "Args" TUIColDuration = "Duration" TUIColExit = "Exit" )
TUI column headers.
const ( TUILogEmpty = "No command history found. Run some gitmap commands first." TUILogHint = "enter: detail r: refresh /: filter" TUILogFilterActive = " Filter: %s (%d matches)" TUILogNoMatch = " No logs match the current filter." )
TUI log messages.
const ( TUIRelEmpty = "No releases found. Use 'gitmap release' to create one." TUIRelHint = "enter: detail r: refresh n: new release" )
TUI release messages.
const ( TUITREmpty = "No temp-release branches found. Use 'gitmap tr <count> <pattern>' to create." TUITRHint = "enter: detail g: group by prefix r: refresh" TUIColTRBranch = "Branch" TUIColTRPrefix = "Prefix" TUIColTRSeq = "Seq" TUIColTRCommit = "Commit" )
TUI temp-release messages.
const ( TUIRelTriggerTitle = " New Release" TUIRelTriggerCmd = "gitmap release %s" TUIRelTriggerBumpCmd = "gitmap release %s" TUIRelTriggerVerPrompt = " Version: " TUIRelTriggerTypeHint = " enter: confirm esc: back" TUIRelTriggerReady = " Release Command" TUIRelTriggerRunHint = " Run this command in your terminal. esc: back" )
TUI release trigger messages.
const ( ErrTUINoTerminal = "interactive mode requires a terminal — use standard commands instead" ErrTUIDBOpen = "failed to open database for interactive mode: %v" )
TUI errors.
const ( UpdateCopyFmtExe = "gitmap-update-%d.exe" UpdateCopyFmtUnix = "gitmap-update-%d" UpdateCopyGlob = "gitmap-update-*" UpdateScriptGlob = "gitmap-update-*.ps1" )
Update handoff file patterns.
const ( ReportErrorsJSON = "json" EnvReportErrorsFormat = "GITMAP_REPORT_ERRORS" EnvReportErrorsFile = "GITMAP_REPORT_ERRORS_FILE" EnvUpdateCleanupDelayMS = "GITMAP_UPDATE_CLEANUP_DELAY_MS" UpdateHandoffLogNameFmt = "gitmap-update-handoff-%s.log" ReportErrorsFilePrefix = "gitmap-update-report-" ReportErrorsFileSuffix = ".jsonl" )
Report-errors values and env-var bridge to run.ps1 / run.sh.
const ( MsgReportErrorsEnabled = " → Error report (json): %s\n" MsgReportErrorsSummary = " → Wrote %d non-fatal failure entr%s to %s\n" WarnReportErrorsCreate = " ⚠ Could not create report-errors file at %s: %v\n" ErrReportErrorsValue = " ✗ Unsupported --report-errors value: %q (supported: json)\n" )
Report-errors UI messages.
const ( EnvDebugRepoDetect = "GITMAP_DEBUG_REPO_DETECT" MsgDebugRepoDetectOn = " → Repo-detect debug enabled (will print marker checks)\n" )
Debug-repo-detect bridge.
const ( UpdaterBin = "gitmap-updater" MsgUpdaterFallback = " → No source repo found. Delegating to %s...\n\n" UpdateCleanupSourceConfig = "config" UpdateCleanupSourceSibling = "sibling" UpdateCleanupSourcePath = "PATH" UpdateCleanupSourceUnknown = "unknown" )
Updater fallback.
const ( MsgUpdateActive = " → Active: %s\n → Handoff: %s\n" MsgUpdateCleanStart = "\n Cleaning up update artifacts..." MsgUpdateCleanBinary = " → Cleanup binary: %s\n" MsgUpdateCleanDelay = " → Waiting %dms for deploy handles to settle...\n" MsgUpdateCleanDone = " ✓ Removed %d file(s)\n\n" MsgUpdateCleanNone = " ✓ Nothing to clean up" MsgUpdateTempRemoved = " → Removed temp copy: %s\n" MsgUpdateOldRemoved = " → Removed backup: %s\n" MsgUpdatePhase3Handoff = "\n → Handing off cleanup to deployed binary: %s update-cleanup\n" MsgUpdatePhase3Resolve = " → Cleanup target resolved via: %s\n" MsgUpdatePhase3Target = " → Cleanup target path: %s\n" MsgUpdatePhase3Started = " → Cleanup process started (pid=%d)\n" MsgUpdatePhase3LogFile = " → Handoff log file: %s\n" UpdateRunnerLogStart = "update-runner starting, repo=%s" UpdateScriptLogExec = "executing update script: %s" UpdateScriptLogExit = "update script exited: err=%v" UpdatePhase3LogResolve = "update-cleanup target resolved via %s: %s" UpdatePhase3LogStarted = "update-cleanup started pid=%d target=%s" UpdatePhase3LogStartFail = "update-cleanup launch failed target=%s err=%v" UpdatePhase3LogTargetMissing = "update-cleanup handoff skipped: deployed target could not be resolved" UpdatePhase3LogInline = "update-cleanup running inline from deployed binary: %s" UpdateCleanupLogStart = "update-cleanup starting: self=%s" UpdateCleanupLogDone = "update-cleanup finished: removed=%d" UpdateCleanupLogDelayInvalid = "update-cleanup ignored invalid delay value: %q" )
Update UI messages.
const ( MsgDebugWinHeader = "\n[debug-windows] ===== update-cleanup handoff diagnostics =====\n" MsgDebugWinPhase = "[debug-windows] phase : %s\n" MsgDebugWinGOOS = "[debug-windows] GOOS : %s\n" MsgDebugWinSelf = "[debug-windows] self executable : %s\n" MsgDebugWinPID = "[debug-windows] self pid : %d\n" MsgDebugWinPPID = "[debug-windows] parent pid : %d\n" MsgDebugWinLogFile = "[debug-windows] handoff log file : %s\n" MsgDebugWinSource = "[debug-windows] resolution source: %s\n" MsgDebugWinTarget = "[debug-windows] resolved target : %s\n" MsgDebugWinTargetExists = "[debug-windows] target exists : %t\n" MsgDebugWinChildArgv = "[debug-windows] child argv : %v\n" MsgDebugWinChildEnv = "[debug-windows] %-16s : %s\n" MsgDebugWinChildPID = "[debug-windows] spawned child pid: %d\n" MsgDebugWinNote = "[debug-windows] %s\n" // Command-line rendering: exact invocation that Phase 3 will run, // formatted so the user can copy-paste it into a shell to reproduce. MsgDebugWinCmdLine = "[debug-windows] spawn command : %s\n" MsgDebugWinCmdNote = "" /* 137-byte string literal not displayed */ // Cleanup plan: the actual filesystem operations the deployed binary // will perform, enumerated BEFORE any deletion happens. MsgDebugWinCleanHdr = "[debug-windows] ----- planned cleanup operations -----\n" MsgDebugWinCleanGlob = "[debug-windows] glob : %s\n" MsgDebugWinCleanMatch = "[debug-windows] → os.Remove : %s\n" MsgDebugWinCleanEmpty = "[debug-windows] (no matches)\n" MsgDebugWinCleanSwap = "[debug-windows] → os.RemoveAll : %s\n" MsgDebugWinCleanShim = "[debug-windows] drive-root shim : %s (%s)\n" MsgDebugWinCleanShimSkip = "skipped" MsgDebugWinCleanShimDel = "will os.Remove" // JSON sink — appended NDJSON events alongside the console dump. MsgDebugWinJSONFile = "[debug-windows] json sink file : %s\n" MsgDebugWinJSONOpenFail = "[debug-windows] json sink open failed: %s (%v)\n" )
--debug-windows dump messages. All routed via fmt.Fprintf(os.Stderr, ...) so the dump survives even when stdout is being captured by a parent process. The dump is intentionally verbose and prefixed with `[debug-windows]` so it's grep-friendly in CI logs and bug reports.
const ( ErrUpdateExecFind = "Error finding executable: %v\n" ErrUpdateCopyFail = "Error creating update copy: %v\n" ErrUpdateNoRunSH = " ✗ run.sh not found at %s — cannot update on this platform without it.\n" ErrUpdateCleanupExecPath = "Error: could not resolve executable path at active-binary: %v (operation: resolve executable, reason: os.Executable failed)\n" ErrUpdateCleanupConfigRead = "Error: could not read cleanup config at %s: %v (operation: read config, reason: cleanup path resolution unavailable)\n" ErrUpdateCleanupGlob = "Error: could not enumerate cleanup matches at %s: %v (operation: glob, reason: invalid cleanup pattern)\n" ErrUpdateCleanupRemove = "Error: could not remove cleanup artifact at %s: %v (operation: remove, reason: file may be locked or missing)\n" ErrUpdateCleanDelayInvalid = "" /* 127-byte string literal not displayed */ ErrUpdatePhase3TargetMissing = "" /* 144-byte string literal not displayed */ ErrUpdatePhase3Handoff = "" /* 145-byte string literal not displayed */ )
Update error messages.
const ( MsgUpdatePathMissing = "\n ⚠ The saved source repository path no longer exists on disk.\n" MsgUpdatePathPrompt = " Enter the new path to the gitmap source repo: " ErrUpdatePathInvalid = " ✗ Directory not found at %s (operation: resolve, reason: file does not exist)\n" )
Update path resolution messages.
const ( SourceRepoCloneURL = "https://github.com/alimtvnetwork/gitmap-v16.git" MsgUpdateCloning = "\n ■ Path does not exist. Cloning gitmap source into %s...\n" MsgUpdateCloneOK = " ✓ Cloned successfully.\n" ErrUpdateCloneFailed = " ✗ Clone failed: %v\n" )
Clone-on-missing-path constants.
const ( UpdatePSHeader = `` /* 1146-byte string literal not displayed */ // UpdatePSDeployDetect format args (in order): // %[1]s — repo path (e.g. C:\dev\gitmap-v16) // %[2]s — gitmap subdir (sourceRepoSubdir from manifest) // %[3]s — app subdir (appSubdir from manifest, e.g. gitmap-cli) // %[4]s — binary name (gitmap.exe) // %[5]s — known-subdir array (PowerShell @("a","b") literal of app + legacy) UpdatePSDeployDetect = `` /* 1046-byte string literal not displayed */ UpdatePSVersionBefore = `` /* 278-byte string literal not displayed */ UpdatePSRunUpdate = `` /* 198-byte string literal not displayed */ UpdatePSSync = `` /* 3694-byte string literal not displayed */ UpdatePSVersionAfter = `` /* 773-byte string literal not displayed */ UpdatePSVerify = `` /* 2542-byte string literal not displayed */ UpdatePSPostActions = `` /* 1138-byte string literal not displayed */ )
Update PowerShell script template sections.
const ( RevertPSHeader = `# gitmap revert script (auto-generated) Set-Location "%s" ` RevertPSBuild = `` /* 191-byte string literal not displayed */ RevertPSPostActions = `` /* 675-byte string literal not displayed */ )
Revert PowerShell script template sections.
const ( ErrSetSourceRepoNoPath = " ✗ set-source-repo requires a path argument\n" ErrSetSourceRepoInvalid = " ✗ Invalid source repo path: %s\n" MsgSetSourceRepoDone = " ✓ Source repo path saved: %s\n" )
Set-source-repo messages.
const ( PSBin = "powershell" PSExecPolicy = "-ExecutionPolicy" PSBypass = "Bypass" PSNoProfile = "-NoProfile" PSNoLogo = "-NoLogo" PSFile = "-File" PSNonInteractive = "-NonInteractive" PSCommand = "-Command" )
PowerShell execution arguments.
const ( CmdHasChange = "has-change" CmdHasChangeAlias = "hc" )
gitmap:cmd top-level New CLI commands.
const ( FlagHCMode = "mode" FlagHCAll = "all" FlagHCFetch = "fetch" FlagDescHCMode = "Dimension to check: dirty (default), ahead, or behind" FlagDescHCAll = "Print all three dimensions as structured output" FlagDescHCFetch = "Run 'git fetch' before checking ahead/behind (default true)" )
has-change flag names + descriptions.
const ( HCModeDirty = "dirty" HCModeAhead = "ahead" HCModeBehind = "behind" HCTrue = "true" HCFalse = "false" )
has-change mode values + literals.
const ( MsgHCAllFmt = "dirty=%s ahead=%s behind=%s\n" MsgHCAllNoUpstream = "dirty=%s ahead=n/a behind=n/a (no upstream)\n" ErrHCUsage = "Usage: gitmap has-change <repo> [--mode dirty|ahead|behind] [--all]" ErrHCBadMode = " ✗ Unknown mode %q. Use one of: dirty, ahead, behind.\n" WarnHCFetchFailed = " ⚠ git fetch failed in %s: %v (ahead/behind may be stale)\n" )
has-change messages + errors.
const ( MsgRRStartingFmt = " → Releasing %s at %s (version %s)...\n" MsgRRFetchingFmt = " 📡 Fetching remote refs in %s...\n" MsgRRRebasingFmt = " 🔁 Pull --rebase in %s...\n" MsgRRReturnedFmt = " ↩ Returned to %s\n" ErrRRFetchFailedFmt = " ✗ git fetch failed in %s: %v" ErrRRRebaseFailedFmt = " ✗ git pull --rebase failed in %s: %v\n Resolve the conflict, then re-run the release." )
Cross-dir release (`r <repo> <ver>`) messages + errors.
const ( MsgCNXStartingFmt = " → clone-next for %s at %s (version %s)...\n" MsgCNXReturnedFmt = " ↩ Returned to %s\n" )
Cross-dir clone-next (`cn <repo> <ver>`) messages.
const ( // CloneNextDefaultVersionArg is what the single-positional folder // form defaults to when the user omits a version. v++ is the // established muscle-memory shortcut for "next sibling version". CloneNextDefaultVersionArg = "v++" // ErrCNFolderNotFound fires when a path-shaped token (slash, ~, // or otherwise hint-bearing) does not resolve to an existing // directory. Includes the original token (not the resolved abs) // so the user sees what they typed verbatim. ErrCNFolderNotFound = " ✗ cn: folder not found or not a directory: %s\n" // ErrCNAmbiguousBothVersions fires when both positional args // match the version pattern (e.g. `cn v++ v15`). The user almost // certainly meant one of them as a folder; refuse instead of // silently picking one. ErrCNAmbiguousBothVersions = " ✗ cn: ambiguous arguments — both look like version strings (use 'cn vN' for in-place, 'cn vN <folder>' for cross-dir)" // ErrCNAmbiguousBothFolders fires when neither positional arg // matches the version pattern AND the second isn't folder-shaped. // Most often a typo where the version was misspelled. ErrCNAmbiguousBothFolders = " ✗ cn: ambiguous arguments — neither looks like a version (use vN, v+N, or v++)" )
Folder-arg clone-next (`cn vX <folder>` and `cn <folder>`) — v3.117.0. See spec/01-app/111-cn-folder-arg.md for the full classification table.
const ( MsgInjectStart = "→ injecting %s (%s)\n" MsgInjectDone = "✓ injected %s\n" MsgInjectNoRemote = " ↳ no remote origin configured for %s — skipping database upsert\n" MsgInjectDBOK = " ↳ database: upserted %s (%s)\n" ErrInjectResolve = " ✗ inject: %v\n" WarnInjectDBOpen = " ⚠ inject: could not open database: %v\n" WarnInjectDBUpsert = " ⚠ inject: could not save repo to database: %v\n" )
gitmap inject (alias: inj) — v3.119.0. Registers an existing folder with GitHub Desktop + VS Code, and (when a remote origin exists) upserts into the SQLite database. See gitmap/cmd/inject.go and gitmap/helptext/inject.md.
const ( MsgSSHExistsOnDisk = "\n ℹ SSH key already exists on disk: %s\n Reusing existing key (no regeneration needed).\n\n" MsgSSHForceHint = "\n 💡 Pass --force to back up and regenerate this key.\n" MsgSSHBackedUp = " 💾 Backed up existing key: %s.bak.<timestamp>\n" ErrSSHBackup = " ✗ Could not back up existing SSH key: %v\n" )
SSH existing-key-on-disk fix messages.
const ( SQLAddCurrentVersionTag = "ALTER TABLE Repo ADD COLUMN CurrentVersionTag TEXT DEFAULT ''" SQLAddCurrentVersionNum = "ALTER TABLE Repo ADD COLUMN CurrentVersionNum INTEGER DEFAULT 0" )
SQL: add version columns to Repo (v15 table name).
const ( SQLInsertVersionHistory = `` /* 144-byte string literal not displayed */ SQLSelectVersionHistory = `` /* 190-byte string literal not displayed */ SQLUpdateRepoVersion = `UPDATE Repo SET CurrentVersionTag = ?, CurrentVersionNum = ?, UpdatedAt = CURRENT_TIMESTAMP WHERE RepoId = ?` SQLSelectRepoIDByPath = "SELECT RepoId FROM Repo WHERE AbsolutePath = ?" SQLDropRepoVersionHistory = "DROP TABLE IF EXISTS RepoVersionHistory" )
SQL: version history operations (v15: RepoVersionHistoryId PK).
const ( MsgFlattenRemoving = "Removing existing %s for fresh clone...\n" MsgFlattenCloning = "Cloning %s into %s (flattened)...\n" MsgFlattenDone = "✓ Cloned %s into %s\n" MsgFlattenVersionDB = "✓ Recorded version transition v%d -> v%d\n" )
Flatten messages.
const ( CmdVersionHistory = "version-history" CmdVersionHistoryAlias = "vh" )
gitmap:cmd top-level Version history CLI commands.
const ( MsgVersionHistoryEmpty = "No version history found for this repo.\n" MsgVersionHistoryHeader = "Version history for %s:\n\n" MsgVersionHistoryColumns = "FROM TO FOLDER TIMESTAMP" MsgVersionHistoryRowFmt = "%-11s %-11s %-25s %s\n" MsgVersionHistoryCount = "\n%d transition(s) recorded.\n" )
Version history terminal output.
const ( ErrVersionHistoryCwd = "Error: cannot determine current directory: %v\n" ErrVersionHistoryDB = "Error: failed to query version history: %v\n" )
Version history error messages.
const ( VisibilityPublic = "public" VisibilityPrivate = "private" VisShortPub = "pub" VisShortPri = "pri" )
Visibility target tokens — what the provider CLI expects, what the user can type for the (optional) explicit-target form, and what we store/print internally.
const ( FlagVisYes = "yes" FlagVisYesAlt = "y" FlagVisDryRun = "dry-run" FlagVisVerbose = "verbose" FlagDescVisYes = "Skip the private→public confirmation prompt (no-op for public→private)." FlagDescVisDryRun = "Print the provider CLI command that would run; do not invoke it." FlagDescVisVerbose = "Echo every shell command to stderr before running it." )
Visibility flags. --yes skips the private→public confirmation; --dry-run prints what would change without invoking the provider CLI; --verbose echoes each shell command before running it.
const ( ProviderGitHub = "github" ProviderGitLab = "gitlab" HostGitHub = "github.com" HostGitLab = "gitlab.com" CLIGitHub = "gh" CLIGitLab = "glab" )
Provider tokens — match what we detect from the origin URL host.
const ( HelpMakePublic = " make-public Make current repo public on GitHub/GitLab (gh/glab required)" HelpMakePrivate = " make-private Make current repo private on GitHub/GitLab (gh/glab required)" )
Visibility help-line entries surfaced by `gitmap help` (Utilities).
const ( MsgVisAlreadyFmt = "visibility: already %s on %s\n" MsgVisChangedFmt = "visibility: %s → %s on %s (%s)\n" MsgVisDryRunFmt = "[dry-run] visibility: %s → %s on %s (%s)\n" MsgVisConfirmFmt = "Make %s PUBLIC on %s? Type 'yes' to confirm: " MsgVisVerboseExec = "+ %s %s\n" MsgVisVerifyOK = " ✓ verified: visibility is now %s\n" )
Visibility user-facing messages.
const ( ErrVisNotInRepo = "visibility: not a git repository\n" ErrVisNoOrigin = "visibility: no `origin` remote configured\n" ErrVisBadProviderFmt = "visibility: unsupported host in %q (only github.com / gitlab.com are supported)\n" ErrVisBadSlugFmt = "visibility: cannot parse owner/repo from %q\n" ErrVisCLIMissingFmt = "visibility: %q not found on PATH (install: https://cli.github.com or https://gitlab.com/gitlab-org/cli)\n" ErrVisReadCurrentFmt = "visibility: cannot read current visibility (auth via `%s auth login`?): %v\n" ErrVisConfirmRequired = "visibility: confirmation required (re-run with --yes for non-interactive use)\n" ErrVisApplyFailedFmt = "visibility: apply failed: %v\n%s" ErrVisVerifyFailedFmt = "visibility: verification failed — current is %q, expected %q\n" )
Visibility error messages.
const ( ExitVisOK = 0 ExitVisNotARepo = 2 ExitVisNoOrigin = 3 ExitVisBadProvider = 4 ExitVisAuthFailed = 5 ExitVisBadFlag = 6 ExitVisConfirmReq = 7 ExitVisVerifyFailed = 8 )
Visibility exit codes (mirrored from visibility-change.ps1 so wrappers and CI can branch on the same numbers).
const ( VSCodeExeBin = "Code.exe" VSCodeFlagUserDataDir = "--user-data-dir" VSCodeUserDataDirName = "gitmap-vscode-user-data" VSCodeEnvLocalAppData = "LOCALAPPDATA" VSCodeEnvProgramFiles = "ProgramFiles" VSCodeEnvProgramFilesX86 = "ProgramFiles(x86)" VSCodeProgramsDirName = "Programs" VSCodeInstallDirName = "Microsoft VS Code" )
VS Code executable discovery and isolation constants.
const ( VSCodeUserDataRootDirName = "Code" VSCodeUserDataMacRel = "Library/Application Support/Code" VSCodeUserDataLinuxFallback = ".config/Code" VSCodeEnvAppData = "APPDATA" VSCodeEnvUserProfile = "USERPROFILE" VSCodeEnvHome = "HOME" VSCodeEnvXDGConfigHome = "XDG_CONFIG_HOME" VSCodeUserProfileAppDataRel = "AppData/Roaming/Code" )
User-data root segments per OS.
const ( VSCodePMUserDir = "User" VSCodePMGlobalStorageDir = "globalStorage" VSCodePMExtensionDir = "alefragnani.project-manager" VSCodePMProjectsFile = "projects.json" VSCodePMProjectsTempSuffix = ".tmp" VSCodePMJSONIndent = "\t" )
Relative tail under the user-data root (constant across all OSes).
const ( VSCodePMDefaultEnabled = true VSCodePMDefaultProfile = "" )
Default field values gitmap writes when inserting a NEW projects.json entry. Existing entries' values are preserved across re-syncs.
const ( FlagNoVSCodeSync = "no-vscode-sync" FlagDescNoVSCodeSync = "skip syncing scanned repos into VS Code Project Manager projects.json" )
CLI flag for opting out of the automatic sync during scan.
const ( FlagVSCodeSyncDisabled = "vscode-sync-disabled" FlagDescVSCodeSyncDisabled = "" /* 126-byte string literal not displayed */ EnvVSCodeSyncDisabled = "GITMAP_VSCODE_SYNC_DISABLED" EnvVSCodeSyncDisabledOn = "1" MsgVSCodePMSyncDisabled = " • VS Code Project Manager sync disabled (--vscode-sync-disabled / GITMAP_VSCODE_SYNC_DISABLED=1)\n" )
Global kill switch for the VS Code Project Manager sync. When the flag is passed at any position on the gitmap command line, OR when the env var is set to "1", every clone/scan/reclone helper that would otherwise call vscodepm.Sync short-circuits and prints MsgVSCodePMSyncDisabled instead. This is the "fully disable" lever for users who never want gitmap to touch projects.json — distinct from the per-command `--no-vscode-sync` opt-out.
const ( EnvDebugPaths = "GITMAP_DEBUG_PATHS" EnvDebugPathsOn = "1" MsgDebugPathsTrace = "[debug-paths] in=%q clean=%q resolved=%q\n" )
Debug-paths process-wide switch. The CLI flag (FlagDebugPaths in constants_cli.go) sets this env var to "1" for the current process so every code path that calls canonicalizePMPath — across every clone variant — emits the same trace line without N flag-plumbing edits. Reading from an env var (instead of a struct field) keeps the helper signature stable and lets future callers opt in by setting the env var directly in CI.
const ( ErrVSCodePMUserDataNotFound = "vscode: user data directory not found at %q (is VS Code installed?)\n" ErrVSCodePMExtDirMissing = "" /* 133-byte string literal not displayed */ ErrVSCodePMReadFailed = "vscode: failed to read %s: %v\n" ErrVSCodePMParseFailed = "vscode: %s is not valid JSON: %v (left untouched)\n" ErrVSCodePMWriteTempFailed = "vscode: failed to write temp %s: %v\n" ErrVSCodePMRenameFailed = "vscode: failed to commit %s: %v\n" ErrVSCodePMNoUserDataEnv = "vscode: cannot determine user-data directory (no APPDATA / USERPROFILE / HOME env)\n" )
Error messages (Code Red zero-swallow policy).
const ( MsgVSCodePMSectionHeader = " → VS Code Project Manager: %s\n" MsgVSCodePMSyncSummary = " ✓ projects.json synced: %d added, %d updated, %d unchanged (%d total)\n" MsgVSCodePMSyncSkipped = " • VS Code Project Manager sync skipped (--no-vscode-sync)\n" MsgVSCodePMRenamed = " ✓ projects.json: renamed %q -> %q\n" MsgVSCodePMRenameNoMatch = " • projects.json: no entry matched %q (skipped rename)\n" // Diagnostic messages used by `gitmap vscode-pm-path` (v3.41.0+). MsgVSCodePMPathRootMissing = "vscode: user-data directory not found (is VS Code installed? checked APPDATA / HOME / XDG_CONFIG_HOME)" MsgVSCodePMPathExtMissing = "" /* 143-byte string literal not displayed */ )
User-facing messages.
const ( AutoTagGit = "git" AutoTagNode = "node" AutoTagGo = "go" AutoTagPython = "python" AutoTagRust = "rust" AutoTagDocker = "docker" )
Canonical tag identifiers — keep in sync with AutoTagMarkers / AutoTagOrder.
const ( FlagNoAutoTags = "no-auto-tags" FlagDescNoAutoTags = "skip auto-derived tags (git/node/go/...) when syncing VS Code Project Manager projects.json" )
CLI flag for opting out of auto-tag detection during sync.
const ( FlagVSCodeTag = "vscode-tag" FlagDescVSCodeTag = "always add this tag to every VS Code Project Manager entry (repeatable; accepts comma-list)" FlagVSCodeTagSkip = "vscode-tag-skip" FlagDescVSCodeTagSkip = "drop this auto-detected tag from every VS Code Project Manager entry (repeatable; accepts comma-list)" FlagVSCodeTagMarker = "vscode-tag-marker" FlagDescVSCodeTagMarker = "register a marker→tag rule, e.g. Gemfile=ruby (repeatable; accepts comma-list)" EnvVSCodeTagAdd = "GITMAP_VSCODE_TAG_ADD" EnvVSCodeTagSkip = "GITMAP_VSCODE_TAG_SKIP" EnvVSCodeTagMarker = "GITMAP_VSCODE_TAG_MARKER" EnvVSCodeTagSeparator = "\x1f" TagMarkerKVSeparator = "=" )
Global tag-customization flags (v4.18.0+). Like `--vscode-sync-disabled`, these are stripped from argv at Run() and persisted into env vars so every code path that ultimately calls vscodepm.DetectTagsCustom inherits the rules without per-flagset plumbing. All three are repeatable AND accept comma-separated values, e.g. `--vscode-tag work --vscode-tag urgent` is equivalent to `--vscode-tag work,urgent`.
--vscode-tag <name> always add <name> to every entry --vscode-tag-skip <name> never emit auto-detected <name> --vscode-tag-marker <file>=<tag> register marker→tag rule
Env vars use ASCII unit separator (\x1f) between values so commas inside individual tokens stay intact.
const ( SQLUpsertVSCodeProject = `` /* 282-byte string literal not displayed */ SQLSelectAllVSCodeProjects = `` /* 156-byte string literal not displayed */ SQLSelectVSCodeProjectByPath = `` /* 152-byte string literal not displayed */ SQLSelectVSCodeProjectByName = `` /* 156-byte string literal not displayed */ SQLRenameVSCodeProject = `UPDATE VSCodeProject SET Name = ?, UpdatedAt = CURRENT_TIMESTAMP WHERE RootPath = ? COLLATE NOCASE` SQLUpdateVSCodeProjectPaths = `UPDATE VSCodeProject SET Paths = ?, UpdatedAt = CURRENT_TIMESTAMP WHERE RootPath = ? COLLATE NOCASE` SQLDeleteVSCodeProjectByPath = `DELETE FROM VSCodeProject WHERE RootPath = ? COLLATE NOCASE` )
const ( ErrVSCodePMUpsert = "failed to upsert VSCodeProject %q: %v" ErrVSCodePMList = "failed to list VSCodeProject rows: %v" ErrVSCodePMRename = "failed to rename VSCodeProject %q: %v" ErrVSCodePMDelete = "failed to delete VSCodeProject %q: %v" ErrVSCodePMUpdatePaths = "failed to update Paths for VSCodeProject %q: %v" ErrVSCodePMPathsEncode = "failed to encode Paths for VSCodeProject %q: %v" ErrVSCodePMPathsDecode = "failed to decode Paths for VSCodeProject %q: %v" ErrVSCodePMAliasNotFound = "no VS Code project registered with alias %q (register one first via `gitmap code %s`)" )
Error messages.
const ( MsgVSCodePMPathsAdded = " ✓ added extra path to %q: %s\n" MsgVSCodePMPathsRemoved = " ✓ removed extra path from %q: %s\n" MsgVSCodePMPathsExists = " • path already attached to %q: %s\n" MsgVSCodePMPathsMissing = " • path not attached to %q: %s\n" MsgVSCodePMPathsList = "%s (%s)\n rootPath: %s\n paths : %s\n" MsgVSCodePMPathsNone = " (no extra paths)\n" )
User-facing messages for the `code paths` subcommand.
const ( VSCodeWorkspaceDefaultFilename = "gitmap.code-workspace" VSCodeWorkspaceJSONIndent = "\t" VSCodeWorkspaceTempSuffix = ".tmp" )
VS Code multi-root workspace (`*.code-workspace`) constants.
A `.code-workspace` file is a small JSON document VS Code opens via File → Open Workspace from File…. Schema (only the parts gitmap emits — extensions/settings are kept as `{}` to match a fresh VS Code "Save Workspace As…" file byte-for-byte where possible):
{
"folders": [ { "name": "<repo>", "path": "<abs-or-rel-path>" } ],
"settings": {}
}
Source-of-truth is the same Repo table that drives the Project Manager sync, so the workspace file always mirrors the latest `gitmap scan` output without a separate plumbing path.
const ( FlagVSCodeWorkspaceOut = "out" FlagDescVSCodeWorkspaceOut = "output `.code-workspace` file path (default: ./" + VSCodeWorkspaceDefaultFilename + ")" FlagVSCodeWorkspaceRelative = "relative" FlagDescVSCodeWorkspaceRelative = "emit folder paths relative to the workspace file's directory" FlagVSCodeWorkspaceTag = "tag" FlagDescVSCodeWorkspaceTag = "include only repos whose auto-detected tag set contains the given tag (e.g. go, node, git)" FlagVSCodeWorkspaceRootSubdir = "root-subdir" FlagDescVSCodeWorkspaceRootSubdir = "add `<repo>/<subdir>` as the workspace folder instead of the repo root; repos without that subdir are skipped" )
CLI flag IDs for `gitmap vscode-workspace`.
const ( MsgVSCodeWorkspaceWritten = " ✓ wrote %s with %d folder(s)\n" MsgVSCodeWorkspaceEmpty = " • no tracked repos — workspace not written (run `gitmap scan` first)\n" MsgVSCodeWorkspaceSubdirSkip = " • skipped %s: subdir %q not found\n" )
User-facing messages.
const ( ErrVSCodeWorkspaceDBOpen = "vscode-workspace: failed to open repo database: %v\n" ErrVSCodeWorkspaceDBList = "vscode-workspace: failed to list repos: %v\n" ErrVSCodeWorkspaceWriteTemp = "vscode-workspace: failed to write temp file %q: %v\n" ErrVSCodeWorkspaceRename = "vscode-workspace: failed to commit %q: %v\n" ErrVSCodeWorkspaceRelativize = "vscode-workspace: failed to relativize %q against %q: %v\n" )
Error templates (Code Red zero-swallow policy).
const ( CmdWatch = "watch" CmdWatchAlias = "w" )
gitmap:cmd top-level Watch CLI commands.
const ( WatchDefaultInterval = 30 WatchMinInterval = 5 )
Watch defaults.
const ( WatchBannerTop = "╔══════════════════════════════════════╗" WatchBannerTitle = "║ gitmap watch ║" WatchBannerBottom = "╚══════════════════════════════════════╝" WatchRefreshFmt = "gitmap watch — refreshing every %ds (Ctrl+C to stop)" WatchLastUpdFmt = "Last updated: %s" WatchHeaderFmt = " %s%-22s %-10s %-16s %-6s %-8s %-6s%s\n" WatchRowFmt = " %-22s %s %-16s %-6s %-8s %s\n" WatchErrorRowFmt = " %s%-22s %serror%s\n" WatchSummaryFmt = "Repos: %d | Dirty: %d | Behind: %d | Stash: %d" WatchStoppedMsg = "\ngitmap watch stopped." )
Watch display messages.
const ( FlagDescWatchInterval = "Refresh interval in seconds (minimum 5)" FlagDescWatchNoFetch = "Skip git fetch; use local refs only" FlagDescWatchJSON = "Output single snapshot as JSON and exit" )
Watch flag descriptions.
const ( CmdZipGroup = "zip-group" CmdZipGroupShort = "z" SubCmdZGCreate = "create" SubCmdZGAdd = "add" SubCmdZGRemove = "remove" SubCmdZGList = "list" SubCmdZGShow = "show" SubCmdZGDelete = "delete" SubCmdZGRename = "rename" )
gitmap:cmd top-level Zip group command names.
const ( TableZipGroup = "ZipGroup" TableZipGroupItem = "ZipGroupItem" )
Zip group table names (v15: PascalCase singular + {Table}Id PK).
const ( LegacyTableZipGroups = "ZipGroups" LegacyTableZipGroupItems = "ZipGroupItems" )
Legacy plural names retained for migration detection.
const ( SQLMigrateZGIRepoPath = `ALTER TABLE ZipGroupItems ADD COLUMN RepoPath TEXT NOT NULL DEFAULT ''` SQLMigrateZGIRelativePath = `ALTER TABLE ZipGroupItems ADD COLUMN RelativePath TEXT NOT NULL DEFAULT ''` SQLMigrateZGIFullPath = `ALTER TABLE ZipGroupItems ADD COLUMN FullPath TEXT NOT NULL DEFAULT ''` SQLMigrateZGICopyPath = `UPDATE ZipGroupItems SET FullPath = Path WHERE FullPath = '' AND Path IS NOT NULL AND Path != ''` SQLMigrateZGIDropPath = `ALTER TABLE ZipGroupItems DROP COLUMN Path` )
SQL: legacy ALTERs for pre-v15 ZipGroupItems (still target legacy plural — run BEFORE v15 rebuild copies the table). Idempotent.
const ( SQLInsertZipGroup = `INSERT INTO ZipGroup (Name, ArchiveName) VALUES (?, ?)` SQLSelectAllZipGroups = `SELECT ZipGroupId, Name, ArchiveName, CreatedAt FROM ZipGroup ORDER BY Name` SQLSelectZipGroupByName = `SELECT ZipGroupId, Name, ArchiveName, CreatedAt FROM ZipGroup WHERE Name = ?` SQLDeleteZipGroup = `DELETE FROM ZipGroup WHERE Name = ?` SQLUpdateZipGroupArchive = `UPDATE ZipGroup SET ArchiveName = ? WHERE Name = ?` )
SQL: zip group operations (v15 singular tables + ZipGroupId PK).
const ( SQLInsertZipGroupItem = `INSERT OR IGNORE INTO ZipGroupItem (ZipGroupId, RepoPath, RelativePath, FullPath, IsFolder) VALUES (?, ?, ?, ?, ?)` SQLDeleteZipGroupItem = `DELETE FROM ZipGroupItem WHERE ZipGroupId = ? AND FullPath = ?` SQLSelectZipGroupItems = `SELECT ZipGroupId, RepoPath, RelativePath, FullPath, IsFolder FROM ZipGroupItem WHERE ZipGroupId = ? ORDER BY FullPath` SQLCountZipGroupItems = `SELECT COUNT(*) FROM ZipGroupItem WHERE ZipGroupId = ?` SQLSelectAllZipGroupsWithCount = `` /* 177-byte string literal not displayed */ )
SQL: zip group item operations.
const ( SQLDropZipGroup = "DROP TABLE IF EXISTS ZipGroup" SQLDropZipGroups = "DROP TABLE IF EXISTS ZipGroups" // legacy SQLDropZipGroupItem = "DROP TABLE IF EXISTS ZipGroupItem" SQLDropZipGroupItems = "DROP TABLE IF EXISTS ZipGroupItems" // legacy )
SQL: drop zip group tables (v15 + legacy plurals retained for Reset).
const ( FlagDescZGArchive = "Custom output archive filename" FlagDescZGZipGroup = "Include a persistent zip group as a release asset" FlagDescZGZipItem = "Add ad-hoc file or folder to zip as a release asset" FlagDescZGBundle = "Bundle all -Z items into a single named archive" )
Zip group flag descriptions.
const ( ZGJSONDir = ".gitmap" ZGJSONFile = "zip-groups.json" )
Zip group JSON persistence directory/file.
const ( MsgZGCreated = " ✓ Created zip group %q\n" MsgZGCreatedPath = " ✓ Created zip group %q with %s %s\n" MsgZGDeleted = " ✓ Deleted zip group %q\n" MsgZGItemAdded = " ✓ Added %s to %q (%s)\n" MsgZGItemRemoved = " ✓ Removed %s from %q\n" MsgZGArchiveSet = " ✓ Archive name set to %q for group %q\n" MsgZGListHeader = "\n Zip Groups (%d):\n\n" MsgZGListRow = " %-20s %3d item(s) %s\n" MsgZGShowHeader = "\n %s (%d item(s)):\n\n" MsgZGShowFile = " 📄 %s\n" MsgZGShowFolder = " 📁 %s\n" MsgZGShowArchive = " Archive: %s\n" MsgZGShowPaths = " repo: %s\n relative: %s\n full: %s\n" MsgZGCompressed = " ✓ Compressed %s → %s\n" MsgZGDryRunHeader = " [dry-run] Would create %d zip archive(s):\n" MsgZGDryRunEntry = " → %s (%d items: %s)\n" MsgZGSkipEmpty = " ⚠ Skipping empty group %q\n" MsgZGSkipMissing = " ⚠ Skipping missing item: %s\n" MsgZGProcessing = " Processing %d zip group(s)...\n" MsgZGNoArchives = " ⚠ No zip archives were produced from %d group(s)\n" ErrZGStagingDir = " ✗ Cannot create staging dir at %s: %v (operation: mkdir)\n" MsgZGTypeFolder = "folder" MsgZGTypeFile = "file" MsgZGJSONWritten = " ✓ Saved %s\n" MsgZGShowExpanded = " Contents (%d files):\n" MsgZGShowExpFile = " %s\n" )
Zip group messages.
const ( ErrZGNotFound = "no zip group found: %s" ErrZGEmpty = "zip group name cannot be empty" ErrZGCreate = "failed to create zip group: %v" ErrZGQuery = "failed to query zip groups: %v" ErrZGDelete = "failed to delete zip group: %v" ErrZGAddItem = "failed to add item to zip group: %v" ErrZGRemoveItem = "failed to remove item from zip group: %v" ErrZGCompress = " ✗ Failed to create archive for %s: %v (operation: write)\n" ErrZGGroupNotDB = "zip group %q not found in database" ErrZGPathResolve = "cannot resolve path %q: %v (operation: resolve)" ErrZGJSONWrite = "failed to write zip-groups.json at %s: %v (operation: write)" )
Zip group error messages.
const CDDefaultsFile = "cd-defaults.json"
CD file.
const CDFuncBash = `` /* 1012-byte string literal not displayed */
CDFuncBash installs gitmap and gcd wrappers for Bash.
const CDFuncMarker = "# gitmap shell wrapper v2"
CD shell wrapper functions — installed by setup/completion.
const CDFuncPowerShell = `` /* 1754-byte string literal not displayed */
CDFuncPowerShell installs gitmap and gcd wrappers for PowerShell.
const CDFuncZsh = `` /* 1028-byte string literal not displayed */
CDFuncZsh installs gitmap and gcd wrappers for Zsh.
const CloneAutoMaxConcurrency = 0
CloneAutoMaxConcurrency is the public name of the sentinel; use it at comparison sites instead of repeating the literal `0`.
const CloneDefaultMaxConcurrency = 0
CloneDefaultMaxConcurrency is the sentinel default. 0 means "auto" (resolved by ResolveCloneConcurrency to runtime.NumCPU at run time). The historical sequential behavior is still reachable with `--max-concurrency 1`.
const CloneFlagAudit = "audit"
CloneFlagAudit is the long-form flag name (`--audit`) that switches `gitmap clone` into the read-only planner.
const CloneFlagMaxConcurrency = "max-concurrency"
CloneFlagMaxConcurrency is the long-form flag name shared by every batch clone command.
const CloneFromErrTrimLimit = 80
CloneFromErrTrimLimit caps the per-row stderr summary length. 80 chars fits a typical terminal column; longer messages are truncated with an ellipsis. Full stderr remains in the user's scrollback (we use CombinedOutput so it was printed live).
const CloneFromReportJSONNameFmt = "clone-from-report-%d.json"
JSON report on-disk filename pattern. Mirrors the CSV pattern so both files sort next to each other in `ls .gitmap/`. %d = unix seconds at write time.
const CloneFromReportSchemaVersion = 3
JSON report envelope. CloneFromReportSchemaVersion is embedded as `schemaVersion` at the top of every JSON report so downstream consumers (jq pipelines, dashboards, custom CI gates) can branch on shape changes without sniffing fields. Bump ONLY when the `rows[]` field set, field rename, or envelope shape changes — not for value-level changes (new status strings, etc.). The matching golden test (TestCloneFromReportJSON_SchemaVersion_Pinned) will fail loudly on any unintentional bump.
const CloneFromSummaryTransportFmt = "transport: %d ssh, %d https, %d other\n"
CloneFromSummaryTransportFmt is the one-line transport split shared by both the legacy RenderSummary and the enriched terminal block. SSH = ssh:// + scp-style; HTTPS = https://; OTHER folds http://, git://, file://, and unrecognized forms so the line stays at three stable columns regardless of manifest contents. Derived from ClassifyScheme so this counter and the per-scheme tally can never disagree. %d ssh, %d https, %d other.
const CloneFromTermSummaryFoundFmt = " found: %d repo(s)\n"
CloneFromTermSummaryFoundFmt prints the "found" total — the number of repos in the user's manifest after dedup, NOT the number that were successfully cloned (use the status tally for that). Wording matches the user's phrasing in the request ("count of found repos"). %d = total row count.
const CloneFromTermSummaryHeader = "\ngitmap clone-from: summary\n"
CloneFromTermSummaryHeader is the banner that opens the terminal- mode summary. Plain ASCII so the byte width matches the terminal column count Windows cmd.exe assumes (mem://constraints/powershell-encoding).
const CloneFromTermSummaryReportFmt = " report %s: %s\n"
CloneFromTermSummaryReportFmt is one report-path line. Used twice (once for CSV, once for JSON) so the same format string covers both. %s = label ("csv"/"json"), %s = absolute path.
const CloneFromTermSummaryReportNone = " report: (skipped — --no-report or write failed)\n"
CloneFromTermSummaryReportNoneFmt is the placeholder when --no-report is in effect or report writing failed. Shown in place of the path rows so the summary shape stays predictable for log scrapers.
const CloneFromTermSummarySchemeHeader = " by mode:\n"
CloneFromTermSummarySchemeHeader introduces the per-scheme block. Indent matches the rest of the block so the renderer never has to compute column widths at runtime.
const CloneFromTermSummarySchemeRowFmt = " %-7s %d\n"
CloneFromTermSummarySchemeRowFmt renders one scheme row inside the "by mode" block. Two-space indent INSIDE the block (so 4 from the left edge) keeps the visual hierarchy clear without ANSI escapes. %-7s = left-padded scheme label (https / ssh / git / file / scp / other), %d = count.
const CloneFromTermSummaryStatusFmt = " status: %d ok, %d skipped, %d failed (%d total)\n"
CloneFromTermSummaryStatusFmt is the one-line status tally inside the terminal summary. Mirrors the wording of the legacy MsgCloneFromSummaryHeader so users who already know the default summary recognize the numbers. %d ok, %d skipped, %d failed, %d total.
const CloneNowConfirmYes = "y"
CloneNowConfirmYes is the only stdin response that proceeds with --execute when destinations already exist. Anything else (including the empty default) aborts with exit code 2. Stable so shell scripts piping `yes` keep working: `yes | gitmap reclone --execute`.
const CloneNowErrTrimLimit = 80
CloneNowErrTrimLimit caps the per-row stderr summary length so the summary table stays scannable in an 80-column terminal. Full stderr remains in the user's scrollback because we use CombinedOutput.
const CloneNowExistingPreviewLimit = 10
CloneNowExistingPreviewLimit caps how many existing destinations are listed in the prompt to keep terminal output scannable. The total count is always shown so the user knows the full impact.
const CloneNowExitConfirmAborted = 2
CloneNowExitConfirmAborted is the exit code used when the user declines the prompt OR when --execute is passed in a non-TTY context with existing destinations and no --yes. Distinct from the per-row failure exit (1) so wrappers can tell "user said no" apart from "git clone failed".
const CloneNowExitManifestInvalid = 2
CloneNowExitManifestInvalid is the exit code used when the manifest parses cleanly but one or more rows fail semantic validation (missing repo name, unusable URL, absent / absolute / traversal RelativePath). Same numeric code as the bad-flag exit (2) because both represent "you fed me invalid input" rather than a runtime clone failure (1). Aliased to a named constant so the validator's intent is self-documenting at the call site.
const CloneNowSummaryTreeLimit = 40
CloneNowSummaryTreeLimit caps how many destination paths are rendered in the folder-layout tree to keep terminal output scannable on large round-trips. The total row count is always shown in the header so the user knows the full impact.
const ClonePickExitUserCancel = 130
User-cancel exit code. 130 mirrors the SIGINT convention so shell scripts can branch on `$? -eq 130` cleanly.
const ClonePickPathMaxBytes = 4096
ClonePickPathMaxBytes caps a single path entry at git's documented sparse-checkout pattern length limit. Anything longer is rejected up-front with ErrClonePickPathTooLong.
const (
CmdReinstall = "reinstall"
)
gitmap:cmd top-level Reinstall command.
const CmdSelfUninstallRunner = "self-uninstall-runner" // gitmap:cmd skip
Hidden runner subcommand for the self-uninstall handoff (lets the temp copy delete the original .exe on Windows where the running file is locked).
const CompListSSHKeys = "--list-ssh-keys"
SSH completion flag.
const DebugWindowsJSONFileFmt = "gitmap-debug-windows-%s.jsonl"
Default filename pattern for the JSON sink. %s = local timestamp formatted as 2006-01-02_15-04-05.
const (
DefaultCleanCodeURL = "https://raw.githubusercontent.com/alimtvnetwork/coding-guidelines-v15/main/install.ps1"
)
Clean-code / coding-guidelines installer. One-liner published at the URL below installs the alimtvnetwork coding-guidelines (v15) into the current directory via PowerShell IRM | IEX.
The four CLI aliases (clean-code, code-guide, cg, cc) all dispatch to the same flow — see gitmap/cmd/installcleancode.go.
const DefaultDashboardRefresh = 30
TUI defaults.
const DefaultDownloaderConfigSeedPath = "./data/downloader-config.json"
Default Seedable-Config path, relative to the gitmap binary's data dir.
const DefaultExportFile = "gitmap-export.json"
Export default file name.
const (
DefaultLatestFile = "latest.json"
)
const (
DefaultSSHHost = "github.com"
)
SSH defaults.
const DirPermission = 0o755
File and directory permissions.
const (
DoctorLegacyDirsOK = "No legacy directories (.release/, gitmap-output/, .deployed/)"
)
Doctor legacy directory messages.
const EnvDebugWindows = "GITMAP_DEBUG_WINDOWS"
Debug-windows env bridge — propagated to the detached cleanup child so the dump runs on both sides of the handoff without requiring users to pass the flag twice.
const EnvDebugWindowsJSON = "GITMAP_DEBUG_WINDOWS_JSON"
Debug-windows JSON-sink env bridge. Set automatically when the sink opens so the Phase 3 cleanup child appends to the SAME file as the parent, giving one consolidated NDJSON trace per handoff.
const EnvGitmapHandoffFile = "GITMAP_HANDOFF_FILE"
Shell-handoff sentinel file env var. Set by the wrapper function to a writable temp file path; commands like clone-next, as, cd write the destination directory to that file, and the wrapper cds to it.
Spec: spec/04-generic-cli/21-post-install-shell-activation/01-contract.md
const EnvStartupAutostartDir = "GITMAP_AUTOSTART_DIR"
EnvStartupAutostartDir is an explicit override for AutostartDir(). When set and non-empty, AutostartDir() returns this path verbatim on every OS (Linux, macOS, Windows), bypassing the per-OS default resolution (XDG_CONFIG_HOME/autostart, ~/Library/LaunchAgents, Registry/Startup folder respectively).
Two intended uses:
- Tests that need a writable, isolated autostart dir on every OS without per-OS skips. Set via t.Setenv inside the test body.
- Power users who keep their dotfiles under a non-default root and want gitmap to install autostart entries alongside them (e.g. inside a Nix profile or a portable USB-stick install).
const ErrAmendListFailed = "error: failed to list amendments: %v\n"
Amend-list error messages.
const ErrCloneAuditDirectURL = "clone --audit: requires a manifest file (json|csv|text|path), not a direct git URL\n"
ErrCloneAuditDirectURL is printed when the user combines `--audit` with a direct git URL. Audit only makes sense against a manifest file because it needs a list of records to validate.
const ErrCloneAuditLoad = "clone --audit: could not load %q: %v\n"
Error format used when the audit cannot load the source manifest. The runtime falls back to os.Exit(1) after printing this — partial output would be misleading in audit mode.
const ErrCloneMaxConcurrencyInvalid = "clone --max-concurrency: must be a non-negative integer (got %d)\n"
ErrCloneMaxConcurrencyInvalid is printed when the user supplies a non-positive integer to --max-concurrency. The CLI exits 1 to keep the contract: invalid input never silently degrades to a default.
const ErrCloneStaleBinaryFolderURL = "" +
" ✗ Refusing to clone: the folder name resolved to a URL (%q).\n" +
" This means your installed gitmap binary is older than v3.80.0\n" +
" (current source: v%s). The multi-URL clone fix is not present\n" +
" in the binary on your PATH.\n\n" +
" To fix:\n" +
" 1. gitmap doctor # confirm the active binary version\n" +
" 2. gitmap update # rebuild + redeploy from current source\n" +
" 3. open a NEW terminal so PATH refreshes\n" +
" 4. gitmap pending clear --yes # drop any orphaned pending rows\n" +
" 5. retry the clone — `gitmap clone <url1> <url2>` works either\n" +
" space-separated or comma-separated in PowerShell and bash.\n"
Stale-binary detection — fired when executeDirectClone is called with a folder name that itself parses as a URL. That shape is impossible in current source (multi-URL routing in runClone catches it), so when it happens it almost always means the user is running a deployed binary that pre-dates v3.80.0's multi-URL fix. We refuse to build the broken `D:\...\https:\github.com\...` path and tell the user exactly why.
const ErrDBVersionHistory = "failed to query version history: %v"
Version history error messages.
const (
ErrListVersionsNoTags = "Error: no version tags found. Create a release first."
)
List-versions error messages.
const ErrReplaceBadExtCase = "replace: --ext-case must be %q or %q (got %q)\n"
Error format for an unknown --ext-case value. Kept here so the message stays in sync with the constants above.
const ErrSelfInstallProfileInvalid = "Error: --profile %q is not valid. Accepted: %s\n"
ErrSelfInstallProfileInvalid is the back-compat error for the legacy --profile flag. Same wording as before to keep CI grep patterns valid.
const ErrSelfInstallShellModeInvalid = "Error: --shell-mode %q is not valid. " +
"Accepted singletons: %s. Combos: any '+'-joined combination of singletons " +
"(e.g. zsh+pwsh, bash+fish, zsh+bash+pwsh).\n"
ErrSelfInstallShellModeInvalid fires when --shell-mode gets an unknown value (singleton or combo token). Format: %q = full bad value, %s = accepted singletons (combos are documented separately in help text to avoid an unbounded "valid values" string).
const ErrShellHandoffWriteFmt = " ⚠ Could not write shell-handoff file %s: %v\n"
Shell-handoff error format.
const (
ErrWatchNoRepos = "No repos to watch. Run 'gitmap scan' first."
)
Watch error messages.
const FilePermission = 0o644
const FlagAmendListBranch = "--branch"
Amend-list flag.
const FlagDebugRepoDetect = "--debug-repo-detect"
const FlagDebugWindows = "--debug-windows"
const FlagDebugWindowsJSON = "--debug-windows-json"
const FlagDescCloneAudit = "Validate planned git clone commands and print a diff-style summary; never executes."
FlagDescCloneAudit is the help text shown by `gitmap help clone`.
const FlagDescCloneMaxConcurrency = "Run up to N clones in parallel (0 = auto / NumCPU, 1 = sequential). Hierarchy is preserved at any N."
FlagDescCloneMaxConcurrency is the help text shown by every `gitmap <clone-cmd> --help`. Kept short so it fits one line in `flag.PrintDefaults`.
const FlagDescExportOut = "Output file path for the export"
Export flag descriptions.
const (
FlagDescHDPort = "Port to serve the dashboard on (default: 5173)"
)
Help-dashboard flag descriptions.
const (
FlagDescStatsCommand = "Show stats for a specific command only"
)
Stats flag descriptions.
const FlagRepoPath = "--repo-path"
const FlagReportErrors = "--report-errors"
const FlagReportErrorsFile = "--report-errors-file"
const FlagVerbose = "--verbose"
Update flags.
const GitBranchDashFormat = "%(refname:short)|%(objectname:short)|%(creatordate:iso-strict)"
Dashboard git branch format — pipe-delimited fields: refname short | objectname short | creator date ISO.
const GitLogDashFormat = "%H|%h|%an|%ae|%aI|%s|%P"
Dashboard git log format — pipe-delimited fields: full SHA | short SHA | author name | author email | ISO date | subject | parent hashes.
const GitMapDir = ".gitmap"
Root directory for all repo-local gitmap data.
const GitTagDashFormat = "%(refname:short)|%(objectname:short)|%(creatordate:iso-strict)"
Dashboard git tag format — pipe-delimited fields: refname short | objectname short | creator date ISO.
const GoModCommitMsgFmt = "" /* 131-byte string literal not displayed */
GoMod commit message format.
const GoModMergeMsgFmt = "merge: module rename to %s"
GoMod merge message format.
const (
HelpBookmark = " bookmark (bk) <sub> Save and replay command+flag combinations (save, list, run, delete)"
)
Bookmark help text.
const HelpCD = " cd (go) <name> Navigate to a tracked repo directory"
CD help text.
const (
HelpChangelogGen = " changelog-gen (cg) Auto-generate changelog from commits between tags (--from, --to, --write)"
)
Changelog generate help text.
const HelpCompletionLong = " completion (cmp) Generate or install shell tab-completion scripts"
Completion help text.
const HelpDashboard = " dashboard (db) Generate an interactive HTML dashboard for a repo"
Dashboard help text.
const HelpDiffProfiles = " diff-profiles (dp) Compare repos across two database profiles"
Diff-profiles help text.
const HelpDownloaderConfig = " downloader-config (dc) [path] Set/seed downloader config (aria2c parallel, splits, thresholds)"
HelpDownloaderConfig is shown in the root usage table once the command is listed by the help generator.
const HelpEnv = " env (ev) <sub> Manage environment variables and PATH"
Env help text.
const HelpExport = " export (ex) [file] Export full database as portable JSON (default: gitmap-export.json)"
Export help text.
const HelpHasAnyUpdates = " has-any-updates (hau/hac) Check if remote has new commits"
Has-any-updates help text.
const HelpHelpDashboard = " help-dashboard (hd) Serve the docs site locally in your browser"
Help-dashboard help text.
const HelpImport = " import (im) [file] Import database from a gitmap-export.json file (--confirm required)"
Import help text.
const HelpProfile = " profile (pf) <sub> Manage database profiles (create, list, switch, delete, show)"
Profile help text.
const HelpPrune = " prune (pr) Delete stale release branches that have been tagged"
Prune help text.
const (
HelpStats = " stats (ss) Show aggregated command usage statistics (--json, --command)"
)
Stats help text.
const HelpTask = " task (tk) <sub> Manage file-sync watch tasks"
Task help text.
const (
HelpTempRelease = " temp-release (tr) <count> <pattern> [-s N] Create temp branches from recent commits"
)
Temp-release help text.
const HelpVersionHistory = " version-history (vh) Show version transitions for the current repo (--limit N, --json)"
Version history help text.
const HelpWatch = " watch (w) Live-refresh dashboard of repo status"
Watch help text.
const (
InstallLogDir = ".gitmap/logs"
)
Install log directory.
const JSONIndent = " "
JSON formatting.
const LegacyTableAliases = "Aliases"
Legacy plural retained for migration detection.
const LegacyTableAmendments = "Amendments"
Legacy plural retained for migration detection.
const LegacyTableBookmarks = "Bookmarks"
Legacy plural retained for migration detection.
const LegacyTableCommitTemplates = "CommitTemplates"
Legacy plural retained for migration detection.
const LegacyTableInstalledTools = "InstalledTools"
Legacy plural retained for migration detection.
const LegacyTableSSHKeys = "SSHKeys"
Legacy plural retained for migration detection.
const LegacyTableSettings = "Settings"
Legacy plural retained for migration detection.
const LegacyTableTempReleases = "TempReleases"
Legacy plural retained for migration detection.
const MaxCompactFlattenLayers = 4
MaxCompactFlattenLayers caps how many duplicate same-name folder layers the compact-extract algorithm collapses. The spec calls for 2..4 layers of tolerance; we set the upper bound at 4 to match.
const MsgCloneConcurrencyEnabledFmt = " ↪ parallel clone enabled: %d workers\n"
MsgCloneConcurrencyEnabledFmt is printed once before the first progress line when the parallel runner takes over. Single stable line that scripts can grep for. Resolved (effective) worker count is substituted, NOT the raw flag value.
const MsgHintHeader = "\nHints:\n"
Hint header.
const MsgHintRowFmt = " → %-35s %s\n"
Hint format.
const (
MsgLegacyProjectData = "Database contains legacy project data from a previous version.\n" +
"To fix, run one of:\n\n" +
" gitmap rescan Re-scan repos and rebuild project data\n" +
" gitmap db-reset --confirm Reset the entire database\n"
)
Legacy data recovery messages.
const (
MsgUpdateInstallDir = " → Installed directory: %s\n"
)
Unix update messages.
const MsgVersionFmt = "gitmap v%s\n"
Version display.
const OSDarwin = "darwin"
OS platform constants.
const OldBackupGlob = "*.old"
Backup file extension glob.
const ReplaceBinarySniffBytes = 8192
ReplaceBinarySniffBytes is the number of bytes scanned for null bytes when classifying a file as binary.
const SQLAddRepoScanFolderId = "ALTER TABLE Repo ADD COLUMN ScanFolderId INTEGER DEFAULT NULL"
SQL: ALTER Repo with nullable ScanFolderId FK. Idempotent via addColumnIfNotExists. SQLite cannot add a REFERENCES clause via ALTER without a table rebuild, so the column stores the FK value without a declared FOREIGN KEY constraint — application code enforces validity.
const SQLAddSourceColumn = "ALTER TABLE Release ADD COLUMN Source TEXT DEFAULT 'release'"
SQL: add Source column — v15: now targets singular Release table.
const SQLAddVSCodeProjectPathsColumn = `ALTER TABLE VSCodeProject ADD COLUMN Paths TEXT NOT NULL DEFAULT '[]'`
Idempotent additive migration — safe to re-run on legacy v18/v19 DBs that pre-date the Paths column. SQLite's ALTER TABLE ADD COLUMN errors when the column already exists, so callers must IGNORE that single error.
const SQLCountProjectsByTypeKey = `SELECT COUNT(*)
FROM DetectedProject dp
JOIN ProjectType pt ON dp.ProjectTypeId = pt.ProjectTypeId
WHERE pt.Key = ?`
SQL: count projects by type key.
const SQLCreateAbsPathIndex = "CREATE UNIQUE INDEX IF NOT EXISTS IdxRepo_AbsolutePath ON Repo(AbsolutePath)"
SQL: create unique index on AbsolutePath for upsert-by-path (v15: IdxRepo_AbsolutePath).
const SQLCreateAlias = `` /* 228-byte string literal not displayed */
SQL: create Alias table (v15: singular + AliasId PK). FK references Repo(RepoId).
const SQLCreateAmendment = `` /* 451-byte string literal not displayed */
SQL: create Amendment table (v15).
const SQLCreateArchiveHistory = `` /* 649-byte string literal not displayed */
SQL: create ArchiveHistory table (PascalCase, INTEGER PK AUTOINCREMENT, matches v15 conventions). Stored under .gitmap/db/<profile>.db like every other table — no separate per-command schema.
const SQLCreateBookmark = `` /* 248-byte string literal not displayed */
SQL: create Bookmark table (v15: singular + BookmarkId PK).
const SQLCreateCloneInteractiveSelection = `` /* 636-byte string literal not displayed */
SQL: create CloneInteractiveSelection table (spec 100, v3.153.0+).
Records every `gitmap clone-pick` invocation so the same selection can be re-applied with `--replay <id|name>` -- without forcing the user to re-type the path list or remember which sparse-checkout flags they used.
Why no FK to Repo(RepoId):
The repo being picked may not exist in any prior `gitmap scan` output. A user can `clone-pick owner/repo docs` against a fresh clone they've never indexed locally; gating that behind a "must scan first" requirement would gut the command's usefulness. We instead identify the repo by its canonical id (host/owner/repo) stored as text and indexed.
Why no UNIQUE on Name:
'' is the default Name (auto-saves without --name). SQLite UNIQUE would reject the second nameless save. Uniqueness for non-empty names is enforced in the store layer (a SELECT-then-INSERT race is acceptable here -- worst case the second user sees an error when their `--replay <name>` lookup returns >1 row, which is the MsgClonePickReplayAmbiguous path and prints the candidate IDs).
const SQLCreateClonePickNameIndex = `CREATE INDEX IF NOT EXISTS idx_clonepick_name
ON CloneInteractiveSelection(Name) WHERE Name <> ''`
SQLCreateClonePickNameIndex is partial: empty Names share no uniqueness or lookup pressure, so the index is cheaper.
const SQLCreateClonePickRepoCanonIndex = `CREATE INDEX IF NOT EXISTS idx_clonepick_repocanon
ON CloneInteractiveSelection(RepoCanonicalId)`
SQLCreateClonePickRepoCanonIndex speeds up "show me everything I've ever picked from this repo" lookups (used implicitly when --replay resolves a numeric id within the matching repo's history).
const SQLCreateCommandHistory = `` /* 499-byte string literal not displayed */
SQL: create CommandHistory table (v15: CommandHistoryId PK).
const SQLCreateCommitInConflictMode = `` /* 195-byte string literal not displayed */
const SQLCreateCommitInExclusionKind = `` /* 199-byte string literal not displayed */
const SQLCreateCommitInInputKind = `` /* 183-byte string literal not displayed */
const SQLCreateCommitInInputRepo = `` /* 461-byte string literal not displayed */
const SQLCreateCommitInLanguage = `` /* 231-byte string literal not displayed */
const SQLCreateCommitInMessageRuleKind = `` /* 207-byte string literal not displayed */
const SQLCreateCommitInOutcome = `` /* 199-byte string literal not displayed */
const SQLCreateCommitInProfile = `` /* 302-byte string literal not displayed */
---- Profile (defined before CommitInRun so the FK can resolve) ---
const SQLCreateCommitInProfileDefaultIdx = `CREATE UNIQUE INDEX IF NOT EXISTS
UX_Profile_DefaultPerSource ON Profile (SourceRepoPath) WHERE IsDefault = 1`
One default profile per source repo (partial unique index).
const SQLCreateCommitInProfileExclusion = `` /* 390-byte string literal not displayed */
const SQLCreateCommitInProfileMessageRule = `` /* 406-byte string literal not displayed */
const SQLCreateCommitInRewritten = `` /* 737-byte string literal not displayed */
const SQLCreateCommitInRewrittenShaIdx = `CREATE INDEX IF NOT EXISTS
IX_RewrittenCommit_NewSha ON RewrittenCommit (NewSha)`
const SQLCreateCommitInRun = `` /* 521-byte string literal not displayed */
---- Core run/commit tables ---------------------------------------
const SQLCreateCommitInRunSourceIdx = `CREATE INDEX IF NOT EXISTS
IX_CommitInRun_SourceRepoPath ON CommitInRun (SourceRepoPath)`
const SQLCreateCommitInRunStatus = `` /* 183-byte string literal not displayed */
---- Enum-mirror tables -------------------------------------------
const SQLCreateCommitInShaMap = `` /* 300-byte string literal not displayed */
const SQLCreateCommitInShaMapIdx = `CREATE INDEX IF NOT EXISTS
IX_ShaMap_SourceSha ON ShaMap (SourceSha)`
const SQLCreateCommitInSkipLog = `` /* 578-byte string literal not displayed */
const SQLCreateCommitInSkipReason = `` /* 187-byte string literal not displayed */
const SQLCreateCommitInSourceCommit = `` /* 525-byte string literal not displayed */
const SQLCreateCommitInSourceCommitFile = `` /* 341-byte string literal not displayed */
const SQLCreateCommitInSourceCommitShaIdx = `CREATE INDEX IF NOT EXISTS
IX_SourceCommit_SourceSha ON SourceCommit (SourceSha)`
const SQLCreateCommitTemplate = `` /* 222-byte string literal not displayed */
SQL: create CommitTemplate table.
const SQLCreateCompletedTask = `` /* 437-byte string literal not displayed */
SQL: create CompletedTask table (v15: CompletedTaskId PK).
const SQLCreateCsharpKeyFile = `` /* 350-byte string literal not displayed */
SQL: create CsharpKeyFile table (v15: singular + CsharpKeyFileId PK).
const SQLCreateCsharpProjectFile = `` /* 518-byte string literal not displayed */
SQL: create CsharpProjectFile table (v15: singular + CsharpProjectFileId PK).
const SQLCreateCsharpProjectMeta = `` /* 395-byte string literal not displayed */
SQL: create CsharpProjectMetadata table (v15: CsharpProjectMetadataId PK + Csharp abbreviation per strict v15 PascalCase rule).
const SQLCreateDetectedProject = `` /* 520-byte string literal not displayed */
SQL: create DetectedProject table (v15: singular + DetectedProjectId PK). FK references v15 Repo(RepoId) and ProjectType(ProjectTypeId).
const SQLCreateGoProjectMetadata = `` /* 363-byte string literal not displayed */
SQL: create GoProjectMetadata table (v15: GoProjectMetadataId PK).
const SQLCreateGoRunnableFile = `` /* 339-byte string literal not displayed */
SQL: create GoRunnableFile table (v15: singular + GoRunnableFileId PK).
const SQLCreateGroup = `` /* 225-byte string literal not displayed */
SQL: create Group table (v15 singular). "Group" is a SQL reserved word so it MUST be double-quoted everywhere it appears in DDL/DML.
const SQLCreateGroupRepo = `` /* 213-byte string literal not displayed */
SQL: create GroupRepo join table (v15: singular). FKs reference v15 PKs.
const SQLCreateInstalledTool = `` /* 529-byte string literal not displayed */
SQL: create InstalledTool table (v15: singular + InstalledToolId PK).
const SQLCreatePendingTask = `` /* 454-byte string literal not displayed */
SQL: create PendingTask table (v15: PendingTaskId PK).
const SQLCreateProjectType = `` /* 190-byte string literal not displayed */
SQL: create ProjectType table (v15: singular + ProjectTypeId PK).
const SQLCreateRelease = `` /* 573-byte string literal not displayed */
SQL: create Release table (v17: + RepoId FK to Repo, composite UNIQUE(RepoId, Tag)). See spec/04-generic-cli/24-release-repo-relationship.md for the rationale.
const SQLCreateReleaseRepoIdIndex = "CREATE INDEX IF NOT EXISTS IdxRelease_RepoId ON Release(RepoId)"
SQL: index on Release.RepoId for fast per-repo filtering (future multi-repo mode).
const SQLCreateRepo = `` /* 486-byte string literal not displayed */
SQL: create Repo table (v15: singular + RepoId PK).
const SQLCreateRepoVersionHistory = `` /* 434-byte string literal not displayed */
SQL: create RepoVersionHistory table (v15: RepoVersionHistoryId PK). FK references v15 Repo(RepoId).
const SQLCreateScanFolder = `` /* 278-byte string literal not displayed */
SQL: create ScanFolder table.
const SQLCreateScanFolderPathIndex = "CREATE UNIQUE INDEX IF NOT EXISTS IdxScanFolder_AbsolutePath ON ScanFolder(AbsolutePath)"
SQL: unique index on AbsolutePath so EnsureScanFolder is idempotent.
const SQLCreateSetting = `CREATE TABLE IF NOT EXISTS Setting (
Key TEXT PRIMARY KEY,
Value TEXT NOT NULL
)`
SQL: create Setting table (v15).
const SQLCreateSshKey = `` /* 278-byte string literal not displayed */
SQL: create SshKey table (v15).
const SQLCreateTaskType = `CREATE TABLE IF NOT EXISTS TaskType (
TaskTypeId INTEGER PRIMARY KEY AUTOINCREMENT,
Name TEXT NOT NULL UNIQUE
)`
SQL: create TaskType table (v15: TaskTypeId PK).
const SQLCreateTempRelease = `` /* 357-byte string literal not displayed */
SQL: create TempRelease table (v15).
const SQLCreateVSCodeProject = `` /* 439-byte string literal not displayed */
const SQLCreateVSCodeProjectRootPathIndex = `CREATE UNIQUE INDEX IF NOT EXISTS UX_VSCodeProject_RootPath ON VSCodeProject(RootPath COLLATE NOCASE)`
COLLATE NOCASE so Windows path matching is case-insensitive while staying byte-exact on Unix when the user happens to use the same case.
const SQLCreateVersionProbe = `` /* 394-byte string literal not displayed */
SQL: create VersionProbe table (populated starting Phase 2.3).
const SQLCreateVersionProbeRepoIndex = "CREATE INDEX IF NOT EXISTS IdxVersionProbe_RepoId ON VersionProbe(RepoId, ProbedAt DESC)"
SQL: index for fast latest-probe lookups per repo.
const SQLCreateZipGroup = `` /* 196-byte string literal not displayed */
SQL: create ZipGroup table (v15: singular + ZipGroupId PK).
const SQLCreateZipGroupItem = `` /* 314-byte string literal not displayed */
SQL: create ZipGroupItem table (v15 singular). Composite PK retained.
const SQLDropLegacyAbsPathIndex = "DROP INDEX IF EXISTS idx_Repos_AbsolutePath"
SQL: drop the legacy index name from pre-v15 installs.
const SQLDropVSCodeProject = "DROP TABLE IF EXISTS VSCodeProject"
const SQLEnableFK = "PRAGMA foreign_keys = ON"
SQL: enable foreign keys.
const SQLImportInsertBookmark = `INSERT OR IGNORE INTO Bookmark (Name, Command, Args, Flags) VALUES (?, ?, ?, ?)`
SQL: import-side bookmark insert.
const SQLImportInsertGroup = `INSERT OR IGNORE INTO "Group" (Name, Description, Color) VALUES (?, ?, ?)`
SQL: import-side group insert (used by store/import.go to insert without conflict).
const SQLInsertVersionProbe = `INSERT INTO VersionProbe
(RepoId, NextVersionTag, NextVersionNum, Method, IsAvailable, Error)
VALUES (?, ?, ?, ?, ?, ?)`
SQL: insert a new probe row.
const SQLMigrateTRCommitSha = `ALTER TABLE TempReleases RENAME COLUMN "Commit" TO CommitSha`
SQL: migrate Commit → CommitSha column. Operates on legacy TempReleases — the v15 rebuild copies the already-renamed column into TempRelease.
const SQLSeedProjectTypes = `` /* 299-byte string literal not displayed */
SQL: seed project types.
const SQLSeedTaskTypes = `INSERT OR IGNORE INTO TaskType (Name)
VALUES ('Delete'), ('Remove'), ('Scan'), ('Clone'), ('Pull'), ('Exec')`
SQL: seed TaskType values.
const SQLSelectCsharpKeyFiles = `` /* 145-byte string literal not displayed */
SQL: query C# key files.
const SQLSelectCsharpMetadata = `` /* 152-byte string literal not displayed */
SQL: query C# metadata.
const SQLSelectCsharpProjectFiles = `` /* 200-byte string literal not displayed */
SQL: query C# project files.
const SQLSelectDetectedProjectID = `SELECT DetectedProjectId
FROM DetectedProject
WHERE RepoId = ? AND ProjectTypeId = ? AND RelativePath = ?`
SQL: query detected project ID by identity tuple.
const SQLSelectFindNext = `` /* 415-byte string literal not displayed */
SQL: every repo whose latest VersionProbe row has IsAvailable=1. Sort by NextVersionNum DESC so the freshest tags float to the top.
const SQLSelectFindNextByScanFolder = `` /* 440-byte string literal not displayed */
SQL: same as above, scoped to a specific ScanFolderId.
const SQLSelectGoMetadata = `` /* 143-byte string literal not displayed */
SQL: query Go metadata.
const SQLSelectGoRunnables = `` /* 143-byte string literal not displayed */
SQL: query Go runnables.
const SQLSelectLatestVersionProbe = `` /* 190-byte string literal not displayed */
SQL: latest probe per repo.
const SQLSelectProjectsByTypeKey = `` /* 337-byte string literal not displayed */
SQL: query projects by type key (v15: JOIN Repo on RepoId, ProjectType on ProjectTypeId).
const SQLSelectTaskTypeByName = `SELECT TaskTypeId FROM TaskType WHERE Name = ?`
SQL: task type lookup (v15: TaskTypeId PK).
const SQLTagReposByScanFolderTpl = `UPDATE Repo SET ScanFolderId = ? WHERE AbsolutePath IN (%s)`
SQL: bulk-tag every repo whose AbsolutePath was just scanned with the active ScanFolderId. Path list is interpolated as `?,?,?,...` because SQLite has no array binding.
const SQLUpsertCsharpKeyFile = `` /* 218-byte string literal not displayed */
SQL: upsert C# key file.
const SQLUpsertCsharpMetadata = `` /* 301-byte string literal not displayed */
SQL: upsert C# metadata.
const SQLUpsertCsharpProjectFile = `` /* 415-byte string literal not displayed */
SQL: upsert C# project file.
const SQLUpsertDetectedProject = `` /* 396-byte string literal not displayed */
SQL: upsert detected project.
const SQLUpsertGoMetadata = `` /* 294-byte string literal not displayed */
SQL: upsert Go metadata.
const SQLUpsertGoRunnable = `` /* 223-byte string literal not displayed */
SQL: upsert Go runnable file.
const SQLUpsertRepoByPath = `` /* 449-byte string literal not displayed */
SQL: upsert by AbsolutePath (spec requirement).
const SSHConfigHostEntry = `Host %s
HostName %s
User git
IdentityFile %s
IdentitiesOnly yes
`
SSH config host template.
const SchemaVersionCurrent = 24
SchemaVersionCurrent is the target schema version produced by the current build of Migrate(). Bump this integer whenever a NEW migration step is added to gitmap/store/store.go:Migrate (a new v15 phase, a new ALTER, a new seed table, etc.).
Migrate() short-circuits when Setting[schema_version] == this value, so every gitmap subcommand that calls openDB() pays only a single SELECT against Setting instead of re-running the full v15 phase pipeline.
Bump policy:
- Bump on ANY structural change to Migrate() — new CREATE TABLE, new ALTER TABLE, new v15 phase, new seed call, new ID rename.
- Do NOT bump for cosmetic changes (comments, log strings, code moves that produce identical SQL).
- The marker is cleared by `gitmap db-reset` and by migrateLegacyIDs() when it detects pre-integer-PK rows, so legacy databases will always re-run the full pipeline regardless of this number.
const TableAlias = "Alias"
Alias table name (v15: singular).
const TableAmendment = "Amendment"
Amendment table (v15: singular + AmendmentId PK).
const TableBookmark = "Bookmark"
Bookmark table name (v15: singular).
const TableCommandHistory = "CommandHistory"
History table name (v15: singular preserved; PK Id → CommandHistoryId).
const TableCommitTemplate = "CommitTemplate"
CommitTemplate table (v15: singular + CommitTemplateId PK).
const TableRepoVersionHistory = "RepoVersionHistory"
Table name for version history (v15: singular preserved; PK renamed).
const TableSetting = "Setting"
Settings table (v15: Setting singular). The PK is Key (TEXT) so no {Table}Id rename is needed.
const TableSshKey = "SshKey"
SshKey table (v15: singular + SshKeyId PK; abbreviation per v15: Ssh, not SSH).
const TableTempRelease = "TempRelease"
TempRelease table (v15: singular + TempReleaseId PK).
const TableVSCodeProject = "VSCodeProject"
const TasksFilePath = GitMapDir + "/" + TasksFileName
Task file path within .gitmap.
const TempReleaseBranchPrefix = "temp-release/"
Temp-release branch prefix.
const TempReleaseMaxCount = 50
Temp-release limits.
const TempReleasePlaceholder = "$$"
Temp-release placeholder.
const UsageHeaderFmt = "gitmap v%s\n\n"
Usage header.
const VerboseLogFileFmt = "gitmap-verbose-%s.log"
Verbose log file.
const Version = "4.18.0"
Version.
const (
WatchClearScreen = "\033[2J\033[H"
)
Watch ANSI control.
Variables ¶
var ( ReplaceExcludedDirs = []string{".git", ".gitmap", ".release", "node_modules", "vendor"} // Path prefixes are matched against the path relative to repo root. ReplaceExcludedPrefixes = []string{".gitmap/release", ".gitmap/release-assets"} )
Replace exclusion sets. Directory names matched by base name only.
var ( // GitMapSubdir is the SOURCE-REPO subdirectory name (<RepoRoot>/gitmap/...). GitMapSubdir string // GitMapCliSubdir is the DEPLOY-TARGET subdirectory name // (<DeployRoot>/gitmap-cli/gitmap.exe). Renamed from "gitmap" in v3.6.0. // Sourced from deploy-manifest.json — never hardcode this string. GitMapCliSubdir string // LegacyAppSubdirs lists deploy-folder names from prior schema versions. // Migration code uses this to detect and rename old layouts. LegacyAppSubdirs []string )
GitMapSubdir, GitMapCliSubdir are populated from Manifest at init(). They remain `var` (not `const`) so the manifest is the only edit point.
var AutoTagMarkers = map[string]string{ ".git": AutoTagGit, "package.json": AutoTagNode, "go.mod": AutoTagGo, "pyproject.toml": AutoTagPython, "requirements.txt": AutoTagPython, "Cargo.toml": AutoTagRust, "Dockerfile": AutoTagDocker, "compose.yaml": AutoTagDocker, "compose.yml": AutoTagDocker, "docker-compose.yml": AutoTagDocker, }
AutoTagMarkers maps a top-level filesystem entry name to the tag it implies. Both files and directories qualify (.git can be either).
var AutoTagOrder = []string{ AutoTagGit, AutoTagNode, AutoTagGo, AutoTagPython, AutoTagRust, AutoTagDocker, }
AutoTagOrder is the canonical emission order. Tags not listed here are dropped (the detector never invents tags outside this list).
var CSVColumnAliases = map[string]string{ "url": CSVColumnURL, "urls": CSVColumnURL, "httpsurl": CSVColumnURL, "httpurl": CSVColumnURL, "giturl": CSVColumnURL, "repo": CSVColumnURL, "repourl": CSVColumnURL, "clone": CSVColumnURL, "cloneurl": CSVColumnURL, "dest": CSVColumnDest, "relpath": CSVColumnDest, "path": CSVColumnDest, "folder": CSVColumnDest, "dir": CSVColumnDest, "target": CSVColumnDest, "destpath": CSVColumnDest, "branch": CSVColumnBranch, "ref": CSVColumnBranch, "tag": CSVColumnBranch, "depth": CSVColumnDepth, "clonedepth": CSVColumnDepth, "checkout": CSVColumnCheckout, "checkoutmode": CSVColumnCheckout, "mode": CSVColumnCheckout, }
CSV header aliases for clone-from. Spreadsheets, copy-pasted docs, and hand-edited files in the wild use a handful of common variations for the same logical column ("URL" vs "httpsURL", "dest" vs "relpath", etc.). Rather than fail those files with an opaque "url column missing" error, we normalize them to the canonical column name before validation.
Rules:
- Lookup is case-insensitive — keys are stored lowercase and the header value is lowercased + trimmed before lookup.
- The canonical name itself is INTENTIONALLY included so callers can do a single map lookup with no fallback branch.
- Aliases must be unambiguous: a single alias may map to exactly one canonical column. Adding a conflicting alias is a bug.
Keep this list short and obvious. Exotic spellings should be fixed in the source CSV, not silently accepted here.
var CloneFromReportProvenance = []CloneFromReportProvenanceField{ {Field: "url", Stage: ProvenanceStageScan}, {Field: "dest", Stage: ProvenanceStageMapper}, {Field: "branch", Stage: ProvenanceStageScan}, {Field: "depth", Stage: ProvenanceStageScan}, {Field: "status", Stage: ProvenanceStageClonefrom}, {Field: "detail", Stage: ProvenanceStageClonefrom}, {Field: "duration_seconds", Stage: ProvenanceStageClonefrom}, }
CloneFromReportProvenance is the canonical field → stage mapping embedded under `provenance` in every JSON report. Order matches reportRowJSON's struct field order so a reader scanning the envelope sees provenance entries in the same order as the row columns. Adding a new row field MUST add a corresponding entry here; the test guard fails fast on omission.
var ClonePickAutoExclude = []string{
".git",
"node_modules",
"vendor",
"dist",
"build",
"__pycache__",
".venv",
"target",
}
ClonePickAutoExclude lists folder names auto-greyed in the picker and pre-unchecked even when matched by a glob. Override per-project via the `clonePick.autoExclude` config array.
Conservative defaults: things every developer wants out of sparse-checkouts almost always (build outputs, vendored deps, language caches). The list is small on purpose -- false positives here are silent data loss for the user.
var CsharpKeyFilePatterns = []string{
"global.json",
"nuget.config",
"Directory.Build.props",
"Directory.Build.targets",
"launchSettings.json",
"appsettings.json",
}
C# key file patterns.
var DefaultReleaseDir = GitMapDir + "/" + ReleaseDirName
DefaultReleaseDir is a var so tests can override it.
var FindNextKnownFlags = []string{ FindNextFlagScanFolder, FindNextFlagJSON, }
FindNextKnownFlags lists every flag find-next accepts. Used by the suggestion engine to compute "did you mean?" hints for typos and by the validator to detect unknown tokens. Order is irrelevant.
var GitStderrNoisePatterns = []string{
"LF will be replaced by CRLF the next time Git touches it",
}
GitStderrNoisePatterns lists substrings whose presence in a git stderr line marks the line as harmless cosmetic chatter that the release pipeline should suppress. Add ONLY substrings that are guaranteed to not appear in a real error — these lines are silently dropped.
var GoModExcludeDirs = []string{".git", "vendor", "node_modules"}
GoMod excluded directories during file walk.
var HelpGroupKeys = []string{
"scanning",
"cloning",
"gitops",
"navigation",
"release",
"release-info",
"data",
"history",
"amend",
"project",
"ssh",
"zip",
"environment",
"tasks",
"visualization",
"commit-transfer",
"utilities",
}
HelpGroupKeys returns short keywords for tab-completion of group filtering.
var InstallToolCategories = map[string][]string{ ToolCategoryCore: { ToolVSCode, ToolNodeJS, ToolYarn, ToolBun, ToolPnpm, ToolPython, ToolGo, ToolGit, ToolGitLFS, ToolGHCLI, ToolGitHubDesktop, ToolCPP, ToolPHP, ToolPowerShell, ToolChocolatey, ToolWinget, ToolDbeaver, ToolOBS, ToolStickyNotes, ToolVSCodeCtx, ToolPwshCtx, ToolNpp, ToolNppSettings, ToolNppInstall, ToolVSCodeSync, ToolOBSSync, ToolWTSync, ToolScripts, ToolAllDevTools, }, ToolCategoryDatabase: { ToolMySQL, ToolMariaDB, ToolPostgreSQL, ToolSQLite, ToolMongoDB, ToolCouchDB, ToolRedis, ToolCassandra, ToolNeo4j, ToolElasticsearch, ToolDuckDB, ToolLiteDB, }, }
InstallToolCategories groups tools by category for display.
var InstallToolDescriptions = map[string]string{ ToolVSCode: "Visual Studio Code editor", ToolNodeJS: "Node.js JavaScript runtime", ToolYarn: "Yarn package manager", ToolBun: "Bun JavaScript runtime", ToolPnpm: "pnpm package manager", ToolPython: "Python programming language", ToolGo: "Go programming language", ToolGit: "Git version control", ToolGitLFS: "Git Large File Storage", ToolGHCLI: "GitHub CLI", ToolGitHubDesktop: "GitHub Desktop application", ToolCPP: "C++ compiler (MinGW/g++)", ToolPHP: "PHP programming language", ToolPowerShell: "PowerShell shell", ToolChocolatey: "Chocolatey package manager", ToolWinget: "Winget package manager", ToolMySQL: "MySQL relational database", ToolMariaDB: "MariaDB (MySQL-compatible fork)", ToolPostgreSQL: "PostgreSQL relational database", ToolSQLite: "SQLite embedded database", ToolMongoDB: "MongoDB document database", ToolCouchDB: "CouchDB document database (REST API)", ToolRedis: "Redis in-memory key-value store", ToolCassandra: "Apache Cassandra wide-column NoSQL", ToolNeo4j: "Neo4j graph database", ToolElasticsearch: "Elasticsearch search and analytics", ToolDuckDB: "DuckDB analytical columnar database", ToolDbeaver: "DBeaver database management tool", ToolStickyNotes: "Microsoft Sticky Notes", ToolLiteDB: "LiteDB embedded NoSQL database for .NET", ToolOBS: "OBS Studio screen recorder and streamer", ToolVSCodeCtx: "Add VS Code to Windows right-click context menu", ToolPwshCtx: "Add PowerShell to Windows right-click context menu", ToolAllDevTools: "Install all core developer tools at once", ToolNpp: "NPP + Settings -- Notepad++ with settings", ToolNppSettings: "NPP Settings -- Notepad++ settings sync only", ToolNppInstall: "Install NPP -- Notepad++ install only (no settings)", ToolVSCodeSync: "VS Code Settings -- sync VS Code settings and extensions", ToolOBSSync: "OBS Settings -- sync OBS Studio profiles and scenes", ToolWTSync: "WT Settings -- sync Windows Terminal settings.json", ToolScripts: "Clone gitmap scripts to local folder", }
Tool display names for --list output.
var LatestBranchCSVHeaders = []string{
"branch", "remote", "sha", "commitDate", "subject", "ref",
}
var LatestBranchTableColumns = []string{
"DATE", "BRANCH", "SHA", "SUBJECT",
}
Latest-branch terminal table header columns.
var ProjectExcludeDirs = []string{
"node_modules",
"vendor",
".git",
"dist",
"build",
"target",
"bin",
"obj",
"out",
"testdata",
"packages",
".venv",
".cache",
".next",
".nuxt",
".svelte-kit",
".turbo",
".parcel-cache",
".angular",
"coverage",
".nyc_output",
"__pycache__",
".pytest_cache",
".mypy_cache",
".ruff_cache",
".tox",
".gradle",
".idea",
".vs",
".vscode-test",
".terraform",
".serverless",
"tmp",
"temp",
"logs",
"Pods",
"DerivedData",
"wp-content",
"wp-admin",
"wp-includes",
"uploads",
}
Project detection exclusion directories.
These directories are skipped during in-repo project detection walks. Skipping noisy/generated trees (especially node_modules, .git, vendored caches, and CMS upload trees) is the single most important factor in keeping `gitmap scan` fast on real-world projects — a WordPress repo can easily contain 100k+ files under wp-content alone.
var ReactIndicatorDeps = []string{
"react",
"@types/react",
"react-scripts",
"next",
"gatsby",
"remix",
"@remix-run/react",
}
React indicator dependencies.
var RepoPath = ""
RepoPath is set at build time via -ldflags.
var ScanCSVHeaders = []string{
"repoName", "httpsUrl", "sshUrl", "branch", "branchSource",
"relativePath", "absolutePath", "cloneInstruction", "notes", "depth",
"repoId", "discoveredUrl", "transport",
}
CSV headers.
Schema bumps (additive only, append at end so legacy parsers that index columns positionally still see the original layout):
- v0: 8 cols (no branchSource, no depth).
- +branchSource: 9 cols.
- +depth: 10 cols.
- +repoId, +discoveredUrl: 12 cols. repoId is the stable transport-neutral identifier; discoveredUrl is the raw `git remote get-url origin` value, kept verbatim so consumers can audit normalization done into httpsUrl/sshUrl.
- +transport: 13 cols (current). Three-bucket collapse of the discovered remote: "ssh" | "https" | "other". Lets users filter clones by transport with a one-liner without re-deriving the bucket from raw URLs in every consumer. Mirrors the same three buckets clone-from's terminal summary uses (TransportTally).
var SelfInstallProfileModes = SelfInstallShellModes
SelfInstallProfileModes is the back-compat alias kept for existing references in selfinstall.go and tests.
var SelfInstallShellModes = []string{ShellModeAuto, ShellModeBoth, ShellModeZsh, ShellModeBash, ShellModePwsh, ShellModeFish}
SelfInstallShellModes lists the singleton (non-combo) values accepted by --shell-mode. Combos are validated by splitting on ShellModeComboSep and checking each token against this list.
SelfInstallProfileModes is the back-compat alias kept for existing references in selfinstall.go and tests. Single-line initializer (NOT a `var (...)` block) so the constants-collision linter does not misread the indented `ShellMode*,` element lines as new top-level var declarations duplicating the const names above.
var StatusTableColumns = []string{
"REPO", "STATUS", "SYNC", "BRANCH", "STASH", "FILES",
}
Status table column headers.
var WatchTableColumns = []string{
"REPO", "STATUS", "BRANCH", "AHEAD", "BEHIND", "STASH",
}
Watch table column headers.
Functions ¶
func CanonicalCSVColumn ¶
CanonicalCSVColumn returns the canonical column name for a raw header cell, or "" if the header is unknown. Caller is responsible for skipping unknown columns silently — extra columns must not cause a hard parse failure.
Types ¶
type CloneFromReportProvenanceField ¶
CloneFromReportProvenanceField is one entry in the ordered provenance list. Public so tests and the JSON-Schema emitter can iterate it without re-deriving the mapping.
type DeployManifest ¶
type DeployManifest struct {
SchemaVersion int `json:"schemaVersion"`
AppSubdir string `json:"appSubdir"`
LegacyAppSubdirs []string `json:"legacyAppSubdirs"`
BinaryName struct {
Windows string `json:"windows"`
Unix string `json:"unix"`
} `json:"binaryName"`
SourceRepoSubdir string `json:"sourceRepoSubdir"`
}
DeployManifest mirrors the on-disk JSON layout. Keep field names in sync with gitmap/constants/deploy-manifest.json.
var Manifest DeployManifest
Manifest is the parsed deploy manifest, loaded once at package init.
type SettingType ¶
type SettingType string
SettingType enum (stored as a TEXT discriminator on each Setting key).
The current Setting table is keyed by Key (TEXT PK) and stores values as TEXT, so we don't need a separate SettingTypes table — the type lives in code as the SettingType const block. Each new key MUST declare a type so downstream tooling (db inspect, future migrations) can route by category without parsing the JSON value.
const ( SettingTypeDownloaderConfig SettingType = "DownloaderConfig" SettingTypeDatabaseVersion SettingType = "DatabaseVersion" SettingTypeSystemConfig SettingType = "SystemConfig" )
Source Files
¶
- constants.go
- constants_alias.go
- constants_amend.go
- constants_archive.go
- constants_as.go
- constants_assets.go
- constants_autocommit.go
- constants_bookmark.go
- constants_cd.go
- constants_changelog.go
- constants_cleancode.go
- constants_cli.go
- constants_clone.go
- constants_clone_audit.go
- constants_clone_concurrency.go
- constants_clone_term.go
- constants_clonefixrepo.go
- constants_clonefrom.go
- constants_clonefrom_csvaliases.go
- constants_clonefrom_csvcolumns.go
- constants_clonefrom_provenance.go
- constants_clonefrom_schema.go
- constants_clonefrom_summary.go
- constants_clonenext.go
- constants_clonenow.go
- constants_clonepick.go
- constants_clonepick_store.go
- constants_commitin.go
- constants_commitin_sql.go
- constants_committransfer.go
- constants_completion.go
- constants_compress.go
- constants_dashboard.go
- constants_dbmigrate.go
- constants_diff.go
- constants_diffprofile.go
- constants_doctor.go
- constants_downloader.go
- constants_env.go
- constants_export.go
- constants_find_next.go
- constants_fixrepo.go
- constants_fixrepohelp.go
- constants_git.go
- constants_globalflags.go
- constants_gomod.go
- constants_hau.go
- constants_helpdashboard.go
- constants_helpgroups.go
- constants_helpsections.go
- constants_hints.go
- constants_history.go
- constants_historyrewrite.go
- constants_import.go
- constants_install.go
- constants_installedtools.go
- constants_llmdocs.go
- constants_lockcheck.go
- constants_messages.go
- constants_movemerge.go
- constants_multigroup.go
- constants_pathsnippet.go
- constants_pending_task.go
- constants_pending_task_msg.go
- constants_pending_task_sql.go
- constants_probe.go
- constants_profile.go
- constants_project.go
- constants_project_sql.go
- constants_prune.go
- constants_pull.go
- constants_reinstall.go
- constants_release.go
- constants_releasealias.go
- constants_releasepull.go
- constants_replace.go
- constants_scan_folder.go
- constants_selfinstall.go
- constants_seo.go
- constants_settings.go
- constants_ssh.go
- constants_startup.go
- constants_startup_winregistry.go
- constants_stats.go
- constants_store.go
- constants_task.go
- constants_templates_cli.go
- constants_temprelease.go
- constants_terminal.go
- constants_transaction.go
- constants_transaction_action.go
- constants_tui.go
- constants_update.go
- constants_v331.go
- constants_version_history.go
- constants_version_history_cmd.go
- constants_visibility.go
- constants_vscode.go
- constants_vscode_pm.go
- constants_vscode_pm_autotags.go
- constants_vscode_pm_sql.go
- constants_vscode_workspace.go
- constants_watch.go
- constants_zipgroup.go
- deploy_manifest.go