Add sync command
This commit is contained in:
commit
5e6a5e23fd
18 changed files with 1077 additions and 0 deletions
13
commands/command.go
Normal file
13
commands/command.go
Normal 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
88
commands/sync_cmd.go
Normal 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
95
commands/sync_cmd_test.go
Normal 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)
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue