diff --git a/src/cmd/cz.go b/src/cmd/cz.go index 00e8edc..7c33774 100644 --- a/src/cmd/cz.go +++ b/src/cmd/cz.go @@ -55,6 +55,10 @@ This will require the user to have commitizen installed on their system.`, } utils.GitWrapper(message, git_flags) + if update { + update_msg() + } + if pflag { fmt.Println(message) } diff --git a/src/cmd/root.go b/src/cmd/root.go index acec4bd..631d37d 100644 --- a/src/cmd/root.go +++ b/src/cmd/root.go @@ -1,19 +1,29 @@ package cmd import ( + "encoding/json" "fmt" + "net/http" "os" "strings" "github.com/Slug-Boi/cocommit/src/cmd/tui" "github.com/Slug-Boi/cocommit/src/cmd/utils" "github.com/inancgumus/screen" + "github.com/charmbracelet/lipgloss" "github.com/spf13/cobra" ) // Variables lives in here in case of possible future check of updates on running the CLI var Coco_Version string +var update bool + +// print styling for the output for the CLI +var update_style = lipgloss.NewStyle().Bold(true).Foreground(lipgloss.Color("#1aff00")) +var msg_style = lipgloss.NewStyle().BorderStyle(lipgloss.RoundedBorder()).BorderForeground(lipgloss.Color("170")) + +// github_tag struct to hold the tag name from the github api response // rootCmd represents the base command when called without any subcommands // func RootCmd() *cobra.Command { @@ -33,6 +43,12 @@ var rootCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { var message string + // check if user included -m tag and remove. Wrap around for safety's sake + if len(args) > 0 && args[0] == "-m" { + // maybe change to a walk in case it pops up later? + args = args[1:] + } + // check if the print flag is set pflag, _ := cmd.Flags().GetBool("print-output") tflag, _ := cmd.Flags().GetBool("test_print") @@ -43,6 +59,9 @@ var rootCmd = &cobra.Command{ if vflag { fmt.Println("Cocommit version:", Coco_Version) + if update { + update_msg() + } os.Exit(0) } @@ -53,54 +72,38 @@ var rootCmd = &cobra.Command{ } if aflag { - tui.Entry() - os.Exit(0) + sel_auth := tui.Entry() + if len(args) == 0 { + if update { + update_msg() + } + os.Exit(0) + } + args = append(args, sel_auth...) + goto skip } // run execute commands again as root run will not call this part // redundant check for now but will be useful later when we add tui - wrap_around: switch len(args) { case 0: // launch the tui - args = append(args, tui.Entry_CM()) - screen.Clear() - screen.MoveTopLeft() - sel_auth := tui.Entry() - message = utils.Commit(args[0], sel_auth) - if tflag { - fmt.Println(message) - return - } - goto tui + args = call_tui(args) case 1: if len(args) == 1 { - if tflag { - fmt.Println(args[0]) - return - } - - utils.GitWrapper(args[0], git_flags) - if pflag { - fmt.Println(args[0]) - } - - if gpflag { - utils.GitPush() - } - os.Exit(0) + message = args[0] } } - // check if user included -m tag and remove. Wrap around for safety's sake - if args[0] == "-m" { - args = args[1:] - goto wrap_around - } - + skip: // builds the commit message with the selected authors - message = utils.Commit(args[0], args[1:]) + if len(args) > 1 { + message = utils.Commit(args[0], args[1:]) + } + + if update { + update_msg() + } - tui: if tflag { fmt.Println(message) return @@ -120,6 +123,9 @@ var rootCmd = &cobra.Command{ // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. func Execute() { + // check for update + check_update() + // author file check author_file := utils.CheckAuthorFile() // define users @@ -131,6 +137,45 @@ func Execute() { } } +func call_tui(args []string) []string { + // append commit message to args + args = append(args, tui.Entry_CM()) + + // clear the screen + screen.Clear() + screen.MoveTopLeft() + + // run the tui and append authors to args + args = append(args, tui.Entry()...) + return args +} + +func update_msg() { + fmt.Print(update_style.Render("--* A new version of cocommit is available. Please update to the latest version *--")+"\n\n") +} + +// function to check for updates (check tag version from repo with the current version) +func check_update() { + var tag github_release + tags, err := http.Get("https://api.github.com/repos/Slug-Boi/cocommit/releases/latest") + if err != nil { + fmt.Println("Could not fetch tags from github API") + return + } + defer tags.Body.Close() + + err = json.NewDecoder(tags.Body).Decode(&tag) + if err != nil { + fmt.Println("Error decoding json response from github API") + return + } + + // NOTE: maybe change to a split and parse method idk if this can cause issues + if tag.TagName != Coco_Version && Coco_Version != "" { + update = true + } +} + func init() { //rootCmD := RootCmd() rootCmd.Flags().BoolP("print-output", "o", false, "Prints the commit message to the console") diff --git a/src/cmd/update.go b/src/cmd/update.go index 5f9a18d..27a4004 100644 --- a/src/cmd/update.go +++ b/src/cmd/update.go @@ -30,6 +30,17 @@ var updateCmd = &cobra.Command{ Long: `This command will try to update the cocommit cli tool by either running the update script or by running the go get Command if the -g flag is set.`, Run: func(cmd *cobra.Command, args []string) { gflag, _ := cmd.Flags().GetBool("go-get") + cflag, _ := cmd.Flags().GetBool("check") + + if cflag { + fmt.Println("Checking if Cocommit is up to date") + if update { + update_msg() + } else { + fmt.Println("Cocommit is up to date") + } + os.Exit(0) + } // check version of the cli tool Github, err := http.Get("https://api.github.com/repos/Slug-Boi/cocommit/releases/latest") @@ -137,12 +148,12 @@ func updateScript() { } err = unzipper("./", r) if err != nil { - fmt.Println("Error unzipping file") + panic("Error unzipping file - " + err.Error()) } swapper(exec_path) - fmt.Println("Cocommit cli tool updated successfully") + fmt.Println(update_style.Render("Cocommit cli tool updated successfully")) } func swapper(exec_path string) { @@ -203,10 +214,18 @@ func unzipper(dst string, r io.Reader) error { // the target location where the dir/file should be created target := filepath.Join(dst, header.Name) - // ensure the target path is within the destination directory - if !strings.HasPrefix(target, filepath.Clean(dst)+string(os.PathSeparator)) { - return fmt.Errorf("illegal file path: %s", target) - } + // ensure the target path is within the destination directory + cleanTarget, err := filepath.Abs(target) + if err != nil { + return fmt.Errorf("failed to get absolute path: %v", err) + } + cleanDst, err := filepath.Abs(dst) + if err != nil { + return fmt.Errorf("failed to get absolute path: %v", err) + } + if !strings.HasPrefix(cleanTarget, cleanDst+string(os.PathSeparator)) { + return fmt.Errorf("illegal file path: %s\nExpected: %s", cleanTarget, cleanDst+string(os.PathSeparator)) + } // check the file type switch header.Typeflag { @@ -241,4 +260,5 @@ func unzipper(dst string, r io.Reader) error { func init() { rootCmd.AddCommand(updateCmd) updateCmd.Flags().BoolP("go-get", "g", false, "Use the go get command to update the cocommit cli tool") + updateCmd.Flags().BoolP("check", "c", false, "Check if the cocommit cli tool is up to date") } diff --git a/src/cmd/users.go b/src/cmd/users.go index fda9fd7..591558e 100644 --- a/src/cmd/users.go +++ b/src/cmd/users.go @@ -22,6 +22,10 @@ func UsersCmd() *cobra.Command { Short: "Displays all users from the author file located at:\n" + authorfile, Long: `Displays all users from the author file located at:` + "\n" + authorfile, Run: func(cmd *cobra.Command, args []string) { + if update { + update_msg() + } + //TODO: make this print a bit prettier (sort it and maybe use a table) // check if the no pretty print flag is set np, _ := cmd.Flags().GetBool("np") diff --git a/src/cmd/utils/author_file_utils.go b/src/cmd/utils/author_file_utils.go index 62ba9d2..1b071d5 100644 --- a/src/cmd/utils/author_file_utils.go +++ b/src/cmd/utils/author_file_utils.go @@ -6,6 +6,7 @@ import ( "fmt" "os" "regexp" + "strings" ) // Author file utils is a package that contains functions that are used to read @@ -26,6 +27,7 @@ func Find_authorfile() string { } func CheckAuthorFile() string { + var cocommit_folder string authorfile := Find_authorfile() if _, err := os.Stat(authorfile); os.IsNotExist(err) { println("Author file not found at: ", authorfile) @@ -36,18 +38,15 @@ func CheckAuthorFile() string { println("Error reading response") } if response == "y" { - if authorfile == "" { - fmt.Println("author_file environment variable not set using default location:") - config, err := os.UserConfigDir() - if err != nil { - fmt.Println("Error getting user config directory") - os.Exit(1) - } - authorfile = config + "/cocommit/authors" - fmt.Println(authorfile) - } + parts := strings.Split(authorfile, "/") + cocommit_folder = strings.Join(parts[:len(parts)-1], "/") // create the author file + err := os.Mkdir(cocommit_folder, 0766) + if err != nil { + fmt.Println("Error creating directory: ", err, cocommit_folder) + os.Exit(1) + } file, err := os.Create(authorfile) if err != nil { fmt.Println("Error creating file: ", err) diff --git a/src/cmd/utils/user_util.go b/src/cmd/utils/user_util.go index 92ffb04..033c189 100644 --- a/src/cmd/utils/user_util.go +++ b/src/cmd/utils/user_util.go @@ -2,6 +2,7 @@ package utils import ( "bufio" + "fmt" "os" "strings" ) @@ -47,11 +48,19 @@ func Define_users(author_file string) { info := strings.Split(input_str, "|") if len(info) < 4 { if len(info) > 0 { - println("Error: User ", info[0], " is missing information") + if info[0] == "" { + info[0] = "(empty string)" + } + fmt.Println("Error: User", info[0], "is missing information") + } else { + fmt.Println("Error: Some user is missing information") + } + fmt.Println("Please check the author file for proper syntax") + if input_str == "" { + fmt.Println("empty line found in author file") } else { - println("Error: Some user is missing information") + fmt.Println("author file input:", input_str) } - println("Please check the author file for proper syntax") os.Exit(1) } usr := User{Username: info[2], Email: info[3], Names: info[0] + "/" + info[1]}