Add sync command
This commit is contained in:
commit
5e6a5e23fd
18 changed files with 1077 additions and 0 deletions
89
app/app.go
Normal file
89
app/app.go
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"gitlab.com/revalus/grm/commands"
|
||||
"gitlab.com/revalus/grm/config"
|
||||
)
|
||||
|
||||
const (
|
||||
APP_NAME = "Git repository manager"
|
||||
APP_DESCRIPTION = "Manage your repository with simple app"
|
||||
VERSION = "0.1"
|
||||
)
|
||||
|
||||
type GitRepositoryManager struct {
|
||||
cliArguments config.CliArguments
|
||||
configuration config.Configuration
|
||||
console ConsoleOutput
|
||||
}
|
||||
|
||||
func (g *GitRepositoryManager) Parse(args []string) {
|
||||
co := ConsoleOutput{}
|
||||
|
||||
checkCriticalError := func(err error) {
|
||||
if err != nil {
|
||||
co.ErrorfMsg("%v", err.Error())
|
||||
os.Exit(2)
|
||||
}
|
||||
}
|
||||
|
||||
arguments, err := config.ParseCliArguments(APP_NAME, APP_DESCRIPTION, args)
|
||||
checkCriticalError(err)
|
||||
|
||||
configFileContent, err := getFileContent(arguments.ConfigurationFile)
|
||||
checkCriticalError(err)
|
||||
|
||||
fileExcension, err := getFileExcension(arguments.ConfigurationFile)
|
||||
checkCriticalError(err)
|
||||
|
||||
configuration, err := config.GetRepositoryConfig(configFileContent, fileExcension)
|
||||
checkCriticalError(err)
|
||||
co.Color = arguments.Color
|
||||
|
||||
g.console = co
|
||||
g.cliArguments = arguments
|
||||
g.configuration = configuration
|
||||
}
|
||||
|
||||
func (g *GitRepositoryManager) Run() {
|
||||
if g.cliArguments.Sync {
|
||||
|
||||
g.console.InfoFMsg("Synchronizing repositories")
|
||||
println()
|
||||
sync := commands.NewSynchronizer(g.configuration.Workspace)
|
||||
g.runCommand(sync)
|
||||
println()
|
||||
g.console.InfoFMsg("All repositories are synced")
|
||||
}
|
||||
|
||||
if g.cliArguments.Version {
|
||||
g.console.InfoFMsg("Current version: %v", VERSION)
|
||||
}
|
||||
}
|
||||
|
||||
func (g GitRepositoryManager) describeStatus(status commands.CommandStatus) {
|
||||
if status.Error {
|
||||
g.console.ErrorStatusF("Repository \"%v\": an error occurred: %v", status.Name, status.Message)
|
||||
return
|
||||
}
|
||||
|
||||
if status.Changed {
|
||||
g.console.ChangedStatusF("Repository \"%v\": %v", status.Name, status.Message)
|
||||
} else {
|
||||
g.console.UnchangedStatusF("Repository \"%v\": %v", status.Name, status.Message)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GitRepositoryManager) runCommand(cmd commands.Command) {
|
||||
statusChan := make(chan commands.CommandStatus)
|
||||
|
||||
for _, repo := range g.configuration.Repositories {
|
||||
go cmd.Command(repo, statusChan)
|
||||
}
|
||||
|
||||
for range g.configuration.Repositories {
|
||||
g.describeStatus(<-statusChan)
|
||||
}
|
||||
}
|
||||
94
app/app_test.go
Normal file
94
app/app_test.go
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"gitlab.com/revalus/grm/config"
|
||||
)
|
||||
|
||||
func prepareConfigContent() (string, 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)
|
||||
|
||||
configFilePath := fmt.Sprintf("%v/config-file.yaml", tempDir)
|
||||
|
||||
file, err := os.Create(configFilePath)
|
||||
checkErrorDuringPreparation(err)
|
||||
|
||||
defer file.Close()
|
||||
|
||||
yamlConfig := fmt.Sprintf(`
|
||||
workspace: %v
|
||||
repositories:
|
||||
- src: "https://github.com/golang/example.git"`, tempDir)
|
||||
|
||||
_, err = file.WriteString(yamlConfig)
|
||||
|
||||
checkErrorDuringPreparation(err)
|
||||
return tempDir, configFilePath
|
||||
}
|
||||
|
||||
func TestParseApplication(t *testing.T) {
|
||||
workdir, configFile := prepareConfigContent()
|
||||
t.Cleanup(func() {
|
||||
os.Remove(workdir)
|
||||
})
|
||||
|
||||
args := []string{"custom-app", "sync", "-c", configFile}
|
||||
grm := GitRepositoryManager{}
|
||||
grm.Parse(args)
|
||||
|
||||
if workdir != grm.configuration.Workspace {
|
||||
t.Errorf("Expected to get %v, instead of this got %v", workdir, grm.configuration.Repositories)
|
||||
}
|
||||
|
||||
if !grm.cliArguments.Sync {
|
||||
t.Error("The value of \"sync\" is expected to be true")
|
||||
}
|
||||
|
||||
expectedRepo := config.RepositoryConfig{
|
||||
Name: "example",
|
||||
Src: "https://github.com/golang/example.git",
|
||||
Dest: "example",
|
||||
}
|
||||
|
||||
if expectedRepo != grm.configuration.Repositories[0] {
|
||||
t.Errorf("Expected to get %v, instead of this got %v", expectedRepo, grm.configuration.Repositories[0])
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func Example_test_sync_output() {
|
||||
grm := GitRepositoryManager{
|
||||
configuration: config.Configuration{
|
||||
Workspace: "/tmp",
|
||||
},
|
||||
cliArguments: config.CliArguments{
|
||||
Sync: true,
|
||||
Version: true,
|
||||
},
|
||||
console: ConsoleOutput{
|
||||
Color: false,
|
||||
},
|
||||
}
|
||||
grm.Run()
|
||||
// Output:
|
||||
// Info: Synchronizing repositories
|
||||
// Info: All repositories are synced
|
||||
// Info: Current version: 0.1
|
||||
}
|
||||
61
app/console_output.go
Normal file
61
app/console_output.go
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
const (
|
||||
colorReset = "\033[0m"
|
||||
colorRed = "\033[31m"
|
||||
colorGreen = "\033[32m"
|
||||
colorYellow = "\033[33m"
|
||||
colorBlue = "\033[34m"
|
||||
)
|
||||
|
||||
type ConsoleOutput struct {
|
||||
Color bool
|
||||
}
|
||||
|
||||
func (co ConsoleOutput) ErrorfMsg(format string, a ...interface{}) {
|
||||
msg := fmt.Sprintf(format, a...)
|
||||
if co.Color {
|
||||
msg = fmt.Sprintf("%vError:%v %v", colorRed, colorReset, msg)
|
||||
} else {
|
||||
msg = fmt.Sprintf("Error: %v", msg)
|
||||
}
|
||||
fmt.Println(msg)
|
||||
}
|
||||
|
||||
func (co ConsoleOutput) InfoFMsg(format string, a ...interface{}) {
|
||||
msg := fmt.Sprintf(format, a...)
|
||||
if co.Color {
|
||||
msg = fmt.Sprintf("%vInfo:%v %v", colorBlue, colorReset, msg)
|
||||
} else {
|
||||
msg = fmt.Sprintf("Info: %v", msg)
|
||||
}
|
||||
fmt.Println(msg)
|
||||
}
|
||||
|
||||
func (co ConsoleOutput) UnchangedStatusF(format string, a ...interface{}) {
|
||||
msg := fmt.Sprintf(format, a...)
|
||||
if co.Color {
|
||||
msg = fmt.Sprintf("%v%v", colorGreen, msg)
|
||||
}
|
||||
fmt.Println(msg)
|
||||
}
|
||||
|
||||
func (co ConsoleOutput) ChangedStatusF(format string, a ...interface{}) {
|
||||
msg := fmt.Sprintf(format, a...)
|
||||
if co.Color {
|
||||
msg = fmt.Sprintf("%v%v", colorYellow, msg)
|
||||
}
|
||||
fmt.Println(msg)
|
||||
}
|
||||
|
||||
func (co ConsoleOutput) ErrorStatusF(format string, a ...interface{}) {
|
||||
msg := fmt.Sprintf(format, a...)
|
||||
if co.Color {
|
||||
msg = fmt.Sprintf("%v%v", colorRed, msg)
|
||||
}
|
||||
fmt.Println(msg)
|
||||
}
|
||||
25
app/utils.go
Normal file
25
app/utils.go
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
package app
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func getFileContent(pathToFile string) ([]byte, error) {
|
||||
return ioutil.ReadFile(pathToFile)
|
||||
}
|
||||
|
||||
func getFileExcension(pathToFile string) (string, error) {
|
||||
splittedFileName := strings.Split(pathToFile, ".")
|
||||
|
||||
if len(splittedFileName) == 1 {
|
||||
msg := fmt.Sprintf("excension for file \"%v\", not found", splittedFileName)
|
||||
return "", errors.New(msg)
|
||||
}
|
||||
|
||||
fileExcension := splittedFileName[len(splittedFileName)-1]
|
||||
|
||||
return fileExcension, nil
|
||||
}
|
||||
36
app/utils_test.go
Normal file
36
app/utils_test.go
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
package app
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestGetFileExtension(t *testing.T) {
|
||||
|
||||
toTest := map[string]string{
|
||||
"myYamlFile.yaml": "yaml",
|
||||
"myTxtFile.txt": "txt",
|
||||
"myJsonFile.json": "json",
|
||||
}
|
||||
|
||||
for key, value := range toTest {
|
||||
result, err := getFileExcension(key)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if result != value {
|
||||
t.Errorf("Expected to get %v, instead of this got %v", value, result)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestErrorInGetExcensionFile(t *testing.T) {
|
||||
|
||||
result, err := getFileExcension("test")
|
||||
|
||||
if err == nil {
|
||||
t.Errorf("Expected to get error, instead of this got result %v", result)
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue