add pull command

This commit is contained in:
2023-05-26 14:45:13 -07:00
parent 2818cfb61d
commit 2085e2b8b7

View File

@@ -2,19 +2,102 @@ package cmd
import ( import (
"fmt" "fmt"
"log"
"os"
"sync"
git "github.com/go-git/go-git/v5"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
// pullCmd represents the pull command // pullCmd represents the pull command
var pullCmd = &cobra.Command{ var (
Use: "pull", jobs int
Short: "pull all git repos", pullCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) { Use: "pull",
fmt.Println("pull called") Short: "add current path to list of repos",
}, Run: func(_ *cobra.Command, args []string) {
} type RepoError struct {
Error error
Repo string
}
if jobs < 1 {
log.Println("jobs must be greater than 0")
os.Exit(1)
}
conf := GetConfig()
if len(args) > 0 {
log.Println("too many arguments")
os.Exit(1)
}
repoChan := make(chan string, len(conf.Repos))
errs := []RepoError{}
alreadyUpToDate := 0
mutex := sync.Mutex{}
wg := sync.WaitGroup{}
wg.Add(len(conf.Repos))
for i := 0; i < jobs; i++ {
go func() {
for repo := range repoChan {
log.Printf("attempting pull: %s\n", repo)
r, err := git.PlainOpenWithOptions(repo, &(git.PlainOpenOptions{DetectDotGit: true}))
if err != nil {
mutex.Lock()
errs = append(errs, RepoError{Error: err, Repo: repo})
mutex.Unlock()
log.Printf("pull failed for %s: %v\n", repo, err)
wg.Done()
continue
}
w, err := r.Worktree()
if err != nil {
mutex.Lock()
errs = append(errs, RepoError{Error: err, Repo: repo})
mutex.Unlock()
log.Printf("pull failed for %s: %v\n", repo, err)
wg.Done()
continue
}
err = w.Pull(&git.PullOptions{})
if err == git.NoErrAlreadyUpToDate {
mutex.Lock()
alreadyUpToDate++
mutex.Unlock()
fmt.Printf("repo %s: already up to date\n", repo)
wg.Done()
continue
} else if err != nil {
mutex.Lock()
errs = append(errs, RepoError{Error: err, Repo: repo})
mutex.Unlock()
log.Printf("pull failed for %s: %v\n", repo, err)
wg.Done()
continue
} else {
fmt.Printf("successfully pulled %s\n", w.Filesystem.Root())
}
wg.Done()
}
}()
}
for _, repo := range conf.Repos {
repoChan <- repo.Path
}
close(repoChan)
wg.Wait()
for _, err := range errs {
log.Printf("error pulling %s: %s\n", err.Repo, err.Error)
}
lenErrs := len(errs)
fmt.Println()
fmt.Printf("successfully pulled %d/%d repos\n", len(conf.Repos)-lenErrs, len(conf.Repos))
fmt.Printf("%d repos already up to date\n", alreadyUpToDate)
fmt.Printf("failed to pull %d/%d repos\n", lenErrs, len(conf.Repos))
},
}
)
func init() { func init() {
rootCmd.AddCommand(pullCmd) rootCmd.AddCommand(pullCmd)
pullCmd.Flags().IntVarP(&jobs, "jobs", "j", 1, "number of jobs to run in parallel")
} }