summaryrefslogtreecommitdiff
path: root/cmd/generate/gitcache.go
blob: 844408db9407e74f3ceb91e30a5abf27c5e90958 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package main

import (
	"fmt"
	"os"
	"os/exec"
	"strings"
	"time"

	"git.mothstuff.lol/lukeshu/eclipse/lib/gitcache"
)

var gitFetched = map[string]struct{}{}

var gitCache = &gitcache.Cache{
	Dir:       ".git-cache",
	MinPeriod: 1 * time.Hour,
}

func withGit(u string, fn func(dir string) error) error {
	if _, ok := gitFetched[u]; !ok {
		if err := gitCache.Fetch(os.Stderr, u); err != nil {
			return err
		}
	}
	return gitCache.WithFastClone(os.Stderr, u, fn)
}

func getGitTagThatContainsAll(gitURL string, gitHashes ...string) (string, error) {
	if len(gitHashes) == 0 {
		return "", nil
	}
	var tag string
	err := withGit(gitURL, func(dir string) error {
		gitHash := gitHashes[0]
		if len(gitHashes) > 1 {
			cmdline := append([]string{"git", "merge-base", "--independent", "--"}, gitHashes...)
			cmd := exec.Command(cmdline[0], cmdline[1:]...)
			cmd.Dir = dir
			var stdout strings.Builder
			cmd.Stdout = &stdout
			cmd.Stderr = os.Stderr
			if err := cmd.Run(); err != nil {
				return err
			}
			gitHash = strings.TrimSpace(stdout.String())
		}
		cmd := exec.Command("git", "for-each-ref",
			"--count=1",
			"--format=%(refname:lstrip=2)",
			"--contains="+gitHash,
			"refs/tags/",
		)
		cmd.Dir = dir
		var stdout strings.Builder
		cmd.Stdout = &stdout
		cmd.Stderr = os.Stderr
		if err := cmd.Run(); err != nil {
			return err
		}
		tag = strings.TrimSpace(stdout.String())
		return nil
	})
	if err != nil {
		return "", fmt.Errorf("%q: %w", gitURL, err)
	}
	return tag, nil
}