package commands import ( "fmt" "github.com/go-git/go-git/v5" "gitlab.com/revalus/grm/config" ) type Synchronizer struct { workspace string } func NewSynchronizer(workspace string) Synchronizer { return Synchronizer{ workspace: workspace, } } const ( syncUpToDate = "up to date" syncFetched = "has been fetched" // Why fetched, instead of updated? To be consistent with git commands :D syncCloned = "has been cloned" ) func fetchRepository(repo *git.Repository) (bool, error) { err := repo.Fetch(&git.FetchOptions{}) if err == git.NoErrAlreadyUpToDate { return false, nil } if err != nil && err != git.NoErrAlreadyUpToDate { return false, err } return true, nil } func cloneRepository(destPath string, repoCfg *config.RepositoryConfig) (bool, error) { _, err := git.PlainClone(destPath, false, &git.CloneOptions{ URL: repoCfg.Src, }) if err != nil { return false, err } return true, nil } func (s Synchronizer) Command(repoCfg config.RepositoryConfig, status chan CommandStatus) { var err error cmdStatus := CommandStatus{ Name: repoCfg.Name, Changed: false, Message: "", Error: false, } destPath := fmt.Sprintf("%v/%v", s.workspace, repoCfg.Dest) repo, err := git.PlainOpen(destPath) if err != nil && err == git.ErrRepositoryNotExists { cmdStatus.Changed, err = cloneRepository(destPath, &repoCfg) cmdStatus.Message = syncCloned } else if err == nil { cmdStatus.Changed, err = fetchRepository(repo) if cmdStatus.Changed { cmdStatus.Message = syncFetched } else { cmdStatus.Message = syncUpToDate } } else { cmdStatus.Error = true cmdStatus.Message = err.Error() status <- cmdStatus } if err != nil { cmdStatus.Error = true cmdStatus.Message = err.Error() } status <- cmdStatus }