Some checks are pending
check / check (pull_request) Blocked by required conditions
Add the canonical .golangci.yml (v2 layout, default: all with the standard disable list) and pin golangci-lint v2.12.2 in the Makefile deps target using the v2 module path, replacing the @latest install on the old v1 path. The Dockerfile lint stage already pinned the v2.12.2 alpine image by digest and is unchanged. Fix all issues surfaced by the strict config: - err113: introduce wrapped static sentinel errors - gocognit/funlen/nestif: split ExtractDay, Run, DumpAndCompress, VerifyOutput, and the CLI flag parsing into smaller helpers - noctx: use ExecContext/QueryContext/BeginTx and CommandContext - noinlineerr: replace inline if-err assignments with plain ones - wsl_v5/nlreturn: add required blank lines - lll: wrap long lines and SQL strings - gosec: filepath.Clean on file open/create; bounded uint64 conversion in CheckFreeSpace; named output dir permission constant - mnd: use unix.FADV_* constants and named size constants - revive: add package and exported symbol comments - testpackage/paralleltest: move smoke test to bsdaily_test with t.Parallel() - nonamedreturns: drop non-error named returns The remaining nolint directives (gosec subprocess launches with internal paths, unqueryvet full-row SELECT * copies whose schema is defined by the source database) are each justified inline.
73 lines
1.5 KiB
Go
73 lines
1.5 KiB
Go
package bsdaily
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"log/slog"
|
|
"os"
|
|
"path/filepath"
|
|
"sort"
|
|
"time"
|
|
)
|
|
|
|
var errNoSnapshots = errors.New("no daily snapshots found")
|
|
|
|
// FindLatestDailySnapshot locates the newest daily ZFS snapshot that
|
|
// contains the firehose database and returns its directory and date.
|
|
func FindLatestDailySnapshot() (string, time.Time, error) {
|
|
entries, err := os.ReadDir(SnapshotBase)
|
|
if err != nil {
|
|
return "", time.Time{}, fmt.Errorf(
|
|
"reading snapshot directory %s: %w", SnapshotBase, err)
|
|
}
|
|
|
|
type snapshot struct {
|
|
name string
|
|
date time.Time
|
|
}
|
|
|
|
var snapshots []snapshot
|
|
|
|
for _, e := range entries {
|
|
if !e.IsDir() {
|
|
continue
|
|
}
|
|
|
|
m := snapshotPattern.FindStringSubmatch(e.Name())
|
|
if m == nil {
|
|
continue
|
|
}
|
|
|
|
d, perr := time.Parse("2006-01-02", m[1])
|
|
if perr != nil {
|
|
slog.Warn("skipping snapshot with unparseable date",
|
|
"name", e.Name(), "error", perr)
|
|
|
|
continue
|
|
}
|
|
|
|
snapshots = append(snapshots, snapshot{name: e.Name(), date: d})
|
|
}
|
|
|
|
if len(snapshots) == 0 {
|
|
return "", time.Time{}, fmt.Errorf("%w in %s", errNoSnapshots, SnapshotBase)
|
|
}
|
|
|
|
sort.Slice(snapshots, func(i, j int) bool {
|
|
return snapshots[i].date.After(snapshots[j].date)
|
|
})
|
|
|
|
latest := snapshots[0]
|
|
dir := filepath.Join(SnapshotBase, latest.name)
|
|
|
|
dbPath := filepath.Join(dir, DBFilename)
|
|
|
|
_, err = os.Stat(dbPath)
|
|
if err != nil {
|
|
return "", time.Time{}, fmt.Errorf(
|
|
"database not found in snapshot %s: %w", dir, err)
|
|
}
|
|
|
|
return dir, latest.date, nil
|
|
}
|