chore(gonf): fix errcheck and shadow errors

This commit is contained in:
Julien Dessaux 2024-05-01 16:23:08 +02:00
parent 72be13c3e9
commit 8b9195e3e3
Signed by: adyxax
GPG key ID: F92E51B86E07177E
15 changed files with 65 additions and 80 deletions

View file

@ -19,7 +19,7 @@ func cmdBuild(ctx context.Context,
where FLAG can be one or more of`, flag.ContinueOnError) where FLAG can be one or more of`, flag.ContinueOnError)
hostFlag := addHostFlag(f) hostFlag := addHostFlag(f)
f.SetOutput(stderr) f.SetOutput(stderr)
f.Parse(args) _ = f.Parse(args)
if helpMode { if helpMode {
f.SetOutput(stdout) f.SetOutput(stdout)
f.Usage() f.Usage()
@ -32,17 +32,23 @@ where FLAG can be one or more of`, flag.ContinueOnError)
return runBuild(ctx, stderr, hostDir) return runBuild(ctx, stderr, hostDir)
} }
func runBuild(ctx context.Context, stderr io.Writer, hostDir string) error { func runBuild(ctx context.Context, stderr io.Writer, hostDir string) (err error) {
wd, err := os.Getwd() wd, err := os.Getwd()
if err != nil { if err != nil {
return err return err
} }
defer os.Chdir(wd) defer func() {
os.Chdir(hostDir) if e := os.Chdir(wd); err == nil {
err = e
}
}()
if err = os.Chdir(hostDir); err != nil {
return err
}
cmd := exec.CommandContext(ctx, "go", "build", "-ldflags", "-s -w -extldflags \"-static\"", hostDir) cmd := exec.CommandContext(ctx, "go", "build", "-ldflags", "-s -w -extldflags \"-static\"", hostDir)
cmd.Env = append(cmd.Environ(), "CGO_ENABLED=0") cmd.Env = append(cmd.Environ(), "CGO_ENABLED=0")
if out, err := cmd.CombinedOutput(); err != nil { if out, err := cmd.CombinedOutput(); err != nil {
fmt.Fprint(stderr, string(out)) _, _ = fmt.Fprint(stderr, string(out))
return err return err
} }
return nil return nil

View file

@ -49,11 +49,13 @@ where FLAG can be one or more of`, flag.ContinueOnError)
f.BoolVar(&helpMode, "help", false, "show contextual help") f.BoolVar(&helpMode, "help", false, "show contextual help")
f.StringVar(&configDir, "config", "", "(REQUIRED for most commands) path to a gonf configurations repository (overrides the GONF_CONFIG environment variable)") f.StringVar(&configDir, "config", "", "(REQUIRED for most commands) path to a gonf configurations repository (overrides the GONF_CONFIG environment variable)")
f.SetOutput(stderr) f.SetOutput(stderr)
f.Parse(args[1:]) if err := f.Parse(args[1:]); err != nil {
return err
}
if f.NArg() < 1 { if f.NArg() < 1 {
f.Usage() f.Usage()
return errors.New("No command given") return errors.New("no command given")
} }
cmd := f.Arg(0) cmd := f.Arg(0)
argsTail := f.Args()[1:] argsTail := f.Args()[1:]
@ -68,7 +70,7 @@ where FLAG can be one or more of`, flag.ContinueOnError)
configDir = getenv("GONF_CONFIG") configDir = getenv("GONF_CONFIG")
if configDir == "" { if configDir == "" {
f.Usage() f.Usage()
return errors.New("The GONF_CONFIG environment variable is unset and the -config FLAG is missing. Please use one or the other.") return errors.New("the GONF_CONFIG environment variable is unset and the -config FLAG is missing. Please use one or the other")
} }
} }
switch cmd { switch cmd {
@ -76,7 +78,7 @@ where FLAG can be one or more of`, flag.ContinueOnError)
return cmdBuild(ctx, f, argsTail, getenv, stdout, stderr) return cmdBuild(ctx, f, argsTail, getenv, stdout, stderr)
default: default:
f.Usage() f.Usage()
return fmt.Errorf("Invalid command: %s", cmd) return fmt.Errorf("invalid command: %s", cmd)
} }
} }
return nil return nil

View file

@ -6,15 +6,12 @@ import (
"os/exec" "os/exec"
) )
// ----- Globals ---------------------------------------------------------------
var commands []*CommandPromise var commands []*CommandPromise
// ----- Init ------------------------------------------------------------------
func init() { func init() {
commands = make([]*CommandPromise, 0) commands = make([]*CommandPromise, 0)
} }
// ----- Public ----------------------------------------------------------------
func Command(cmd string, args ...string) *CommandPromise { func Command(cmd string, args ...string) *CommandPromise {
return CommandWithEnv([]string{}, cmd, args...) return CommandWithEnv([]string{}, cmd, args...)
} }
@ -81,7 +78,6 @@ func (c CommandPromise) Status() Status {
return c.status return c.status
} }
// ----- Internal --------------------------------------------------------------
func resolveCommands() (status Status) { func resolveCommands() (status Status) {
status = KEPT status = KEPT
for _, c := range commands { for _, c := range commands {

View file

@ -11,15 +11,12 @@ import (
"path/filepath" "path/filepath"
) )
// ----- Globals ---------------------------------------------------------------
var files []*FilePromise var files []*FilePromise
// ----- Init ------------------------------------------------------------------
func init() { func init() {
files = make([]*FilePromise, 0) files = make([]*FilePromise, 0)
} }
// ----- Public ----------------------------------------------------------------
type FilePromise struct { type FilePromise struct {
chain []Promise chain []Promise
contents Value contents Value
@ -62,7 +59,6 @@ func (f *FilePromise) Template(contents any) *FilePromise {
return f return f
} }
// We want to satisfy the Promise interface
func (f *FilePromise) IfRepaired(p ...Promise) Promise { func (f *FilePromise) IfRepaired(p ...Promise) Promise {
f.chain = append(f.chain, p...) f.chain = append(f.chain, p...)
return f return f
@ -127,7 +123,6 @@ func (f FilePromise) Status() Status {
return f.status return f.status
} }
// ----- Internal --------------------------------------------------------------
func resolveFiles() (status Status) { func resolveFiles() (status Status) {
status = KEPT status = KEPT
for _, f := range files { for _, f := range files {
@ -144,12 +139,16 @@ func resolveFiles() (status Status) {
return return
} }
func sha256sumOfFile(filename string) ([]byte, error) { func sha256sumOfFile(filename string) (hash []byte, err error) {
f, err := os.Open(filename) f, err := os.Open(filename)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer f.Close() defer func() {
if e := f.Close(); err == nil {
err = e
}
}()
h := sha256.New() h := sha256.New()
if _, err := io.Copy(h, f); err != nil { if _, err := io.Copy(h, f); err != nil {
return nil, err return nil, err
@ -157,12 +156,16 @@ func sha256sumOfFile(filename string) ([]byte, error) {
return h.Sum(nil), nil return h.Sum(nil), nil
} }
func writeFile(filename string, contents []byte) error { func writeFile(filename string, contents []byte) (err error) {
f, err := os.Create(filename) f, err := os.Create(filename)
if err != nil { if err != nil {
return err return err
} }
defer f.Close() defer func() {
if e := f.Close(); err == nil {
err = e
}
}()
_, err = f.Write(contents) _, err = f.Write(contents)
return err return err
} }

View file

@ -2,20 +2,16 @@ package gonf
import "log/slog" import "log/slog"
// ----- Globals ---------------------------------------------------------------
var packages []*PackagePromise var packages []*PackagePromise
// packages management functions var packagesInstallFunction func([]string) (Status, []string)
var packages_install_function func([]string) (Status, []string)
// ----- Init ------------------------------------------------------------------
func init() { func init() {
packages = make([]*PackagePromise, 0) packages = make([]*PackagePromise, 0)
} }
// ----- Public ----------------------------------------------------------------
func SetPackagesConfiguration(install func([]string) (Status, []string), update *CommandPromise) { func SetPackagesConfiguration(install func([]string) (Status, []string), update *CommandPromise) {
packages_install_function = install packagesInstallFunction = install
} }
func Package(names ...string) *PackagePromise { func Package(names ...string) *PackagePromise {
@ -45,7 +41,7 @@ func (p *PackagePromise) Promise() Promise {
} }
func (p *PackagePromise) Resolve() { func (p *PackagePromise) Resolve() {
status, affected := packages_install_function(p.names) status, affected := packagesInstallFunction(p.names)
switch status { switch status {
case BROKEN: case BROKEN:
slog.Error("package", "names", p.names, "status", status, "broke", affected) slog.Error("package", "names", p.names, "status", status, "broke", affected)
@ -63,7 +59,6 @@ func (p PackagePromise) Status() Status {
return p.status return p.status
} }
// ----- Internal --------------------------------------------------------------
func resolvePackages() (status Status) { func resolvePackages() (status Status) {
status = KEPT status = KEPT
for _, c := range packages { for _, c := range packages {

View file

@ -29,10 +29,10 @@ func (p *Permissions) resolve(filename string) (Status, error) {
if group, err := user.LookupGroup(p.group.String()); err != nil { if group, err := user.LookupGroup(p.group.String()); err != nil {
return BROKEN, err return BROKEN, err
} else { } else {
if groupId, err := strconv.Atoi(group.Gid); err != nil { if groupID, err := strconv.Atoi(group.Gid); err != nil {
return BROKEN, err return BROKEN, err
} else { } else {
g = &IntValue{groupId} g = &IntValue{groupID}
p.group = g p.group = g
} }
} }
@ -46,10 +46,10 @@ func (p *Permissions) resolve(filename string) (Status, error) {
if user, err := user.Lookup(p.user.String()); err != nil { if user, err := user.Lookup(p.user.String()); err != nil {
return BROKEN, err return BROKEN, err
} else { } else {
if userId, err := strconv.Atoi(user.Uid); err != nil { if userID, err := strconv.Atoi(user.Uid); err != nil {
return BROKEN, err return BROKEN, err
} else { } else {
u = &IntValue{userId} u = &IntValue{userID}
p.group = u p.group = u
} }
} }

View file

@ -2,18 +2,14 @@ package gonf
import "log/slog" import "log/slog"
// ----- Globals ---------------------------------------------------------------
var services []*ServicePromise var services []*ServicePromise
// service management function
var serviceFunction func(string, string) (Status, error) var serviceFunction func(string, string) (Status, error)
// ----- Init ------------------------------------------------------------------
func init() { func init() {
services = make([]*ServicePromise, 0) services = make([]*ServicePromise, 0)
} }
// ----- Public ----------------------------------------------------------------
func SetServiceFunction(f func(string, string) (Status, error)) { func SetServiceFunction(f func(string, string) (Status, error)) {
serviceFunction = f serviceFunction = f
} }
@ -82,7 +78,6 @@ func (s ServicePromise) Status() Status {
return s.status return s.status
} }
// ----- Internal --------------------------------------------------------------
func resolveServices() (status Status) { func resolveServices() (status Status) {
status = KEPT status = KEPT
for _, c := range services { for _, c := range services {

View file

@ -7,17 +7,14 @@ import (
"text/template" "text/template"
) )
// ----- Globals ---------------------------------------------------------------
var templates *template.Template var templates *template.Template
// ----- Init ------------------------------------------------------------------
func init() { func init() {
templates = template.New("") templates = template.New("")
templates.Option("missingkey=error") templates.Option("missingkey=error")
templates.Funcs(builtinTemplateFunctions) templates.Funcs(builtinTemplateFunctions)
} }
// ----- Public ----------------------------------------------------------------
type TemplateValue struct { type TemplateValue struct {
contents []byte contents []byte
data string data string

View file

@ -4,20 +4,16 @@ import (
"log/slog" "log/slog"
) )
// ----- Globals ---------------------------------------------------------------
var users []*UserPromise var users []*UserPromise
// users management functions var userAddFunction func(data UserData) (Status, error)
var user_add_function func(data UserData) (Status, error)
// ----- Init ------------------------------------------------------------------
func init() { func init() {
users = make([]*UserPromise, 0) users = make([]*UserPromise, 0)
} }
// ----- Public ----------------------------------------------------------------
func SetUsersConfiguration(useradd func(data UserData) (Status, error)) { func SetUsersConfiguration(useradd func(data UserData) (Status, error)) {
user_add_function = useradd userAddFunction = useradd
} }
func User(data UserData) *UserPromise { func User(data UserData) *UserPromise {
@ -57,7 +53,7 @@ func (u *UserPromise) Promise() Promise {
func (u *UserPromise) Resolve() { func (u *UserPromise) Resolve() {
var err error var err error
u.status, err = user_add_function(u.data) u.status, err = userAddFunction(u.data)
switch u.status { switch u.status {
case BROKEN: case BROKEN:
slog.Error("user", "name", u.data.Name, "status", u.status, "error", err) slog.Error("user", "name", u.data.Name, "status", u.status, "error", err)
@ -77,7 +73,6 @@ func (u UserPromise) Status() Status {
return u.status return u.status
} }
// ----- Internal --------------------------------------------------------------
func resolveUsers() (status Status) { func resolveUsers() (status Status) {
status = KEPT status = KEPT
for _, c := range users { for _, c := range users {

View file

@ -28,15 +28,19 @@ func FilterSlice[T any](slice *[]T, predicate func(T) bool) {
func makeDirectoriesHierarchy(dir string, perms *Permissions) (Status, error) { func makeDirectoriesHierarchy(dir string, perms *Permissions) (Status, error) {
if _, err := os.Lstat(dir); err != nil { if _, err := os.Lstat(dir); err != nil {
if errors.Is(err, fs.ErrNotExist) { if errors.Is(err, fs.ErrNotExist) {
if status, err := makeDirectoriesHierarchy(filepath.Dir(dir), perms); err != nil { if _, err = makeDirectoriesHierarchy(filepath.Dir(dir), perms); err != nil {
return status, err return BROKEN, err
} }
m, err := perms.mode.Int() var m int
if err != nil { if m, err = perms.mode.Int(); err != nil {
return BROKEN, err
}
if err = os.Mkdir(dir, fs.FileMode(m)); err != nil {
return BROKEN, err
}
if _, err = perms.resolve(dir); err != nil {
return BROKEN, err return BROKEN, err
} }
os.Mkdir(dir, fs.FileMode(m))
perms.resolve(dir)
return REPAIRED, nil return REPAIRED, nil
} else { } else {
return BROKEN, err return BROKEN, err

View file

@ -47,7 +47,6 @@ func interfaceToTemplateValue(v any) Value {
panic(fmt.Sprintf("interfaceToTemplateValue cannot take type %T as argument. Value was %#v.", v, v)) panic(fmt.Sprintf("interfaceToTemplateValue cannot take type %T as argument. Value was %#v.", v, v))
} }
// ----- BytesValue ------------------------------------------------------------
type BytesValue struct { type BytesValue struct {
value []byte value []byte
} }
@ -62,7 +61,6 @@ func (b BytesValue) String() string {
return string(b.value[:]) return string(b.value[:])
} }
// ----- IntValue --------------------------------------------------------------
type IntValue struct { type IntValue struct {
value int value int
} }
@ -77,7 +75,6 @@ func (i IntValue) String() string {
return fmt.Sprint(i.value) return fmt.Sprint(i.value)
} }
// ----- StringsListValue ------------------------------------------------------
type StringsListValue struct { type StringsListValue struct {
value []string value []string
} }
@ -95,7 +92,6 @@ func (s StringsListValue) String() string {
return strings.Join(s.value, "\n") return strings.Join(s.value, "\n")
} }
// ----- StringValue -----------------------------------------------------------
type StringValue struct { type StringValue struct {
value string value string
} }

View file

@ -5,15 +5,12 @@ import (
"log/slog" "log/slog"
) )
// ----- Globals ---------------------------------------------------------------
var variables map[string]*VariablePromise var variables map[string]*VariablePromise
// ----- Init ------------------------------------------------------------------
func init() { func init() {
variables = make(map[string]*VariablePromise) variables = make(map[string]*VariablePromise)
} }
// ----- Public ----------------------------------------------------------------
func AppendVariable(name string, values ...string) *VariablePromise { func AppendVariable(name string, values ...string) *VariablePromise {
if v, ok := variables[name]; ok { if v, ok := variables[name]; ok {
if l, ok := v.value.(*StringsListValue); ok { if l, ok := v.value.(*StringsListValue); ok {
@ -66,7 +63,6 @@ type VariablePromise struct {
value Value value Value
} }
// We want VariablePromise to satisfy the Value interface
func (s VariablePromise) Bytes() []byte { func (s VariablePromise) Bytes() []byte {
return s.value.Bytes() return s.value.Bytes()
} }
@ -77,7 +73,6 @@ func (s VariablePromise) String() string {
return s.value.String() return s.value.String()
} }
// ----- Internal --------------------------------------------------------------
func getVariable(name string) string { func getVariable(name string) string {
if v, ok := variables[name]; ok { if v, ok := variables[name]; ok {
return v.value.String() return v.value.String()

View file

@ -14,10 +14,10 @@ import (
var packages map[string]string var packages map[string]string
func init() { func init() {
packages_list() packagesList()
} }
func packages_install(names []string) (gonf.Status, []string) { func packagesInstall(names []string) (gonf.Status, []string) {
gonf.FilterSlice(&names, func(n string) bool { gonf.FilterSlice(&names, func(n string) bool {
_, ok := packages[n] _, ok := packages[n]
return !ok return !ok
@ -28,11 +28,11 @@ func packages_install(names []string) (gonf.Status, []string) {
args := append([]string{"install", "-y", "--no-install-recommends"}, names...) args := append([]string{"install", "-y", "--no-install-recommends"}, names...)
cmd := gonf.CommandWithEnv([]string{"DEBIAN_FRONTEND=noninteractive", "LC_ALL=C"}, "apt-get", args...) cmd := gonf.CommandWithEnv([]string{"DEBIAN_FRONTEND=noninteractive", "LC_ALL=C"}, "apt-get", args...)
cmd.Resolve() cmd.Resolve()
packages_list() packagesList()
return cmd.Status(), names return cmd.Status(), names
} }
func packages_list() { func packagesList() {
packages = make(map[string]string) packages = make(map[string]string)
ecmd := exec.Command("dpkg-query", "-W") ecmd := exec.Command("dpkg-query", "-W")
out, err := ecmd.CombinedOutput() out, err := ecmd.CombinedOutput()

View file

@ -2,21 +2,22 @@ package debian
import ( import (
_ "embed" _ "embed"
"git.adyxax.org/adyxax/gonf/v2/pkg"
gonf "git.adyxax.org/adyxax/gonf/v2/pkg"
"git.adyxax.org/adyxax/gonf/v2/stdlib/os/linux" "git.adyxax.org/adyxax/gonf/v2/stdlib/os/linux"
"git.adyxax.org/adyxax/gonf/v2/stdlib/os/systemd" "git.adyxax.org/adyxax/gonf/v2/stdlib/os/systemd"
) )
//go:embed apt-norecommends //go:embed apt-norecommends
var apt_norecommends []byte var aptNoRecommends []byte
//go:embed sources.list //go:embed sources.list
var sources_list []byte var sourcesList []byte
func Promise() { func Promise() {
// ----- gonf -------------------------------------------------------------- // ----- gonf --------------------------------------------------------------
apt_update := gonf.Command("apt-get", "update", "-qq") aptUpdate := gonf.Command("apt-get", "update", "-qq")
gonf.SetPackagesConfiguration(packages_install, apt_update) gonf.SetPackagesConfiguration(packagesInstall, aptUpdate)
gonf.SetUsersConfiguration(linux.Useradd) gonf.SetUsersConfiguration(linux.Useradd)
// ----- systemd ----------------------------------------------------------- // ----- systemd -----------------------------------------------------------
systemd.Promise() systemd.Promise()
@ -27,12 +28,12 @@ func Promise() {
gonf.AppendVariable("debian-extra-sources", "# Extra sources") gonf.AppendVariable("debian-extra-sources", "# Extra sources")
gonf.File("/etc/apt/sources.list"). gonf.File("/etc/apt/sources.list").
Permissions(rootRO). Permissions(rootRO).
Template(sources_list). Template(sourcesList).
Promise(). Promise().
IfRepaired(apt_update) IfRepaired(aptUpdate)
gonf.File("/etc/apt/apt.conf.d/99_norecommends"). gonf.File("/etc/apt/apt.conf.d/99_norecommends").
DirectoriesPermissions(rootDir). DirectoriesPermissions(rootDir).
Permissions(rootRO). Permissions(rootRO).
Contents(apt_norecommends). Contents(aptNoRecommends).
Promise() Promise()
} }

View file

@ -8,7 +8,7 @@ import (
) )
func Promise() { func Promise() {
gonf.SetServiceFunction(systemd_service) gonf.SetServiceFunction(systemdService)
} }
func isEnabled(name string) bool { func isEnabled(name string) bool {
@ -33,7 +33,7 @@ func systemctlShow(name, field string) string {
return string(out[:len(out)-1]) // remove trailing '\n' and convert to string return string(out[:len(out)-1]) // remove trailing '\n' and convert to string
} }
func systemd_service(name, state string) (gonf.Status, error) { func systemdService(name, state string) (gonf.Status, error) {
switch state { switch state {
case "disabled": case "disabled":
if isEnabled(name) { if isEnabled(name) {