about summary refs log tree commit diff stats
path: root/internal/importer/main.go
blob: 77764824851df5ef352414c68066f9e1f4d11349 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package importer

import (
	"context"
	"io"
	"log/slog"
	"os/exec"
	"path"
	"searchix/internal/config"
	"searchix/internal/fetcher"
	"searchix/internal/index"
	"strings"

	"github.com/pkg/errors"
)

func Start(cfg *config.Config, indexer *index.WriteIndex, replace bool) error {
	if len(cfg.Importer.Sources) == 0 {
		slog.Info("No sources enabled")

		return nil
	}

	ctx, cancel := context.WithTimeout(context.Background(), cfg.Importer.Timeout.Duration)
	defer cancel()

	for name, source := range cfg.Importer.Sources {
		logger := slog.With("name", name, "fetcher", source.Fetcher.String())
		logger.Debug("starting fetcher")

		fetcherDataPath := path.Join(cfg.DataPath, "sources", source.Key)

		fetcher, err := fetcher.New(source, fetcherDataPath, logger)
		if err != nil {
			logger.Warn("error creating fetcher", "error", err)

			continue
		}

		files, updated, err := fetcher.FetchIfNeeded(ctx)

		if err != nil {
			var exerr *exec.ExitError
			if errors.As(err, &exerr) {
				lines := strings.Split(strings.TrimSpace(string(exerr.Stderr)), "\n")
				for _, line := range lines {
					logger.Warn("importer fetch failed", "stderr", line, "status", exerr.ExitCode())
				}
			} else {
				logger.Warn("importer fetch failed", "error", err)
			}

			continue
		}
		logger.Info("importer fetch succeeded", "updated", updated)

		if updated || replace {
			err = setRepoRevision(files.Revision, source)
			if err != nil {
				logger.Warn("could not set source repo revision", "error", err)
			}

			var file io.ReadCloser
			var processor Processor
			switch source.Importer {
			case config.Options:
				logger.Debug(
					"creating processor",
					"filename",
					files.Options,
					"revision",
					source.Repo.Revision,
				)
				file, err = openFileDecoded(files.Options)
				if err != nil {
					logger.Warn("could not open file", "filename", files.Options, "error", err)
				}
				processor, err = NewOptionProcessor(file, source)
			case config.Packages:
				logger.Debug(
					"creating processor",
					"filename",
					files.Packages,
					"revision",
					source.Repo.Revision,
				)
				file, err = openFileDecoded(files.Packages)
				if err != nil {
					logger.Warn("could not open file", "filename", files.Packages, "error", err)
				}
				processor, err = NewPackageProcessor(file, source)
			}
			if err != nil {
				logger.Warn("failed to create processor", "type", source.Importer, "error", err)
			}

			hadWarnings := process(ctx, indexer, processor, logger)

			if hadWarnings {
				logger.Warn("importer succeeded, but with warnings/errors")
			} else {
				logger.Info("importer succeeded")
			}
		}
	}

	return nil
}