98 lines
2.4 KiB
Go
98 lines
2.4 KiB
Go
package git
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"net/url"
|
|
"os/exec"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
var (
|
|
controlChars = regexp.MustCompile("[[:cntrl:]]")
|
|
controlEncoded = regexp.MustCompile("%[0-1][0-9,a-f,A-F]")
|
|
)
|
|
|
|
func Clone(path, url, branch string) error {
|
|
if err := ValidateURL(url); err != nil {
|
|
return err
|
|
}
|
|
return runcmd("git", "clone", "-b", branch, "--single-branch", "--", url, path)
|
|
}
|
|
|
|
func Update(path, commit string) error {
|
|
if err := runcmd("git", "-C", path, "fetch"); err != nil {
|
|
return err
|
|
}
|
|
return runcmd("git", "-C", path, "checkout", commit)
|
|
}
|
|
|
|
func HeadCommit(path string) (string, error) {
|
|
cmd := exec.Command("git", "-C", path, "rev-parse", "HEAD")
|
|
output, err := cmd.Output()
|
|
return strings.Trim(string(output), "\n"), err
|
|
}
|
|
|
|
func RemoteBranchHeadCommit(url, branch string) (string, error) {
|
|
if err := ValidateURL(url); err != nil {
|
|
return "", err
|
|
}
|
|
cmd := exec.Command("git", "ls-remote", "--", url, branch)
|
|
output, err := cmd.CombinedOutput()
|
|
if err != nil {
|
|
return "", errors.Wrap(err, string(output))
|
|
}
|
|
parts := strings.Split(string(output), "\t")
|
|
if len(parts) > 0 && len(parts[0]) > 0 {
|
|
return parts[0], nil
|
|
}
|
|
return "", fmt.Errorf("no commit found for url %s branch %s", branch, url)
|
|
}
|
|
|
|
func IsValid(url string) bool {
|
|
if err := ValidateURL(url); err != nil {
|
|
return false
|
|
}
|
|
err := runcmd("git", "ls-remote", "--", url)
|
|
return err == nil
|
|
}
|
|
|
|
func runcmd(name string, arg ...string) error {
|
|
cmd := exec.Command(name, arg...)
|
|
bufErr := &bytes.Buffer{}
|
|
cmd.Stderr = bufErr
|
|
if err := cmd.Run(); err != nil {
|
|
return errors.Wrap(err, bufErr.String())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// FormatURL generates request url if is a private catalog
|
|
func FormatURL(pathURL, username, password string) string {
|
|
if len(username) > 0 && len(password) > 0 {
|
|
if u, err := url.Parse(pathURL); err == nil {
|
|
u.User = url.UserPassword(username, password)
|
|
return u.String()
|
|
}
|
|
}
|
|
return pathURL
|
|
}
|
|
|
|
func CloneWithDepth(path, url, branch string, depth int) error {
|
|
if err := ValidateURL(url); err != nil {
|
|
return err
|
|
}
|
|
return runcmd("git", "clone", "-b", branch, "--single-branch", fmt.Sprintf("--depth=%v", depth), "--", url, path)
|
|
}
|
|
|
|
func ValidateURL(pathURL string) error {
|
|
// Don't allow a URL containing control characters, standard or url-encoded
|
|
if controlChars.FindStringIndex(pathURL) != nil || controlEncoded.FindStringIndex(pathURL) != nil {
|
|
return errors.New("Invalid characters in url")
|
|
}
|
|
return nil
|
|
}
|