refactor: vcs simplification pass
This commit is contained in:
parent
2c9ecd7caf
commit
52c108f7d3
3 changed files with 48 additions and 84 deletions
|
|
@ -45,11 +45,11 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func vcsInit(cmd *cobra.Command, args []string) error {
|
func vcsInit(cmd *cobra.Command, args []string) error {
|
||||||
repoDir, err := vcsRepoRoot()
|
store := &Store{}
|
||||||
|
repoDir, err := store.path()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
store := &Store{}
|
|
||||||
|
|
||||||
clean, err := cmd.Flags().GetBool("clean")
|
clean, err := cmd.Flags().GetBool("clean")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
89
cmd/sync.go
89
cmd/sync.go
|
|
@ -24,7 +24,6 @@ package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
@ -54,45 +53,7 @@ func sync(manual bool) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var ahead int
|
// Commit local changes first so nothing is lost.
|
||||||
if remoteInfo.Ref != "" {
|
|
||||||
if manual || config.Git.AutoFetch {
|
|
||||||
if err := runGit(repoDir, "fetch", "--prune"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
remoteAhead, behind, err := repoAheadBehind(repoDir, remoteInfo.Ref)
|
|
||||||
if err != nil {
|
|
||||||
ahead = 1 // ref doesn't exist yet; just push
|
|
||||||
} else {
|
|
||||||
ahead = remoteAhead
|
|
||||||
if behind > 0 {
|
|
||||||
if ahead > 0 {
|
|
||||||
return fmt.Errorf("repo diverged from remote (ahead %d, behind %d); resolve manually", ahead, behind)
|
|
||||||
}
|
|
||||||
fmt.Printf("remote has %d commit(s) not present locally; discard local changes and pull? (y/n)\n", behind)
|
|
||||||
var confirm string
|
|
||||||
if _, err := fmt.Scanln(&confirm); err != nil {
|
|
||||||
return fmt.Errorf("cannot continue sync: %w", err)
|
|
||||||
}
|
|
||||||
if strings.ToLower(confirm) != "y" {
|
|
||||||
return fmt.Errorf("aborted sync")
|
|
||||||
}
|
|
||||||
dirty, err := repoHasChanges(repoDir)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if dirty {
|
|
||||||
stashMsg := fmt.Sprintf("pda sync: %s", time.Now().UTC().Format(time.RFC3339))
|
|
||||||
if err := runGit(repoDir, "stash", "push", "-u", "-m", stashMsg); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return pullRemote(repoDir, remoteInfo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := runGit(repoDir, "add", "-A"); err != nil {
|
if err := runGit(repoDir, "add", "-A"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -100,29 +61,54 @@ func sync(manual bool) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
madeCommit := false
|
if changed {
|
||||||
if !changed {
|
|
||||||
if manual {
|
|
||||||
fmt.Println("no changes to commit")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
msg := fmt.Sprintf("sync: %s", time.Now().UTC().Format(time.RFC3339))
|
msg := fmt.Sprintf("sync: %s", time.Now().UTC().Format(time.RFC3339))
|
||||||
if err := runGit(repoDir, "commit", "-m", msg); err != nil {
|
if err := runGit(repoDir, "commit", "-m", msg); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
madeCommit = true
|
} else if manual {
|
||||||
|
fmt.Println("no changes to commit")
|
||||||
}
|
}
|
||||||
if manual || config.Git.AutoPush {
|
|
||||||
if remoteInfo.Ref == "" {
|
if remoteInfo.Ref == "" {
|
||||||
if manual {
|
if manual {
|
||||||
fmt.Println("no remote configured; skipping push")
|
fmt.Println("no remote configured; skipping push")
|
||||||
}
|
}
|
||||||
} else if madeCommit || ahead > 0 {
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch remote state.
|
||||||
|
if manual || config.Git.AutoFetch {
|
||||||
|
if err := runGit(repoDir, "fetch", "--prune"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rebase local commits onto remote if behind.
|
||||||
|
ahead, behind, err := repoAheadBehind(repoDir, remoteInfo.Ref)
|
||||||
|
if err != nil {
|
||||||
|
// Remote ref doesn't exist yet (first push).
|
||||||
|
ahead = 1
|
||||||
|
} else if behind > 0 {
|
||||||
|
if err := pullRemote(repoDir, remoteInfo); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ahead, _, err = repoAheadBehind(repoDir, remoteInfo.Ref)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push if ahead.
|
||||||
|
if manual || config.Git.AutoPush {
|
||||||
|
if ahead > 0 {
|
||||||
return pushRemote(repoDir, remoteInfo)
|
return pushRemote(repoDir, remoteInfo)
|
||||||
} else if manual {
|
}
|
||||||
|
if manual {
|
||||||
fmt.Println("nothing to push")
|
fmt.Println("nothing to push")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,5 +116,8 @@ func autoSync() error {
|
||||||
if !config.Git.AutoCommit {
|
if !config.Git.AutoCommit {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if _, err := ensureVCSInitialized(); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
return sync(false)
|
return sync(false)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
31
cmd/vcs.go
31
cmd/vcs.go
|
|
@ -1,7 +1,6 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -11,12 +10,8 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func vcsRepoRoot() (string, error) {
|
|
||||||
return (&Store{}).path()
|
|
||||||
}
|
|
||||||
|
|
||||||
func ensureVCSInitialized() (string, error) {
|
func ensureVCSInitialized() (string, error) {
|
||||||
repoDir, err := vcsRepoRoot()
|
repoDir, err := (&Store{}).path()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
@ -118,16 +113,6 @@ func repoAheadBehind(dir, ref string) (int, int, error) {
|
||||||
return ahead, behind, nil
|
return ahead, behind, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func repoHasChanges(dir string) (bool, error) {
|
|
||||||
cmd := exec.Command("git", "status", "--porcelain")
|
|
||||||
cmd.Dir = dir
|
|
||||||
out, err := cmd.Output()
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
return len(bytes.TrimSpace(out)) > 0, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func repoHasStagedChanges(dir string) (bool, error) {
|
func repoHasStagedChanges(dir string) (bool, error) {
|
||||||
cmd := exec.Command("git", "diff", "--cached", "--quiet")
|
cmd := exec.Command("git", "diff", "--cached", "--quiet")
|
||||||
cmd.Dir = dir
|
cmd.Dir = dir
|
||||||
|
|
@ -143,27 +128,17 @@ func repoHasStagedChanges(dir string) (bool, error) {
|
||||||
|
|
||||||
func pullRemote(dir string, info gitRemoteInfo) error {
|
func pullRemote(dir string, info gitRemoteInfo) error {
|
||||||
if info.HasUpstream {
|
if info.HasUpstream {
|
||||||
return runGit(dir, "pull", "--ff-only")
|
return runGit(dir, "pull", "--rebase")
|
||||||
}
|
}
|
||||||
if info.Remote != "" && info.Branch != "" {
|
return runGit(dir, "pull", "--rebase", info.Remote, info.Branch)
|
||||||
fmt.Printf("running: git pull --ff-only %s %s\n", info.Remote, info.Branch)
|
|
||||||
return runGit(dir, "pull", "--ff-only", info.Remote, info.Branch)
|
|
||||||
}
|
|
||||||
fmt.Println("no remote configured; skipping pull")
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func pushRemote(dir string, info gitRemoteInfo) error {
|
func pushRemote(dir string, info gitRemoteInfo) error {
|
||||||
if info.HasUpstream {
|
if info.HasUpstream {
|
||||||
return runGit(dir, "push")
|
return runGit(dir, "push")
|
||||||
}
|
}
|
||||||
if info.Remote != "" && info.Branch != "" {
|
|
||||||
fmt.Printf("running: git push -u %s %s\n", info.Remote, info.Branch)
|
|
||||||
return runGit(dir, "push", "-u", info.Remote, info.Branch)
|
return runGit(dir, "push", "-u", info.Remote, info.Branch)
|
||||||
}
|
}
|
||||||
fmt.Println("no remote configured; skipping push")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func repoHasUpstream(dir string) (bool, error) {
|
func repoHasUpstream(dir string) (bool, error) {
|
||||||
cmd := exec.Command("git", "rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}")
|
cmd := exec.Command("git", "rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue