attr.go

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