package git import ( "fmt" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" ) type gitPullParam struct { repoPath string defaultBranch string } func (c *gitClient) pullWorker() { fmt.Println("Started git puller worker routine") for gpp := range c.pullChan { if err := c.pull(gpp); err != nil { fmt.Println(err) } } } func (c *gitClient) pull(gpp *gitPullParam) error { r, err := git.PlainOpen(gpp.repoPath) if err != nil { return fmt.Errorf("failed to open git repo %v: %v", gpp.repoPath, err) } w, err := r.Worktree() if err != nil { return fmt.Errorf("failed to retrieve worktree of git repo %v: %v", gpp.repoPath, err) } // Check if the local repo is on default branch headRef, err := r.Head() if err != nil { // We ignore "reference not found" as this occurs when the local branch // has never been checked out when we are in init-pull mode if err.Error() != "reference not found" { return fmt.Errorf("failed to retrieve HEAD of git repo %v: %v", gpp.repoPath, err) } } else { branchRef := plumbing.ReferenceName(fmt.Sprintf("refs/heads/%s", gpp.defaultBranch)) if headRef.Name() != branchRef { // default branch is not checked out, nothing to do fmt.Printf("Repo %v is not on default branch (%v != %v), skipping pull\n", gpp.repoPath, branchRef, headRef.Name()) return nil } } // Pull the remote // TODO: Just like clone, this is very memory intensive for some reasons... fmt.Printf("Pulling %v\n", gpp.repoPath) if err := w.Pull(&git.PullOptions{RemoteName: c.RemoteName, Depth: c.PullDepth}); err != nil { return fmt.Errorf("failed to pull git repo %v: %v", gpp.repoPath, err) } return nil }