From 2cbdf21a814ed66743c9f044caf3989b8c345f09 Mon Sep 17 00:00:00 2001 From: deranjer Date: Wed, 10 Jun 2020 22:45:15 -0400 Subject: [PATCH] working on merging configs, adding branch/switch/pull commands --- client/.gvc/.gvcconfig.toml | 14 ++-- client/.gvc/.gvcconfig.toml.old | 63 ++++++++++++------ client/client.go | 109 +++++++++++++++++++++++++++++--- client/clientcmd/branch.go | 25 ++++++++ client/clientcmd/refresh.go | 30 ++++++++- client/clientcmd/switch.go | 21 ++++++ client/test/test.go | 15 +---- common/commonlib.go | 14 ++++ common/structures.go | 23 +++---- server/config/serverConfig.toml | 7 +- server/engine/engine.go | 8 ++- server/gvclog.log | 6 ++ 12 files changed, 269 insertions(+), 66 deletions(-) create mode 100644 client/clientcmd/branch.go create mode 100644 client/clientcmd/switch.go diff --git a/client/.gvc/.gvcconfig.toml b/client/.gvc/.gvcconfig.toml index 55a1a94..b8ac4a9 100644 --- a/client/.gvc/.gvcconfig.toml +++ b/client/.gvc/.gvcconfig.toml @@ -2,8 +2,8 @@ version = "0.1.5" rootpath = "" reponame = "gvc" currentbranch = "master" -localbranches = ["master"] -remotebranches = ["master", "test", "test2"] +localbranches = ["master", "localbranch1", "localbranch2"] +remotebranches = ["master", "serveronlybranch", "anotherserverbranch"] [[remote]] name = "test2" @@ -36,12 +36,16 @@ remotebranches = ["master", "test", "test2"] default = false [locked] - files = ["test1\\client8.exe", "client1.exe", "client.go"] - exts = [".png"] + files = ["client1.exe", "client2.exe", "client.go", "serverLocked.go"] + exts = [".exeServer", "serverCOMP2EXT"] [ignore] - files = ["client1.exe", "client2.exe", "client3.exe", "client4.exe", "client5.exe", "client6.exe", "client7.exe", "test1\\client8.exe", "clientcmd\\init.go"] + files = ["client1.exe", "client2.exe", "client3.exe", "client4.exe", "client5.exe", "client6.exe", "client7.exe", "test1\\client8.exe", "clientcmd\\init.go", "localignoreonly.go"] exts = [".exe", ".tl"] + folders = ["serverFolderIgnore", "serverFolderignore2"] [nocompress] + files = ["localnocompress.go"] + exts = ["serverNoCompressEXT", "serverCOMP2EXT"] + folders = [] diff --git a/client/.gvc/.gvcconfig.toml.old b/client/.gvc/.gvcconfig.toml.old index 6e7199a..db14606 100644 --- a/client/.gvc/.gvcconfig.toml.old +++ b/client/.gvc/.gvcconfig.toml.old @@ -1,25 +1,50 @@ -rootPath = "client" version = "0.1.5" +rootpath = "" +reponame = "gvc" +currentbranch = "master" +localbranches = ["master", "localbranch1", "localbranch2"] +remotebranches = ["master"] + +[[remote]] + name = "test2" + host = "localhost" + port = 80 + default = true + +[[remote]] + name = "test4" + host = "localhost" + port = 9998 + default = false + +[[remote]] + name = "test3" + host = "localhost" + port = 9997 + default = false + +[[remote]] + name = "test5" + host = "localhost1" + port = 9997 + default = false + +[[remote]] + name = "test6" + host = "localhost1" + port = 9995 + default = false + +[locked] + files = ["client1.exe", "client2.exe", "client.go", "locallocked.go"] [ignore] - files = [ "file1.txt", "file2.txt" ] - exts = [ ".jpg", ".png" ] - folders = [] - + files = ["client1.exe", "client2.exe", "client3.exe", "client4.exe", "client5.exe", "client6.exe", "client7.exe", "test1\\client8.exe", "clientcmd\\init.go", "localignoreonly.go"] + exts = [".exe", ".tl"] + folders = [] [nocompress] - files = [ "fileA.log", "fileB.txt" ] - exts = [ ".exe", ".jpg" ] - folders = ["binaries"] - -[[remote]] -name = "origin" -host = "testorigin.com" -port = 8694 - -[[remote]] -name = "secondOrigin" -host = "170.5.95.195" -port = 4253 - + files = ["localnocompress.go"] + exts = [] + folders = [] diff --git a/client/client.go b/client/client.go index 75156c6..11ca042 100644 --- a/client/client.go +++ b/client/client.go @@ -67,6 +67,15 @@ func main() { // Adding the "remote" commands remoteCommands(cli, &conf) + // Adding the "branch" command + branchCommand(cli, &conf) + + // Adding the "switch" command + switchCommand(cli, &conf) + + // Adding the "pull" command + pullCommand(cli, &conf) + err = cli.Run() if err != nil { fmt.Printf("Error occurred: %v\n", err) @@ -510,26 +519,26 @@ func lockCommands(cli *clir.Cli, conf *clientconfig.Gvcconfig) { // removeLockCmd removes files/folders/wildcard from the ignore list func removeLockCmd(ignoreCmd *clir.Command, conf *clientconfig.Gvcconfig) { - RemoveLockCmd := ignoreCmd.NewSubCommand("remove", "remove from ignores file(s)/folder(s) (recursively for folder) to repo") - RemoveLockCmd.LongDescription("You can remove from ignore all: all, a -file (-f): file.txt, or a -folder (-fd): folder, or a -wildcard (-wc): *.txt") + removeLockCmd := ignoreCmd.NewSubCommand("remove", "remove from ignores file(s)/folder(s) (recursively for folder) to repo") + removeLockCmd.LongDescription("You can remove from ignore all: all, a -file (-f): file.txt, or a -folder (-fd): folder, or a -wildcard (-wc): *.txt") //File/Folder/Wildcard Ignoring var file string var folder string var wildcard string - fileFlag := RemoveLockCmd.StringFlag("file", "removes ignored file from config", &file) + fileFlag := removeLockCmd.StringFlag("file", "removes ignored file from config", &file) fileFlag.FlagShortCut("file", "f") - folderFlag := RemoveLockCmd.StringFlag("folder", "removes ignored folder", &folder) + folderFlag := removeLockCmd.StringFlag("folder", "removes ignored folder", &folder) folderFlag.FlagShortCut("folder", "fd") - wildCardFlag := RemoveLockCmd.StringFlag("wildcard", "removes wildcard from ignores", &wildcard) + wildCardFlag := removeLockCmd.StringFlag("wildcard", "removes wildcard from ignores", &wildcard) wildCardFlag.FlagShortCut("wildcard", "wc") - RemoveLockCmd.Action(func() error { + removeLockCmd.Action(func() error { isRepo := validateRepo() if !isRepo { fmt.Println("no valid repo found.. please run 'init' to setup a repo first") os.Exit(0) } - if len(RemoveLockCmd.OtherArgs()) > 0 { - RemoveLockCmd.PrintHelp() + if len(removeLockCmd.OtherArgs()) > 0 { + removeLockCmd.PrintHelp() return fmt.Errorf("incorrect input detected, please fix and retry") } if file != "" { // if the file flag was used it won't be empty @@ -559,3 +568,87 @@ func removeLockCmd(ignoreCmd *clir.Command, conf *clientconfig.Gvcconfig) { return nil }) } + +func branchCommand(cli *clir.Cli, conf *config.Gvcconfig) { + branchCommand := cli.NewSubCommand("branch", "creates a new branch off of the current branch") + var branchName string + nameFlag := branchCommand.StringFlag("name", "name of the branch to create", &branchName) + nameFlag.FlagShortCut("name", "n") + nameFlag.FlagRequired("name") + branchCommand.Action(func() error { + isRepo := validateRepo() + if !isRepo { + fmt.Println("no valid repo found.. please run 'init' to setup a repo first") + os.Exit(0) + } + err := clientcmd.CreateBranch(conf, branchName) + if err != nil { + return err + } + return nil + }) +} + +func switchCommand(cli *clir.Cli, conf *config.Gvcconfig) { + switchCommand := cli.NewSubCommand("switch", "switches (and can create if needed) a new branch to work on") + var createBranch bool + createFlag := switchCommand.BoolFlag("create", "creates the branch if it does not exist", &createBranch) + createFlag.FlagShortCut("create", "c") + switchCommand.Action(func() error { + isRepo := validateRepo() + if !isRepo { + fmt.Println("no valid repo found.. please run 'init' to setup a repo first") + os.Exit(0) + } + if createBranch { + if len(switchCommand.OtherArgs()) < 1 { + switchCommand.PrintHelp() + fmt.Println("branch name required..") + os.Exit(0) + } + branchName := switchCommand.OtherArgs()[0] + fmt.Println("attempting to create branch name: ", branchName) + err := clientcmd.CreateBranch(conf, branchName) + if err != nil { + return fmt.Errorf("error creating branch: %s", err) + } + return nil + } + if len(switchCommand.OtherArgs()) == 0 { + switchCommand.PrintHelp() + fmt.Println("branch name required..") + os.Exit(0) + } + branchName := switchCommand.OtherArgs()[0] + err := clientcmd.SwitchBranch(conf, branchName) + if err != nil { + return fmt.Errorf("unable to switch branch: %s", err) + } + return nil + }) +} + +func pullCommand(cli *clir.Cli, conf *config.Gvcconfig) { + pullCommand := cli.NewSubCommand("pull", "pulls the latest commit from the server (default if none specified) on your current branch") + var createBranch bool + createFlag := pullCommand.BoolFlag("create", "creates the branch if it does not exist", &createBranch) + createFlag.FlagShortCut("create", "c") + pullCommand.Action(func() error { + isRepo := validateRepo() + if !isRepo { + fmt.Println("no valid repo found.. please run 'init' to setup a repo first") + os.Exit(0) + } + if len(pullCommand.OtherArgs()) == 0 { + pullCommand.PrintHelp() + fmt.Println("branch name required..") + os.Exit(0) + } + branchName := pullCommand.OtherArgs()[0] + err := clientcmd.SwitchBranch(conf, branchName) + if err != nil { + return fmt.Errorf("unable to pull branch: %s", err) + } + return nil + }) +} diff --git a/client/clientcmd/branch.go b/client/clientcmd/branch.go new file mode 100644 index 0000000..d9adf41 --- /dev/null +++ b/client/clientcmd/branch.go @@ -0,0 +1,25 @@ +package clientcmd + +import ( + "fmt" + + clientconfig "github.com/deranjer/gvc/client/clientconfig" +) + +// CreateBranch creates a new branch with the supplied name +func CreateBranch(conf *clientconfig.Gvcconfig, branchName string) error { + branches := conf.LocalBranches + for _, branch := range branches { + if branch == branchName { + return fmt.Errorf("Branch already exists, unable to create, use the switch command to switch to this branch: %s", branchName) + } + } + conf.LocalBranches = append(conf.LocalBranches, branchName) //add the branch to the config + // TODO Create the branch + //If success, switch to new branch + err := SwitchBranch(conf, branchName) + if err != nil { + return fmt.Errorf("error switching to new branch: %s", err) + } + return nil +} diff --git a/client/clientcmd/refresh.go b/client/clientcmd/refresh.go index 23ee9d6..a99dc90 100644 --- a/client/clientcmd/refresh.go +++ b/client/clientcmd/refresh.go @@ -5,6 +5,7 @@ import ( clientconfig "github.com/deranjer/gvc/client/clientconfig" "github.com/deranjer/gvc/common" + "github.com/deranjer/store" "github.com/go-resty/resty/v2" ) @@ -31,7 +32,34 @@ func RefreshContent(conf *clientconfig.Gvcconfig, repoName string) error { //TOD } return fmt.Errorf("response not a success: %d: connection URL: %s", resp.StatusCode(), resp.Request.URL) } - fmt.Println(resp) + //fmt.Println(resp) fmt.Printf("%+v\n", refreshResult) + fmt.Println("Merging server config with local config...") + // TODO: Save a backup of the config in case we need to roll back + // TODO: Before merging check to make sure the slices aren't already the same + conf.Locked = refreshResult.Locked // Overwriting locks on client since server is authoritative on locks + fmt.Println("Replaced client locked with server locked...") + // Now merging the structs where the user might have customized for their environment + conf.NoCompress.Exts = append(conf.NoCompress.Exts, refreshResult.NoCompress.Exts...) + conf.NoCompress.Files = append(conf.NoCompress.Files, refreshResult.NoCompress.Files...) + conf.NoCompress.Folders = append(conf.NoCompress.Folders, refreshResult.NoCompress.Folders...) + conf.Ignores.Exts = append(conf.Ignores.Exts, refreshResult.Ignores.Exts...) + conf.Ignores.Files = append(conf.Ignores.Files, refreshResult.Ignores.Files...) + conf.Ignores.Folders = append(conf.Ignores.Folders, refreshResult.Ignores.Folders...) + // And then purging the duplicates using a map in case there are very large slices + conf.NoCompress.Exts = common.RemoveDuplicatesFromSlice(conf.NoCompress.Exts) + conf.NoCompress.Files = common.RemoveDuplicatesFromSlice(conf.NoCompress.Files) + conf.NoCompress.Folders = common.RemoveDuplicatesFromSlice(conf.NoCompress.Folders) + conf.Ignores.Exts = common.RemoveDuplicatesFromSlice(conf.Ignores.Exts) + conf.Ignores.Files = common.RemoveDuplicatesFromSlice(conf.Ignores.Files) + conf.Ignores.Folders = common.RemoveDuplicatesFromSlice(conf.Ignores.Folders) + fmt.Println("Joined and purged duplicates for Ignore and NoCompress...") + conf.RemoteBranches = refreshResult.Branches + fmt.Println("updated remote branches...") + // TODO Update Commits + err = store.Save(ConfigPath, &conf) + if err != nil { + return fmt.Errorf("unable to save refreshed config to file: %s", err) + } return nil } diff --git a/client/clientcmd/switch.go b/client/clientcmd/switch.go new file mode 100644 index 0000000..84f86ba --- /dev/null +++ b/client/clientcmd/switch.go @@ -0,0 +1,21 @@ +package clientcmd + +import ( + "fmt" + + clientconfig "github.com/deranjer/gvc/client/clientconfig" +) + +// SwitchBranch switches to a different branch +func SwitchBranch(conf *clientconfig.Gvcconfig, branchName string) error { + fmt.Println("Attempting to switch to branch: ", branchName) + branches := conf.LocalBranches + for _, branch := range branches { + if branch == branchName { + fmt.Println("Found Branch: ", branch) + // TODO: do the actual branch switch + return nil + } + } + return fmt.Errorf("unable to locate requested branch: %s", branchName) +} diff --git a/client/test/test.go b/client/test/test.go index 4699876..5846266 100644 --- a/client/test/test.go +++ b/client/test/test.go @@ -2,7 +2,6 @@ package main import ( "fmt" - "reflect" "github.com/imdario/mergo" ) @@ -21,20 +20,8 @@ func main() { Ignore: []string{"one", "two", "four", "seven"}, } - mergo.Merge(&dest, src, mergo.WithTransformers(StringSliceTransformer{})) + mergo.Merge(&dest, src) fmt.Println(dest) // Will print // {two 2} } - -type StringSliceTransformer struct { -} - -// MergeStrings merges two strings -func (s StringSliceTransformer) Transformer(typ reflect.Type) func(dst, src reflect.Value) error { - if typ == reflect.TypeOf([]string{}) { - return func(dst, src reflect.Value) error { - - } - } -} diff --git a/common/commonlib.go b/common/commonlib.go index 736b9cc..67deaf7 100644 --- a/common/commonlib.go +++ b/common/commonlib.go @@ -36,3 +36,17 @@ func CheckFileTypes(input string, inputType string, excludeList FileTypes) error } return nil } + +// RemoveDuplicatesFromSlice is used when merging configs, just purges duplicates from slice +func RemoveDuplicatesFromSlice(slice []string) []string { + seen := make(map[string]bool) + result := []string{} + + for _, entry := range slice { + if _, value := seen[entry]; !value { + seen[entry] = true + result = append(result, entry) + } + } + return result +} diff --git a/common/structures.go b/common/structures.go index 733ad61..c32005b 100644 --- a/common/structures.go +++ b/common/structures.go @@ -1,22 +1,17 @@ package common -//FileTypes is for ignoring files to add or ignoring compress, or for locked files, all use the same type of struct (files, folders and exts) -// type FileTypes struct { -// Files []string `toml:"files"` -// Exts []string `toml:"exts"` -// Folders []string `toml:"folders"` -// } - +// FileTypes is for ignoring files to add or ignoring compress, or for locked files, all use the same type of struct (files, folders and exts) type FileTypes struct { - Files map[string]string `toml:"files"` - Folders map[string]string `toml:"folders"` - Exts map[string]string `toml:"exts"` + Files []string `toml:"files"` + Exts []string `toml:"exts"` + Folders []string `toml:"folders"` } // RepoRefreshRequest returns locks, ignores, and commits/branches. Server marshals into this, client unmarshals type RepoRefreshRequest struct { - Branches []string // List of known branches on server - Commits string //TODO: This will be pulled from DB and be a different type - Locked FileTypes - Ignores FileTypes + Branches []string // List of known branches on server + Commits string //TODO: This will be pulled from DB and be a different type + Locked FileTypes + Ignores FileTypes + NoCompress FileTypes } diff --git a/server/config/serverConfig.toml b/server/config/serverConfig.toml index ce958c6..c67e022 100644 --- a/server/config/serverConfig.toml +++ b/server/config/serverConfig.toml @@ -9,16 +9,19 @@ reporootpath = "F:\\repos" rootpath = "" reponame = "gvc" defaultbranch = "master" - localbranches = ["master"] + localbranches = ["master", "serveronlybranch", "anotherserverbranch"] [[repo.client]] name = "deranjer" key = "12345" lastcommit = "4343434343434" [repo.locked] - files = ["client1.exe", "client2.exe", "client.go"] + files = ["client1.exe", "client2.exe", "client.go", "serverLocked.go"] + exts = [".exeServer", "serverCOMP2EXT"] [repo.defaultignore] + folders = ["serverFolderIgnore", "serverFolderignore2"] [repo.nocompress] + exts = ["serverNoCompressEXT", "serverCOMP2EXT"] [[repo]] rootpath = "" diff --git a/server/engine/engine.go b/server/engine/engine.go index c89e85b..246fd95 100644 --- a/server/engine/engine.go +++ b/server/engine/engine.go @@ -85,10 +85,12 @@ func (Server *GVCServer) Refresh(context echo.Context) error { branches := serverRepo.LocalBranches serverLocks := serverRepo.Locked serverIgnores := serverRepo.DefaultIgnores + serverNoCompress := serverRepo.NoCompress refreshResult := common.RepoRefreshRequest{ - Branches: branches, - Locked: serverLocks, - Ignores: serverIgnores, + Branches: branches, + Locked: serverLocks, + Ignores: serverIgnores, + NoCompress: serverNoCompress, } return context.JSON(http.StatusOK, refreshResult) } diff --git a/server/gvclog.log b/server/gvclog.log index aeb8dd5..45b5654 100644 --- a/server/gvclog.log +++ b/server/gvclog.log @@ -12,3 +12,9 @@ {"time":"2020-06-09T22:54:58.6865514-04:00","id":"","remote_ip":"::1","host":"localhost:80","method":"GET","uri":"/refresh/gvc","user_agent":"go-resty/2.3.0 (https://github.com/go-resty/resty)","status":200,"error":"","latency":0,"latency_human":"0s","bytes_in":0,"bytes_out":177} {"time":"2020-06-09T22:56:01.309063-04:00","id":"","remote_ip":"::1","host":"localhost:80","method":"GET","uri":"/refresh/gvc","user_agent":"go-resty/2.3.0 (https://github.com/go-resty/resty)","status":200,"error":"","latency":0,"latency_human":"0s","bytes_in":0,"bytes_out":177} {"time":"2020-06-09T22:56:25.9765046-04:00","id":"","remote_ip":"::1","host":"localhost:80","method":"GET","uri":"/refresh/gvc","user_agent":"go-resty/2.3.0 (https://github.com/go-resty/resty)","status":200,"error":"","latency":0,"latency_human":"0s","bytes_in":0,"bytes_out":177} +{"time":"2020-06-10T15:19:25.3707204-04:00","id":"","remote_ip":"::1","host":"localhost:80","method":"GET","uri":"/refresh/gvc","user_agent":"PostmanRuntime/7.24.1","status":200,"error":"","latency":1000400,"latency_human":"1.0004ms","bytes_in":0,"bytes_out":177} +{"time":"2020-06-10T15:56:42.0883534-04:00","id":"","remote_ip":"::1","host":"localhost:80","method":"GET","uri":"/refresh/gvc","user_agent":"go-resty/2.3.0 (https://github.com/go-resty/resty)","status":200,"error":"","latency":0,"latency_human":"0s","bytes_in":0,"bytes_out":177} +{"time":"2020-06-10T15:59:56.9878302-04:00","id":"","remote_ip":"::1","host":"localhost:80","method":"GET","uri":"/refresh/gvc","user_agent":"go-resty/2.3.0 (https://github.com/go-resty/resty)","status":200,"error":"","latency":0,"latency_human":"0s","bytes_in":0,"bytes_out":177} +{"time":"2020-06-10T16:01:25.3086487-04:00","id":"","remote_ip":"::1","host":"localhost:80","method":"GET","uri":"/refresh/gvc","user_agent":"go-resty/2.3.0 (https://github.com/go-resty/resty)","status":200,"error":"","latency":1000600,"latency_human":"1.0006ms","bytes_in":0,"bytes_out":331} +{"time":"2020-06-10T16:03:51.1803332-04:00","id":"","remote_ip":"::1","host":"localhost:80","method":"GET","uri":"/refresh/gvc","user_agent":"go-resty/2.3.0 (https://github.com/go-resty/resty)","status":200,"error":"","latency":0,"latency_human":"0s","bytes_in":0,"bytes_out":358} +{"time":"2020-06-10T16:05:39.6232811-04:00","id":"","remote_ip":"::1","host":"localhost:80","method":"GET","uri":"/refresh/gvc","user_agent":"go-resty/2.3.0 (https://github.com/go-resty/resty)","status":200,"error":"","latency":0,"latency_human":"0s","bytes_in":0,"bytes_out":394}