Documentation
¶
Overview ¶
Package selfupdate implements install-method detection, release resolution, download + checksum verification, and atomic executable replacement for the `ingitdb self-update` command.
Index ¶
- Constants
- func AssetName(version, goos, goarch string) string
- func CompareVersions(a, b string) int
- func ManagerName(m Manager) string
- func ReplaceExecutable(targetPath, newBinaryPath string) error
- func UpgradeCommand(m Manager) (string, bool)
- func VerifyBinaryVersion(path, wantVersion string) error
- type CheckResult
- type Detection
- type Downloader
- type InstallMethod
- type Manager
- type Resolver
- type Verdict
Constants ¶
const DevVersion = "dev"
DevVersion is the placeholder reported by binaries built without -ldflags.
Variables ¶
This section is empty.
Functions ¶
func AssetName ¶
AssetName builds the GoReleaser archive name for the given version and target OS/arch. The version's leading "v" is stripped to match GoReleaser's name_template ("ingitdb_{Version}_{os}_{arch}"). Windows uses .zip; all other platforms use .tar.gz.
func CompareVersions ¶
CompareVersions orders two semver-ish version strings, returning -1 if a < b, 0 if they are equal, and +1 if a > b. A leading "v" is ignored. Comparison is by numeric major/minor/patch; a prerelease suffix (after "-") sorts lower than the same release without it, per semver. This is a minimal comparison sufficient for the self-update downgrade guard, not a full semver implementation.
func ManagerName ¶
ManagerName returns a human-readable name for a manager, for display in the redirect message.
func ReplaceExecutable ¶
ReplaceExecutable atomically swaps the binary at newBinaryPath into targetPath. The new binary is first staged to a temp file in the same directory as targetPath (same filesystem, so os.Rename is atomic), with executable permissions (0755), then renamed over the target.
On POSIX, os.Rename within one directory atomically replaces the target — the install location is never left with a partial or truncated file: it holds either the original or the complete new binary. On Windows, a running .exe cannot be overwritten, so the existing target is first renamed aside to targetPath+".old" before the new binary is moved into place.
Any staging error before the rename returns the error and leaves targetPath untouched. Underlying os errors are wrapped with %w so callers can classify them (e.g. errors.Is(err, fs.ErrPermission)).
func UpgradeCommand ¶
UpgradeCommand returns the exact upgrade command a user should run for a package-manager-managed install, and true when m is a recognized manager. For ManagerNone or any unknown manager it returns ("", false).
ingitdb's managed distribution channels are the Homebrew cask and Snap.
func VerifyBinaryVersion ¶
VerifyBinaryVersion runs "<path> version" (the ingitdb version subcommand; the root command has no --version flag) and returns an error unless the command output contains wantVersion. It is kept separate from ReplaceExecutable so the swap and the post-swap sanity check are independently testable.
Types ¶
type CheckResult ¶
CheckResult captures the comparison between the current build and the latest stable release.
func Compare ¶
func Compare(current, latestTag string) CheckResult
Compare determines the verdict for a current build version against the latest stable release tag. A "dev" current version is Undetermined. Leading "v" prefixes are normalized before comparison.
type Detection ¶
type Detection struct {
Method InstallMethod
Manager Manager
}
Detection is the result of classifying an executable path.
func Classify ¶
Classify decides the install method purely from execPath. It is case-insensitive and treats both '/' and '\' as path separators so Windows paths can be tested on any host.
func DetectSelf ¶
DetectSelf resolves the running executable's path and classifies BOTH the raw (possibly symlink) path and its resolved target. The Homebrew cask installs a symlink in the brew prefix bin directory pointing into the Caskroom, so a managed classification on either path wins. When neither is managed, a manual classification on either path is accepted; otherwise the result is Ambiguous.
type Downloader ¶
type Downloader struct {
// BaseURL is the directory under which the release's assets and checksum
// files live. When empty, the versioned GitHub release download directory
// ("<defaultDownloadBaseURL>/v<version>") is used.
BaseURL string
// Client is the HTTP client used for requests. When nil, http.DefaultClient
// is used.
Client *http.Client
}
Downloader fetches and verifies release assets. BaseURL and Client are injectable so tests can target an httptest.Server.
func (Downloader) DownloadAndVerify ¶
func (d Downloader) DownloadAndVerify(ctx context.Context, version, goos, goarch string) (string, error)
DownloadAndVerify downloads the release asset matching the given version and target OS/arch, verifies its sha256 against the release's per-OS checksum file, and — only on a successful match — extracts the ingitdb binary into a temp file whose path is returned. When goos/goarch are empty, runtime.GOOS/GOARCH are used.
Verification happens before any extraction. On a checksum mismatch or a missing/unfetchable checksum entry, it returns a non-nil error and an empty path, having touched no executable. This function never writes to or replaces the running executable; the swap is a separate concern.
type InstallMethod ¶
type InstallMethod int
InstallMethod classifies how the running binary was installed.
const ( // Managed means a package manager owns the binary; self-update is not eligible. Managed InstallMethod = iota // Manual means the binary was placed by the user (release archive or go install); // self-replace is eligible. Manual // Ambiguous means the location does not clearly indicate either method. Ambiguous )
type Manager ¶
type Manager int
Manager identifies a package manager that owns a managed install.
const ( // ManagerNone means no package manager was detected. ManagerNone Manager = iota // Homebrew is the macOS/Linux Homebrew package manager. ingitdb is // distributed as a Homebrew cask, which installs the binary under a // Caskroom path and symlinks it into the brew prefix bin directory. Homebrew // Snap is the Linux snap package manager. Snap )
type Resolver ¶
type Resolver struct {
// BaseURL is the releases endpoint. When empty, defaultReleasesURL is used.
BaseURL string
// Client is the HTTP client used for requests. When nil, http.DefaultClient
// is used.
Client *http.Client
}
Resolver fetches release information from GitHub. The base URL and HTTP client are injectable so tests can target an httptest.Server.
func (Resolver) LatestStableTag ¶
LatestStableTag returns the tag of the newest non-prerelease, non-draft release. Releases are returned newest-first by the GitHub API; this skips prereleases and drafts and selects the first stable entry.