Pass logger around in a context
ci/woodpecker/push/woodpecker Pipeline was successful Details

This commit is contained in:
Elara 2023-10-06 14:21:12 -07:00
parent 1b8c05b257
commit d86776feb1
26 changed files with 246 additions and 269 deletions

View File

@ -23,11 +23,11 @@ import (
"path/filepath" "path/filepath"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"go.elara.ws/lure/internal/log" "go.elara.ws/lure/internal/config"
"go.elara.ws/lure/internal/osutils" "go.elara.ws/lure/internal/osutils"
"go.elara.ws/lure/internal/types" "go.elara.ws/lure/internal/types"
"go.elara.ws/lure/pkg/build" "go.elara.ws/lure/pkg/build"
"go.elara.ws/lure/internal/config" "go.elara.ws/lure/pkg/loggerctx"
"go.elara.ws/lure/pkg/manager" "go.elara.ws/lure/pkg/manager"
"go.elara.ws/lure/pkg/repos" "go.elara.ws/lure/pkg/repos"
) )
@ -54,12 +54,15 @@ var buildCmd = &cli.Command{
}, },
}, },
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
ctx := c.Context
log := loggerctx.From(ctx)
script := c.String("script") script := c.String("script")
if c.String("package") != "" { if c.String("package") != "" {
script = filepath.Join(config.GetPaths().RepoDir, c.String("package"), "lure.sh") script = filepath.Join(config.GetPaths(ctx).RepoDir, c.String("package"), "lure.sh")
} }
err := repos.Pull(c.Context, config.Config().Repos) err := repos.Pull(ctx, config.Config(ctx).Repos)
if err != nil { if err != nil {
log.Fatal("Error pulling repositories").Err(err).Send() log.Fatal("Error pulling repositories").Err(err).Send()
} }
@ -69,7 +72,7 @@ var buildCmd = &cli.Command{
log.Fatal("Unable to detect a supported package manager on the system").Send() log.Fatal("Unable to detect a supported package manager on the system").Send()
} }
pkgPaths, _, err := build.BuildPackage(c.Context, types.BuildOpts{ pkgPaths, _, err := build.BuildPackage(ctx, types.BuildOpts{
Script: script, Script: script,
Manager: mgr, Manager: mgr,
Clean: c.Bool("clean"), Clean: c.Bool("clean"),

9
fix.go
View File

@ -22,9 +22,9 @@ import (
"os" "os"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"go.elara.ws/lure/internal/log"
"go.elara.ws/lure/internal/config" "go.elara.ws/lure/internal/config"
"go.elara.ws/lure/internal/db" "go.elara.ws/lure/internal/db"
"go.elara.ws/lure/pkg/loggerctx"
"go.elara.ws/lure/pkg/repos" "go.elara.ws/lure/pkg/repos"
) )
@ -32,8 +32,11 @@ var fixCmd = &cli.Command{
Name: "fix", Name: "fix",
Usage: "Attempt to fix problems with LURE", Usage: "Attempt to fix problems with LURE",
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
ctx := c.Context
log := loggerctx.From(ctx)
db.Close() db.Close()
paths := config.GetPaths() paths := config.GetPaths(ctx)
log.Info("Removing cache directory").Send() log.Info("Removing cache directory").Send()
@ -49,7 +52,7 @@ var fixCmd = &cli.Command{
log.Fatal("Unable to create new cache directory").Err(err).Send() log.Fatal("Unable to create new cache directory").Err(err).Send()
} }
err = repos.Pull(c.Context, config.Config().Repos) err = repos.Pull(ctx, config.Config(ctx).Repos)
if err != nil { if err != nil {
log.Fatal("Error pulling repos").Err(err).Send() log.Fatal("Error pulling repos").Err(err).Send()
} }

16
info.go
View File

@ -22,13 +22,12 @@ import (
"fmt" "fmt"
"os" "os"
"go.elara.ws/lure/internal/log"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"go.elara.ws/lure/internal/cliutils" "go.elara.ws/lure/internal/cliutils"
"go.elara.ws/lure/internal/overrides"
"go.elara.ws/lure/internal/config" "go.elara.ws/lure/internal/config"
"go.elara.ws/lure/internal/overrides"
"go.elara.ws/lure/pkg/distro" "go.elara.ws/lure/pkg/distro"
"go.elara.ws/lure/pkg/loggerctx"
"go.elara.ws/lure/pkg/repos" "go.elara.ws/lure/pkg/repos"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )
@ -44,17 +43,20 @@ var infoCmd = &cli.Command{
}, },
}, },
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
ctx := c.Context
log := loggerctx.From(ctx)
args := c.Args() args := c.Args()
if args.Len() < 1 { if args.Len() < 1 {
log.Fatalf("Command info expected at least 1 argument, got %d", args.Len()).Send() log.Fatalf("Command info expected at least 1 argument, got %d", args.Len()).Send()
} }
err := repos.Pull(c.Context, config.Config().Repos) err := repos.Pull(ctx, config.Config(ctx).Repos)
if err != nil { if err != nil {
log.Fatal("Error pulling repositories").Err(err).Send() log.Fatal("Error pulling repositories").Err(err).Send()
} }
found, _, err := repos.FindPkgs(args.Slice()) found, _, err := repos.FindPkgs(ctx, args.Slice())
if err != nil { if err != nil {
log.Fatal("Error finding packages").Err(err).Send() log.Fatal("Error finding packages").Err(err).Send()
} }
@ -63,13 +65,13 @@ var infoCmd = &cli.Command{
os.Exit(1) os.Exit(1)
} }
pkgs := cliutils.FlattenPkgs(found, "show", c.Bool("interactive")) pkgs := cliutils.FlattenPkgs(ctx, found, "show", c.Bool("interactive"))
var names []string var names []string
all := c.Bool("all") all := c.Bool("all")
if !all { if !all {
info, err := distro.ParseOSRelease(c.Context) info, err := distro.ParseOSRelease(ctx)
if err != nil { if err != nil {
log.Fatal("Error parsing os-release file").Err(err).Send() log.Fatal("Error parsing os-release file").Err(err).Send()
} }

View File

@ -23,11 +23,11 @@ import (
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"go.elara.ws/lure/internal/cliutils" "go.elara.ws/lure/internal/cliutils"
"go.elara.ws/lure/internal/log"
"go.elara.ws/lure/internal/types"
"go.elara.ws/lure/pkg/build"
"go.elara.ws/lure/internal/config" "go.elara.ws/lure/internal/config"
"go.elara.ws/lure/internal/db" "go.elara.ws/lure/internal/db"
"go.elara.ws/lure/internal/types"
"go.elara.ws/lure/pkg/build"
"go.elara.ws/lure/pkg/loggerctx"
"go.elara.ws/lure/pkg/manager" "go.elara.ws/lure/pkg/manager"
"go.elara.ws/lure/pkg/repos" "go.elara.ws/lure/pkg/repos"
) )
@ -44,6 +44,9 @@ var installCmd = &cli.Command{
}, },
}, },
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
ctx := c.Context
log := loggerctx.From(ctx)
args := c.Args() args := c.Args()
if args.Len() < 1 { if args.Len() < 1 {
log.Fatalf("Command install expected at least 1 argument, got %d", args.Len()).Send() log.Fatalf("Command install expected at least 1 argument, got %d", args.Len()).Send()
@ -54,18 +57,18 @@ var installCmd = &cli.Command{
log.Fatal("Unable to detect a supported package manager on the system").Send() log.Fatal("Unable to detect a supported package manager on the system").Send()
} }
err := repos.Pull(c.Context, config.Config().Repos) err := repos.Pull(ctx, config.Config(ctx).Repos)
if err != nil { if err != nil {
log.Fatal("Error pulling repositories").Err(err).Send() log.Fatal("Error pulling repositories").Err(err).Send()
} }
found, notFound, err := repos.FindPkgs(args.Slice()) found, notFound, err := repos.FindPkgs(ctx, args.Slice())
if err != nil { if err != nil {
log.Fatal("Error finding packages").Err(err).Send() log.Fatal("Error finding packages").Err(err).Send()
} }
pkgs := cliutils.FlattenPkgs(found, "install", c.Bool("interactive")) pkgs := cliutils.FlattenPkgs(ctx, found, "install", c.Bool("interactive"))
build.InstallPkgs(c.Context, pkgs, notFound, types.BuildOpts{ build.InstallPkgs(ctx, pkgs, notFound, types.BuildOpts{
Manager: mgr, Manager: mgr,
Clean: c.Bool("clean"), Clean: c.Bool("clean"),
Interactive: c.Bool("interactive"), Interactive: c.Bool("interactive"),
@ -73,7 +76,8 @@ var installCmd = &cli.Command{
return nil return nil
}, },
BashComplete: func(c *cli.Context) { BashComplete: func(c *cli.Context) {
result, err := db.GetPkgs("true") log := loggerctx.From(c.Context)
result, err := db.GetPkgs(c.Context, "true")
if err != nil { if err != nil {
log.Fatal("Error getting packages").Err(err).Send() log.Fatal("Error getting packages").Err(err).Send()
} }
@ -96,6 +100,8 @@ var removeCmd = &cli.Command{
Usage: "Remove an installed package", Usage: "Remove an installed package",
Aliases: []string{"rm"}, Aliases: []string{"rm"},
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
log := loggerctx.From(c.Context)
args := c.Args() args := c.Args()
if args.Len() < 1 { if args.Len() < 1 {
log.Fatalf("Command remove expected at least 1 argument, got %d", args.Len()).Send() log.Fatalf("Command remove expected at least 1 argument, got %d", args.Len()).Send()

View File

@ -19,24 +19,25 @@
package cliutils package cliutils
import ( import (
"context"
"os" "os"
"strings" "strings"
"github.com/AlecAivazis/survey/v2" "github.com/AlecAivazis/survey/v2"
"go.elara.ws/lure/internal/log"
"go.elara.ws/lure/internal/pager"
"go.elara.ws/lure/internal/translations"
"go.elara.ws/lure/internal/config" "go.elara.ws/lure/internal/config"
"go.elara.ws/lure/internal/db" "go.elara.ws/lure/internal/db"
"go.elara.ws/lure/internal/pager"
"go.elara.ws/lure/internal/translations"
"go.elara.ws/lure/pkg/loggerctx"
) )
// YesNoPrompt asks the user a yes or no question, using def as the default answer // YesNoPrompt asks the user a yes or no question, using def as the default answer
func YesNoPrompt(msg string, interactive, def bool) (bool, error) { func YesNoPrompt(ctx context.Context, msg string, interactive, def bool) (bool, error) {
if interactive { if interactive {
var answer bool var answer bool
err := survey.AskOne( err := survey.AskOne(
&survey.Confirm{ &survey.Confirm{
Message: translations.Translator().TranslateTo(msg, config.Language()), Message: translations.Translator(ctx).TranslateTo(msg, config.Language(ctx)),
Default: def, Default: def,
}, },
&answer, &answer,
@ -50,13 +51,15 @@ func YesNoPrompt(msg string, interactive, def bool) (bool, error) {
// PromptViewScript asks the user if they'd like to see a script, // PromptViewScript asks the user if they'd like to see a script,
// shows it if they answer yes, then asks if they'd still like to // shows it if they answer yes, then asks if they'd still like to
// continue, and exits if they answer no. // continue, and exits if they answer no.
func PromptViewScript(script, name, style string, interactive bool) error { func PromptViewScript(ctx context.Context, script, name, style string, interactive bool) error {
log := loggerctx.From(ctx)
if !interactive { if !interactive {
return nil return nil
} }
scriptPrompt := translations.Translator().TranslateTo("Would you like to view the build script for", config.Language()) + " " + name scriptPrompt := translations.Translator(ctx).TranslateTo("Would you like to view the build script for", config.Language(ctx)) + " " + name
view, err := YesNoPrompt(scriptPrompt, interactive, false) view, err := YesNoPrompt(ctx, scriptPrompt, interactive, false)
if err != nil { if err != nil {
return err return err
} }
@ -67,13 +70,13 @@ func PromptViewScript(script, name, style string, interactive bool) error {
return err return err
} }
cont, err := YesNoPrompt("Would you still like to continue?", interactive, false) cont, err := YesNoPrompt(ctx, "Would you still like to continue?", interactive, false)
if err != nil { if err != nil {
return err return err
} }
if !cont { if !cont {
log.Fatal(translations.Translator().TranslateTo("User chose not to continue after reading script", config.Language())).Send() log.Fatal(translations.Translator(ctx).TranslateTo("User chose not to continue after reading script", config.Language(ctx))).Send()
} }
} }
@ -100,11 +103,12 @@ func ShowScript(path, name, style string) error {
// FlattenPkgs attempts to flatten the a map of slices of packages into a single slice // FlattenPkgs attempts to flatten the a map of slices of packages into a single slice
// of packages by prompting the user if multiple packages match. // of packages by prompting the user if multiple packages match.
func FlattenPkgs(found map[string][]db.Package, verb string, interactive bool) []db.Package { func FlattenPkgs(ctx context.Context, found map[string][]db.Package, verb string, interactive bool) []db.Package {
log := loggerctx.From(ctx)
var outPkgs []db.Package var outPkgs []db.Package
for _, pkgs := range found { for _, pkgs := range found {
if len(pkgs) > 1 && interactive { if len(pkgs) > 1 && interactive {
choice, err := PkgPrompt(pkgs, verb, interactive) choice, err := PkgPrompt(ctx, pkgs, verb, interactive)
if err != nil { if err != nil {
log.Fatal("Error prompting for choice of package").Send() log.Fatal("Error prompting for choice of package").Send()
} }
@ -117,7 +121,7 @@ func FlattenPkgs(found map[string][]db.Package, verb string, interactive bool) [
} }
// PkgPrompt asks the user to choose between multiple packages. // PkgPrompt asks the user to choose between multiple packages.
func PkgPrompt(options []db.Package, verb string, interactive bool) (db.Package, error) { func PkgPrompt(ctx context.Context, options []db.Package, verb string, interactive bool) (db.Package, error) {
if !interactive { if !interactive {
return options[0], nil return options[0], nil
} }
@ -129,7 +133,7 @@ func PkgPrompt(options []db.Package, verb string, interactive bool) (db.Package,
prompt := &survey.Select{ prompt := &survey.Select{
Options: names, Options: names,
Message: translations.Translator().TranslateTo("Choose which package to "+verb, config.Language()), Message: translations.Translator(ctx).TranslateTo("Choose which package to "+verb, config.Language(ctx)),
} }
var choice int var choice int
@ -143,14 +147,14 @@ func PkgPrompt(options []db.Package, verb string, interactive bool) (db.Package,
// ChooseOptDepends asks the user to choose between multiple optional dependencies. // ChooseOptDepends asks the user to choose between multiple optional dependencies.
// The user may choose multiple items. // The user may choose multiple items.
func ChooseOptDepends(options []string, verb string, interactive bool) ([]string, error) { func ChooseOptDepends(ctx context.Context, options []string, verb string, interactive bool) ([]string, error) {
if !interactive { if !interactive {
return []string{}, nil return []string{}, nil
} }
prompt := &survey.MultiSelect{ prompt := &survey.MultiSelect{
Options: options, Options: options,
Message: translations.Translator().TranslateTo("Choose which optional package(s) to install", config.Language()), Message: translations.Translator(ctx).TranslateTo("Choose which optional package(s) to install", config.Language(ctx)),
} }
var choices []int var choices []int

View File

@ -19,11 +19,12 @@
package config package config
import ( import (
"context"
"os" "os"
"github.com/pelletier/go-toml/v2" "github.com/pelletier/go-toml/v2"
"go.elara.ws/lure/internal/log"
"go.elara.ws/lure/internal/types" "go.elara.ws/lure/internal/types"
"go.elara.ws/lure/pkg/loggerctx"
) )
var defaultConfig = &types.Config{ var defaultConfig = &types.Config{
@ -43,9 +44,10 @@ var config *types.Config
// Config returns a LURE configuration struct. // Config returns a LURE configuration struct.
// The first time it's called, it'll load the config from a file. // The first time it's called, it'll load the config from a file.
// Subsequent calls will just return the same value. // Subsequent calls will just return the same value.
func Config() *types.Config { func Config(ctx context.Context) *types.Config {
log := loggerctx.From(ctx)
if config == nil { if config == nil {
cfgFl, err := os.Open(GetPaths().ConfigPath) cfgFl, err := os.Open(GetPaths(ctx).ConfigPath)
if err != nil { if err != nil {
log.Warn("Error opening config file, using defaults").Err(err).Send() log.Warn("Error opening config file, using defaults").Err(err).Send()
return defaultConfig return defaultConfig

View File

@ -19,10 +19,11 @@
package config package config
import ( import (
"context"
"os" "os"
"strings" "strings"
"go.elara.ws/lure/internal/log" "go.elara.ws/lure/pkg/loggerctx"
"golang.org/x/text/language" "golang.org/x/text/language"
) )
@ -35,7 +36,8 @@ var (
// The first time it's called, it'll detect the langauge based on // The first time it's called, it'll detect the langauge based on
// the $LANG environment variable. // the $LANG environment variable.
// Subsequent calls will just return the same value. // Subsequent calls will just return the same value.
func Language() language.Tag { func Language(ctx context.Context) language.Tag {
log := loggerctx.From(ctx)
if !langSet { if !langSet {
syslang := SystemLang() syslang := SystemLang()
tag, err := language.Parse(syslang) tag, err := language.Parse(syslang)

View File

@ -19,11 +19,12 @@
package config package config
import ( import (
"context"
"os" "os"
"path/filepath" "path/filepath"
"github.com/pelletier/go-toml/v2" "github.com/pelletier/go-toml/v2"
"go.elara.ws/lure/internal/log" "go.elara.ws/lure/pkg/loggerctx"
) )
// Paths contains various paths used by LURE // Paths contains various paths used by LURE
@ -42,7 +43,8 @@ var paths *Paths
// The first time it's called, it'll generate the struct // The first time it's called, it'll generate the struct
// using information from the system. // using information from the system.
// Subsequent calls will return the same value. // Subsequent calls will return the same value.
func GetPaths() *Paths { func GetPaths(ctx context.Context) *Paths {
log := loggerctx.From(ctx)
if paths == nil { if paths == nil {
paths = &Paths{} paths = &Paths{}

View File

@ -19,6 +19,7 @@
package db package db
import ( import (
"context"
"database/sql" "database/sql"
"database/sql/driver" "database/sql/driver"
"encoding/json" "encoding/json"
@ -26,8 +27,8 @@ import (
"fmt" "fmt"
"github.com/jmoiron/sqlx" "github.com/jmoiron/sqlx"
"go.elara.ws/lure/internal/log"
"go.elara.ws/lure/internal/config" "go.elara.ws/lure/internal/config"
"go.elara.ws/lure/pkg/loggerctx"
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
"modernc.org/sqlite" "modernc.org/sqlite"
) )
@ -72,11 +73,12 @@ var (
// DB returns the LURE database. // DB returns the LURE database.
// The first time it's called, it opens the SQLite database file. // The first time it's called, it opens the SQLite database file.
// Subsequent calls return the same connection. // Subsequent calls return the same connection.
func DB() *sqlx.DB { func DB(ctx context.Context) *sqlx.DB {
log := loggerctx.From(ctx)
if conn != nil && !closed { if conn != nil && !closed {
return conn return conn
} }
db, err := open(config.GetPaths().DBPath) db, err := open(ctx, config.GetPaths(ctx).DBPath)
if err != nil { if err != nil {
log.Fatal("Error opening database").Err(err).Send() log.Fatal("Error opening database").Err(err).Send()
} }
@ -84,7 +86,7 @@ func DB() *sqlx.DB {
return conn return conn
} }
func open(dsn string) (*sqlx.DB, error) { func open(ctx context.Context, dsn string) (*sqlx.DB, error) {
db, err := sqlx.Open("sqlite", dsn) db, err := sqlx.Open("sqlite", dsn)
if err != nil { if err != nil {
return nil, err return nil, err
@ -92,7 +94,7 @@ func open(dsn string) (*sqlx.DB, error) {
conn = db conn = db
closed = false closed = false
err = initDB(dsn) err = initDB(ctx, dsn)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -111,9 +113,10 @@ func Close() error {
} }
// initDB initializes the database // initDB initializes the database
func initDB(dsn string) error { func initDB(ctx context.Context, dsn string) error {
log := loggerctx.From(ctx)
conn = conn.Unsafe() conn = conn.Unsafe()
_, err := conn.Exec(` _, err := conn.ExecContext(ctx, `
CREATE TABLE IF NOT EXISTS pkgs ( CREATE TABLE IF NOT EXISTS pkgs (
name TEXT NOT NULL, name TEXT NOT NULL,
repository TEXT NOT NULL, repository TEXT NOT NULL,
@ -142,33 +145,33 @@ func initDB(dsn string) error {
return err return err
} }
ver, ok := GetVersion() ver, ok := GetVersion(ctx)
if ok && ver != CurrentVersion { if ok && ver != CurrentVersion {
log.Warn("Database version mismatch; resetting").Int("version", ver).Int("expected", CurrentVersion).Send() log.Warn("Database version mismatch; resetting").Int("version", ver).Int("expected", CurrentVersion).Send()
reset() reset(ctx)
return initDB(dsn) return initDB(ctx, dsn)
} else if !ok { } else if !ok {
log.Warn("Database version does not exist. Run lure fix if something isn't working.").Send() log.Warn("Database version does not exist. Run lure fix if something isn't working.").Send()
return addVersion(CurrentVersion) return addVersion(ctx, CurrentVersion)
} }
return nil return nil
} }
// reset drops all the database tables // reset drops all the database tables
func reset() error { func reset(ctx context.Context) error {
_, err := DB().Exec("DROP TABLE IF EXISTS pkgs;") _, err := DB(ctx).ExecContext(ctx, "DROP TABLE IF EXISTS pkgs;")
if err != nil { if err != nil {
return err return err
} }
_, err = DB().Exec("DROP TABLE IF EXISTS lure_db_version;") _, err = DB(ctx).ExecContext(ctx, "DROP TABLE IF EXISTS lure_db_version;")
return err return err
} }
// IsEmpty returns true if the database has no packages in it, otherwise it returns false. // IsEmpty returns true if the database has no packages in it, otherwise it returns false.
func IsEmpty() bool { func IsEmpty(ctx context.Context) bool {
var count int var count int
err := DB().Get(&count, "SELECT count(1) FROM pkgs;") err := DB(ctx).GetContext(ctx, &count, "SELECT count(1) FROM pkgs;")
if err != nil { if err != nil {
return true return true
} }
@ -177,23 +180,23 @@ func IsEmpty() bool {
// GetVersion returns the database version and a boolean indicating // GetVersion returns the database version and a boolean indicating
// whether the database contained a version number // whether the database contained a version number
func GetVersion() (int, bool) { func GetVersion(ctx context.Context) (int, bool) {
var ver version var ver version
err := DB().Get(&ver, "SELECT * FROM lure_db_version LIMIT 1;") err := DB(ctx).GetContext(ctx, &ver, "SELECT * FROM lure_db_version LIMIT 1;")
if err != nil { if err != nil {
return 0, false return 0, false
} }
return ver.Version, true return ver.Version, true
} }
func addVersion(ver int) error { func addVersion(ctx context.Context, ver int) error {
_, err := DB().Exec(`INSERT INTO lure_db_version(version) VALUES (?);`, ver) _, err := DB(ctx).ExecContext(ctx, `INSERT INTO lure_db_version(version) VALUES (?);`, ver)
return err return err
} }
// InsertPackage adds a package to the database // InsertPackage adds a package to the database
func InsertPackage(pkg Package) error { func InsertPackage(ctx context.Context, pkg Package) error {
_, err := DB().NamedExec(` _, err := DB(ctx).NamedExecContext(ctx, `
INSERT OR REPLACE INTO pkgs ( INSERT OR REPLACE INTO pkgs (
name, name,
repository, repository,
@ -234,8 +237,8 @@ func InsertPackage(pkg Package) error {
} }
// GetPkgs returns a result containing packages that match the where conditions // GetPkgs returns a result containing packages that match the where conditions
func GetPkgs(where string, args ...any) (*sqlx.Rows, error) { func GetPkgs(ctx context.Context, where string, args ...any) (*sqlx.Rows, error) {
stream, err := DB().Queryx("SELECT * FROM pkgs WHERE "+where, args...) stream, err := DB(ctx).QueryxContext(ctx, "SELECT * FROM pkgs WHERE "+where, args...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -243,15 +246,15 @@ func GetPkgs(where string, args ...any) (*sqlx.Rows, error) {
} }
// GetPkg returns a single package that matches the where conditions // GetPkg returns a single package that matches the where conditions
func GetPkg(where string, args ...any) (*Package, error) { func GetPkg(ctx context.Context, where string, args ...any) (*Package, error) {
out := &Package{} out := &Package{}
err := DB().Get(out, "SELECT * FROM pkgs WHERE "+where+" LIMIT 1", args...) err := DB(ctx).GetContext(ctx, out, "SELECT * FROM pkgs WHERE "+where+" LIMIT 1", args...)
return out, err return out, err
} }
// DeletePkgs deletes all packages matching the where conditions // DeletePkgs deletes all packages matching the where conditions
func DeletePkgs(where string, args ...any) error { func DeletePkgs(ctx context.Context, where string, args ...any) error {
_, err := DB().Exec("DELETE FROM pkgs WHERE "+where, args...) _, err := DB(ctx).ExecContext(ctx, "DELETE FROM pkgs WHERE "+where, args...)
return err return err
} }

View File

@ -37,7 +37,7 @@ import (
"github.com/PuerkitoBio/purell" "github.com/PuerkitoBio/purell"
"github.com/vmihailenco/msgpack/v5" "github.com/vmihailenco/msgpack/v5"
"go.elara.ws/lure/internal/dlcache" "go.elara.ws/lure/internal/dlcache"
"go.elara.ws/lure/internal/log" "go.elara.ws/lure/pkg/loggerctx"
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
) )
@ -154,6 +154,7 @@ type UpdatingDownloader interface {
// it downloads the source to a new cache directory and links it // it downloads the source to a new cache directory and links it
// to the destination. // to the destination.
func Download(ctx context.Context, opts Options) (err error) { func Download(ctx context.Context, opts Options) (err error) {
log := loggerctx.From(ctx)
normalized, err := normalizeURL(opts.URL) normalized, err := normalizeURL(opts.URL)
if err != nil { if err != nil {
return err return err
@ -168,7 +169,7 @@ func Download(ctx context.Context, opts Options) (err error) {
} }
var t Type var t Type
cacheDir, ok := dlcache.Get(opts.URL) cacheDir, ok := dlcache.Get(ctx, opts.URL)
if ok { if ok {
var updated bool var updated bool
if d, ok := d.(UpdatingDownloader); ok { if d, ok := d.(UpdatingDownloader); ok {
@ -216,7 +217,7 @@ func Download(ctx context.Context, opts Options) (err error) {
log.Info("Downloading source").Str("source", opts.Name).Str("downloader", d.Name()).Send() log.Info("Downloading source").Str("source", opts.Name).Str("downloader", d.Name()).Send()
cacheDir, err = dlcache.New(opts.URL) cacheDir, err = dlcache.New(ctx, opts.URL)
if err != nil { if err != nil {
return err return err
} }

View File

@ -19,6 +19,7 @@
package dlcache package dlcache
import ( import (
"context"
"crypto/sha1" "crypto/sha1"
"encoding/hex" "encoding/hex"
"io" "io"
@ -29,19 +30,19 @@ import (
) )
// BasePath returns the base path of the download cache // BasePath returns the base path of the download cache
func BasePath() string { func BasePath(ctx context.Context) string {
return filepath.Join(config.GetPaths().RepoDir, "dl") return filepath.Join(config.GetPaths(ctx).RepoDir, "dl")
} }
// New creates a new directory with the given ID in the cache. // New creates a new directory with the given ID in the cache.
// If a directory with the same ID already exists, // If a directory with the same ID already exists,
// it will be deleted before creating a new one. // it will be deleted before creating a new one.
func New(id string) (string, error) { func New(ctx context.Context, id string) (string, error) {
h, err := hashID(id) h, err := hashID(id)
if err != nil { if err != nil {
return "", err return "", err
} }
itemPath := filepath.Join(BasePath(), h) itemPath := filepath.Join(BasePath(ctx), h)
fi, err := os.Stat(itemPath) fi, err := os.Stat(itemPath)
if err == nil || (fi != nil && !fi.IsDir()) { if err == nil || (fi != nil && !fi.IsDir()) {
@ -64,12 +65,12 @@ func New(id string) (string, error) {
// returns the directory and true. If it // returns the directory and true. If it
// does not exist, it returns an empty string // does not exist, it returns an empty string
// and false. // and false.
func Get(id string) (string, bool) { func Get(ctx context.Context, id string) (string, bool) {
h, err := hashID(id) h, err := hashID(id)
if err != nil { if err != nil {
return "", false return "", false
} }
itemPath := filepath.Join(BasePath(), h) itemPath := filepath.Join(BasePath(ctx), h)
_, err = os.Stat(itemPath) _, err = os.Stat(itemPath)
if err != nil { if err != nil {

View File

@ -19,6 +19,7 @@
package dlcache_test package dlcache_test
import ( import (
"context"
"crypto/sha1" "crypto/sha1"
"encoding/hex" "encoding/hex"
"io" "io"
@ -26,8 +27,8 @@ import (
"path/filepath" "path/filepath"
"testing" "testing"
"go.elara.ws/lure/internal/dlcache"
"go.elara.ws/lure/internal/config" "go.elara.ws/lure/internal/config"
"go.elara.ws/lure/internal/dlcache"
) )
func init() { func init() {
@ -35,7 +36,7 @@ func init() {
if err != nil { if err != nil {
panic(err) panic(err)
} }
config.GetPaths().RepoDir = dir config.GetPaths(context.Background()).RepoDir = dir
} }
func TestNew(t *testing.T) { func TestNew(t *testing.T) {

View File

@ -1,100 +0,0 @@
/*
* LURE - Linux User REpository
* Copyright (C) 2023 Elara Musayelyan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package log
import (
"go.elara.ws/logger"
)
var Logger logger.Logger = logger.NewNop()
// NoPanic prevents the logger from panicking on panic events
func NoPanic() {
Logger.NoPanic()
}
// NoExit prevents the logger from exiting on fatal events
func NoExit() {
Logger.NoExit()
}
// SetLevel sets the log level of the logger
func SetLevel(l logger.LogLevel) {
Logger.SetLevel(l)
}
// Debug creates a new debug event with the given message
func Debug(msg string) logger.LogBuilder {
return Logger.Debug(msg)
}
// Debugf creates a new debug event with the formatted message
func Debugf(format string, v ...any) logger.LogBuilder {
return Logger.Debugf(format, v...)
}
// Info creates a new info event with the given message
func Info(msg string) logger.LogBuilder {
return Logger.Info(msg)
}
// Infof creates a new info event with the formatted message
func Infof(format string, v ...any) logger.LogBuilder {
return Logger.Infof(format, v...)
}
// Warn creates a new warn event with the given message
func Warn(msg string) logger.LogBuilder {
return Logger.Warn(msg)
}
// Warnf creates a new warn event with the formatted message
func Warnf(format string, v ...any) logger.LogBuilder {
return Logger.Warnf(format, v...)
}
// Error creates a new error event with the given message
func Error(msg string) logger.LogBuilder {
return Logger.Error(msg)
}
// Errorf creates a new error event with the formatted message
func Errorf(format string, v ...any) logger.LogBuilder {
return Logger.Errorf(format, v...)
}
// Fatal creates a new fatal event with the given message
func Fatal(msg string) logger.LogBuilder {
return Logger.Fatal(msg)
}
// Fatalf creates a new fatal event with the formatted message
func Fatalf(format string, v ...any) logger.LogBuilder {
return Logger.Fatalf(format, v...)
}
// Fatal creates a new fatal event with the given message
func Panic(msg string) logger.LogBuilder {
return Logger.Panic(msg)
}
// Fatalf creates a new fatal event with the formatted message
func Panicf(format string, v ...any) logger.LogBuilder {
return Logger.Panicf(format, v...)
}

View File

@ -19,10 +19,11 @@
package translations package translations
import ( import (
"context"
"embed" "embed"
"go.elara.ws/logger" "go.elara.ws/logger"
"go.elara.ws/lure/internal/log" "go.elara.ws/lure/pkg/loggerctx"
"go.elara.ws/translate" "go.elara.ws/translate"
"golang.org/x/text/language" "golang.org/x/text/language"
) )
@ -32,7 +33,8 @@ var translationFS embed.FS
var translator *translate.Translator var translator *translate.Translator
func Translator() *translate.Translator { func Translator(ctx context.Context) *translate.Translator {
log := loggerctx.From(ctx)
if translator == nil { if translator == nil {
t, err := translate.NewFromFS(translationFS) t, err := translate.NewFromFS(translationFS)
if err != nil { if err != nil {
@ -43,6 +45,6 @@ func Translator() *translate.Translator {
return translator return translator
} }
func NewLogger(l logger.Logger, lang language.Tag) *translate.TranslatedLogger { func NewLogger(ctx context.Context, l logger.Logger, lang language.Tag) *translate.TranslatedLogger {
return translate.NewLogger(l, *Translator(), lang) return translate.NewLogger(l, *Translator(ctx), lang)
} }

11
list.go
View File

@ -22,9 +22,9 @@ import (
"fmt" "fmt"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"go.elara.ws/lure/internal/log"
"go.elara.ws/lure/internal/config" "go.elara.ws/lure/internal/config"
"go.elara.ws/lure/internal/db" "go.elara.ws/lure/internal/db"
"go.elara.ws/lure/pkg/loggerctx"
"go.elara.ws/lure/pkg/manager" "go.elara.ws/lure/pkg/manager"
"go.elara.ws/lure/pkg/repos" "go.elara.ws/lure/pkg/repos"
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
@ -41,7 +41,10 @@ var listCmd = &cli.Command{
}, },
}, },
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
err := repos.Pull(c.Context, config.Config().Repos) ctx := c.Context
log := loggerctx.From(ctx)
err := repos.Pull(ctx, config.Config(ctx).Repos)
if err != nil { if err != nil {
log.Fatal("Error pulling repositories").Err(err).Send() log.Fatal("Error pulling repositories").Err(err).Send()
} }
@ -53,7 +56,7 @@ var listCmd = &cli.Command{
args = []any{c.Args().First(), c.Args().First()} args = []any{c.Args().First(), c.Args().First()}
} }
result, err := db.GetPkgs(where, args...) result, err := db.GetPkgs(ctx, where, args...)
if err != nil { if err != nil {
log.Fatal("Error getting packages").Err(err).Send() log.Fatal("Error getting packages").Err(err).Send()
} }
@ -79,7 +82,7 @@ var listCmd = &cli.Command{
return err return err
} }
if slices.Contains(config.Config().IgnorePkgUpdates, pkg.Name) { if slices.Contains(config.Config(ctx).IgnorePkgUpdates, pkg.Name) {
continue continue
} }

13
main.go
View File

@ -28,10 +28,10 @@ import (
"github.com/mattn/go-isatty" "github.com/mattn/go-isatty"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"go.elara.ws/logger" "go.elara.ws/logger"
"go.elara.ws/lure/internal/log"
"go.elara.ws/lure/internal/translations"
"go.elara.ws/lure/internal/config" "go.elara.ws/lure/internal/config"
"go.elara.ws/lure/internal/db" "go.elara.ws/lure/internal/db"
"go.elara.ws/lure/internal/translations"
"go.elara.ws/lure/pkg/loggerctx"
"go.elara.ws/lure/pkg/manager" "go.elara.ws/lure/pkg/manager"
) )
@ -88,16 +88,17 @@ var versionCmd = &cli.Command{
} }
func main() { func main() {
log.Logger = translations.NewLogger(logger.NewCLI(os.Stderr), config.Language()) ctx := context.Background()
log := translations.NewLogger(ctx, logger.NewCLI(os.Stderr), config.Language(ctx))
ctx = loggerctx.With(ctx, log)
if !config.Config().Unsafe.AllowRunAsRoot && os.Geteuid() == 0 { if !config.Config(ctx).Unsafe.AllowRunAsRoot && os.Geteuid() == 0 {
log.Fatal("Running LURE as root is forbidden as it may cause catastrophic damage to your system").Send() log.Fatal("Running LURE as root is forbidden as it may cause catastrophic damage to your system").Send()
} }
// Set the root command to the one set in the LURE config // Set the root command to the one set in the LURE config
manager.DefaultRootCmd = config.Config().RootCmd manager.DefaultRootCmd = config.Config(ctx).RootCmd
ctx := context.Background()
ctx, cancel := signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGTERM) ctx, cancel := signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGTERM)
defer cancel() defer cancel()

View File

@ -39,16 +39,16 @@ import (
"github.com/goreleaser/nfpm/v2" "github.com/goreleaser/nfpm/v2"
"github.com/goreleaser/nfpm/v2/files" "github.com/goreleaser/nfpm/v2/files"
"go.elara.ws/lure/internal/cliutils" "go.elara.ws/lure/internal/cliutils"
"go.elara.ws/lure/internal/config"
"go.elara.ws/lure/internal/cpu" "go.elara.ws/lure/internal/cpu"
"go.elara.ws/lure/internal/db"
"go.elara.ws/lure/internal/dl" "go.elara.ws/lure/internal/dl"
"go.elara.ws/lure/internal/log"
"go.elara.ws/lure/internal/shutils" "go.elara.ws/lure/internal/shutils"
"go.elara.ws/lure/internal/shutils/decoder" "go.elara.ws/lure/internal/shutils/decoder"
"go.elara.ws/lure/internal/shutils/helpers" "go.elara.ws/lure/internal/shutils/helpers"
"go.elara.ws/lure/internal/types" "go.elara.ws/lure/internal/types"
"go.elara.ws/lure/internal/config"
"go.elara.ws/lure/internal/db"
"go.elara.ws/lure/pkg/distro" "go.elara.ws/lure/pkg/distro"
"go.elara.ws/lure/pkg/loggerctx"
"go.elara.ws/lure/pkg/manager" "go.elara.ws/lure/pkg/manager"
"go.elara.ws/lure/pkg/repos" "go.elara.ws/lure/pkg/repos"
"mvdan.cc/sh/v3/expand" "mvdan.cc/sh/v3/expand"
@ -59,6 +59,8 @@ import (
// BuildPackage builds the script at the given path. It returns two slices. One contains the paths // BuildPackage builds the script at the given path. It returns two slices. One contains the paths
// to the built package(s), the other contains the names of the built package(s). // to the built package(s), the other contains the names of the built package(s).
func BuildPackage(ctx context.Context, opts types.BuildOpts) ([]string, []string, error) { func BuildPackage(ctx context.Context, opts types.BuildOpts) ([]string, []string, error) {
log := loggerctx.From(ctx)
info, err := distro.ParseOSRelease(ctx) info, err := distro.ParseOSRelease(ctx)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -77,7 +79,7 @@ func BuildPackage(ctx context.Context, opts types.BuildOpts) ([]string, []string
return nil, nil, err return nil, nil, err
} }
dirs := getDirs(vars, opts.Script) dirs := getDirs(ctx, vars, opts.Script)
// If opts.Clean isn't set and we find the package already built, // If opts.Clean isn't set and we find the package already built,
// just return it rather than rebuilding // just return it rather than rebuilding
@ -93,7 +95,7 @@ func BuildPackage(ctx context.Context, opts types.BuildOpts) ([]string, []string
} }
// Ask the user if they'd like to see the build script // Ask the user if they'd like to see the build script
err = cliutils.PromptViewScript(opts.Script, vars.Name, config.Config().PagerStyle, opts.Interactive) err = cliutils.PromptViewScript(ctx, opts.Script, vars.Name, config.Config(ctx).PagerStyle, opts.Interactive)
if err != nil { if err != nil {
log.Fatal("Failed to prompt user to view build script").Err(err).Send() log.Fatal("Failed to prompt user to view build script").Err(err).Send()
} }
@ -114,7 +116,7 @@ func BuildPackage(ctx context.Context, opts types.BuildOpts) ([]string, []string
return nil, nil, err return nil, nil, err
} }
cont, err := performChecks(vars, opts.Interactive, installed) cont, err := performChecks(ctx, vars, opts.Interactive, installed)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} else if !cont { } else if !cont {
@ -181,7 +183,7 @@ func BuildPackage(ctx context.Context, opts types.BuildOpts) ([]string, []string
return nil, nil, err return nil, nil, err
} }
err = removeBuildDeps(buildDeps, opts) err = removeBuildDeps(ctx, buildDeps, opts)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -251,8 +253,8 @@ func executeFirstPass(ctx context.Context, info *distro.OSRelease, fl *syntax.Fi
} }
// getDirs returns the appropriate directories for the script // getDirs returns the appropriate directories for the script
func getDirs(vars *types.BuildVars, script string) types.Directories { func getDirs(ctx context.Context, vars *types.BuildVars, script string) types.Directories {
baseDir := filepath.Join(config.GetPaths().PkgsDir, vars.Name) baseDir := filepath.Join(config.GetPaths(ctx).PkgsDir, vars.Name)
return types.Directories{ return types.Directories{
BaseDir: baseDir, BaseDir: baseDir,
SrcDir: filepath.Join(baseDir, "src"), SrcDir: filepath.Join(baseDir, "src"),
@ -297,9 +299,10 @@ func prepareDirs(dirs types.Directories) error {
} }
// performChecks checks various things on the system to ensure that the package can be installed. // performChecks checks various things on the system to ensure that the package can be installed.
func performChecks(vars *types.BuildVars, interactive bool, installed map[string]string) (bool, error) { func performChecks(ctx context.Context, vars *types.BuildVars, interactive bool, installed map[string]string) (bool, error) {
log := loggerctx.From(ctx)
if !cpu.IsCompatibleWith(cpu.Arch(), vars.Architectures) { if !cpu.IsCompatibleWith(cpu.Arch(), vars.Architectures) {
cont, err := cliutils.YesNoPrompt("Your system's CPU architecture doesn't match this package. Do you want to build anyway?", interactive, true) cont, err := cliutils.YesNoPrompt(ctx, "Your system's CPU architecture doesn't match this package. Do you want to build anyway?", interactive, true)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -322,9 +325,10 @@ func performChecks(vars *types.BuildVars, interactive bool, installed map[string
// installBuildDeps installs any build dependencies that aren't already installed and returns // installBuildDeps installs any build dependencies that aren't already installed and returns
// a slice containing the names of all the packages it installed. // a slice containing the names of all the packages it installed.
func installBuildDeps(ctx context.Context, vars *types.BuildVars, opts types.BuildOpts, installed map[string]string) ([]string, error) { func installBuildDeps(ctx context.Context, vars *types.BuildVars, opts types.BuildOpts, installed map[string]string) ([]string, error) {
log := loggerctx.From(ctx)
var buildDeps []string var buildDeps []string
if len(vars.BuildDepends) > 0 { if len(vars.BuildDepends) > 0 {
found, notFound, err := repos.FindPkgs(vars.BuildDepends) found, notFound, err := repos.FindPkgs(ctx, vars.BuildDepends)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -333,7 +337,7 @@ func installBuildDeps(ctx context.Context, vars *types.BuildVars, opts types.Bui
log.Info("Installing build dependencies").Send() log.Info("Installing build dependencies").Send()
flattened := cliutils.FlattenPkgs(found, "install", opts.Interactive) flattened := cliutils.FlattenPkgs(ctx, found, "install", opts.Interactive)
buildDeps = packageNames(flattened) buildDeps = packageNames(flattened)
InstallPkgs(ctx, flattened, notFound, opts) InstallPkgs(ctx, flattened, notFound, opts)
} }
@ -344,7 +348,7 @@ func installBuildDeps(ctx context.Context, vars *types.BuildVars, opts types.Bui
// If the user chooses to install any optional dependencies, it performs the installation. // If the user chooses to install any optional dependencies, it performs the installation.
func installOptDeps(ctx context.Context, vars *types.BuildVars, opts types.BuildOpts, installed map[string]string) error { func installOptDeps(ctx context.Context, vars *types.BuildVars, opts types.BuildOpts, installed map[string]string) error {
if len(vars.OptDepends) > 0 { if len(vars.OptDepends) > 0 {
optDeps, err := cliutils.ChooseOptDepends(vars.OptDepends, "install", opts.Interactive) optDeps, err := cliutils.ChooseOptDepends(ctx, vars.OptDepends, "install", opts.Interactive)
if err != nil { if err != nil {
return err return err
} }
@ -353,13 +357,13 @@ func installOptDeps(ctx context.Context, vars *types.BuildVars, opts types.Build
return nil return nil
} }
found, notFound, err := repos.FindPkgs(optDeps) found, notFound, err := repos.FindPkgs(ctx, optDeps)
if err != nil { if err != nil {
return err return err
} }
found = removeAlreadyInstalled(found, installed) found = removeAlreadyInstalled(found, installed)
flattened := cliutils.FlattenPkgs(found, "install", opts.Interactive) flattened := cliutils.FlattenPkgs(ctx, found, "install", opts.Interactive)
InstallPkgs(ctx, flattened, notFound, opts) InstallPkgs(ctx, flattened, notFound, opts)
} }
return nil return nil
@ -369,18 +373,19 @@ func installOptDeps(ctx context.Context, vars *types.BuildVars, opts types.Build
// of the packages it built, as well as all the dependencies it didn't find in the LURE repo so // of the packages it built, as well as all the dependencies it didn't find in the LURE repo so
// they can be installed from the system repos. // they can be installed from the system repos.
func buildLUREDeps(ctx context.Context, opts types.BuildOpts, vars *types.BuildVars) (builtPaths, builtNames, repoDeps []string, err error) { func buildLUREDeps(ctx context.Context, opts types.BuildOpts, vars *types.BuildVars) (builtPaths, builtNames, repoDeps []string, err error) {
log := loggerctx.From(ctx)
if len(vars.Depends) > 0 { if len(vars.Depends) > 0 {
log.Info("Installing dependencies").Send() log.Info("Installing dependencies").Send()
found, notFound, err := repos.FindPkgs(vars.Depends) found, notFound, err := repos.FindPkgs(ctx, vars.Depends)
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, nil, err
} }
repoDeps = notFound repoDeps = notFound
// If there are multiple options for some packages, flatten them all into a single slice // If there are multiple options for some packages, flatten them all into a single slice
pkgs := cliutils.FlattenPkgs(found, "install", opts.Interactive) pkgs := cliutils.FlattenPkgs(ctx, found, "install", opts.Interactive)
scripts := GetScriptPaths(pkgs) scripts := GetScriptPaths(ctx, pkgs)
for _, script := range scripts { for _, script := range scripts {
newOpts := opts newOpts := opts
newOpts.Script = script newOpts.Script = script
@ -410,6 +415,7 @@ func buildLUREDeps(ctx context.Context, opts types.BuildOpts, vars *types.BuildV
// executeFunctions executes the special LURE functions, such as version(), prepare(), etc. // executeFunctions executes the special LURE functions, such as version(), prepare(), etc.
func executeFunctions(ctx context.Context, dec *decoder.Decoder, dirs types.Directories, vars *types.BuildVars) (err error) { func executeFunctions(ctx context.Context, dec *decoder.Decoder, dirs types.Directories, vars *types.BuildVars) (err error) {
log := loggerctx.From(ctx)
version, ok := dec.GetFunc("version") version, ok := dec.GetFunc("version")
if ok { if ok {
log.Info("Executing version()").Send() log.Info("Executing version()").Send()
@ -585,9 +591,9 @@ func buildContents(vars *types.BuildVars, dirs types.Directories) ([]*files.Cont
// removeBuildDeps asks the user if they'd like to remove the build dependencies that were // removeBuildDeps asks the user if they'd like to remove the build dependencies that were
// installed by installBuildDeps. If so, it uses the package manager to do that. // installed by installBuildDeps. If so, it uses the package manager to do that.
func removeBuildDeps(buildDeps []string, opts types.BuildOpts) error { func removeBuildDeps(ctx context.Context, buildDeps []string, opts types.BuildOpts) error {
if len(buildDeps) > 0 { if len(buildDeps) > 0 {
remove, err := cliutils.YesNoPrompt("Would you like to remove the build dependencies?", opts.Interactive, false) remove, err := cliutils.YesNoPrompt(ctx, "Would you like to remove the build dependencies?", opts.Interactive, false)
if err != nil { if err != nil {
return err return err
} }
@ -688,6 +694,7 @@ func createBuildEnvVars(info *distro.OSRelease, dirs types.Directories) []string
// getSources downloads the sources from the script. // getSources downloads the sources from the script.
func getSources(ctx context.Context, srcdir string, bv *types.BuildVars) error { func getSources(ctx context.Context, srcdir string, bv *types.BuildVars) error {
log := loggerctx.From(ctx)
if len(bv.Sources) != len(bv.Checksums) { if len(bv.Sources) != len(bv.Checksums) {
log.Fatal("The checksums array must be the same length as sources").Send() log.Fatal("The checksums array must be the same length as sources").Send()
} }

View File

@ -22,15 +22,17 @@ import (
"context" "context"
"path/filepath" "path/filepath"
"go.elara.ws/lure/internal/log"
"go.elara.ws/lure/internal/types"
"go.elara.ws/lure/internal/config" "go.elara.ws/lure/internal/config"
"go.elara.ws/lure/internal/db" "go.elara.ws/lure/internal/db"
"go.elara.ws/lure/internal/types"
"go.elara.ws/lure/pkg/loggerctx"
) )
// InstallPkgs installs native packages via the package manager, // InstallPkgs installs native packages via the package manager,
// then builds and installs the LURE packages // then builds and installs the LURE packages
func InstallPkgs(ctx context.Context, lurePkgs []db.Package, nativePkgs []string, opts types.BuildOpts) { func InstallPkgs(ctx context.Context, lurePkgs []db.Package, nativePkgs []string, opts types.BuildOpts) {
log := loggerctx.From(ctx)
if len(nativePkgs) > 0 { if len(nativePkgs) > 0 {
err := opts.Manager.Install(nil, nativePkgs...) err := opts.Manager.Install(nil, nativePkgs...)
if err != nil { if err != nil {
@ -38,15 +40,15 @@ func InstallPkgs(ctx context.Context, lurePkgs []db.Package, nativePkgs []string
} }
} }
InstallScripts(ctx, GetScriptPaths(lurePkgs), opts) InstallScripts(ctx, GetScriptPaths(ctx, lurePkgs), opts)
} }
// GetScriptPaths returns a slice of script paths corresponding to the // GetScriptPaths returns a slice of script paths corresponding to the
// given packages // given packages
func GetScriptPaths(pkgs []db.Package) []string { func GetScriptPaths(ctx context.Context, pkgs []db.Package) []string {
var scripts []string var scripts []string
for _, pkg := range pkgs { for _, pkg := range pkgs {
scriptPath := filepath.Join(config.GetPaths().RepoDir, pkg.Repository, pkg.Name, "lure.sh") scriptPath := filepath.Join(config.GetPaths(ctx).RepoDir, pkg.Repository, pkg.Name, "lure.sh")
scripts = append(scripts, scriptPath) scripts = append(scripts, scriptPath)
} }
return scripts return scripts
@ -54,6 +56,7 @@ func GetScriptPaths(pkgs []db.Package) []string {
// InstallScripts builds and installs the given LURE build scripts // InstallScripts builds and installs the given LURE build scripts
func InstallScripts(ctx context.Context, scripts []string, opts types.BuildOpts) { func InstallScripts(ctx context.Context, scripts []string, opts types.BuildOpts) {
log := loggerctx.From(ctx)
for _, script := range scripts { for _, script := range scripts {
opts.Script = script opts.Script = script
builtPkgs, _, err := BuildPackage(ctx, opts) builtPkgs, _, err := BuildPackage(ctx, opts)

View File

@ -1,11 +0,0 @@
package log
import (
"go.elara.ws/logger"
"go.elara.ws/lure/internal/log"
)
// SetLogger sets LURE's global logger, which is disabled by default
func SetLogger(l logger.Logger) {
log.Logger = l
}

25
pkg/loggerctx/log.go Normal file
View File

@ -0,0 +1,25 @@
package loggerctx
import (
"context"
"go.elara.ws/logger"
)
type loggerCtxKey struct{}
func With(ctx context.Context, log logger.Logger) context.Context {
return context.WithValue(ctx, loggerCtxKey{}, log)
}
func From(ctx context.Context) logger.Logger {
if val := ctx.Value(loggerCtxKey{}); val != nil {
if log, ok := val.(logger.Logger); ok && log != nil {
return log
} else {
return logger.NewNop()
}
} else {
return logger.NewNop()
}
}

View File

@ -18,12 +18,16 @@
package repos package repos
import "go.elara.ws/lure/internal/db" import (
"context"
"go.elara.ws/lure/internal/db"
)
// FindPkgs looks for packages matching the inputs inside the database. // FindPkgs looks for packages matching the inputs inside the database.
// It returns a map that maps the package name input to any packages found for it. // It returns a map that maps the package name input to any packages found for it.
// It also returns a slice that contains the names of all packages that were not found. // It also returns a slice that contains the names of all packages that were not found.
func FindPkgs(pkgs []string) (map[string][]db.Package, []string, error) { func FindPkgs(ctx context.Context, pkgs []string) (map[string][]db.Package, []string, error) {
found := map[string][]db.Package{} found := map[string][]db.Package{}
notFound := []string(nil) notFound := []string(nil)
@ -32,7 +36,7 @@ func FindPkgs(pkgs []string) (map[string][]db.Package, []string, error) {
continue continue
} }
result, err := db.GetPkgs("name LIKE ?", pkgName) result, err := db.GetPkgs(ctx, "name LIKE ?", pkgName)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -51,7 +55,7 @@ func FindPkgs(pkgs []string) (map[string][]db.Package, []string, error) {
result.Close() result.Close()
if added == 0 { if added == 0 {
result, err := db.GetPkgs("json_array_contains(provides, ?)", pkgName) result, err := db.GetPkgs(ctx, "json_array_contains(provides, ?)", pkgName)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }

View File

@ -24,8 +24,8 @@ import (
"strings" "strings"
"testing" "testing"
"go.elara.ws/lure/internal/types"
"go.elara.ws/lure/internal/db" "go.elara.ws/lure/internal/db"
"go.elara.ws/lure/internal/types"
"go.elara.ws/lure/pkg/repos" "go.elara.ws/lure/pkg/repos"
) )

View File

@ -36,11 +36,11 @@ import (
"github.com/pelletier/go-toml/v2" "github.com/pelletier/go-toml/v2"
"go.elara.ws/lure/internal/config" "go.elara.ws/lure/internal/config"
"go.elara.ws/lure/internal/db" "go.elara.ws/lure/internal/db"
"go.elara.ws/lure/internal/log"
"go.elara.ws/lure/internal/shutils" "go.elara.ws/lure/internal/shutils"
"go.elara.ws/lure/internal/shutils/decoder" "go.elara.ws/lure/internal/shutils/decoder"
"go.elara.ws/lure/internal/types" "go.elara.ws/lure/internal/types"
"go.elara.ws/lure/pkg/distro" "go.elara.ws/lure/pkg/distro"
"go.elara.ws/lure/pkg/loggerctx"
"go.elara.ws/vercmp" "go.elara.ws/vercmp"
"mvdan.cc/sh/v3/expand" "mvdan.cc/sh/v3/expand"
"mvdan.cc/sh/v3/interp" "mvdan.cc/sh/v3/interp"
@ -52,8 +52,10 @@ import (
// In this case, only changed packages will be processed if possible. // In this case, only changed packages will be processed if possible.
// If repos is set to nil, the repos in the LURE config will be used. // If repos is set to nil, the repos in the LURE config will be used.
func Pull(ctx context.Context, repos []types.Repo) error { func Pull(ctx context.Context, repos []types.Repo) error {
log := loggerctx.From(ctx)
if repos == nil { if repos == nil {
repos = config.Config().Repos repos = config.Config(ctx).Repos
} }
for _, repo := range repos { for _, repo := range repos {
@ -63,7 +65,7 @@ func Pull(ctx context.Context, repos []types.Repo) error {
} }
log.Info("Pulling repository").Str("name", repo.Name).Send() log.Info("Pulling repository").Str("name", repo.Name).Send()
repoDir := filepath.Join(config.GetPaths().RepoDir, repo.Name) repoDir := filepath.Join(config.GetPaths(ctx).RepoDir, repo.Name)
var repoFS billy.Filesystem var repoFS billy.Filesystem
gitDir := filepath.Join(repoDir, ".git") gitDir := filepath.Join(repoDir, ".git")
@ -93,7 +95,7 @@ func Pull(ctx context.Context, repos []types.Repo) error {
repoFS = w.Filesystem repoFS = w.Filesystem
// Make sure the DB is created even if the repo is up to date // Make sure the DB is created even if the repo is up to date
if !errors.Is(err, git.NoErrAlreadyUpToDate) || db.IsEmpty() { if !errors.Is(err, git.NoErrAlreadyUpToDate) || db.IsEmpty(ctx) {
new, err := r.Head() new, err := r.Head()
if err != nil { if err != nil {
return err return err
@ -102,7 +104,7 @@ func Pull(ctx context.Context, repos []types.Repo) error {
// If the DB was not present at startup, that means it's // If the DB was not present at startup, that means it's
// empty. In this case, we need to update the DB fully // empty. In this case, we need to update the DB fully
// rather than just incrementally. // rather than just incrementally.
if db.IsEmpty() { if db.IsEmpty(ctx) {
err = processRepoFull(ctx, repo, repoDir) err = processRepoFull(ctx, repo, repoDir)
if err != nil { if err != nil {
return err return err
@ -271,7 +273,7 @@ func processRepoChanges(ctx context.Context, repo types.Repo, r *git.Repository,
return err return err
} }
err = db.DeletePkgs("name = ? AND repository = ?", pkg.Name, repo.Name) err = db.DeletePkgs(ctx, "name = ? AND repository = ?", pkg.Name, repo.Name)
if err != nil { if err != nil {
return err return err
} }
@ -306,7 +308,7 @@ func processRepoChanges(ctx context.Context, repo types.Repo, r *git.Repository,
resolveOverrides(runner, &pkg) resolveOverrides(runner, &pkg)
err = db.InsertPackage(pkg) err = db.InsertPackage(ctx, pkg)
if err != nil { if err != nil {
return err return err
} }
@ -376,7 +378,7 @@ func processRepoFull(ctx context.Context, repo types.Repo, repoDir string) error
resolveOverrides(runner, &pkg) resolveOverrides(runner, &pkg)
err = db.InsertPackage(pkg) err = db.InsertPackage(ctx, pkg)
if err != nil { if err != nil {
return err return err
} }

View File

@ -24,9 +24,9 @@ import (
"path/filepath" "path/filepath"
"testing" "testing"
"go.elara.ws/lure/internal/types"
"go.elara.ws/lure/internal/config" "go.elara.ws/lure/internal/config"
"go.elara.ws/lure/internal/db" "go.elara.ws/lure/internal/db"
"go.elara.ws/lure/internal/types"
"go.elara.ws/lure/pkg/repos" "go.elara.ws/lure/pkg/repos"
) )

28
repo.go
View File

@ -24,10 +24,10 @@ import (
"github.com/pelletier/go-toml/v2" "github.com/pelletier/go-toml/v2"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"go.elara.ws/lure/internal/log"
"go.elara.ws/lure/internal/types"
"go.elara.ws/lure/internal/config" "go.elara.ws/lure/internal/config"
"go.elara.ws/lure/internal/db" "go.elara.ws/lure/internal/db"
"go.elara.ws/lure/internal/types"
"go.elara.ws/lure/pkg/loggerctx"
"go.elara.ws/lure/pkg/repos" "go.elara.ws/lure/pkg/repos"
"golang.org/x/exp/slices" "golang.org/x/exp/slices"
) )
@ -51,10 +51,13 @@ var addrepoCmd = &cli.Command{
}, },
}, },
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
ctx := c.Context
log := loggerctx.From(ctx)
name := c.String("name") name := c.String("name")
repoURL := c.String("url") repoURL := c.String("url")
cfg := config.Config() cfg := config.Config(ctx)
for _, repo := range cfg.Repos { for _, repo := range cfg.Repos {
if repo.URL == repoURL { if repo.URL == repoURL {
@ -67,7 +70,7 @@ var addrepoCmd = &cli.Command{
URL: repoURL, URL: repoURL,
}) })
cfgFl, err := os.Create(config.GetPaths().ConfigPath) cfgFl, err := os.Create(config.GetPaths(ctx).ConfigPath)
if err != nil { if err != nil {
log.Fatal("Error opening config file").Err(err).Send() log.Fatal("Error opening config file").Err(err).Send()
} }
@ -77,7 +80,7 @@ var addrepoCmd = &cli.Command{
log.Fatal("Error encoding config").Err(err).Send() log.Fatal("Error encoding config").Err(err).Send()
} }
err = repos.Pull(c.Context, cfg.Repos) err = repos.Pull(ctx, cfg.Repos)
if err != nil { if err != nil {
log.Fatal("Error pulling repos").Err(err).Send() log.Fatal("Error pulling repos").Err(err).Send()
} }
@ -99,8 +102,11 @@ var removerepoCmd = &cli.Command{
}, },
}, },
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
ctx := c.Context
log := loggerctx.From(ctx)
name := c.String("name") name := c.String("name")
cfg := config.Config() cfg := config.Config(ctx)
found := false found := false
index := 0 index := 0
@ -116,7 +122,7 @@ var removerepoCmd = &cli.Command{
cfg.Repos = slices.Delete(cfg.Repos, index, index+1) cfg.Repos = slices.Delete(cfg.Repos, index, index+1)
cfgFl, err := os.Create(config.GetPaths().ConfigPath) cfgFl, err := os.Create(config.GetPaths(ctx).ConfigPath)
if err != nil { if err != nil {
log.Fatal("Error opening config file").Err(err).Send() log.Fatal("Error opening config file").Err(err).Send()
} }
@ -126,12 +132,12 @@ var removerepoCmd = &cli.Command{
log.Fatal("Error encoding config").Err(err).Send() log.Fatal("Error encoding config").Err(err).Send()
} }
err = os.RemoveAll(filepath.Join(config.GetPaths().RepoDir, name)) err = os.RemoveAll(filepath.Join(config.GetPaths(ctx).RepoDir, name))
if err != nil { if err != nil {
log.Fatal("Error removing repo directory").Err(err).Send() log.Fatal("Error removing repo directory").Err(err).Send()
} }
err = db.DeletePkgs("repository = ?", name) err = db.DeletePkgs(ctx, "repository = ?", name)
if err != nil { if err != nil {
log.Fatal("Error removing packages from database").Err(err).Send() log.Fatal("Error removing packages from database").Err(err).Send()
} }
@ -145,7 +151,9 @@ var refreshCmd = &cli.Command{
Usage: "Pull all repositories that have changed", Usage: "Pull all repositories that have changed",
Aliases: []string{"ref"}, Aliases: []string{"ref"},
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
err := repos.Pull(c.Context, config.Config().Repos) ctx := c.Context
log := loggerctx.From(ctx)
err := repos.Pull(ctx, config.Config(ctx).Repos)
if err != nil { if err != nil {
log.Fatal("Error pulling repos").Err(err).Send() log.Fatal("Error pulling repos").Err(err).Send()
} }

View File

@ -23,12 +23,12 @@ import (
"fmt" "fmt"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"go.elara.ws/lure/internal/log"
"go.elara.ws/lure/internal/types"
"go.elara.ws/lure/pkg/build"
"go.elara.ws/lure/internal/config" "go.elara.ws/lure/internal/config"
"go.elara.ws/lure/internal/db" "go.elara.ws/lure/internal/db"
"go.elara.ws/lure/internal/types"
"go.elara.ws/lure/pkg/build"
"go.elara.ws/lure/pkg/distro" "go.elara.ws/lure/pkg/distro"
"go.elara.ws/lure/pkg/loggerctx"
"go.elara.ws/lure/pkg/manager" "go.elara.ws/lure/pkg/manager"
"go.elara.ws/lure/pkg/repos" "go.elara.ws/lure/pkg/repos"
"go.elara.ws/vercmp" "go.elara.ws/vercmp"
@ -48,7 +48,10 @@ var upgradeCmd = &cli.Command{
}, },
}, },
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
info, err := distro.ParseOSRelease(c.Context) ctx := c.Context
log := loggerctx.From(ctx)
info, err := distro.ParseOSRelease(ctx)
if err != nil { if err != nil {
log.Fatal("Error parsing os-release file").Err(err).Send() log.Fatal("Error parsing os-release file").Err(err).Send()
} }
@ -58,18 +61,18 @@ var upgradeCmd = &cli.Command{
log.Fatal("Unable to detect a supported package manager on the system").Send() log.Fatal("Unable to detect a supported package manager on the system").Send()
} }
err = repos.Pull(c.Context, config.Config().Repos) err = repos.Pull(ctx, config.Config(ctx).Repos)
if err != nil { if err != nil {
log.Fatal("Error pulling repos").Err(err).Send() log.Fatal("Error pulling repos").Err(err).Send()
} }
updates, err := checkForUpdates(c.Context, mgr, info) updates, err := checkForUpdates(ctx, mgr, info)
if err != nil { if err != nil {
log.Fatal("Error checking for updates").Err(err).Send() log.Fatal("Error checking for updates").Err(err).Send()
} }
if len(updates) > 0 { if len(updates) > 0 {
build.InstallPkgs(c.Context, updates, nil, types.BuildOpts{ build.InstallPkgs(ctx, updates, nil, types.BuildOpts{
Manager: mgr, Manager: mgr,
Clean: c.Bool("clean"), Clean: c.Bool("clean"),
Interactive: c.Bool("interactive"), Interactive: c.Bool("interactive"),
@ -89,14 +92,14 @@ func checkForUpdates(ctx context.Context, mgr manager.Manager, info *distro.OSRe
} }
pkgNames := maps.Keys(installed) pkgNames := maps.Keys(installed)
found, _, err := repos.FindPkgs(pkgNames) found, _, err := repos.FindPkgs(ctx, pkgNames)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var out []db.Package var out []db.Package
for pkgName, pkgs := range found { for pkgName, pkgs := range found {
if slices.Contains(config.Config().IgnorePkgUpdates, pkgName) { if slices.Contains(config.Config(ctx).IgnorePkgUpdates, pkgName) {
continue continue
} }