diff --git a/src_code/go_src/cocommit.go b/src_code/go_src/cocommit.go index 402e972..ece86ec 100644 --- a/src_code/go_src/cocommit.go +++ b/src_code/go_src/cocommit.go @@ -6,6 +6,7 @@ import ( "os" "os/exec" "regexp" + "slices" "strings" ) @@ -14,24 +15,28 @@ type user struct { email string } +var users = make(map[string]user) +var sb strings.Builder +var all_flag = false + func main() { - users := make(map[string]user) + // Reads a shell env variable :: author_file authors := os.Getenv("author_file") - + file, err := os.Open(authors) if err != nil { print("File not found") os.Exit(2) } defer file.Close() - + scanner := bufio.NewScanner(file) - + // eat a single input scanner.Scan() - + // reads the input of authors file and formats accordingly for scanner.Scan() { info := strings.Split(scanner.Text(), "|") @@ -39,30 +44,32 @@ func main() { users[info[0]] = usr users[info[1]] = usr } - + if err := scanner.Err(); err != nil { os.Exit(2) } - + args := os.Args[1:] NoInput(args, users) - - + + excludeMode := []string{} + // builds the commit message with the selected authors - var sb strings.Builder - sb.WriteString(string(args[0])+"\n") + sb.WriteString(string(args[0]) + "\n") reg, _ := regexp.Compile("([^:]+):([^:]+)") - for _, commiter := range args[1:] { - if _, ok := users[commiter]; ok { - sb.WriteString("\nCo-authored-by: ") - sb.WriteString(users[commiter].username) - sb.WriteString(" <") - sb.WriteString(users[commiter].email) - sb.WriteRune('>') - } else if match := reg.MatchString(commiter); match { - str := strings.Split(commiter, ":") + if args[1] == "all" || args[1] == "All" { + all_flag = true + goto skip_loop + } + + + for _, committer := range args[1:] { + if _, ok := users[committer]; ok { + sb_author(committer) + } else if match := reg.MatchString(committer); match { + str := strings.Split(committer, ":") sb.WriteString("\nCo-authored-by: ") sb.WriteString(str[0]) @@ -70,18 +77,32 @@ func main() { sb.WriteString(str[1]) sb.WriteRune('>') + } else if committer[0] == '^' { + excludeMode = append(excludeMode, users[committer[1:]].username) + } else { - println(commiter, " was unknown. User either not defined or name typed wrong") + println(committer, " was unknown. User either not defined or name typed wrong") } } - // commit msg built - commit := sb.String() + + skip_loop: + if len(excludeMode) > 0 || all_flag { + add_x_users(excludeMode) + } + + + // commit msg built + commit := sb_build() + + //NOTE: Uncomment for testing + //print(commit) + // commit shell command cmd := exec.Command("git", "commit", "-m", commit) // https://stackoverflow.com/questions/18159704/how-to-debug-exit-status-1-error-when-running-exec-command-in-golang - + cmd_output, err := cmd.CombinedOutput() if err != nil { @@ -92,7 +113,28 @@ func main() { } -//TODO: move half this into another function and call before building users to improve performance +func add_x_users(excludeMode []string) { + for key, user := range users { + if !slices.Contains(excludeMode, user.username) { + sb_author(key) + excludeMode = append(excludeMode, user.username) + } + } +} + +func sb_build() string { + return sb.String() +} + +func sb_author(committer string) { + sb.WriteString("\nCo-authored-by: ") + sb.WriteString(users[committer].username) + sb.WriteString(" <") + sb.WriteString(users[committer].email) + sb.WriteRune('>') +} + +// TODO: move half this into another function and call before building users to improve performance func NoInput(args []string, users map[string]user) { if len(args) < 2 { // If you call binary with users prints users @@ -103,9 +145,9 @@ func NoInput(args []string, users map[string]user) { } os.Exit(1) } - // if calling binary with nothing or only string + // if calling binary with nothing or only string print("Usage: cocommit [co-author2] [co-author3] || \n cocommit [co-author2:email] [co-author3:email] || Mixes of both") - + os.Exit(1) } } diff --git a/src_code/go_src/cocommit_test.go b/src_code/go_src/cocommit_test.go index 2cc4bb7..cf08549 100644 --- a/src_code/go_src/cocommit_test.go +++ b/src_code/go_src/cocommit_test.go @@ -3,6 +3,7 @@ package main import ( "os" "os/exec" + "strings" "testing" ) @@ -37,6 +38,50 @@ func Test_usersInput(t *testing.T) { } t.Fatalf("process ran with err %v, want exit status 1", err) } +//TODO: Turn this into a fuzz test + +func Test_commit_message(t *testing.T) { + //authors := make(map[string]user) + users["test"] = user{username: "test", email: "test"} + sb_author("test") + commit := sb_build() + if commit != "\nCo-authored-by: test " { + t.Fatalf("String built incorrectly. Strings did not match: Created -> %s Expected -> Co-authored-by: test ",commit) + } +} +//TODO: Turn this into a fuzz test +func Test_add_all(t *testing.T) { + for k := range users { + delete(users, k) + } + sb.Reset() + users["test1"] = user{username: "test1", email: "test1"} + users["test2"] = user{username: "test2", email: "test2"} + users["test3"] = user{username: "test3", email: "test3"} + all_flag = true + add_x_users([]string{}) + + commit := sb_build() + if !strings.Contains(commit, "\nCo-authored-by: test1 ") || + !strings.Contains(commit, "\nCo-authored-by: test2 ") || + !strings.Contains(commit, "\nCo-authored-by: test3 ") { + t.Fatalf("String built incorrectly. Strings did not match: Created -> %s Expected -> Co-authored-by: test ",commit) + } +} + +func Test_exclude_user(t *testing.T) { + // Reusing users map from last test + excludeMode := []string{"test1"} + + sb.Reset() + + add_x_users(excludeMode) + + commit := sb_build() + if strings.Contains(commit, "\nCo-authored-by: test1 ") { + t.Fatalf("String built incorrectly. Strings did not match: Created -> %s Expected -> Co-authored-by: test ",commit) + } +}