vuln-list-update/git/git.go

188 lines
3.9 KiB
Go
Raw Normal View History

2019-04-30 07:02:09 +03:00
package git
import (
"log"
"os"
"os/exec"
"path/filepath"
"strings"
2019-08-19 11:47:18 +03:00
"github.com/aquasecurity/vuln-list-update/utils"
2019-04-30 07:02:09 +03:00
"golang.org/x/xerrors"
)
type Operations interface {
2020-12-17 18:05:35 +03:00
CloneOrPull(string, string, string) (map[string]struct{}, error)
RemoteBranch(string) ([]string, error)
Checkout(string, string) error
}
type Config struct {
}
func (gc Config) CloneOrPull(url, repoPath, branch string, debug bool) (map[string]struct{}, error) {
2019-04-30 07:02:09 +03:00
exists, err := utils.Exists(filepath.Join(repoPath, ".git"))
if err != nil {
return nil, err
}
updatedFiles := map[string]struct{}{}
if exists {
if debug {
log.Println("Skip git pull")
return nil, nil
}
2019-04-30 07:02:09 +03:00
log.Println("git pull")
2020-12-17 18:05:35 +03:00
files, err := pull(url, repoPath, branch)
2019-04-30 07:02:09 +03:00
if err != nil {
return nil, xerrors.Errorf("git pull error: %w", err)
}
for _, filename := range files {
updatedFiles[strings.TrimSpace(filename)] = struct{}{}
}
} else {
if err = os.MkdirAll(repoPath, 0700); err != nil {
return nil, err
}
if err := clone(url, repoPath, branch); err != nil {
2019-04-30 07:02:09 +03:00
return nil, err
}
2020-04-06 12:57:24 +03:00
if err := fetchAll(repoPath); err != nil {
return nil, err
}
2019-04-30 07:02:09 +03:00
err = filepath.Walk(repoPath, func(path string, info os.FileInfo, err error) error {
if info.IsDir() {
return nil
}
updatedFiles[path] = struct{}{}
return nil
})
if err != nil {
return nil, err
}
}
return updatedFiles, nil
}
func clone(url, repoPath, branch string) error {
commandAndArgs := []string{
"clone",
"--depth",
"1",
url,
repoPath,
}
if branch != "" {
commandAndArgs = append(commandAndArgs, "-b", branch)
}
2019-04-30 07:02:09 +03:00
cmd := exec.Command("git", commandAndArgs...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return xerrors.Errorf("failed to clone: %w", err)
}
return nil
}
2020-12-17 18:05:35 +03:00
func pull(url, repoPath, branch string) ([]string, error) {
2019-04-30 07:02:09 +03:00
commandArgs := generateGitArgs(repoPath)
remoteCmd := []string{
"remote",
"get-url",
"--push",
"origin",
}
output, err := utils.Exec("git", append(commandArgs, remoteCmd...))
2019-04-30 07:02:09 +03:00
if err != nil {
return nil, xerrors.Errorf("error in git rev-list: %w", err)
}
remoteURL := strings.TrimSpace(output)
if remoteURL != url {
return nil, xerrors.Errorf("remote url is %s, target is %s", remoteURL, url)
}
revParseCmd := []string{
"rev-list",
"-n",
"1",
"--all",
}
output, err = utils.Exec("git", append(commandArgs, revParseCmd...))
if err != nil {
return nil, xerrors.Errorf("error in git rev-list: %w", err)
2019-04-30 07:02:09 +03:00
}
commitHash := strings.TrimSpace(output)
if len(commitHash) == 0 {
log.Println("no commit yet")
return nil, nil
}
2019-04-30 07:02:09 +03:00
pullCmd := []string{
"pull",
"origin",
}
if branch != "" {
pullCmd = append(pullCmd, branch)
}
2019-04-30 07:02:09 +03:00
if _, err = utils.Exec("git", append(commandArgs, pullCmd...)); err != nil {
return nil, xerrors.Errorf("error in git pull: %w", err)
}
fetchCmd := []string{
"fetch",
"--prune",
}
2019-04-30 07:02:09 +03:00
if _, err = utils.Exec("git", append(commandArgs, fetchCmd...)); err != nil {
return nil, xerrors.Errorf("error in git fetch: %w", err)
}
diffCmd := []string{
"diff",
commitHash,
"HEAD",
"--name-only",
}
2019-04-30 07:02:09 +03:00
output, err = utils.Exec("git", append(commandArgs, diffCmd...))
if err != nil {
return nil, err
}
updatedFiles := strings.Split(strings.TrimSpace(output), "\n")
return updatedFiles, nil
}
2020-04-06 12:57:24 +03:00
func fetchAll(repoPath string) error {
commandArgs := generateGitArgs(repoPath)
configCmd := []string{
"config",
"remote.origin.fetch",
"+refs/heads/*:refs/remotes/origin/*",
}
2020-04-06 12:57:24 +03:00
if _, err := utils.Exec("git", append(commandArgs, configCmd...)); err != nil {
return xerrors.Errorf("error in git config: %w", err)
}
fetchCmd := []string{
"fetch",
"--all",
}
2020-04-06 12:57:24 +03:00
if _, err := utils.Exec("git", append(commandArgs, fetchCmd...)); err != nil {
return xerrors.Errorf("error in git fetch: %w", err)
}
return nil
}
2019-04-30 07:02:09 +03:00
func generateGitArgs(repoPath string) []string {
gitDir := filepath.Join(repoPath, ".git")
return []string{
"--git-dir",
gitDir,
"--work-tree",
repoPath,
}
}