commit 5d7cd682792736af91c4abc5d85326c9db8191d4 Author: deranjer Date: Tue May 26 22:58:24 2020 -0400 adding custom config library, can read/write TOML, started config validation diff --git a/client/.gvcconfig.toml b/client/.gvcconfig.toml new file mode 100644 index 0000000..6e7199a --- /dev/null +++ b/client/.gvcconfig.toml @@ -0,0 +1,25 @@ +rootPath = "client" +version = "0.1.5" + +[ignore] + files = [ "file1.txt", "file2.txt" ] + exts = [ ".jpg", ".png" ] + 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 + + diff --git a/client/.gvcconfigNew.toml b/client/.gvcconfigNew.toml new file mode 100644 index 0000000..22df86a --- /dev/null +++ b/client/.gvcconfigNew.toml @@ -0,0 +1,28 @@ +version = 1.0 +RootPath = "client" + +[[remote]] + name = "origin" + host = "" + port = 8694 + +[[remote]] + name = "secondOrigin" + host = "" + port = 4253 + +[[remote]] + name = "my new Remote" + host = "hostname.com" + port = 1234 + +[ignore] + files = ["file1.txt", "file2.txt"] + exts = [".jpg", ".png"] + folders = [] + +[nocompress] + files = ["fileA.log", "fileB.txt"] + exts = [".exe", ".jpg"] + folders = ["binaries"] + diff --git a/client/.gvcignore.toml b/client/.gvcignore.toml new file mode 100644 index 0000000..e69de29 diff --git a/client/client.exe b/client/client.exe new file mode 100644 index 0000000..081e02a Binary files /dev/null and b/client/client.exe differ diff --git a/client/client.go b/client/client.go new file mode 100644 index 0000000..d7745d4 --- /dev/null +++ b/client/client.go @@ -0,0 +1,95 @@ +package main + +import ( + "fmt" + "os" + + clir "github.com/deranjer/clir" + clientcmd "github.com/deranjer/gvc/client/clientcmd" + clientconfig "github.com/deranjer/gvc/client/clientconfig" + "github.com/deranjer/store" +) + +var version = "0.1.5" + +func main() { + var conf clientconfig.Gvcconfig + + err := store.Load(".gvcconfig.toml", &conf) + if err != nil { + fmt.Println("Error loading config file into struct! ", err) + } + clientconfig.ValidateConfig(&conf, version) + + // Initialize our new cli + cli := clir.NewCli("gvcc", "Version control client for GVC", version) + + // Adding the init command + initCommand(cli, &conf) + + // Adding all the "add" commands + addCommands(cli, &conf) + + err = cli.Run() + if err != nil { + fmt.Printf("Error occurred: : %v\n", err) + } + // After the cli is finished running and writing new values, then validate the input and write it back to the TOML config file + clientconfig.ValidateConfig(&conf, version) + err = store.Save(".gvcconfigNew.toml", &conf) + if err != nil { + fmt.Println("Error saving config back to toml file: ", err) + } + +} + +// validateRepo just ensures that the command is being run against an actual repo (bool yes or no) +func validateRepo() bool { + if _, err := os.Stat(".gvcconfig.toml"); os.IsNotExist(err) { + return false + } + return true +} + +func initCommand(cli *clir.Cli, conf *clientconfig.Gvcconfig) { + //The init subcommand + initCmd := cli.NewSubCommand("init", "initializes a new gvc repo") + initCmd.LongDescription("This will create the .gvcconfig.toml (with defaults) file in this directory. You can edit this file directly (unsafe) or with the client(safe)") + initCmd.Action(func() error { + isRepo := validateRepo() + if !isRepo { + err := clientcmd.InitializeRepo() + if err != nil { + err = fmt.Errorf("unable to initialize repo: %s", err) + fmt.Println(err) + return err + } + return nil + } + fmt.Println("appears that this directory is already a gvc repo") + return nil + }) +} + +func addCommands(cli *clir.Cli, conf *clientconfig.Gvcconfig) { + //All the add commands and subcommands + //The add subcommand + addCmd := cli.NewSubCommand("add", "adds file(s)/folder(s) (recursively for folder) to repo") + addCmd.LongDescription("You can add all: all, a -file: file.txt, or a -folder: folder, or a -wildcard: *.txt") + //File/Folder/Wildcard adding + addCmd.Action(clientcmd.AddFiles) + //Add all files recursively to repo + addall := addCmd.NewSubCommand("all", "add all of the file(s)/folders(s) recursively to repo") + addall.Action(clientcmd.AddAll) + //The remote command + remoteCmd := cli.NewSubCommand("remote", "add/delete/show remotes") + var name string + var host string + var port int + remoteAddCmd := remoteCmd.NewSubCommand("add", "add a remote, requires -name -host and -port") + remoteAddCmd.LongDescription("Adds a remote to the .gvcconfig.toml. Requires the -name, -host and -port flags. Example: gvc remote add -name exampleRemote -host examplehost.com -port 8080") + remoteAddCmd.StringFlag("name", "the name you want for your remote server", &name) + remoteAddCmd.StringFlag("host", "the hostname or IP Address of the remote", &host) + remoteAddCmd.IntFlag("port", "the port the remote server is listening on", &port) + +} diff --git a/client/clientcmd/add.go b/client/clientcmd/add.go new file mode 100644 index 0000000..5ad98b4 --- /dev/null +++ b/client/clientcmd/add.go @@ -0,0 +1,18 @@ +package clientcmd + +import ( + "fmt" + "os" +) + +//AddFiles adds files to the repo +func AddFiles() error { + fmt.Println("File/folder/wildcard to add", os.Args[2]) + return nil +} + +//AddAll adds all files in working dir +func AddAll() error { + fmt.Println("Adding all files", os.Args[2]) + return nil +} diff --git a/client/clientcmd/commonlib.go b/client/clientcmd/commonlib.go new file mode 100644 index 0000000..a55e450 --- /dev/null +++ b/client/clientcmd/commonlib.go @@ -0,0 +1 @@ +package clientcmd diff --git a/client/clientcmd/ignore.go b/client/clientcmd/ignore.go new file mode 100644 index 0000000..cc8e4a4 --- /dev/null +++ b/client/clientcmd/ignore.go @@ -0,0 +1,12 @@ +package clientcmd + +import ( + "fmt" + "os" +) + +//IgnoreFiles ignores file(s)/folder based on name/wildcard, etc +func IgnoreFiles() error { + fmt.Println("File/folder/wildcard to ignore", os.Args[2]) + return nil +} diff --git a/client/clientcmd/init.go b/client/clientcmd/init.go new file mode 100644 index 0000000..6f747c5 --- /dev/null +++ b/client/clientcmd/init.go @@ -0,0 +1,16 @@ +package clientcmd + +import ( + "fmt" + "os" +) + +//AddFiles adds files to the repo +func InitializeRepo() error { + cwd, err := os.Getwd() + if err != nil { + return err + } + fmt.Println("Initializing repo in dir: ", cwd) + return nil +} diff --git a/client/clientconfig/config.go b/client/clientconfig/config.go new file mode 100644 index 0000000..22e4837 --- /dev/null +++ b/client/clientconfig/config.go @@ -0,0 +1,87 @@ +package config + +import ( + "fmt" + "os" +) + +// ValidateConfig will go through the entire config and do basic sanity checks +func ValidateConfig(conf *Gvcconfig, version string) error { + if conf.Version == "" { // No version found, should we update it? + fmt.Printf("No version found, inputing current client version: %s", version) + conf.Version = version + } + if conf.RootPath == "" { + path, err := os.Getwd() + if err != nil { + return fmt.Errorf("unable to get current working directory, and rootpath of repo is not set: %s", err) + } + fmt.Printf("No root path found, inputting current working directory: %s", path) + } + err := validateRemotes(conf) + if err != nil { + return err + } + err = validateCompress(conf) + if err != nil { + return err + } + //TODO validate ignores (pretty similar to compress) + return nil +} + +// validateCompress checks the compression settings to make sure they are valid //TODO return error needed? +func validateCompress(conf *Gvcconfig) error { + compress := conf.NoCompress + for i, file := range compress.Files { + if file == "" { + fmt.Println("empty file in compress files, removing... ") + compress.Files[i] = compress.Files[len(compress.Files)-1] + } + // TODO: write more validation + return nil + } + for i, folder := range compress.Folders { + file, err := os.Stat(folder) // TODO: check to see if it returns ABS or not, might need to convert + if err != nil { + fmt.Println("unable to find folder listed in array, removing it: ", folder) + compress.Folders[i] = compress.Folders[len(compress.Folders)-1] + continue + } + fileType := file.Mode() + if fileType.IsRegular() { // Not a folder + fmt.Println("compressed folder in array is not actually a folder, moving it to file compress: ", folder) + compress.Folders[i] = compress.Folders[len(compress.Folders)-1] + compress.Files = append(compress.Files, folder) + continue + } + } + for i, ext := range compress.Exts { + if ext == "" { + fmt.Println("empty ext in compress exts, removing... ") + compress.Exts[i] = compress.Exts[len(compress.Exts)-1] + continue + } + // TODO: validate there is a "." in front of the ext, if not add it? + } + return nil +} + +// validateRemotes ranges through all of the remotes and validates them +func validateRemotes(conf *Gvcconfig) error { + remotes := conf.Remotes + for _, remote := range remotes { + if remote.Name == "" { + return fmt.Errorf("Unnamed remote found in config, all remotes require name") + } + if remote.Host == "" { + return fmt.Errorf("Host cannot be empty: %s in %s", remote.Name, remote.Host) + } // Checking for a valid port // TODO: might need to move this function to common library, feel like we will need this in the future? + if remote.Port == 0 || remote.Port == 1 || remote.Port > 65535 { // TODO: edit the config library to allow default options? + fmt.Printf("Remote %s did not have a valid port set, setting it to the default port 8888", remote.Name) + remote.Port = 8888 + conf.Remotes = append(conf.Remotes, remote) + } + } + return nil +} diff --git a/client/clientconfig/structures.go b/client/clientconfig/structures.go new file mode 100644 index 0000000..ec291e7 --- /dev/null +++ b/client/clientconfig/structures.go @@ -0,0 +1,24 @@ +package config + +//Gvcconfig will be the struct that holds the entire client settings +type Gvcconfig struct { + Version string `toml:"version"` + RootPath string `toml:rootPath` + Remotes []Remote `toml:"remote"` //The remote servers for the repo + Ignores Ignore `toml:"ignore"` //These files will be ignored for all add functions + NoCompress Ignore `toml:"nocompress"` //For binary compression some files should be ignored because the performance hit isn't worth the size savings +} + +//Remote will be a slice of remote server information +type Remote struct { + Name string `toml:"name"` + Host string `toml:"host"` + Port int `toml:"port"` +} + +//Ignore is for ignoring files to add or ignoring compress +type Ignore struct { + Files []string `toml:"files"` + Exts []string `toml:"exts"` + Folders []string `toml:"folders"` +} diff --git a/client/go.mod b/client/go.mod new file mode 100644 index 0000000..0e02734 --- /dev/null +++ b/client/go.mod @@ -0,0 +1,12 @@ +module github.com/deranjer/gvc/client + +go 1.14 + +replace derajnet.duckdns.org/git/deranjer/gvc => ../gvc //alias for local development + +replace github.com/deranjer/gvc => ../gvc + +require ( + github.com/deranjer/clir v1.0.5 + github.com/deranjer/store v0.0.0-20200526205429-464dd59c6031 +) diff --git a/client/go.sum b/client/go.sum new file mode 100644 index 0000000..975d966 --- /dev/null +++ b/client/go.sum @@ -0,0 +1,10 @@ +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/deranjer/clir v1.0.5 h1:tEunZj5qJLYNBtzMQ/vH8hEAIv4NptWFmTldsP9U2qY= +github.com/deranjer/clir v1.0.5/go.mod h1:x/FAjr5CHGsBT0yjs+NYxX3qFxx8G15gbeCcN6FFuyU= +github.com/deranjer/store v0.0.0-20200526205429-464dd59c6031 h1:sPjxPMNILoBbu6uhDfa97AhlUhTgtPY2HqySAzuLd4o= +github.com/deranjer/store v0.0.0-20200526205429-464dd59c6031/go.mod h1:wPOs9IJ77lRTXyjEOQeegCFjIlm21qOFcv33lXmU7gE= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/client/test/test.go b/client/test/test.go new file mode 100644 index 0000000..fd7378c --- /dev/null +++ b/client/test/test.go @@ -0,0 +1,24 @@ +package main + +import ( + "fmt" + + "github.com/deranjer/clir" +) + +func main() { + + // Create new cli + cli := clir.NewCli("Other Args", "A basic example", "v0.0.1") + + // Set long description + cli.LongDescription("This app shows positional arguments") + + name := cli.NewSubCommand("name", "Shows your name!") + name.Action(func() error { + fmt.Printf("The remaining arguments were: %+v\n", name.OtherArgs()) + return nil + }) + // Run! + cli.Run() +}