From a6d90b86dc941e5abb672775abcfd6940c8a4539 Mon Sep 17 00:00:00 2001 From: Slug-Boi Date: Mon, 16 Jun 2025 17:30:23 +0200 Subject: [PATCH 01/15] refactor: author file config --- src/cmd/utils/author_file_utils.go | 35 +++++++++++++++--------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/cmd/utils/author_file_utils.go b/src/cmd/utils/author_file_utils.go index e8ebe05..059b9d0 100644 --- a/src/cmd/utils/author_file_utils.go +++ b/src/cmd/utils/author_file_utils.go @@ -14,27 +14,26 @@ import ( // An example of the author file can be found in the examples folder of the repo func Find_authorfile() string { var file string - - if os.Getenv("author_file") == "" { - if ConfigVar == nil { - cfg, _ := LoadConfig() - if cfg == nil { - // mimic the default config structure - cfg = &Config{ - Settings: struct { - AuthorFile string `mapstructure:"author_file"` - StartingScope string `mapstructure:"starting_scope"` - Editor string `mapstructure:"editor"` - }{ - AuthorFile: "", - StartingScope: "git", - Editor: "built-in", - }, - } - cfg.SetGlobalConfig() + if ConfigVar == nil { + cfg, _ := LoadConfig() + if cfg == nil { + // mimic the default config structure + cfg = &Config{ + Settings: struct { + AuthorFile string `mapstructure:"author_file"` + StartingScope string `mapstructure:"starting_scope"` + Editor string `mapstructure:"editor"` + }{ + AuthorFile: "", + StartingScope: "git", + Editor: "built-in", + }, } } + cfg.SetGlobalConfig() + } + if os.Getenv("author_file") == "" { if ConfigVar.Settings.AuthorFile != "" { file = ConfigVar.Settings.AuthorFile } else if os.Getenv("author_file") != "" { From 1367d50fcee0eff324f974498499b0f3f18560ab Mon Sep 17 00:00:00 2001 From: Slug-Boi Date: Mon, 16 Jun 2025 17:30:48 +0200 Subject: [PATCH 02/15] feat: add editor util to handle and launch editors outside of built-in --- src/cmd/utils/editor.go | 107 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 src/cmd/utils/editor.go diff --git a/src/cmd/utils/editor.go b/src/cmd/utils/editor.go new file mode 100644 index 0000000..c27ec58 --- /dev/null +++ b/src/cmd/utils/editor.go @@ -0,0 +1,107 @@ +package utils + +import ( + "fmt" + "os" + "os/exec" + "strings" +) + + +func HandleEditor() (string, error) { + editor := ConfigVar.Settings.Editor + if editor == "built-in" { + return "", nil + } + + if editor == "" || editor == "default" { + editor = os.Getenv("EDITOR") + if editor == "" { + editor = "vim" // default to vim if no editor is set + } + } + + if _, err := exec.LookPath(editor); err != nil { + return "", fmt.Errorf("editor %s not found in PATH", editor) + } + + + output, err := LaunchEditor(editor, "") + if err != nil { + return "", fmt.Errorf("failed to launch editor %s: %v", editor, err) + } + return output, nil +} + +func LaunchEditor(editor string, filepath string) (string,error) { + // Create a temp file or use an existing file + var tempFile *os.File + var err error + + switch strings.ToLower(editor) { + case "default", "": + editor = os.Getenv("EDITOR") + if editor == "" { + editor = "vim" // default to vim if no editor is set + } + case "built-in": + // fallback to built-in editor + return "", nil + default: + if _, err := exec.LookPath(editor); err != nil { + return "", fmt.Errorf("editor %s not found in PATH", editor) + } + } + + if filepath == "" { + tempFile, err = os.CreateTemp("", "cocommit_editor_*.txt") + } else { + tempFile, err = os.OpenFile(filepath, os.O_RDWR, 0666) + } + if err != nil { + return "", fmt.Errorf("Could not create or open tempfile: %s", err.Error()) + } + + cmd := exec.Command(editor, tempFile.Name()) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + if err := cmd.Run(); err != nil { + return "", fmt.Errorf("error running editor command: %v", err) + } + + + data, err := os.ReadFile(tempFile.Name()) + if err != nil { + return "", fmt.Errorf("error reading temp file: %v", err) + } + + message := string(data) + if message == "" { + return "", fmt.Errorf("commit message is empty") + } + + // Clean up the temp file + if err := os.Remove(tempFile.Name()); err != nil { + return "", fmt.Errorf("error removing temp file: %v", err) + } + if strings.HasSuffix(message, "\n") { + message = strings.TrimSuffix(message, "\n") + } + if strings.HasSuffix(message, "\r") { + message = strings.TrimSuffix(message, "\r") + } + if strings.TrimSpace(message) == "" { + return "", fmt.Errorf("commit message is empty after trimming") + } + // If the message is too long, truncate it + if len(message) > 72 { + fmt.Printf("Warning: Commit message is too long (%d characters). It will be truncated to 72 characters.\n", len(message)) + //TODO: Maybe add the rest to the description of the message? + //description := message[72:] + message = message[:72] + } + + return message, nil +} \ No newline at end of file From eeb93fb4115a5a44f79734d86749aedf3ee62c4d Mon Sep 17 00:00:00 2001 From: Slug-Boi Date: Mon, 16 Jun 2025 17:31:09 +0200 Subject: [PATCH 03/15] refactor: change root command to use the new editor launcher --- src/cmd/root.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/cmd/root.go b/src/cmd/root.go index 12b09f4..9d2f59f 100644 --- a/src/cmd/root.go +++ b/src/cmd/root.go @@ -9,8 +9,8 @@ import ( "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/inancgumus/screen" "github.com/spf13/cobra" ) @@ -155,7 +155,16 @@ func Execute() { func call_tui(args []string) []string { // append commit message to args - args = append(args, tui.Entry_CM()) + //args = append(args, tui.Entry_CM()) + message, err := utils.LaunchEditor(utils.ConfigVar.Settings.Editor,"") + if err != nil { + panic(fmt.Sprintf("Error launching editor: %v", err)) + } + if message == "" { + message = tui.Entry_CM() + } + + args = append(args, message) // clear the screen screen.Clear() From 9e85fdd1b992fd24129453f613c3c23359a97b27 Mon Sep 17 00:00:00 2001 From: Slug-Boi Date: Mon, 16 Jun 2025 17:43:02 +0200 Subject: [PATCH 04/15] refactor: change commit length limit and change exit codes --- src/cmd/utils/editor.go | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/cmd/utils/editor.go b/src/cmd/utils/editor.go index c27ec58..676a3ce 100644 --- a/src/cmd/utils/editor.go +++ b/src/cmd/utils/editor.go @@ -7,7 +7,6 @@ import ( "strings" ) - func HandleEditor() (string, error) { editor := ConfigVar.Settings.Editor if editor == "built-in" { @@ -25,7 +24,6 @@ func HandleEditor() (string, error) { return "", fmt.Errorf("editor %s not found in PATH", editor) } - output, err := LaunchEditor(editor, "") if err != nil { return "", fmt.Errorf("failed to launch editor %s: %v", editor, err) @@ -33,7 +31,7 @@ func HandleEditor() (string, error) { return output, nil } -func LaunchEditor(editor string, filepath string) (string,error) { +func LaunchEditor(editor string, filepath string) (string, error) { // Create a temp file or use an existing file var tempFile *os.File var err error @@ -55,12 +53,12 @@ func LaunchEditor(editor string, filepath string) (string,error) { if filepath == "" { tempFile, err = os.CreateTemp("", "cocommit_editor_*.txt") - } else { - tempFile, err = os.OpenFile(filepath, os.O_RDWR, 0666) - } - if err != nil { - return "", fmt.Errorf("Could not create or open tempfile: %s", err.Error()) - } + } else { + tempFile, err = os.OpenFile(filepath, os.O_RDWR, 0666) + } + if err != nil { + return "", fmt.Errorf("Could not create or open tempfile: %s", err.Error()) + } cmd := exec.Command(editor, tempFile.Name()) cmd.Stdin = os.Stdin @@ -71,7 +69,6 @@ func LaunchEditor(editor string, filepath string) (string,error) { return "", fmt.Errorf("error running editor command: %v", err) } - data, err := os.ReadFile(tempFile.Name()) if err != nil { return "", fmt.Errorf("error reading temp file: %v", err) @@ -79,7 +76,8 @@ func LaunchEditor(editor string, filepath string) (string,error) { message := string(data) if message == "" { - return "", fmt.Errorf("commit message is empty") + fmt.Printf("Error: Commit message is empty. Please provide a commit message.\n") + os.Exit(0) } // Clean up the temp file @@ -93,15 +91,16 @@ func LaunchEditor(editor string, filepath string) (string,error) { message = strings.TrimSuffix(message, "\r") } if strings.TrimSpace(message) == "" { - return "", fmt.Errorf("commit message is empty after trimming") + fmt.Printf("Error: Commit message is empty. Please provide a commit message.\n") + os.Exit(0) } // If the message is too long, truncate it - if len(message) > 72 { - fmt.Printf("Warning: Commit message is too long (%d characters). It will be truncated to 72 characters.\n", len(message)) - //TODO: Maybe add the rest to the description of the message? - //description := message[72:] - message = message[:72] - } + // if len(message) > 72 { + // fmt.Printf("Warning: Commit message is too long (%d characters). It will be truncated to 72 characters.\n", len(message)) + // //TODO: Maybe add the rest to the description of the message? + // //description := message[72:] + // message = message[:72] + // } return message, nil -} \ No newline at end of file +} From b0591306f5eec51ad2450ede51f9257a44e2370f Mon Sep 17 00:00:00 2001 From: Slug-Boi Date: Tue, 17 Jun 2025 21:02:11 +0200 Subject: [PATCH 05/15] refactor: redudandant --- src/cmd/utils/author_file_utils.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/cmd/utils/author_file_utils.go b/src/cmd/utils/author_file_utils.go index 059b9d0..a020dec 100644 --- a/src/cmd/utils/author_file_utils.go +++ b/src/cmd/utils/author_file_utils.go @@ -36,14 +36,11 @@ func Find_authorfile() string { if os.Getenv("author_file") == "" { if ConfigVar.Settings.AuthorFile != "" { file = ConfigVar.Settings.AuthorFile - } else if os.Getenv("author_file") != "" { - file = os.Getenv("author_file") } else { userconf, err :=os.UserConfigDir() if err != nil { panic(fmt.Sprintf("Error getting user config dir: %v", err)) - } - + } if _, err := os.Stat(userconf+"/cocommit/authors.json"); os.IsNotExist(err) { panic(fmt.Sprintf("No author file set, please set the author_file environment variable or create a config file using the command: cocommit config -c")) } else { From 183788fda4cdc93ceebbe41203496301252f2660 Mon Sep 17 00:00:00 2001 From: Slug-Boi Date: Tue, 17 Jun 2025 21:28:28 +0200 Subject: [PATCH 06/15] feat: allow editing for amend commits --- src/cmd/utils/commit.go | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/src/cmd/utils/commit.go b/src/cmd/utils/commit.go index be7cbac..72ffcf4 100644 --- a/src/cmd/utils/commit.go +++ b/src/cmd/utils/commit.go @@ -2,6 +2,7 @@ package utils import ( "fmt" + "os" "os/exec" "regexp" "slices" @@ -129,7 +130,7 @@ func group_selection(group []User, excludeMode []string) []string { return excludeMode } -func GitCommitAppender(authors string, hash string, flags []string, t,p bool) (error, string) { +func GitCommitAppender(authors string, hash string, flags []string, t,p,n bool) (error, string) { // Get old commit message var cmd *exec.Cmd @@ -153,9 +154,36 @@ func GitCommitAppender(authors string, hash string, flags []string, t,p bool) (e // commit shell command // specify git command1 input := []string{"commit"} + + // Edit the old message input = append(input, flags...) old_commit = strings.TrimSpace(old_commit) - input = append(input, "--amend", "-m", old_commit+"\n"+authors) + + // Edit old commit message + var edited_commit string + if !n { + // Create tempfile for the commit message + file, err := os.CreateTemp("", "cocommit_editor_*.txt") + if err != nil { + return fmt.Errorf("Could not create tempfile: %s", err.Error()), "" + } + defer os.Remove(file.Name()) + + // Write the old commit message to the file + _, err = file.WriteString(old_commit + "\n" + authors) + if err != nil { + return fmt.Errorf("Could not write to tempfile: %s", err.Error()), "" + } + file.Close() + edited_commit, err = LaunchEditor(ConfigVar.Settings.Editor, file.Name()) + if err != nil { + return fmt.Errorf("Could not launch editor: %s", err.Error()), "" + } + } else { + edited_commit = old_commit + "\n" + authors + } + + input = append(input, "--amend", "-m", edited_commit) if p { println(old_commit + "\n" + authors) From 2e8b56c7194dc81cadcd82d75e8bac3e5a402d35 Mon Sep 17 00:00:00 2001 From: Slug-Boi Date: Tue, 17 Jun 2025 21:28:38 +0200 Subject: [PATCH 07/15] refactor: defer remove --- src/cmd/utils/editor.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/cmd/utils/editor.go b/src/cmd/utils/editor.go index 676a3ce..42dc882 100644 --- a/src/cmd/utils/editor.go +++ b/src/cmd/utils/editor.go @@ -31,7 +31,7 @@ func HandleEditor() (string, error) { return output, nil } -func LaunchEditor(editor string, filepath string) (string, error) { +func LaunchEditor(editor string, filepath string, ) (string, error) { // Create a temp file or use an existing file var tempFile *os.File var err error @@ -53,6 +53,7 @@ func LaunchEditor(editor string, filepath string) (string, error) { if filepath == "" { tempFile, err = os.CreateTemp("", "cocommit_editor_*.txt") + defer os.Remove(tempFile.Name()) } else { tempFile, err = os.OpenFile(filepath, os.O_RDWR, 0666) } @@ -81,9 +82,6 @@ func LaunchEditor(editor string, filepath string) (string, error) { } // Clean up the temp file - if err := os.Remove(tempFile.Name()); err != nil { - return "", fmt.Errorf("error removing temp file: %v", err) - } if strings.HasSuffix(message, "\n") { message = strings.TrimSuffix(message, "\n") } From 68024507e8131c890d8dcbdd82cf47718f6ee1fa Mon Sep 17 00:00:00 2001 From: Slug-Boi Date: Tue, 17 Jun 2025 21:28:49 +0200 Subject: [PATCH 08/15] test: add new bool to func call --- src/cmd/utils/util_test.go | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/cmd/utils/util_test.go b/src/cmd/utils/util_test.go index d8a8db7..16f2676 100644 --- a/src/cmd/utils/util_test.go +++ b/src/cmd/utils/util_test.go @@ -166,6 +166,7 @@ func Test_FindAuthorFilePanic(t *testing.T) { os.Setenv("author_file", "") os.Setenv("HOME", "") os.Setenv("XDG_CONFIG_HOME", "") + utils.ConfigVar.Settings.AuthorFile = "" utils.Find_authorfile() } @@ -178,14 +179,10 @@ func Test_FindAuthorFileEnv(t *testing.T) { defer func() { os.Setenv("author_file", originalAuthorFile) - - if r := recover(); r == nil { - t.Errorf("Find_authorfile() did not panic") - } }() - // Set an invalid environment variable to trigger panic - os.Setenv("author_file", "") + os.Setenv("author_file", "author_file_test") + utils.ConfigVar.Settings.AuthorFile = "" utils.Find_authorfile() } @@ -652,7 +649,7 @@ func Test_CommitAppender(t *testing.T) { message := strings.TrimSpace(string(out)) commit := utils.Commit("", authors) - err, appendedMessage := utils.GitCommitAppender(commit, "", nil, true, true) + err, appendedMessage := utils.GitCommitAppender(commit, "", nil, true, true, true) if err != nil { t.Errorf("GitCommitAppender() returned error: %v", err) } @@ -665,7 +662,7 @@ func Test_CommitAppender(t *testing.T) { // check inverted commit authors = []string{"^te"} commit = utils.Commit("", authors) - err, appendedMessage = utils.GitCommitAppender(commit, "", nil, true, true) + err, appendedMessage = utils.GitCommitAppender(commit, "", nil, true, true, true) if err != nil { t.Errorf("GitCommitAppender() returned error: %v", err) } @@ -678,7 +675,7 @@ func Test_CommitAppender(t *testing.T) { // Test CommitAppender with multiple authors authors = []string{"te", "testtest"} commit = utils.Commit("", authors) - err, appendedMessage = utils.GitCommitAppender(commit, "", nil, true, true) + err, appendedMessage = utils.GitCommitAppender(commit, "", nil, true, true, true) if err != nil { t.Errorf("GitCommitAppender() returned error: %v", err) } @@ -690,7 +687,7 @@ func Test_CommitAppender(t *testing.T) { // Test CommitAppender with all authors authors = []string{"all"} commit = utils.Commit("", authors) - err, appendedMessage = utils.GitCommitAppender(commit, "", nil, true, true) + err, appendedMessage = utils.GitCommitAppender(commit, "", nil, true, true, true) if err != nil { t.Errorf("GitCommitAppender() returned error: %v", err) } @@ -704,7 +701,7 @@ func Test_CommitAppender(t *testing.T) { // Test CommitAppender with group authors authors = []string{"gr1"} commit = utils.Commit("", authors) - err, appendedMessage = utils.GitCommitAppender(commit, "", nil, true, true) + err, appendedMessage = utils.GitCommitAppender(commit, "", nil, true, true, true) if err != nil { t.Errorf("GitCommitAppender() returned error: %v", err) } From 70259d17f73328224f270e00188fa6dae8cb812a Mon Sep 17 00:00:00 2001 From: Slug-Boi Date: Tue, 17 Jun 2025 21:29:18 +0200 Subject: [PATCH 09/15] refactor: allow for editing of amend commits --- src/cmd/amend.go | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/cmd/amend.go b/src/cmd/amend.go index 315c695..0510a7e 100644 --- a/src/cmd/amend.go +++ b/src/cmd/amend.go @@ -24,7 +24,7 @@ var amendCmd = &cobra.Command{ pflag, _ := cmd.Flags().GetBool("print-output") tflag, _ := cmd.Flags().GetBool("test_print") git_flags, _ := cmd.Flags().GetString("git-flags") - edit, _ := cmd.Flags().GetBool("edit") + no_edit, _ := cmd.Flags().GetBool("no-edit") hash, _ := cmd.Flags().GetString("hash") @@ -33,10 +33,6 @@ var amendCmd = &cobra.Command{ hash = "" return } - - if edit { - - } var authors string if len(args) == 0 { @@ -56,7 +52,7 @@ var amendCmd = &cobra.Command{ git_flags_split = strings.Split(git_flags, " ") } - err, _ := utils.GitCommitAppender(authors, hash, git_flags_split, tflag, pflag) + err, _ := utils.GitCommitAppender(authors, hash, git_flags_split, tflag, pflag, no_edit) if err != nil { println("Error amending commit:", err.Error()) os.Exit(1) @@ -70,6 +66,6 @@ func init() { amendCmd.Flags().StringP("git-flags", "g", "", "Git flags to add to the commit command") amendCmd.Flags().BoolP("print-output", "p", false, "Print the commit message to stdout") amendCmd.Flags().BoolP("test_print", "t", false, "Print the commit message to stdout without amending") - amendCmd.Flags().BoolP("edit", "e", false, "Edit the commit message in the editor") + amendCmd.Flags().BoolP("no-edit", "n", false, "Do not edit the commit message in the editor") amendCmd.Flags().StringP("hash", "s", "", "Hash of the commit to amend") } From 98ceadf98b2f651ff53822ee84d1dad4da56d01b Mon Sep 17 00:00:00 2001 From: Slug-Boi Date: Tue, 24 Jun 2025 12:23:32 +0200 Subject: [PATCH 10/15] test: add a config save test function --- src/cmd/utils/util_test.go | 62 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/src/cmd/utils/util_test.go b/src/cmd/utils/util_test.go index 16f2676..826347c 100644 --- a/src/cmd/utils/util_test.go +++ b/src/cmd/utils/util_test.go @@ -7,11 +7,12 @@ import ( "io" "net/http" "os" + "os/exec" "strings" "testing" - "os/exec" "github.com/Slug-Boi/cocommit/src/cmd/utils" + "github.com/spf13/viper" ) const author_data = ` @@ -839,6 +840,61 @@ func Test_FetchGHProfileHTTP(t *testing.T) { } } - - // Github tests END + +func Test_Save(t *testing.T) { + setup() + defer teardown() + + filename := "test_save_config.toml" + + initial_config_data := `[settings] +author_file = "test_authors.json" +starting_scope = "git" +editor = "built-in"` + + os.Create(filename) + defer os.Remove(filename) + // Write some test data to the file + os.WriteFile(filename, []byte(initial_config_data), 0644) + + override_cfg := &utils.Config{ + Settings: struct { + AuthorFile string `mapstructure:"author_file"` + StartingScope string `mapstructure:"starting_scope"` + Editor string `mapstructure:"editor"` + }{ + AuthorFile: "test_authors.json", + StartingScope: "git", + Editor: "built-in", + }} + + + + // Set viper config file to be cfg + viper.SetConfigFile(filename) + // Set the config type to toml + viper.SetConfigType("toml") + + + // Change some values in the config + override_cfg.Settings.AuthorFile = "test" + override_cfg.Settings.StartingScope = "not_git" + override_cfg.Settings.Editor = "test_editor" + + // Save the config + err := override_cfg.Save() + if err != nil { + t.Errorf("Save() returned error: %v", err) + } + + // Check if file exists and contains expected content + data, err := os.ReadFile(filename) + if err != nil { + t.Errorf("Save() did not create file: %v", data) + } + if string(initial_config_data) == string(data) { + t.Errorf("Save() did not write expected content:\nNew:\n%s\n\nOld:\n%s", string(data), string(initial_config_data)) + } +} + From 96d117cadd358f247ac97e39843284f7c6a0fd93 Mon Sep 17 00:00:00 2001 From: Slug-Boi Date: Tue, 24 Jun 2025 12:55:19 +0200 Subject: [PATCH 11/15] refactor: change the way the viper config is stored and add helper functions --- src/cmd/utils/config.go | 121 ++++++++++++++++++++++++++-------------- 1 file changed, 80 insertions(+), 41 deletions(-) diff --git a/src/cmd/utils/config.go b/src/cmd/utils/config.go index d151e2d..1b893f4 100644 --- a/src/cmd/utils/config.go +++ b/src/cmd/utils/config.go @@ -40,10 +40,11 @@ func init() { } } +var v *viper.Viper + func LoadConfig() (*Config, error) { // TODO: create if and give param as default config location - - v := viper.New() + v = viper.New() v.SetConfigName(configName) v.SetConfigType(configType) @@ -89,10 +90,10 @@ func (c *Config) SetGlobalConfig() { ConfigVar = c // This doesnt really do much right now but might be useful later viper.WatchConfig() - } + } } -func handleMissingConfig(v *viper.Viper) error { +func HandleMissingConfig() error { fmt.Println("Config file not found. Would you like to create one? (y/n)") var response string if _, err := fmt.Scanln(&response); err != nil { @@ -104,10 +105,48 @@ func handleMissingConfig(v *viper.Viper) error { return fmt.Errorf("config file not found") } - return createConfig(v) + if v == nil { + v = viper.New() + + v.SetConfigName(configName) + v.SetConfigType(configType) + } + + return CreateConfig() } -func createConfig(v *viper.Viper) error { +func CheckConfig() bool { + if v == nil { + return false + } else if v.ConfigFileUsed() == "" { + return false + } else { + return true + } +} + +func GetConfigFilePath() string { + if v == nil || v.ConfigFileUsed() == "" { + return "" + } + return v.ConfigFileUsed() +} + +func RemoveConfig() error { + if v == nil || v.ConfigFileUsed() == "" { + return fmt.Errorf("no config file to remove") + } + + configPath := v.ConfigFileUsed() + if err := os.Remove(configPath); err != nil { + return fmt.Errorf("failed to remove config file: %w", err) + } + + fmt.Printf("Config file removed: %s\n", configPath) + return nil +} + +func CreateConfig() error { fmt.Println("Where would you like to create the config file?") for i, path := range defaultConfigLocations { fmt.Printf("%d. %s\n", i, path) @@ -145,38 +184,38 @@ func createConfig(v *viper.Viper) error { } func (c *Config) Save() error { - v := viper.New() - - // Set all configuration values from the struct - v.Set("settings.author_file", c.Settings.AuthorFile) - v.Set("settings.starting_scope", c.Settings.StartingScope) - v.Set("settings.editor", c.Settings.Editor) - - v.SetConfigName(configName) - v.SetConfigType(configType) - - // Try to determine the original config file location - if viper.ConfigFileUsed() != "" { - v.SetConfigFile(viper.ConfigFileUsed()) - } else { - // Fall back to first default location if no existing config - if len(defaultConfigLocations) > 0 && defaultConfigLocations[0] != "" { - v.SetConfigFile(filepath.Join(defaultConfigLocations[0], fmt.Sprintf("%s.%s", configName, configType))) - } else { - return fmt.Errorf("no config file location available") - } - } - - // Ensure the directory exists - configDir := filepath.Dir(v.ConfigFileUsed()) - if err := os.MkdirAll(configDir, 0755); err != nil { - return fmt.Errorf("failed to create config directory: %w", err) - } - - // Write the config file - if err := v.WriteConfig(); err != nil { - return fmt.Errorf("failed to save config: %w", err) - } - - return nil -} \ No newline at end of file + v := viper.New() + + // Set all configuration values from the struct + v.Set("settings.author_file", c.Settings.AuthorFile) + v.Set("settings.starting_scope", c.Settings.StartingScope) + v.Set("settings.editor", c.Settings.Editor) + + v.SetConfigName(configName) + v.SetConfigType(configType) + + // Try to determine the original config file location + if viper.ConfigFileUsed() != "" { + v.SetConfigFile(viper.ConfigFileUsed()) + } else { + // Fall back to first default location if no existing config + if len(defaultConfigLocations) > 0 && defaultConfigLocations[0] != "" { + v.SetConfigFile(filepath.Join(defaultConfigLocations[0], fmt.Sprintf("%s.%s", configName, configType))) + } else { + return fmt.Errorf("no config file location available") + } + } + + // Ensure the directory exists + configDir := filepath.Dir(v.ConfigFileUsed()) + if err := os.MkdirAll(configDir, 0755); err != nil { + return fmt.Errorf("failed to create config directory: %w", err) + } + + // Write the config file + if err := v.WriteConfig(); err != nil { + return fmt.Errorf("failed to save config: %w", err) + } + + return nil +} From ab3f16be4acb684aa512517f38e2fae161e00dc8 Mon Sep 17 00:00:00 2001 From: Slug-Boi Date: Tue, 24 Jun 2025 12:55:51 +0200 Subject: [PATCH 12/15] feat: add the base config command with flags to help configure the tool and create one if its missing --- src/cmd/config.go | 70 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/cmd/config.go diff --git a/src/cmd/config.go b/src/cmd/config.go new file mode 100644 index 0000000..79020d0 --- /dev/null +++ b/src/cmd/config.go @@ -0,0 +1,70 @@ +package cmd + +import ( + "fmt" + + "github.com/Slug-Boi/cocommit/src/cmd/utils" + "github.com/spf13/cobra" +) + +// configCmd represents the config command +var configCmd = &cobra.Command{ + Use: "config", + Short: "This command will create or edit the configuration file for cocommit", + Long: `This command will create or edit the configuration file for cocommit. +You can set various settings like the author file, starting scope, and which editor to use. +A flag can be used to print the current configuration, as well as its location. +To see what options are available to use in the config file, please refer to the wiki page on the GitHub repository: +COMING SOON`, + Run: func(cmd *cobra.Command, args []string) { + printConfig, _ := cmd.Flags().GetBool("print") + editConfig, _ := cmd.Flags().GetBool("edit") + configLocation, _ := cmd.Flags().GetBool("location") + removeConfig, _ := cmd.Flags().GetBool("remove") + + if printConfig { + if !utils.CheckConfig() { + fmt.Println("No configuration file found. Default is being used.") + fmt.Println("Default configuration:") + + } else { + fmt.Println("Current configuration:") + } + fmt.Println("Author File:", utils.ConfigVar.Settings.AuthorFile) + fmt.Println("Starting Scope:", utils.ConfigVar.Settings.StartingScope) + fmt.Println("Editor:", utils.ConfigVar.Settings.Editor) + } + + // Check if the config file exists + if !utils.CheckConfig() { + err := utils.HandleMissingConfig() + if err != nil { + panic(fmt.Sprintf("Error handling missing configuration file: %v", err)) + } + return + } + if printConfig { + return + } + + if editConfig { + utils.LaunchEditor("default",utils.GetConfigFilePath()) + return + } else if configLocation { + fmt.Println("Configuration file location:", utils.GetConfigFilePath()) + return + } else if removeConfig { + utils.RemoveConfig() + return + } + fmt.Println("No action specified. Use flags to specify an action, use -h for help.") + }, +} + +func init() { + rootCmd.AddCommand(configCmd) + configCmd.Flags().BoolP("print", "p", false, "Print the current configuration") + configCmd.Flags().BoolP("edit", "e", false, "Edit the configuration file in your default editor") + configCmd.Flags().BoolP("location", "l", false, "Print the location of the configuration file") + configCmd.Flags().BoolP("remove", "r", false, "Remove the configuration file") +} From 01c6581027cb3e5eb8326b90195efdb4d0851aa9 Mon Sep 17 00:00:00 2001 From: Slug-Boi Date: Mon, 18 Aug 2025 13:24:42 +0200 Subject: [PATCH 13/15] refactor: add string function to config struct to allow for extendable printing of future fields --- src/cmd/config.go | 4 +--- src/cmd/utils/config.go | 7 +++++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/cmd/config.go b/src/cmd/config.go index 79020d0..bf48e89 100644 --- a/src/cmd/config.go +++ b/src/cmd/config.go @@ -30,9 +30,7 @@ COMING SOON`, } else { fmt.Println("Current configuration:") } - fmt.Println("Author File:", utils.ConfigVar.Settings.AuthorFile) - fmt.Println("Starting Scope:", utils.ConfigVar.Settings.StartingScope) - fmt.Println("Editor:", utils.ConfigVar.Settings.Editor) + fmt.Println(utils.ConfigVar.String()) } // Check if the config file exists diff --git a/src/cmd/utils/config.go b/src/cmd/utils/config.go index 1b893f4..35efdf4 100644 --- a/src/cmd/utils/config.go +++ b/src/cmd/utils/config.go @@ -33,6 +33,13 @@ type Config struct { } `mapstructure:"settings"` } +func (c *Config) String() string { + return fmt.Sprintf("Author File: %s\nStarting Scope: %s\nEditor: %s", + c.Settings.AuthorFile, + c.Settings.StartingScope, + c.Settings.Editor) +} + func init() { configDir, err := os.UserConfigDir() if err == nil { From 0425795101bd0d9cf130c5dfd6a5455c5961ed55 Mon Sep 17 00:00:00 2001 From: Slug-Boi Date: Mon, 18 Aug 2025 13:24:52 +0200 Subject: [PATCH 14/15] test: comment begin --- src/cmd/utils/util_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/cmd/utils/util_test.go b/src/cmd/utils/util_test.go index 826347c..7eb0376 100644 --- a/src/cmd/utils/util_test.go +++ b/src/cmd/utils/util_test.go @@ -842,6 +842,8 @@ func Test_FetchGHProfileHTTP(t *testing.T) { // Github tests END +// Config tests BEGIN + func Test_Save(t *testing.T) { setup() defer teardown() @@ -898,3 +900,5 @@ editor = "built-in"` } } + + From 4badd8ebae875874a3e27072fc8741ad88c90e30 Mon Sep 17 00:00:00 2001 From: Slug-Boi Date: Mon, 18 Aug 2025 13:40:37 +0200 Subject: [PATCH 15/15] ci: update go version of ci to 1.24 --- ci/build_test_release.go | 2 +- ci/go.mod | 2 +- ci/test_on_push.go | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ci/build_test_release.go b/ci/build_test_release.go index 6bf7408..1e4d36d 100644 --- a/ci/build_test_release.go +++ b/ci/build_test_release.go @@ -24,7 +24,7 @@ func main() { // mount the source code directory on the host // at /src in the container source := client.Container(). - From("golang:1.23"). + From("golang:1.24"). WithDirectory("/src_d", client.Host().Directory(".", dagger.HostDirectoryOpts{ Exclude: []string{}, })).WithMountedCache("/src_d/dagger_dep_cache/go_dep", goCache) diff --git a/ci/go.mod b/ci/go.mod index dfa1893..0c3440b 100644 --- a/ci/go.mod +++ b/ci/go.mod @@ -1,6 +1,6 @@ module ci -go 1.23.2 +go 1.24.6 require dagger.io/dagger v0.13.6 diff --git a/ci/test_on_push.go b/ci/test_on_push.go index 17edfd5..2509e61 100644 --- a/ci/test_on_push.go +++ b/ci/test_on_push.go @@ -24,7 +24,7 @@ func main() { // mount the source code directory on the host // at /src in the container source := client.Container(). - From("golang:1.23"). + From("golang:1.24"). WithDirectory("/src_d", client.Host().Directory(".", dagger.HostDirectoryOpts{ Exclude: []string{"build/"}, })).WithMountedCache("/src_d/dagger_dep_cache/go_dep", goCache) @@ -41,4 +41,4 @@ func main() { panic(err) } fmt.Println(out) -} \ No newline at end of file +}