1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package gitcli_test
4
5import (
6 "archive/tar"
7 "bytes"
8 "compress/gzip"
9 "context"
10 "io"
11 "strings"
12 "testing"
13
14 "github.com/stretchr/testify/assert"
15 "github.com/stretchr/testify/require"
16
17 "bnema.dev/ermite/internal/domain"
18)
19
20func TestArchiveWritesAGzipTarUnderThePrefix(t *testing.T) {
21 g, data := newGit(t)
22 ctx := context.Background()
23 m := newMergeFixture(t, data)
24 t.Cleanup(func() { _ = g.Close(ctx) })
25
26 var buf bytes.Buffer
27 require.NoError(t, g.Archive(ctx, m.f.Name, m.d, "owner-proj-abcdef0", &buf))
28 zr, err := gzip.NewReader(&buf)
29 require.NoError(t, err)
30 tr := tar.NewReader(zr)
31 files := map[string]string{}
32 for {
33 h, err := tr.Next()
34 if err == io.EOF {
35 break
36 }
37 require.NoError(t, err)
38 if h.Typeflag == tar.TypeXGlobalHeader {
39 // git archive records the commit id here, as GitHub's tarballs do.
40 assert.Equal(t, m.d.String(), h.PAXRecords["comment"])
41 continue
42 }
43 require.True(t, strings.HasPrefix(h.Name, "owner-proj-abcdef0/"), h.Name)
44 if h.Typeflag == tar.TypeReg {
45 b, _ := io.ReadAll(tr)
46 files[h.Name] = string(b)
47 }
48 }
49 assert.Equal(t, "one\n2\nthree\n", files["owner-proj-abcdef0/a.txt"], "the tree of the commit asked, not of HEAD")
50 assert.Equal(t, "see\n", files["owner-proj-abcdef0/c.txt"])
51 assert.NotContains(t, files, "owner-proj-abcdef0/.git")
52}
53
54func TestArchiveOfAMissingCommitWritesNothing(t *testing.T) {
55 g, data := newGit(t)
56 ctx := context.Background()
57 m := newMergeFixture(t, data)
58 t.Cleanup(func() { _ = g.Close(ctx) })
59
60 var buf bytes.Buffer
61 missing, err := domain.ParseObjectID(strings.Repeat("1", 40))
62 require.NoError(t, err)
63 err = g.Archive(ctx, m.f.Name, missing, "p", &buf)
64 assert.ErrorIs(t, err, domain.ErrNotFound)
65 assert.Zero(t, buf.Len(), "nothing was written, so the caller can still answer 404")
66
67 err = g.Archive(ctx, name(t, "nope"), m.d, "p", &buf)
68 assert.ErrorIs(t, err, domain.ErrNotFound)
69}
70
71func TestArchiveStopsWithItsContext(t *testing.T) {
72 g, data := newGit(t)
73 m := newMergeFixture(t, data)
74 t.Cleanup(func() { _ = g.Close(context.Background()) })
75
76 ctx, cancel := context.WithCancel(context.Background())
77 cancel()
78 err := g.Archive(ctx, m.f.Name, m.d, "p", io.Discard)
79 assert.ErrorIs(t, err, context.Canceled)
80}