2021-09-10 22:54:02 +00:00
|
|
|
package git
|
|
|
|
|
|
|
|
import (
|
2021-09-14 14:00:15 +00:00
|
|
|
"fmt"
|
2021-09-10 22:54:02 +00:00
|
|
|
"os"
|
2021-11-02 12:36:40 +00:00
|
|
|
"path/filepath"
|
2021-09-14 14:00:15 +00:00
|
|
|
"strings"
|
2021-09-10 22:54:02 +00:00
|
|
|
|
|
|
|
"github.com/go-git/go-git/v5"
|
2021-09-14 14:00:15 +00:00
|
|
|
"github.com/go-git/go-git/v5/config"
|
2021-09-10 22:54:02 +00:00
|
|
|
"github.com/go-git/go-git/v5/plumbing"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Clone runs a git clone which accounts for different default branches.
|
|
|
|
func Clone(dir, url string) error {
|
|
|
|
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
|
|
|
logrus.Debugf("'%s' does not exist, attempting to git clone from '%s'", dir, url)
|
|
|
|
_, err := git.PlainClone(dir, false, &git.CloneOptions{URL: url, Tags: git.AllTags})
|
|
|
|
if err != nil {
|
2021-09-16 14:28:11 +00:00
|
|
|
logrus.Debugf("cloning '%s' default branch failed, attempting from main branch", url)
|
2021-09-10 22:54:02 +00:00
|
|
|
_, err := git.PlainClone(dir, false, &git.CloneOptions{
|
|
|
|
URL: url,
|
|
|
|
Tags: git.AllTags,
|
|
|
|
ReferenceName: plumbing.ReferenceName("refs/heads/main"),
|
|
|
|
})
|
|
|
|
if err != nil {
|
2021-11-02 12:36:40 +00:00
|
|
|
if strings.Contains(err.Error(), "authentication required") {
|
|
|
|
name := filepath.Base(dir)
|
|
|
|
return fmt.Errorf("unable to clone %s, does %s exist?", name, url)
|
|
|
|
}
|
2021-09-10 22:54:02 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2021-09-14 14:00:15 +00:00
|
|
|
logrus.Debugf("'%s' has been git cloned successfully", dir)
|
|
|
|
} else {
|
|
|
|
logrus.Debugf("'%s' already exists, doing nothing", dir)
|
2021-09-10 22:54:02 +00:00
|
|
|
}
|
|
|
|
|
2021-09-14 14:00:15 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// EnsureUpToDate ensures that a git repo on disk has the latest changes (git-fetch).
|
|
|
|
func EnsureUpToDate(dir string) error {
|
|
|
|
repo, err := git.PlainOpen(dir)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-11-22 16:49:31 +00:00
|
|
|
recipeName := filepath.Base(dir)
|
|
|
|
isClean, err := IsClean(recipeName)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if !isClean {
|
|
|
|
return fmt.Errorf("'%s' has locally unstaged changes", recipeName)
|
|
|
|
}
|
|
|
|
|
2021-09-14 14:00:15 +00:00
|
|
|
branch := "master"
|
|
|
|
if _, err := repo.Branch("master"); err != nil {
|
|
|
|
if _, err := repo.Branch("main"); err != nil {
|
2021-09-16 14:28:11 +00:00
|
|
|
logrus.Debugf("failed to select branch in '%s'", dir)
|
2021-09-14 14:00:15 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
branch = "main"
|
|
|
|
}
|
|
|
|
|
2021-09-16 14:28:11 +00:00
|
|
|
logrus.Debugf("choosing '%s' as main git branch in '%s'", branch, dir)
|
2021-09-14 14:00:15 +00:00
|
|
|
|
|
|
|
worktree, err := repo.Worktree()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
refName := fmt.Sprintf("refs/heads/%s", branch)
|
|
|
|
checkOutOpts := &git.CheckoutOptions{
|
|
|
|
Create: false,
|
2021-12-12 01:04:13 +00:00
|
|
|
Force: true,
|
2021-09-14 14:00:15 +00:00
|
|
|
Branch: plumbing.ReferenceName(refName),
|
|
|
|
}
|
|
|
|
if err := worktree.Checkout(checkOutOpts); err != nil {
|
2021-09-16 14:28:11 +00:00
|
|
|
logrus.Debugf("failed to check out '%s' in '%s'", refName, dir)
|
2021-09-14 14:00:15 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-09-16 14:28:11 +00:00
|
|
|
logrus.Debugf("successfully checked out '%s' in '%s'", branch, dir)
|
2021-09-14 14:00:15 +00:00
|
|
|
|
|
|
|
remote, err := repo.Remote("origin")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
fetchOpts := &git.FetchOptions{
|
|
|
|
RemoteName: "origin",
|
|
|
|
RefSpecs: []config.RefSpec{"refs/heads/*:refs/remotes/origin/*"},
|
|
|
|
Force: true,
|
|
|
|
}
|
|
|
|
if err := remote.Fetch(fetchOpts); err != nil {
|
|
|
|
if !strings.Contains(err.Error(), "already up-to-date") {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
logrus.Debugf("successfully fetched all changes in '%s'", dir)
|
2021-09-10 22:54:02 +00:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|