diff options
author | Alan Pearce | 2025-03-12 22:39:51 +0100 |
---|---|---|
committer | Alan Pearce | 2025-03-12 22:39:51 +0100 |
commit | 9015baf955c94a806c01b3dcd5648c8e68ad2685 (patch) | |
tree | 5f59386c2ab31b6e45b85576e45a1fc8ae448ae0 | |
parent | 7bb77ff5729cc9434afee895a470fd3b4c12e6d1 (diff) | |
download | searchix-9015baf955c94a806c01b3dcd5648c8e68ad2685.tar.lz searchix-9015baf955c94a806c01b3dcd5648c8e68ad2685.tar.zst searchix-9015baf955c94a806c01b3dcd5648c8e68ad2685.zip |
29 files changed, 179 insertions, 177 deletions
diff --git a/frontend/assets.go b/frontend/assets.go index b1c2efa..831ea84 100644 --- a/frontend/assets.go +++ b/frontend/assets.go @@ -8,7 +8,7 @@ import ( "io" "io/fs" - "github.com/pkg/errors" + "gitlab.com/tozd/go/errors" ) var Assets = &AssetCollection{ @@ -30,7 +30,7 @@ type AssetCollection struct { ByPath map[string]*Asset } -func newAsset(filename string) (*Asset, error) { +func newAsset(filename string) (*Asset, errors.E) { file, err := Files.Open(filename) if err != nil { return nil, errors.WithMessagef(err, "could not open file %s", filename) @@ -51,7 +51,7 @@ func newAsset(filename string) (*Asset, error) { }, nil } -func hashScripts() error { +func hashScripts() errors.E { scripts, err := fs.Glob(Files, "static/**.js") if err != nil { return errors.WithMessage(err, "could not glob files") @@ -68,7 +68,7 @@ func hashScripts() error { return nil } -func hashStyles() error { +func hashStyles() errors.E { styles, err := fs.Glob(Files, "static/**.css") if err != nil { return errors.WithMessage(err, "could not glob files") @@ -85,7 +85,7 @@ func hashStyles() error { return nil } -func Rehash() (err error) { +func Rehash() (err errors.E) { Assets.Scripts = []*Asset{} err = hashScripts() if err != nil { diff --git a/go.mod b/go.mod index 538a3f3..106a618 100644 --- a/go.mod +++ b/go.mod @@ -15,9 +15,9 @@ require ( github.com/mitchellh/mapstructure v1.5.0 github.com/osdevisnot/sorvor v0.4.4 github.com/pelletier/go-toml/v2 v2.2.3 - github.com/pkg/errors v0.9.1 github.com/stoewer/go-strcase v1.3.0 github.com/yuin/goldmark v1.7.8 + gitlab.com/tozd/go/errors v0.10.0 go.alanpearce.eu/x v0.0.0-20241203124832-a29434dba11a go.uber.org/zap v1.27.0 golang.org/x/net v0.33.0 @@ -56,6 +56,7 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mschoch/smat v0.2.0 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/stretchr/testify v1.10.0 // indirect github.com/sykesm/zap-logfmt v0.0.4 // indirect diff --git a/go.sum b/go.sum index ce25867..60f4bba 100644 --- a/go.sum +++ b/go.sum @@ -140,6 +140,8 @@ github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9dec github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic= github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= +gitlab.com/tozd/go/errors v0.10.0 h1:A98kL+gaDvWnY6ZB/u8zP+sYaWsWUGBHeFMtamvW/74= +gitlab.com/tozd/go/errors v0.10.0/go.mod h1:q3Ugr0C8dCzMEkrzjjlV2qNsm9e0KvqBjwcbcjCpBe4= go.alanpearce.eu/x v0.0.0-20241203124832-a29434dba11a h1:NUv3AzGxwMVSq26takww8/nyl+sPO2BsESoVSU8G49U= go.alanpearce.eu/x v0.0.0-20241203124832-a29434dba11a/go.mod h1:FRM6J9HMQ/RV2Q5j+6RKBYWh/YNeEUriGSqDRchiHuQ= go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0= diff --git a/gomod2nix.toml b/gomod2nix.toml index 6f342ac..0f6e067 100644 --- a/gomod2nix.toml +++ b/gomod2nix.toml @@ -151,6 +151,9 @@ schema = 3 [mod."github.com/yuin/goldmark"] version = "v1.7.8" hash = "sha256-SNJMPPiXkRDLVOldrHN0ErC3bUB2VoWaLDkd9zmMATw=" + [mod."gitlab.com/tozd/go/errors"] + version = "v0.10.0" + hash = "sha256-oW37KsieVKJOWk9ZXbGuQvuU4nyJCZzgYrTZHFkoCs4=" [mod."go.alanpearce.eu/x"] version = "v0.0.0-20241203124832-a29434dba11a" hash = "sha256-ojqWkz3VqeAOevFxOTO5S3acRItCA4pUrTaul887+x8=" diff --git a/internal/components/markdown.templ b/internal/components/markdown.templ index ff1212f..0ce98ad 100644 --- a/internal/components/markdown.templ +++ b/internal/components/markdown.templ @@ -5,9 +5,9 @@ import ( "go.alanpearce.eu/searchix/internal/nix" + "context" "github.com/yuin/goldmark" "github.com/yuin/goldmark/extension" - "context" "io" ) @@ -27,7 +27,7 @@ func firstSentence[T ~string](text T) T { } func markdown(text nix.Markdown) templ.Component { - return templ.ComponentFunc(func(ctx context.Context, w io.Writer) error { + return templ.ComponentFunc(func(ctx context.Context, w io.Writer) errors.E { err := md.Convert([]byte(text), w) return err diff --git a/internal/components/page.templ b/internal/components/page.templ index 4ba3741..63d0439 100644 --- a/internal/components/page.templ +++ b/internal/components/page.templ @@ -81,7 +81,7 @@ templ script(s *frontend.Asset) { } func Unsafe(html string) templ.Component { - return templ.ComponentFunc(func(_ context.Context, w io.Writer) (err error) { + return templ.ComponentFunc(func(_ context.Context, w io.Writer) (err errors.E) { _, err = io.WriteString(w, html) return }) diff --git a/internal/config/config.go b/internal/config/config.go index b2af53c..2822d0c 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -7,7 +7,7 @@ import ( "time" "github.com/pelletier/go-toml/v2" - "github.com/pkg/errors" + "gitlab.com/tozd/go/errors" "go.alanpearce.eu/x/log" ) @@ -103,7 +103,7 @@ func mustLocalTime(in string) (time LocalTime) { return } -func GetConfig(filename string, log *log.Logger) (*Config, error) { +func GetConfig(filename string, log *log.Logger) (*Config, errors.E) { config := DefaultConfig if filename != "" { log.Debug("reading config", "filename", filename) diff --git a/internal/config/fetcher.go b/internal/config/fetcher.go index fd95b32..fca6cb1 100644 --- a/internal/config/fetcher.go +++ b/internal/config/fetcher.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/stoewer/go-strcase" + "gitlab.com/tozd/go/errors" ) type Fetcher int @@ -37,7 +38,7 @@ func ParseFetcher(name string) (Fetcher, error) { case "download": return Download, nil default: - return UnknownFetcher, fmt.Errorf("unsupported fetcher %s", name) + return UnknownFetcher, errors.Errorf("unsupported fetcher %s", name) } } diff --git a/internal/config/repository.go b/internal/config/repository.go index a074cbc..52b255e 100644 --- a/internal/config/repository.go +++ b/internal/config/repository.go @@ -3,6 +3,8 @@ package config import ( "fmt" "strings" + + "gitlab.com/tozd/go/errors" ) type RepoType int @@ -28,12 +30,12 @@ func (f RepoType) String() string { } } -func parseRepoType(name string) (RepoType, error) { +func parseRepoType(name string) (RepoType, errors.E) { switch strings.ToLower(name) { case "github": return GitHub, nil default: - return UnknownRepoType, fmt.Errorf("unsupported repo type %s", name) + return UnknownRepoType, errors.Errorf("unsupported repo type %s", name) } } diff --git a/internal/fetcher/channel.go b/internal/fetcher/channel.go index 8f0aa03..86e2c60 100644 --- a/internal/fetcher/channel.go +++ b/internal/fetcher/channel.go @@ -14,7 +14,7 @@ import ( "go.alanpearce.eu/searchix/internal/index" "go.alanpearce.eu/x/log" - "github.com/pkg/errors" + "gitlab.com/tozd/go/errors" ) type ChannelFetcher struct { @@ -26,7 +26,7 @@ type ChannelFetcher struct { func NewChannelFetcher( source *config.Source, logger *log.Logger, -) (*ChannelFetcher, error) { +) (*ChannelFetcher, errors.E) { switch source.Importer { case config.Options: return &ChannelFetcher{ @@ -34,14 +34,14 @@ func NewChannelFetcher( Logger: logger, }, nil default: - return nil, fmt.Errorf("unsupported importer type %s", source.Importer) + return nil, errors.Errorf("unsupported importer type %s", source.Importer) } } func (i *ChannelFetcher) FetchIfNeeded( ctx context.Context, sourceMeta *index.SourceMeta, -) (f FetchedFiles, err error) { +) (*FetchedFiles, errors.E) { args := []string{ "--no-build-output", "--timeout", @@ -58,12 +58,9 @@ func (i *ChannelFetcher) FetchIfNeeded( i.Logger.Debug("nix-build command", "args", args) cmd := exec.CommandContext(ctx, "nix-build", args...) - var out []byte - out, err = cmd.Output() + out, err := cmd.Output() if err != nil { - err = errors.WithMessage(err, "failed to run nix-build (--dry-run)") - - return + return nil, errors.WithMessage(err, "failed to run nix-build (--dry-run)") } outPath := path.Join(strings.TrimSpace(string(out)), i.Source.OutputPath, "options.json") @@ -80,14 +77,10 @@ func (i *ChannelFetcher) FetchIfNeeded( file, err := os.Open(outPath) if err != nil { - err = errors.WithMessage(err, "failed to open options.json") - - return + return nil, errors.WithMessage(err, "failed to open options.json") } - f = FetchedFiles{ + return &FetchedFiles{ Options: file, - } - - return + }, nil } diff --git a/internal/fetcher/download.go b/internal/fetcher/download.go index a34c838..6c5bae8 100644 --- a/internal/fetcher/download.go +++ b/internal/fetcher/download.go @@ -2,13 +2,12 @@ package fetcher import ( "context" - "fmt" "net/url" "go.alanpearce.eu/searchix/internal/config" "go.alanpearce.eu/searchix/internal/index" - "github.com/pkg/errors" + "gitlab.com/tozd/go/errors" "go.alanpearce.eu/x/log" ) @@ -21,7 +20,7 @@ type DownloadFetcher struct { func NewDownloadFetcher( source *config.Source, logger *log.Logger, -) (*DownloadFetcher, error) { +) (*DownloadFetcher, errors.E) { switch source.Importer { case config.Options: return &DownloadFetcher{ @@ -29,7 +28,7 @@ func NewDownloadFetcher( Logger: logger, }, nil default: - return nil, fmt.Errorf("unsupported importer type %s", source.Importer) + return nil, errors.Errorf("unsupported importer type %s", source.Importer) } } @@ -41,20 +40,18 @@ var files = map[string]string{ func (i *DownloadFetcher) FetchIfNeeded( ctx context.Context, sourceMeta *index.SourceMeta, -) (f FetchedFiles, err error) { - var fetchURL string +) (*FetchedFiles, errors.E) { + f := &FetchedFiles{} sourceUpdated := sourceMeta.Updated for key, filename := range files { - fetchURL, err = url.JoinPath(i.Source.URL, filename) - if err != nil { - err = errors.WithMessagef( - err, + fetchURL, baseErr := url.JoinPath(i.Source.URL, filename) + if baseErr != nil { + return nil, errors.WithMessagef( + baseErr, "could not build URL with elements %s and %s", i.Source.URL, filename, ) - - return } i.Logger.Debug("preparing to fetch URL", "url", fetchURL) @@ -63,7 +60,7 @@ func (i *DownloadFetcher) FetchIfNeeded( if err != nil { i.Logger.Warn("failed to fetch file", "url", fetchURL, "error", err) - return f, err + return nil, err } // don't bother to issue requests for the later files if mtime.Before(sourceUpdated) { @@ -81,5 +78,5 @@ func (i *DownloadFetcher) FetchIfNeeded( } } - return + return f, nil } diff --git a/internal/fetcher/http.go b/internal/fetcher/http.go index c5ec8fc..ba99c3a 100644 --- a/internal/fetcher/http.go +++ b/internal/fetcher/http.go @@ -11,7 +11,7 @@ import ( "go.alanpearce.eu/searchix/internal/config" "github.com/andybalholm/brotli" - "github.com/pkg/errors" + "gitlab.com/tozd/go/errors" "go.alanpearce.eu/x/log" ) @@ -36,17 +36,20 @@ func fetchFileIfNeeded( log *log.Logger, mtime time.Time, url string, -) (body io.ReadCloser, newMtime time.Time, err error) { +) (io.ReadCloser, time.Time, errors.E) { + var newMtime time.Time var ifModifiedSince string if !mtime.IsZero() { ifModifiedSince = strings.Replace(mtime.UTC().Format(time.RFC1123), "UTC", "GMT", 1) } - req, err := http.NewRequestWithContext(ctx, "GET", url, http.NoBody) - if err != nil { - err = errors.WithMessagef(err, "could not create HTTP request for %s", url) - - return + req, baseErr := http.NewRequestWithContext(ctx, "GET", url, http.NoBody) + if baseErr != nil { + return nil, newMtime, errors.WithMessagef( + baseErr, + "could not create HTTP request for %s", + url, + ) } req.Header.Set("User-Agent", fmt.Sprintf("Searchix %s", config.Version)) @@ -54,21 +57,22 @@ func fetchFileIfNeeded( if ifModifiedSince != "" { req.Header.Set("If-Modified-Since", ifModifiedSince) } - res, err := http.DefaultClient.Do(req) - if err != nil { - err = errors.WithMessagef(err, "could not make HTTP request to %s", url) - - return + res, baseErr := http.DefaultClient.Do(req) + if baseErr != nil { + return nil, newMtime, errors.WithMessagef(baseErr, "could not make HTTP request to %s", url) } + var body io.ReadCloser + var err errors.E switch res.StatusCode { case http.StatusNotModified: newMtime = mtime - return + return nil, newMtime, nil case http.StatusOK: - newMtime, err = time.Parse(time.RFC1123, res.Header.Get("Last-Modified")) - if err != nil { + var baseErr error + newMtime, baseErr = time.Parse(time.RFC1123, res.Header.Get("Last-Modified")) + if baseErr != nil { log.Warn( "could not parse Last-Modified header from response", "value", @@ -84,11 +88,11 @@ func fetchFileIfNeeded( case "", "identity", "gzip": body = res.Body default: - err = fmt.Errorf("cannot handle a body with content-encoding %s", ce) + err = errors.Errorf("cannot handle a body with content-encoding %s", ce) } default: - err = fmt.Errorf("got response code %d, don't know what to do", res.StatusCode) + err = errors.Errorf("got response code %d, don't know what to do", res.StatusCode) } - return + return body, newMtime, err } diff --git a/internal/fetcher/main.go b/internal/fetcher/main.go index ac40ead..c027fbb 100644 --- a/internal/fetcher/main.go +++ b/internal/fetcher/main.go @@ -8,7 +8,7 @@ import ( "go.alanpearce.eu/searchix/internal/index" "go.alanpearce.eu/x/log" - "github.com/pkg/errors" + "gitlab.com/tozd/go/errors" ) type FetchedFiles struct { @@ -18,13 +18,13 @@ type FetchedFiles struct { } type Fetcher interface { - FetchIfNeeded(context.Context, *index.SourceMeta) (FetchedFiles, error) + FetchIfNeeded(context.Context, *index.SourceMeta) (*FetchedFiles, errors.E) } func New( source *config.Source, logger *log.Logger, -) (fetcher Fetcher, err error) { +) (fetcher Fetcher, err errors.E) { switch source.Fetcher { case config.ChannelNixpkgs: fetcher, err = NewNixpkgsChannelFetcher(source, logger) diff --git a/internal/fetcher/nixpkgs-channel.go b/internal/fetcher/nixpkgs-channel.go index 6f8ca63..0424602 100644 --- a/internal/fetcher/nixpkgs-channel.go +++ b/internal/fetcher/nixpkgs-channel.go @@ -2,13 +2,12 @@ package fetcher import ( "context" - "fmt" "net/url" "go.alanpearce.eu/searchix/internal/config" "go.alanpearce.eu/searchix/internal/index" - "github.com/pkg/errors" + "gitlab.com/tozd/go/errors" "go.alanpearce.eu/x/log" ) @@ -17,7 +16,7 @@ type NixpkgsChannelFetcher struct { Logger *log.Logger } -func makeChannelURL(channel string, subPath string) (string, error) { +func makeChannelURL(channel string, subPath string) (string, errors.E) { url, err := url.JoinPath("https://channels.nixos.org/", channel, subPath) return url, errors.WithMessagef(err, "error creating URL") @@ -26,7 +25,7 @@ func makeChannelURL(channel string, subPath string) (string, error) { func NewNixpkgsChannelFetcher( source *config.Source, logger *log.Logger, -) (*NixpkgsChannelFetcher, error) { +) (*NixpkgsChannelFetcher, errors.E) { switch source.Importer { case config.Options, config.Packages: return &NixpkgsChannelFetcher{ @@ -34,7 +33,7 @@ func NewNixpkgsChannelFetcher( Logger: logger, }, nil default: - return nil, fmt.Errorf("unsupported importer type %s", source.Importer) + return nil, errors.Errorf("unsupported importer type %s", source.Importer) } } @@ -47,7 +46,7 @@ const ( func (i *NixpkgsChannelFetcher) FetchIfNeeded( ctx context.Context, sourceMeta *index.SourceMeta, -) (f FetchedFiles, err error) { +) (f *FetchedFiles, err errors.E) { filesToFetch := make([]string, 2) filesToFetch[0] = revisionFilename diff --git a/internal/file/utils.go b/internal/file/utils.go index efcf0f6..eb04fa0 100644 --- a/internal/file/utils.go +++ b/internal/file/utils.go @@ -5,10 +5,10 @@ import ( "io/fs" "os" - "github.com/pkg/errors" + "gitlab.com/tozd/go/errors" ) -func Mkdirp(dir string) error { +func Mkdirp(dir string) errors.E { err := os.MkdirAll(dir, os.ModeDir|os.ModePerm) if err != nil { return errors.WithMessagef(err, "could not create directory %s", dir) @@ -17,27 +17,27 @@ func Mkdirp(dir string) error { return nil } -func NeedNotExist(err error) error { +func NeedNotExist(err error) errors.E { if err != nil && !errors.Is(err, fs.ErrNotExist) { - return err + return errors.WithStack(err) } return nil } -func StatIfExists(file string) (fs.FileInfo, error) { +func StatIfExists(file string) (fs.FileInfo, errors.E) { stat, err := os.Stat(file) return stat, NeedNotExist(err) } -func Exists(file string) (bool, error) { +func Exists(file string) (bool, errors.E) { stat, err := StatIfExists(file) return stat != nil, err } -func WriteToFile(path string, body io.Reader) error { +func WriteToFile(path string, body io.Reader) errors.E { file, err := os.Create(path) if err != nil { return errors.WithMessagef(err, "error creating file at %s", path) diff --git a/internal/importer/importer.go b/internal/importer/importer.go index 0b2db43..9334f7d 100644 --- a/internal/importer/importer.go +++ b/internal/importer/importer.go @@ -4,13 +4,14 @@ import ( "context" "sync" + "gitlab.com/tozd/go/errors" "go.alanpearce.eu/searchix/internal/index" "go.alanpearce.eu/searchix/internal/nix" "go.alanpearce.eu/x/log" ) type Processor interface { - Process(context.Context) (<-chan nix.Importable, <-chan error) + Process(context.Context) (<-chan nix.Importable, <-chan errors.E) } func process( @@ -18,7 +19,7 @@ func process( indexer *index.WriteIndex, processor Processor, logger *log.Logger, -) (bool, error) { +) (bool, errors.E) { wg := sync.WaitGroup{} wg.Add(1) @@ -28,7 +29,7 @@ func process( iErrs := indexer.Import(ctx, objects) var hadObjectErrors bool - var criticalError error + var criticalError errors.E go func() { for { select { diff --git a/internal/importer/main.go b/internal/importer/main.go index 7181926..e2c222c 100644 --- a/internal/importer/main.go +++ b/internal/importer/main.go @@ -14,7 +14,7 @@ import ( "go.alanpearce.eu/searchix/internal/programs" "go.alanpearce.eu/x/log" - "github.com/pkg/errors" + "gitlab.com/tozd/go/errors" ) func createSourceImporter( @@ -23,8 +23,8 @@ func createSourceImporter( meta *index.Meta, indexer *index.WriteIndex, forceUpdate bool, -) func(*config.Source) error { - return func(source *config.Source) error { +) func(*config.Source) errors.E { + return func(source *config.Source) errors.E { logger := log.With( "name", source.Key, @@ -165,7 +165,7 @@ func (imp *Importer) Start( ctx context.Context, forceUpdate bool, onlyUpdateSources *[]string, -) error { +) errors.E { if len(imp.config.Importer.Sources) == 0 { imp.log.Info("No sources enabled") diff --git a/internal/importer/options.go b/internal/importer/options.go index 763f57f..a586a3f 100644 --- a/internal/importer/options.go +++ b/internal/importer/options.go @@ -11,7 +11,7 @@ import ( "github.com/bcicen/jstream" "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" + "gitlab.com/tozd/go/errors" ) type nixValueJSON struct { @@ -68,7 +68,7 @@ func NewOptionProcessor( infile io.ReadCloser, source *config.Source, log *log.Logger, -) (*OptionIngester, error) { +) (*OptionIngester, errors.E) { i := OptionIngester{ dec: jstream.NewDecoder(infile, 1).EmitKV(), log: log, @@ -94,9 +94,9 @@ func NewOptionProcessor( return &i, nil } -func (i *OptionIngester) Process(ctx context.Context) (<-chan nix.Importable, <-chan error) { +func (i *OptionIngester) Process(ctx context.Context) (<-chan nix.Importable, <-chan errors.E) { results := make(chan nix.Importable) - errs := make(chan error) + errs := make(chan errors.E) go func() { defer i.infile.Close() diff --git a/internal/importer/package.go b/internal/importer/package.go index 59bccd8..34293a7 100644 --- a/internal/importer/package.go +++ b/internal/importer/package.go @@ -14,7 +14,7 @@ import ( "github.com/bcicen/jstream" "github.com/mitchellh/mapstructure" - "github.com/pkg/errors" + "gitlab.com/tozd/go/errors" ) type packageJSON struct { @@ -69,7 +69,7 @@ func NewPackageProcessor( source *config.Source, log *log.Logger, programsDB *programs.DB, -) (*PackageIngester, error) { +) (*PackageIngester, errors.E) { i := &PackageIngester{ dec: jstream.NewDecoder(infile, 2).EmitKV(), log: log, @@ -116,9 +116,9 @@ func convertToLicense(in map[string]any) *nix.License { return l } -func (i *PackageIngester) Process(ctx context.Context) (<-chan nix.Importable, <-chan error) { +func (i *PackageIngester) Process(ctx context.Context) (<-chan nix.Importable, <-chan errors.E) { results := make(chan nix.Importable) - errs := make(chan error) + errs := make(chan errors.E) if i.programs != nil { err := i.programs.Open() @@ -135,7 +135,7 @@ func (i *PackageIngester) Process(ctx context.Context) (<-chan nix.Importable, < outer: for mv := range i.dec.Stream() { - var err error + var err errors.E var programs []string select { case <-ctx.Done(): @@ -222,8 +222,7 @@ func (i *PackageIngester) Process(ctx context.Context) (<-chan nix.Importable, < } i.pkg = packageJSON{} - err = i.ms.Decode(x) // stores in i.pkg - if err != nil { + if err := i.ms.Decode(x); err != nil { // stores in i.pkg errs <- errors.WithMessagef(err, "failed to decode package %#v", x) continue diff --git a/internal/importer/utils.go b/internal/importer/utils.go index da10735..0ca6890 100644 --- a/internal/importer/utils.go +++ b/internal/importer/utils.go @@ -10,7 +10,7 @@ import ( "go.alanpearce.eu/searchix/internal/nix" "github.com/bcicen/jstream" - "github.com/pkg/errors" + "gitlab.com/tozd/go/errors" ) func ValueTypeToString(valueType jstream.ValueType) string { @@ -34,7 +34,7 @@ func ValueTypeToString(valueType jstream.ValueType) string { return "very strange" } -func makeRepoURL(repo config.Repository, subPath string, line string) (string, error) { +func makeRepoURL(repo config.Repository, subPath string, line string) (string, errors.E) { switch repo.Type { case config.GitHub: ref := repo.Revision @@ -55,7 +55,7 @@ func makeRepoURL(repo config.Repository, subPath string, line string) (string, e } } -func MakeChannelLink(repo config.Repository, subPath string) (*nix.Link, error) { +func MakeChannelLink(repo config.Repository, subPath string) (*nix.Link, errors.E) { url, err := makeRepoURL(repo, subPath, "") if err != nil { return nil, err @@ -67,7 +67,7 @@ func MakeChannelLink(repo config.Repository, subPath string) (*nix.Link, error) }, nil } -func setRepoRevision(file io.ReadCloser, source *config.Source) error { +func setRepoRevision(file io.ReadCloser, source *config.Source) errors.E { if file != nil { defer file.Close() var str strings.Builder diff --git a/internal/index/index_meta.go b/internal/index/index_meta.go index 336bae0..635965a 100644 --- a/internal/index/index_meta.go +++ b/internal/index/index_meta.go @@ -8,7 +8,7 @@ import ( "go.alanpearce.eu/searchix/internal/file" "go.alanpearce.eu/x/log" - "github.com/pkg/errors" + "gitlab.com/tozd/go/errors" ) const CurrentSchemaVersion = 3 @@ -31,7 +31,7 @@ type Meta struct { data } -func createMeta(path string, log *log.Logger) (*Meta, error) { +func createMeta(path string, log *log.Logger) (*Meta, errors.E) { exists, err := file.Exists(path) if err != nil { return nil, errors.WithMessage(err, "could not check for existence of index metadata") @@ -49,7 +49,7 @@ func createMeta(path string, log *log.Logger) (*Meta, error) { }, nil } -func openMeta(path string, log *log.Logger) (*Meta, error) { +func openMeta(path string, log *log.Logger) (*Meta, errors.E) { exists, err := file.Exists(path) if err != nil { return nil, errors.WithMessage(err, "could not check for existence of index metadata") @@ -58,16 +58,16 @@ func openMeta(path string, log *log.Logger) (*Meta, error) { return createMeta(path, log) } - j, err := os.ReadFile(path) - if err != nil { - return nil, errors.WithMessage(err, "could not open index metadata file") + j, baseErr := os.ReadFile(path) + if baseErr != nil { + return nil, errors.WithMessage(baseErr, "could not open index metadata file") } meta := Meta{ path: path, log: log, } - err = json.Unmarshal(j, &meta.data) - if err != nil { + + if err := json.Unmarshal(j, &meta.data); err != nil { return nil, errors.WithMessage(err, "index metadata is corrupt, try replacing the index") } @@ -88,7 +88,7 @@ func (i *Meta) checkSchemaVersion() { } } -func (i *Meta) Save() error { +func (i *Meta) Save() errors.E { i.SchemaVersion = CurrentSchemaVersion j, err := json.Marshal(i.data) if err != nil { diff --git a/internal/index/indexer.go b/internal/index/indexer.go index 6a1dcf0..6000358 100644 --- a/internal/index/indexer.go +++ b/internal/index/indexer.go @@ -26,7 +26,7 @@ import ( "github.com/blevesearch/bleve/v2/document" "github.com/blevesearch/bleve/v2/mapping" indexAPI "github.com/blevesearch/bleve_index_api" - "github.com/pkg/errors" + "gitlab.com/tozd/go/errors" ) type WriteIndex struct { @@ -36,16 +36,16 @@ type WriteIndex struct { } type BatchError struct { - error + errors.E } func (e *BatchError) Error() string { - return e.error.Error() + return e.E.Error() } var batchSize = 10_000 -func createIndexMapping() (mapping.IndexMapping, error) { +func createIndexMapping() (mapping.IndexMapping, errors.E) { indexMapping := bleve.NewIndexMapping() indexMapping.StoreDynamic = false indexMapping.IndexDynamic = false @@ -124,7 +124,7 @@ func createIndexMapping() (mapping.IndexMapping, error) { return indexMapping, nil } -func createIndex(indexPath string, options *Options) (bleve.Index, error) { +func createIndex(indexPath string, options *Options) (bleve.Index, errors.E) { indexMapping, err := createIndexMapping() if err != nil { return nil, err @@ -136,15 +136,15 @@ func createIndex(indexPath string, options *Options) (bleve.Index, error) { "PersisterNapUnderNumFiles": 500, } } - idx, err := bleve.NewUsing( + idx, baseErr := bleve.NewUsing( indexPath, indexMapping, bleve.Config.DefaultIndexType, bleve.Config.DefaultKVStore, kvconfig, ) - if err != nil { - return nil, errors.WithMessagef(err, "unable to create index at path %s", indexPath) + if baseErr != nil { + return nil, errors.WithMessagef(baseErr, "unable to create index at path %s", indexPath) } return idx, nil @@ -162,7 +162,7 @@ var expectedDataFiles = []string{ "nixpkgs-programs.db", } -func deleteIndex(dataRoot string) error { +func deleteIndex(dataRoot string) errors.E { dir, err := os.ReadDir(dataRoot) if err != nil { return errors.WithMessagef(err, "could not read data directory %s", dataRoot) @@ -195,8 +195,8 @@ func OpenOrCreate( dataRoot string, force bool, options *Options, -) (*ReadIndex, *WriteIndex, bool, error) { - var err error +) (*ReadIndex, *WriteIndex, bool, errors.E) { + var err errors.E bleve.SetLog(zap.NewStdLog(options.Logger.Named("bleve").GetLogger())) indexPath := path.Join(dataRoot, indexBaseName) @@ -231,9 +231,10 @@ func OpenOrCreate( } } else { - idx, err = bleve.Open(indexPath) - if err != nil { - return nil, nil, exists, errors.WithMessagef(err, "could not open index at path %s", indexPath) + var baseErr error + idx, baseErr = bleve.Open(indexPath) + if baseErr != nil { + return nil, nil, exists, errors.WithMessagef(baseErr, "could not open index at path %s", indexPath) } meta, err = openMeta(metaPath, options.Logger) @@ -260,16 +261,16 @@ func OpenOrCreate( nil } -func (i *WriteIndex) SaveMeta() error { +func (i *WriteIndex) SaveMeta() errors.E { return i.Meta.Save() } func (i *WriteIndex) Import( ctx context.Context, objects <-chan nix.Importable, -) <-chan error { - var err error - errs := make(chan error) +) <-chan errors.E { + var err errors.E + errs := make(chan errors.E) go func() { defer close(errs) @@ -288,8 +289,7 @@ func (i *WriteIndex) Import( } doc := document.NewDocument(nix.GetKey(obj)) - err = indexMapping.MapDocument(doc, obj) - if err != nil { + if err := indexMapping.MapDocument(doc, obj); err != nil { errs <- errors.WithMessagef(err, "could not map document for object: %s", obj.GetName()) continue @@ -297,8 +297,7 @@ func (i *WriteIndex) Import( var data bytes.Buffer enc := gob.NewEncoder(&data) - err = enc.Encode(&obj) - if err != nil { + if err := enc.Encode(&obj); err != nil { errs <- errors.WithMessage(err, "could not store object in search index") continue @@ -307,9 +306,7 @@ func (i *WriteIndex) Import( newDoc := doc.AddField(field) // log.Debug("adding object to index", "name", opt.Name) - err = batch.IndexAdvanced(newDoc) - - if err != nil { + if err := batch.IndexAdvanced(newDoc); err != nil { errs <- errors.WithMessagef(err, "could not index object %s", obj.GetName()) continue @@ -334,11 +331,11 @@ func (i *WriteIndex) Import( return errs } -func (i *WriteIndex) Flush(batch *bleve.Batch) error { +func (i *WriteIndex) Flush(batch *bleve.Batch) errors.E { size := batch.Size() if size == 0 { return &BatchError{ - error: errors.New("no documents to flush"), + E: errors.New("no documents to flush"), } } i.log.Debug("flushing batch", "size", size) @@ -346,7 +343,7 @@ func (i *WriteIndex) Flush(batch *bleve.Batch) error { err := i.index.Batch(batch) if err != nil { return &BatchError{ - error: errors.WithMessagef(err, "could not flush batch"), + E: errors.WithMessagef(err, "could not flush batch"), } } @@ -355,7 +352,7 @@ func (i *WriteIndex) Flush(batch *bleve.Batch) error { return nil } -func (i *WriteIndex) Close() (err error) { +func (i *WriteIndex) Close() (err errors.E) { if e := i.Meta.Save(); e != nil { // index needs to be closed anyway err = errors.WithMessage(e, "could not save metadata") @@ -368,7 +365,7 @@ func (i *WriteIndex) Close() (err error) { return err } -func (i *WriteIndex) DeleteBySource(source string) error { +func (i *WriteIndex) DeleteBySource(source string) errors.E { query := bleve.NewTermQuery(source) search := bleve.NewSearchRequest(query) search.Size = math.MaxInt @@ -392,7 +389,7 @@ func (i *WriteIndex) DeleteBySource(source string) error { } err = i.Flush(batch) if err != nil { - return err + return errors.WithStack(err) } if uint64(search.Size) < results.Total { diff --git a/internal/index/search.go b/internal/index/search.go index 50a5ce2..3f9c13a 100644 --- a/internal/index/search.go +++ b/internal/index/search.go @@ -12,7 +12,7 @@ import ( "github.com/blevesearch/bleve/v2" "github.com/blevesearch/bleve/v2/search" "github.com/blevesearch/bleve/v2/search/query" - "github.com/pkg/errors" + "gitlab.com/tozd/go/errors" ) const DefaultPageSize = 100 @@ -33,7 +33,7 @@ type ReadIndex struct { meta *Meta } -func (index *ReadIndex) GetEnabledSources() ([]string, error) { +func (index *ReadIndex) GetEnabledSources() ([]string, errors.E) { facet := bleve.NewFacetRequest("Source", 100) query := bleve.NewMatchAllQuery() search := bleve.NewSearchRequest(query) @@ -64,13 +64,13 @@ func setField[T query.FieldableQuery]( func (index *ReadIndex) search( ctx context.Context, request *bleve.SearchRequest, -) (*Result, error) { +) (*Result, errors.E) { request.Fields = []string{"_data", "Source"} bleveResult, err := index.index.SearchInContext(ctx, request) select { case <-ctx.Done(): - return nil, ctx.Err() + return nil, errors.WithStack(ctx.Err()) default: if err != nil { return nil, errors.WithMessage(err, "failed to execute search query") @@ -104,7 +104,7 @@ func (index *ReadIndex) Search( keyword string, from int, pageSize int, -) (*Result, error) { +) (*Result, errors.E) { query := bleve.NewBooleanQuery() // match the user's query in any field ... @@ -157,7 +157,7 @@ func (index *ReadIndex) GetDocument( ctx context.Context, source *config.Source, id string, -) (*nix.Importable, error) { +) (*nix.Importable, errors.E) { key := nix.MakeKey(source, id) query := bleve.NewDocIDQuery([]string{key}) search := bleve.NewSearchRequest(query) diff --git a/internal/programs/programs.go b/internal/programs/programs.go index 5088444..090bcf1 100644 --- a/internal/programs/programs.go +++ b/internal/programs/programs.go @@ -7,7 +7,7 @@ import ( "os/exec" "strings" - "github.com/pkg/errors" + "gitlab.com/tozd/go/errors" "go.alanpearce.eu/searchix/internal/config" "go.alanpearce.eu/x/log" _ "modernc.org/sqlite" //nolint:blank-imports // sqlite driver needed for database/sql @@ -26,7 +26,7 @@ func Instantiate( ctx context.Context, source *config.Source, logger *log.Logger, -) (*DB, error) { +) (*DB, errors.E) { // nix-instantiate --eval --json -I nixpkgs=channel:nixos-unstable --expr 'toString <nixpkgs/programs.sqlite>' args := []string{ "--eval", @@ -53,7 +53,7 @@ func Instantiate( }, nil } -func (p *DB) Open() error { +func (p *DB) Open() errors.E { var err error p.db, err = sql.Open("sqlite", p.Path) if err != nil { @@ -96,7 +96,7 @@ WHERE package = ? return nil } -func (p *DB) Close() error { +func (p *DB) Close() errors.E { if err := p.db.Close(); err != nil { return errors.WithMessage(err, "failed to close sqlite database") } @@ -104,7 +104,8 @@ func (p *DB) Close() error { return nil } -func (p *DB) GetPackagePrograms(ctx context.Context, pkg string) (programs []string, err error) { +func (p *DB) GetPackagePrograms(ctx context.Context, pkg string) ([]string, errors.E) { + programs := make([]string, 10) if p.db == nil { return nil, errors.New("database not open") } @@ -127,5 +128,5 @@ func (p *DB) GetPackagePrograms(ctx context.Context, pkg string) (programs []str return nil, errors.WithMessage(rerr, "sql error") } - return + return programs, nil } diff --git a/internal/server/dev.go b/internal/server/dev.go index f5fd4fd..89ac069 100644 --- a/internal/server/dev.go +++ b/internal/server/dev.go @@ -8,7 +8,7 @@ import ( "time" "github.com/fsnotify/fsnotify" - "github.com/pkg/errors" + "gitlab.com/tozd/go/errors" "go.alanpearce.eu/x/log" ) @@ -17,7 +17,7 @@ type FileWatcher struct { log *log.Logger } -func NewFileWatcher(log *log.Logger) (*FileWatcher, error) { +func NewFileWatcher(log *log.Logger) (*FileWatcher, errors.E) { watcher, err := fsnotify.NewWatcher() if err != nil { return nil, errors.WithMessage(err, "could not create watcher") @@ -29,7 +29,7 @@ func NewFileWatcher(log *log.Logger) (*FileWatcher, error) { }, nil } -func (i FileWatcher) AddRecursive(from string) error { +func (i FileWatcher) AddRecursive(from string) errors.E { i.log.Debug(fmt.Sprintf("watching files under %s", from)) err := filepath.WalkDir(from, func(path string, entry fs.DirEntry, err error) error { if err != nil { diff --git a/internal/server/logging.go b/internal/server/logging.go index 5930b9d..e11b16f 100644 --- a/internal/server/logging.go +++ b/internal/server/logging.go @@ -3,7 +3,7 @@ package server import ( "net/http" - "github.com/pkg/errors" + "gitlab.com/tozd/go/errors" "go.alanpearce.eu/x/log" ) diff --git a/internal/server/mux.go b/internal/server/mux.go index 37435d4..1507860 100644 --- a/internal/server/mux.go +++ b/internal/server/mux.go @@ -25,7 +25,7 @@ import ( "go.alanpearce.eu/x/log" "github.com/osdevisnot/sorvor/pkg/livereload" - "github.com/pkg/errors" + "gitlab.com/tozd/go/errors" ) type HTTPError struct { @@ -65,7 +65,7 @@ func NewMux( index *search.ReadIndex, log *log.Logger, liveReload bool, -) (*http.ServeMux, error) { +) (*http.ServeMux, errors.E) { if cfg == nil { return nil, errors.New("cfg is nil") } @@ -171,15 +171,16 @@ func NewMux( w.Header().Add("Cache-Control", "max-age=300") w.Header().Add("Vary", "Fetch") + var baseErr error if r.Header.Get("Fetch") == "true" { w.Header().Add("Content-Type", "text/html; charset=utf-8") - err = components.Results(tdata).Render(r.Context(), w) + baseErr = components.Results(tdata).Render(r.Context(), w) } else { - err = components.ResultsPage(tdata).Render(r.Context(), w) + baseErr = components.ResultsPage(tdata).Render(r.Context(), w) } - if err != nil { - log.Error("template error", "template", importerType, "error", err) - errorHandler(w, r, err.Error(), http.StatusInternalServerError) + if baseErr != nil { + log.Error("template error", "template", importerType, "error", baseErr) + errorHandler(w, r, baseErr.Error(), http.StatusInternalServerError) } } else { w.Header().Add("Cache-Control", "max-age=14400") @@ -244,15 +245,16 @@ func NewMux( Sources: sources, Assets: frontend.Assets, } + var baseErr error if r.Header.Get("Fetch") == "true" { w.Header().Add("Content-Type", "text/html; charset=utf-8") - err = components.Detail(*doc).Render(r.Context(), w) + baseErr = components.Detail(*doc).Render(r.Context(), w) } else { - err = components.DetailPage(tdata, *doc).Render(r.Context(), w) + baseErr = components.DetailPage(tdata, *doc).Render(r.Context(), w) } - if err != nil { - log.Error("template error", "template", importerSingular, "error", err) - errorHandler(w, r, err.Error(), http.StatusInternalServerError) + if baseErr != nil { + log.Error("template error", "template", importerSingular, "error", baseErr) + errorHandler(w, r, baseErr.Error(), http.StatusInternalServerError) } } } diff --git a/internal/server/server.go b/internal/server/server.go index aacef30..17d3512 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -11,7 +11,7 @@ import ( "go.alanpearce.eu/searchix/internal/index" "go.alanpearce.eu/x/log" - "github.com/pkg/errors" + "gitlab.com/tozd/go/errors" "golang.org/x/net/http2" "golang.org/x/net/http2/h2c" ) @@ -28,7 +28,7 @@ func New( index *index.ReadIndex, log *log.Logger, liveReload bool, -) (*Server, error) { +) (*Server, errors.E) { mux, err := NewMux(conf, index, log, liveReload) if err != nil { return nil, err @@ -49,7 +49,7 @@ func New( }, nil } -func (s *Server) Start() error { +func (s *Server) Start() errors.E { listenAddress := net.JoinHostPort(s.cfg.Web.ListenAddress, strconv.Itoa(s.cfg.Web.Port)) l, err := net.Listen("tcp", listenAddress) if err != nil { diff --git a/searchix.go b/searchix.go index be76af6..1c870df 100644 --- a/searchix.go +++ b/searchix.go @@ -14,7 +14,7 @@ import ( "go.alanpearce.eu/x/log" "github.com/getsentry/sentry-go" - "github.com/pkg/errors" + "gitlab.com/tozd/go/errors" ) func nextUTCOccurrenceOfTime(t config.LocalTime) time.Time { @@ -44,7 +44,7 @@ type IndexOptions struct { Logger *log.Logger } -func (s *Server) SetupIndex(ctx context.Context, options *IndexOptions) error { +func (s *Server) SetupIndex(ctx context.Context, options *IndexOptions) errors.E { var i uint cfgEnabledSources := make([]string, len(s.cfg.Importer.Sources)) for key := range s.cfg.Importer.Sources { @@ -139,7 +139,7 @@ type Server struct { writeIndex *index.WriteIndex } -func New(cfg *config.Config, log *log.Logger) (*Server, error) { +func New(cfg *config.Config, log *log.Logger) (*Server, errors.E) { err := sentry.Init(sentry.ClientOptions{ EnableTracing: true, TracesSampleRate: 1.0, @@ -164,7 +164,7 @@ func (s *Server) startUpdateTimer( ) { const monitorSlug = "import" localHub.WithScope(func(scope *sentry.Scope) { - var err error + var err errors.E scope.SetContext("monitor", sentry.Context{"slug": monitorSlug}) monitorConfig := &sentry.MonitorConfig{ Schedule: sentry.IntervalSchedule(1, sentry.MonitorScheduleUnitDay), @@ -219,8 +219,8 @@ func (s *Server) startUpdateTimer( }) } -func (s *Server) Start(ctx context.Context, liveReload bool) error { - var err error +func (s *Server) Start(ctx context.Context, liveReload bool) errors.E { + var err errors.E s.sv, err = server.New(s.cfg, s.readIndex, s.log.Named("server"), liveReload) if err != nil { return errors.Wrap(err, "error setting up server") |