Add sync command

This commit is contained in:
Mikołaj Pęczkowski 2021-11-02 19:19:31 +01:00
commit 5e6a5e23fd
18 changed files with 1077 additions and 0 deletions

13
commands/command.go Normal file
View file

@ -0,0 +1,13 @@
package commands
import "gitlab.com/revalus/grm/config"
type Command interface {
Command(repoCfg config.RepositoryConfig, cmdStatus chan CommandStatus)
}
type CommandStatus struct {
Name string
Changed bool
Message string
Error bool
}

88
commands/sync_cmd.go Normal file
View file

@ -0,0 +1,88 @@
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
}

95
commands/sync_cmd_test.go Normal file
View file

@ -0,0 +1,95 @@
package commands
import (
"fmt"
"os"
"testing"
"gitlab.com/revalus/grm/config"
)
func createTempDir() string {
checkErrorDuringPreparation := func(err error) {
if err != nil {
fmt.Printf("Cannot prepare a temporary directory for testing! %v ", err.Error())
os.Exit(2)
}
}
baseTmp := fmt.Sprintf("%v/grmTest", os.TempDir())
if _, ok := os.Stat(baseTmp); ok != nil {
err := os.Mkdir(baseTmp, 0777)
checkErrorDuringPreparation(err)
}
tempDir, err := os.MkdirTemp(baseTmp, "*")
checkErrorDuringPreparation(err)
return tempDir
}
func TestSyncInit(t *testing.T) {
sync := NewSynchronizer("test")
if sync.workspace != "test" {
t.Errorf("Expected to get \"test\", instead of this got %v", sync.workspace)
}
}
func TestSyncCommand(t *testing.T) {
workdir := createTempDir()
defer func() {
os.RemoveAll(workdir)
}()
sync := Synchronizer{
workspace: workdir,
}
cfg := config.RepositoryConfig{
Src: "https://github.com/avelino/awesome-go",
Dest: "awesome-go",
}
ch := make(chan CommandStatus)
// Pull part
go sync.Command(cfg, ch)
cloneStatus := <-ch
if cloneStatus.Error {
t.Errorf("Unexpected error: %v", cloneStatus.Message)
}
info, err := os.Stat(fmt.Sprintf("%v/awesome-go/.git", workdir))
if err != nil {
t.Errorf("Unexpected error: %v", err.Error())
}
if !info.IsDir() {
t.Errorf("Expected that the selected path is dir")
}
if cloneStatus.Changed != true {
t.Errorf("Expected that the status is changed")
}
if cloneStatus.Message != syncCloned {
t.Errorf("Expected to get %v, instead of this got %v", syncCloned, cloneStatus.Message)
}
// Fetch part
go sync.Command(cfg, ch)
fetchStatus := <-ch
if fetchStatus.Error {
t.Errorf("Unexpected error: %v", err.Error())
}
if fetchStatus.Changed != false {
t.Errorf("Expected that the status is not changed")
}
if fetchStatus.Message != syncUpToDate {
t.Errorf("Expected to get %v, instead of this got %v", syncUpToDate, cloneStatus.Message)
}
}