1package git
2
3import (
4	"fmt"
5	"os"
6	"os/exec"
7	"strings"
8
9	"github.com/aws/aws-sdk-go-v2/internal/repotools/changes/util"
10)
11
12// Client is a wrapper around the git CLI tool.
13type Client struct {
14	RepoPath string // RepoPath is the path to the git repository's root. Git commands executed by this Client will be run at this path.
15}
16
17// VcsClient is a client that interacts with a version control system.
18type VcsClient interface {
19	Tag(tag, message string) error
20	Tags(prefix string) ([]string, error)
21	Commit(unstagedPaths []string, message string) error
22	Push() error
23	CommitHash() (string, error)
24}
25
26// Tag creates an annotated git tag with the given message.
27func (c Client) Tag(tag, message string) error {
28	cmd := exec.Command("git", "tag", "-a", tag, "-m", message)
29	_, err := util.ExecAt(cmd, c.RepoPath)
30	if err != nil {
31		return err
32	}
33
34	return nil
35}
36
37// Tags returns all git tags with the given prefix.
38func (c Client) Tags(prefix string) ([]string, error) {
39	cmd := exec.Command("git", "tag", "-l", prefix+"*")
40	output, err := util.ExecAt(cmd, c.RepoPath)
41	if err != nil {
42		return nil, err
43	}
44
45	return strings.Split(string(output), "\n"), nil
46}
47
48// Commit stages all given paths and commits with the given message.
49func (c Client) Commit(unstagedPaths []string, message string) error {
50	for _, p := range unstagedPaths {
51		cmd := exec.Command("git", "add", p)
52		_, err := util.ExecAt(cmd, c.RepoPath)
53		if err != nil {
54			return err
55		}
56	}
57
58	cmd := exec.Command("git", "commit", "-m", message)
59	_, err := util.ExecAt(cmd, c.RepoPath)
60
61	return err
62}
63
64// Push pushes commits and tags to the repository.
65func (c Client) Push() error {
66	cmd := exec.Command("git", "push", "--follow-tags")
67	_, err := util.ExecAt(cmd, c.RepoPath)
68	return err
69}
70
71// CommitHash returns a timestamp and commit hash for the HEAD commit of the given repository, formatted in the way
72// expected for a go.mod file pseudo-version.
73func (c Client) CommitHash() (string, error) {
74	cmd := exec.Command("git", "show", "--quiet", "--abbrev=12", "--date=format-local:%Y%m%d%H%M%S", "--format=%cd-%h")
75	cmd.Env = os.Environ()
76	cmd.Env = append(cmd.Env, "TZ=UTC")
77
78	output, err := util.ExecAt(cmd, c.RepoPath)
79	if err != nil {
80		return "", fmt.Errorf("couldn't make pseudo-version: %v", err)
81	}
82
83	return strings.Trim(string(output), "\n"), nil // clean up git show output and return
84}
85