versionroute

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Apr 24, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package versionroute selects the per-quarter crdb-sql backend that matches the user's --target-version and re-execs into it. CockroachDB releases follow Year.Quarter.Patch (e.g. 25.4.0), and parser behavior can change between quarters; this package is the router that turns "the user asked for 25.4" into "exec crdb-sql-v254".

Layout: a single crdb-sql distribution ships one latest binary (crdb-sql) plus optional per-quarter siblings (crdb-sql-v251, crdb-sql-v262, ...). MaybeReexec, called from main as the very first action, scans os.Args for --target-version, computes the requested Quarter, compares it to the binary's compiled Quarter, and execs the matching sibling on a mismatch. Missing sibling is a hard error — silent fallback to the wrong parser is the bug this package exists to prevent.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FindBackend

func FindBackend(want Quarter) (string, bool)

FindBackend locates a sibling backend matching want. The search order matches Discover (executable's directory first, then $PATH); the first match wins. Returns ("", false) when no match exists.

Callers in MaybeReexec use the returned path to syscall.Exec (or the Windows equivalent). The path is always absolute when found.

func MaybeReexec

func MaybeReexec()

MaybeReexec inspects os.Args for a --target-version, and if it requests a different Year.Quarter than the running binary, locates the matching sibling backend and re-execs into it. This must be the first call in main() — before flag parsing, builtin registration, or any work that depends on the parser version. Routing earlier guarantees the eventual cobra/parsing pipeline runs in the correct per-quarter binary.

On a successful re-exec the call does not return (the process is replaced on Unix, or this process exits with the child's status on Windows). On a routing-not-needed outcome (no flag, malformed flag, matching quarter, or unstamped binary) the function returns and main() proceeds normally.

On a routing-needed-but-impossible outcome (sibling missing) the function writes a discovery-hint message to stderr and exits with status 2. Silent fallback to the wrong parser would defeat the reason this package exists.

func StampDiagnostic

func StampDiagnostic() string

StampDiagnostic returns a non-empty string when builtQuarterStamp was set at build time but does not parse as a Quarter tag. The returned string is suitable for one-line stderr output. Returns "" when the stamp is absent or valid (the common cases).

MaybeReexec emits this diagnostic before any routing decision so operators see the build-pipeline bug directly rather than through the second-order symptom of a confusing missing-backend error.

Types

type Backend

type Backend struct {
	// Quarter is the parsed Year.Quarter the backend is built against.
	// May be the zero value for the running binary when no stamp and
	// no parser dep are available; sibling entries always have a
	// valid Quarter (their filename was the source of truth).
	Quarter Quarter
	// Path is the absolute filesystem path to the binary. Always
	// populated for entries that appear in Discover's output —
	// selfBackend skips the running binary entirely if os.Executable
	// fails, so a Backend with an empty Path is never produced.
	Path string
	// IsSelf is true for the entry that represents the currently
	// running binary. The discovery walk skips Path-equal duplicates
	// elsewhere in the search order so each backend appears at most
	// once per Discover call.
	IsSelf bool
}

Backend describes one discovered crdb-sql backend on the host. It is returned by Discover and consumed by both the routing logic (FindBackend) and the `versions` subcommand.

func Discover

func Discover() []Backend

Discover enumerates every crdb-sql-vXXX backend reachable from the current process: the running binary itself, any sibling alongside it, and any matching binaries on $PATH. Results are sorted by Quarter (newest first) so the `versions` subcommand can print them directly.

Duplicates (same absolute path discovered via two search-path entries) are coalesced; the first occurrence wins. Sibling shadowing: if two siblings carry the same Quarter (e.g. one in $PATH and one alongside the binary), the first wins by search order, which mirrors how the OS resolves command names. The self entry claims its own Quarter the same way, so a sibling with the same Quarter as the running binary is suppressed.

The running binary is included with IsSelf=true whenever os.Executable() succeeds (the common case on supported platforms). On the rare failure, no self entry is produced and the result contains only siblings; the missing-backend error path documents the expected non-empty case.

type Quarter

type Quarter struct {
	Year int
	Q    int
}

Quarter identifies a CockroachDB quarterly release. Year is the year suffix (e.g. 25 for 2025) and Q is the quarter ordinal in 1..4. The zero value is the sentinel for "no quarter known" (e.g. an unstamped local build whose parser dep is missing from BuildInfo).

Construct non-zero values via MakeQuarter, ParseFromTarget, ParseTag, or parseForkVersion — those are the only producers that enforce the year>=1 / 1<=Q<=4 invariant. The fields are exported for ergonomic reads (comparison, map keys) but a caller writing a literal struct is responsible for validity; the formatter methods (String, Tag, BackendName) handle the zero value cleanly but make no other claims for out-of-range fields.

func Built

func Built() (Quarter, bool)

Built returns the Quarter this binary represents. Resolution order:

  1. Filename. A binary installed as `crdb-sql-v254[.exe]` declares its quarter via the suffix, and the filename is authoritative over any compiled-in stamp. This makes routing self-consistent under copies/renames (e.g. a hand-installed sibling) and prevents exec loops where a binary stamped v262 sits on disk as crdb-sql-v251 and tries to exec "itself" forever.
  2. Build-time ldflag stamp (builtQuarterStamp), set by the `make build` / `make build-vXXX` targets. This covers the unsuffixed latest binary (`crdb-sql`), whose filename carries no quarter info.
  3. BuildInfo fallback for unstamped local builds (`go run`, `go build` results without ldflag stamping). `go test` binaries typically have no parser dep recorded in BuildInfo, so this branch returns (zero, false) under tests — which is the correct outcome (tests don't route).

Returns (zero, false) when no source yields a usable Quarter. Callers that need to know *why* the answer is zero (specifically to distinguish "no info" from "stamp is malformed and should be fixed") should consult StampDiagnostic afterward.

func MakeQuarter

func MakeQuarter(year, q int) (Quarter, error)

MakeQuarter constructs a Quarter and validates that year>=1 and 1<=q<=4. Returns the zero Quarter and a non-nil error on bad input. Use this wherever a Quarter is built from numeric inputs that have not already been validated by one of the parsers; the parsers themselves route through here so all Quarter construction sites share one enforcement point.

func ParseFromTarget

func ParseFromTarget(s string) (Quarter, bool)

ParseFromTarget extracts the Quarter from a --target-version value. Accepted shapes mirror output.ValidateTargetVersion: MAJOR.MINOR or MAJOR.MINOR.PATCH, optionally prefixed with a single 'v'. Only the MAJOR (Year) and MINOR (Quarter) components affect routing — patch is ignored.

Returns (zero, false) on any parse failure. MaybeReexec must remain permissive on bad input: this code runs before cobra's flag parser, and a malformed --target-version will surface a structured error from cobra later. We must not panic or print here.

func ParseTag

func ParseTag(s string) (Quarter, bool)

ParseTag is the inverse of Quarter.Tag. It accepts a binary-suffix form ("v254" or "254") and returns the parsed Quarter. Used by discovery when scanning filenames in $PATH or the install dir.

Returns (zero, false) for any string that is not exactly an optional 'v' followed by a Year.Quarter pair where each component fits the constraints in ParseFromTarget. The expected layout is 1-2 digits of Year followed by exactly one quarter digit (1-4), because real CRDB versions never use Q=0 or Q>4.

func (Quarter) BackendName

func (q Quarter) BackendName() string

BackendName returns the on-disk backend filename for this quarter (e.g. "crdb-sql-v254"). For the zero value returns "crdb-sql" (the unsuffixed latest binary), so callers can use this method uniformly when rendering discovery rows. Do not append a platform suffix here; callers add ".exe" on Windows via execSuffix.

func (Quarter) IsZero

func (q Quarter) IsZero() bool

IsZero reports whether q is the zero value, used as a sentinel for "no quarter known" (e.g. when the binary was built without a stamp and BuildInfo lacks the parser dep).

func (Quarter) String

func (q Quarter) String() string

String returns the human-readable form (e.g. "25.4"), or "unknown" for the zero value. Used in error messages and discovery output; callers do not need to gate on IsZero before invoking it.

func (Quarter) Tag

func (q Quarter) Tag() string

Tag returns the binary-suffix form used in filenames and ldflag stamps (e.g. "v254"), or "" for the zero value. This is the canonical short identifier that appears in crdb-sql-v254, build/go.v254.mod, and the builtQuarterStamp ldflag.

Jump to

Keyboard shortcuts

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