about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAlan Pearce2024-05-14 17:24:31 +0200
committerAlan Pearce2024-05-14 17:24:31 +0200
commitdf3b6bfd571c38aa7099838aa43bb3aff0eff2bf (patch)
tree5695d3a1d537b3456c13b60b0bb10a444ad39089
parent5f9c7ef00b1ed56fb1abbade4d5dbc3041acd4fc (diff)
downloadsearchix-df3b6bfd571c38aa7099838aa43bb3aff0eff2bf.tar.lz
searchix-df3b6bfd571c38aa7099838aa43bb3aff0eff2bf.tar.zst
searchix-df3b6bfd571c38aa7099838aa43bb3aff0eff2bf.zip
feat: add DownloadOptions importer (fetches pre-built options.json)
-rw-r--r--internal/config/source.go5
-rw-r--r--internal/importer/download-options.go87
-rw-r--r--internal/importer/importer.go14
-rw-r--r--internal/importer/main.go2
4 files changed, 108 insertions, 0 deletions
diff --git a/internal/config/source.go b/internal/config/source.go
index 2b1b440..28451e3 100644
--- a/internal/config/source.go
+++ b/internal/config/source.go
@@ -13,6 +13,7 @@ const (
 	Unknown = iota
 	Channel
 	ChannelNixpkgs
+	DownloadOptions
 )
 
 func (f Type) String() string {
@@ -21,6 +22,8 @@ func (f Type) String() string {
 		return "channel"
 	case ChannelNixpkgs:
 		return "channel-nixpkgs"
+	case DownloadOptions:
+		return "download-options"
 	}
 
 	return fmt.Sprintf("Fetcher(%d)", f)
@@ -32,6 +35,8 @@ func parseType(name string) (Type, error) {
 		return Channel, nil
 	case "channel-nixpkgs":
 		return ChannelNixpkgs, nil
+	case "download-options":
+		return DownloadOptions, nil
 	default:
 		return Unknown, fmt.Errorf("unsupported fetcher %s", name)
 	}
diff --git a/internal/importer/download-options.go b/internal/importer/download-options.go
new file mode 100644
index 0000000..6727138
--- /dev/null
+++ b/internal/importer/download-options.go
@@ -0,0 +1,87 @@
+package importer
+
+import (
+	"bytes"
+	"context"
+	"log/slog"
+	"net/url"
+	"os"
+	"path"
+	"searchix/internal/config"
+	"searchix/internal/file"
+	"searchix/internal/index"
+
+	"github.com/pkg/errors"
+)
+
+type DownloadOptionsImporter struct {
+	DataPath   string
+	Source     *config.Source
+	SourceFile string
+	Logger     *slog.Logger
+}
+
+var optionsFiles = map[string]string{
+	"revision": "revision",
+	"options":  "options.json",
+}
+
+func (i *DownloadOptionsImporter) FetchIfNeeded(parent context.Context) (bool, error) {
+	ctx, cancel := context.WithTimeout(parent, i.Source.FetchTimeout)
+	defer cancel()
+
+	root := i.DataPath
+
+	err := file.Mkdirp(root)
+	if err != nil {
+		return false, errors.WithMessagef(err, "error creating directory for data: %s", root)
+	}
+
+	var updated bool
+	for _, filename := range optionsFiles {
+		url, err := url.JoinPath(i.Source.URL, filename)
+		if err != nil {
+			return false, errors.WithMessagef(
+				err,
+				"could not build URL with elements %s and %s",
+				i.Source.URL,
+				filename,
+			)
+		}
+
+		path := path.Join(root, filename)
+
+		i.Logger.Debug("preparing to fetch URL", "url", url, "path", path)
+
+		updated, err = fetchFileIfNeeded(ctx, path, url)
+		if err != nil {
+			return false, err
+		}
+		// don't bother to issue requests for the later files
+		if !updated {
+			return false, err
+		}
+	}
+
+	return updated, nil
+}
+
+func (i *DownloadOptionsImporter) Import(
+	parent context.Context,
+	indexer *index.WriteIndex,
+) (bool, error) {
+	filename := path.Join(i.DataPath, optionsFiles["options"])
+	revFilename := path.Join(i.DataPath, optionsFiles["revision"])
+	bits, err := os.ReadFile(revFilename)
+	if err != nil {
+		return false, errors.WithMessagef(err, "unable to read revision file at %s", revFilename)
+	}
+	i.Source.Repo.Revision = string(bytes.TrimSpace(bits))
+	i.Logger.Debug("preparing import run", "revision", i.Source.Repo.Revision, "filename", filename)
+
+	return processOptions(parent, indexer, &importConfig{
+		Source:   i.Source,
+		Filename: filename,
+		Logger:   i.Logger,
+	})
+}
diff --git a/internal/importer/importer.go b/internal/importer/importer.go
index b66b6d3..c50a72b 100644
--- a/internal/importer/importer.go
+++ b/internal/importer/importer.go
@@ -42,6 +42,20 @@ func NewChannelImporter(
 	}
 }
 
+func NewDownloadOptionsImporter(
+	source *config.Source,
+	dataPath string,
+	logger *slog.Logger,
+) *DownloadOptionsImporter {
+	fullpath := path.Join(dataPath, source.Channel)
+
+	return &DownloadOptionsImporter{
+		DataPath: fullpath,
+		Source:   source,
+		Logger:   logger,
+	}
+}
+
 type importConfig struct {
 	Filename string
 	Source   *config.Source
diff --git a/internal/importer/main.go b/internal/importer/main.go
index 2d87e33..0b7a99d 100644
--- a/internal/importer/main.go
+++ b/internal/importer/main.go
@@ -34,6 +34,8 @@ func Start(cfg *config.Config, indexer *index.WriteIndex, replace bool) error {
 			imp = NewNixpkgsChannelImporter(source, importerDataPath, logger)
 		case config.Channel:
 			imp = NewChannelImporter(source, importerDataPath, logger)
+		case config.DownloadOptions:
+			imp = NewDownloadOptionsImporter(source, importerDataPath, logger)
 		default:
 			log.Printf("unsupported importer type %s", source.Type.String())