attr.go

 1// Package git provides git repository operations and utilities.
 2package git
 3
 4import (
 5	"math/rand"
 6	"os"
 7	"path/filepath"
 8	"strconv"
 9	"strings"
10	"time"
11)
12
13// Attribute represents a Git attribute.
14type Attribute struct {
15	Name  string
16	Value string
17}
18
19// CheckAttributes checks the attributes of the given ref and path.
20func (r *Repository) CheckAttributes(ref *Reference, path string) ([]Attribute, error) {
21	rnd := rand.NewSource(time.Now().UnixNano())
22	fn := "soft-serve-index-" + strconv.Itoa(rand.New(rnd).Int()) //nolint: gosec
23	tmpindex := filepath.Join(os.TempDir(), fn)
24
25	defer os.Remove(tmpindex) //nolint: errcheck
26
27	readTree := NewCommand("read-tree", "--reset", "-i", ref.Name().String()).
28		AddEnvs("GIT_INDEX_FILE=" + tmpindex)
29	if _, err := readTree.RunInDir(r.Path); err != nil {
30		return nil, err //nolint:wrapcheck
31	}
32
33	checkAttr := NewCommand("check-attr", "--cached", "-a", "--", path).
34		AddEnvs("GIT_INDEX_FILE=" + tmpindex)
35	out, err := checkAttr.RunInDir(r.Path)
36	if err != nil {
37		return nil, err //nolint:wrapcheck
38	}
39
40	return parseAttributes(path, out), nil
41}
42
43func parseAttributes(path string, buf []byte) []Attribute {
44	attrs := make([]Attribute, 0)
45	for _, line := range strings.Split(string(buf), "\n") {
46		if line == "" {
47			continue
48		}
49
50		line = strings.TrimPrefix(line, path+": ")
51		parts := strings.SplitN(line, ": ", 2)
52		if len(parts) != 2 {
53			continue
54		}
55
56		attrs = append(attrs, Attribute{
57			Name:  parts[0],
58			Value: parts[1],
59		})
60	}
61
62	return attrs
63}