1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package ermitegit_test
4
5import (
6 "context"
7 "os"
8 "os/exec"
9 "path/filepath"
10 "testing"
11 "time"
12
13 "github.com/stretchr/testify/require"
14
15 "bnema.dev/ermite/internal/adapters/ermitegit"
16 "bnema.dev/ermite/internal/adapters/gitcli"
17 "bnema.dev/ermite/internal/domain"
18)
19
20// newAdapter prepares a data directory and an ermitegit adapter around a
21// gitcli reader, with the given routes. Without git it skips locally and
22// fails when CI is set. Both are closed when the test ends.
23func newAdapter(t testing.TB, routes ermitegit.Routes, tune func(*ermitegit.Config)) (*ermitegit.Adapter, *gitcli.Git, string) {
24 t.Helper()
25 bin, err := exec.LookPath("git")
26 if err != nil {
27 unusable(t, "git not found")
28 }
29 data := t.TempDir()
30 for _, d := range []string{"repos/.staging", "trash", "run/git-home", "kv"} {
31 require.NoError(t, os.MkdirAll(filepath.Join(data, d), 0o700))
32 }
33 g := gitcli.New(gitcli.Config{Bin: bin, DataDir: data, Path: os.Getenv("PATH")})
34 if _, err := g.CheckVersion(context.Background()); err != nil {
35 unusable(t, "git is not usable by ermite: %v", err)
36 }
37 cfg := ermitegit.Config{
38 Fallback: g,
39 RepoDir: func(n domain.RepoName) string { return gitcli.RepoDir(data, n) },
40 Routes: &routes,
41 }
42 if tune != nil {
43 tune(&cfg)
44 }
45 a := ermitegit.New(cfg)
46 g.OnTrash(a.Forget)
47 t.Cleanup(func() {
48 a.Close()
49 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
50 defer cancel()
51 require.NoError(t, g.Close(ctx))
52 })
53 return a, g, data
54}
55
56// unusable skips the test, or fails it in CI so that CI cannot pass vacuously.
57func unusable(t testing.TB, format string, args ...any) {
58 t.Helper()
59 if os.Getenv("CI") != "" {
60 t.Fatalf(format, args...)
61 }
62 t.Skipf(format, args...)
63}