Skip to content
quarry Artifact [b20357c081]
Login

Artifact [b20357c081]

Artifact b20357c081a2644cd2566e870577bef07fbee130617265220af70969840113de:


package index

import (
	"strings"
	"testing"

	"craftdesign.group/quarry/internal/artifact"
)

// A TAG ADDED TO A CHECK-IN IS ONE ROW, ON THE CHECK-IN THAT CARRIES IT
// (RFC 0020 §releases, the `tag` event).
//
// What counts is what a person means by tagging: `fossil tag add NAME
// CHECKIN` writes `+sym-NAME`, `fossil commit --tag NAME` writes the
// same card inline, and `*sym-NAME` without a branch is a propagating
// tag on its carrier only. A branch's own `sym-` names, raw tags
// (closed, hidden, comment, ci-pass), cancellations, a tag since
// cancelled, and a tag on something that is not a check-in do not.
func TestTagsAddedListsTagsAddedToCheckins(t *testing.T) {
	ix := openIndex(t)
	a, b, c := strings.Repeat("a1", 32), strings.Repeat("b2", 32), strings.Repeat("c3", 32)
	x, y, z := strings.Repeat("d4", 32), strings.Repeat("e5", 32), strings.Repeat("f6", 32)
	manifest := func(hash, date string, parents []string, tags ...artifact.Tag) Parsed {
		return Parsed{Hash: hash, Art: &artifact.Artifact{
			Type: artifact.Manifest, Date: date, User: "dan",
			Comment: "c", Parents: parents, Tags: tags}}
	}
	control := func(hash, date string, tags ...artifact.Tag) Parsed {
		return Parsed{Hash: hash, Art: &artifact.Artifact{
			Type: artifact.Control, Date: date, User: "dan", Tags: tags}}
	}
	if err := ix.FoldNow([]Parsed{
		manifest(a, "2026-09-01T10:00:00", nil,
			artifact.Tag{Name: "*branch", Target: "*", Value: "trunk"},
			artifact.Tag{Name: "*sym-trunk", Target: "*"}),
		manifest(b, "2026-09-02T10:00:00", []string{a},
			artifact.Tag{Name: "*branch", Target: "*", Value: "feature"},
			artifact.Tag{Name: "*sym-feature", Target: "*"},
			artifact.Tag{Name: "-sym-trunk", Target: "*"}),
		manifest(c, "2026-09-03T10:00:00", []string{a},
			artifact.Tag{Name: "+sym-version-0.1.0", Target: "*"}),
		control(x, "2026-09-04T10:00:00",
			artifact.Tag{Name: "+sym-version-0.2.0", Target: a},
			artifact.Tag{Name: "*sym-rel", Target: a},
			artifact.Tag{Name: "+sym-gone", Target: a},
			artifact.Tag{Name: "+closed", Target: b},
			artifact.Tag{Name: "+sym-elsewhere", Target: strings.Repeat("99", 32)}),
		control(y, "2026-09-05T10:00:00",
			artifact.Tag{Name: "-sym-gone", Target: a},
			artifact.Tag{Name: "+ci-pass", Target: c, Value: "ci/test.yml"}),
		control(z, "2026-09-06T10:00:00",
			artifact.Tag{Name: "+sym-feature", Target: c}),
	}); err != nil {
		t.Fatal(err)
	}

	got, err := ix.TagsAdded()
	if err != nil {
		t.Fatal(err)
	}
	type row struct{ checkin, name, branch, src string }
	want := []row{
		{c, "version-0.1.0", "trunk", c},
		{a, "rel", "trunk", x},
		{a, "version-0.2.0", "trunk", x},
	}
	if len(got) != len(want) {
		t.Fatalf("FAIL: TagsAdded = %+v; want %d rows", got, len(want))
	}
	for i, w := range want {
		g := got[i]
		if g.Checkin != w.checkin || g.Name != w.name || g.Branch != w.branch || g.Src != w.src {
			t.Errorf("FAIL: row %d = %.4s %s on %s from %.4s; want %.4s %s on %s from %.4s",
				i, g.Checkin, g.Name, g.Branch, g.Src, w.checkin, w.name, w.branch, w.src)
		}
	}

	// A tag that arrives before its check-in is listed once the
	// check-in is folded, under the same key: the card on 99.. above.
	late := strings.Repeat("99", 32)
	if err := ix.FoldNow([]Parsed{manifest(late, "2026-08-01T10:00:00", []string{a})}); err != nil {
		t.Fatal(err)
	}
	got, err = ix.TagsAdded()
	if err != nil {
		t.Fatal(err)
	}
	found := false
	for _, g := range got {
		if g.Checkin == late && g.Name == "elsewhere" && g.Src == x {
			found = true
		}
	}
	if len(got) != 4 || !found {
		t.Errorf("FAIL: after its check-in arrived, TagsAdded = %+v; want the waiting tag listed too", got)
	}
	t.Log("ok: added sym tags on check-ins only, once on the carrier, branch names and raw tags excluded, a waiting tag listed when its check-in arrives")
}