123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- package main
- import (
- "strings"
- "fmt"
- "flag"
- "os"
- "path/filepath"
- )
- const (
- EXIT_SUCCESS int = iota
- EXIT_ENV_INVALID
- EXIT_CONFIG_INVALID
- EXIT_SPECIFIED_PATH_INVALID
- EXIT_HOME_INVALID
- EXIT_SSH_ERROR
- EXIT_SCP_ERROR
- )
- func main() {
- // query program name by call
- program := os.Args[0][strings.LastIndex(os.Args[0], "/") + 1 : len(os.Args[0])]
- // query environment
- user, user_ok := os.LookupEnv("USER");
- home, home_ok := os.LookupEnv("HOME");
- if !(user_ok && home_ok) {
- fmt.Fprintf(os.Stderr, "%s: error: environment variables $USER and $HOME need to be set\n", program)
- os.Exit(EXIT_ENV_INVALID)
- }
- // register help functions
- flag.Usage = func() {
- fmt.Fprintf(os.Stdout, "usage: %s [-s|--save] [-c|--config path] [-l|--list-config] [-e|--print-example-config] [-g|--generate-config path] [-G|--generate-config-auto] command [files]\n", program)
- // TODO: default generated by flag pkg is ugly, redo
- flag.PrintDefaults()
- os.Exit(EXIT_SUCCESS)
- }
- // add save flag
- var save bool
- default_save := false
- help_save := "saves the result of an operation if true (only for some operations)"
- flag.BoolVar(&save, "s", default_save, help_save)
- flag.BoolVar(&save, "save", default_save, help_save)
- // add configuration file path option (with alias for --config)
- var configuration_path string
- default_path := fmt.Sprintf("%s/.config/%s/%s", home, user, user)
- help_configuration_path := "specifies the file path of the configuration to be used"
- flag.StringVar(&configuration_path, "c", default_path, help_configuration_path)
- flag.StringVar(&configuration_path, "config", default_path, help_configuration_path)
- // add print example configuration flag
- var list_config bool
- default_list_config := false
- help_list_config := "lists current configuration obfuscating the secret and exits"
- flag.BoolVar(&list_config, "l", default_list_config, help_list_config)
- flag.BoolVar(&list_config, "list-config", default_list_config, help_list_config)
- // add print example configuration flag
- var print_example_config bool
- default_print_example_config := false
- help_print_example_config := "prints example configuration if true and exits"
- flag.BoolVar(&print_example_config, "e", default_print_example_config, help_print_example_config)
- flag.BoolVar(&print_example_config, "print-example-config", default_print_example_config, help_print_example_config)
- // add generate example configuration option
- var generate_config_path string
- default_generate_config_path := ""
- help_generate_config := "generates and example configuration to a specified path and exits"
- flag.StringVar(&generate_config_path, "g", default_generate_config_path, help_generate_config)
- flag.StringVar(&generate_config_path, "generate-config", default_generate_config_path, help_generate_config)
- // add generate example configuration auto flag
- var generate_config_auto bool
- default_generate_config_auto := false
- help_generate_config_auto := fmt.Sprintf("generates and example configuration to %s and exits", GetConfigDefaultPath())
- flag.BoolVar(&generate_config_auto, "G", default_generate_config_auto, help_generate_config_auto)
- flag.BoolVar(&generate_config_auto, "generate-config-auto", default_generate_config_auto, help_generate_config_auto)
- // finally parse everything and use arguments afterwards
- flag.CommandLine.Parse(os.Args[1:])
- // if user wants to print example configuration
- if print_example_config {
- fmt.Println(CONFIG_EXAMPLE)
- return
- }
- // if user wants to generate example configuration
- if generate_config_auto || generate_config_path != "" {
- // query default location and split to dir and file
- default_path := GetConfigDefaultPath()
- // in case user specified his own path
- if generate_config_path != "" {
- default_path = generate_config_path
- // take care to expand unexpanded tilde
- fmt.Printf(default_path, strings.HasPrefix(default_path, "~"))
- if strings.HasPrefix(default_path, "~") {
- default_path = strings.Replace(default_path, "~", GetHomeDir(), 1)
- }
- }
- dir, filename := filepath.Split(default_path)
- fmt.Printf("generating configuration at %s\n", default_path)
- os.MkdirAll(dir, os.ModePerm)
- // TODO: ask user in case file already exists?
- err := os.WriteFile(default_path, []byte(CONFIG_EXAMPLE), 0644)
- if err != nil {
- fmt.Fprintf(os.Stderr, "fatal error: file %s could not be opened for reading\n", filename)
- }
- return
- }
- // get and check configuration
- config := GetConfiguration(&program, &configuration_path)
- if !IsConfigurationValid(&config) {
- fmt.Fprintf(os.Stderr, "%s: configuration is invalid: %s\n", program, ConfigurationToString(&config, true))
- os.Exit(EXIT_CONFIG_INVALID)
- }
- // if user wants to list current configuration
- if list_config {
- fmt.Println(ConfigurationToString(&config, true))
- return
- }
- // print available commands in case user needs them
- ExtendedUsage := func() {
- fmt.Printf("available commands are: `list`, `push [files]`, `pull [files]`, `commit`\n\n")
- flag.Usage()
- }
- // one command is necessary
- if flag.NArg() < 1 {
- ExtendedUsage()
- }
- // split command and (sometimes) optional positional file arguments
- arguments := flag.Args()
- command, files := arguments[0], arguments[1:]
- // show usage in case an invalid command is issued
- if IsImplemented(command) {
- Exec(command, &config, files, save)
- } else {
- ExtendedUsage()
- }
- }
|