diff --git a/default.nix b/default.nix index 9750f0d..3c062dc 100644 --- a/default.nix +++ b/default.nix @@ -1,8 +1,6 @@ -{lib, buildGoModule, fetchFromGitHub }: +{ lib, buildGoModule, fetchFromGitHub }: buildGoModule rec { - - pname = "cocommit"; version = "1.3.0"; @@ -10,20 +8,20 @@ buildGoModule rec { owner = "Slug-Boi"; repo = pname; rev = "v${version}"; - sha256 = "sha256-oraadDCyek8qnXFZPj2yitXL3KPK+uW1/VZphrEa/MU="; + sha256 = "sha256-mSu9IW14y4vgvV3/N4EG9oMvB5eTfcneF03kMmHMXIU="; }; - vendorHash = null; + vendorHash = "sha256-GcRGae42KiqMhxc2Q7Ct+uJ4Wg2odUEwWyXffamOjWY="; buildPhase = '' - make build-nix + make build ''; doCheck = false; installPhase = '' mkdir -p $out/bin - cp "src_code/go_src/${pname}" "$out/bin/${pname}" + cp "src/${pname}" "$out/bin/${pname}" chmod +x $out/bin/${pname} ''; diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..70d65af --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1745377448, + "narHash": "sha256-jhZDfXVKdD7TSEGgzFJQvEEZ2K65UMiqW5YJ2aIqxMA=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "507b63021ada5fee621b6ca371c4fca9ca46f52c", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix index d20159b..0af3b76 100644 --- a/flake.nix +++ b/flake.nix @@ -2,34 +2,32 @@ inputs = { nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; flake-utils.url = "github:numtide/flake-utils"; - prog_src = { - flake = false; - url = "github:Slug-Boi/cocommit"; - rev = "v1.3.0"; - }; }; + outputs = { self, nixpkgs, flake-utils, ... }@inputs: let forAllSys = flake-utils.lib.eachSystem flake-utils.lib.allSystems; APPNAME = "cocommit"; appOverlay = final: prev: { - # any pkgs overrides made here will be - # inherited in the arguments of default.nix - # because we used final.callPackage instead of prev.callPackage - # i.e. - # nodejs = prev.nodejs.overrideAttrs { name = "stinky"; }; - # would make it so that final.callPackage gives the altered nodejs - ${APPNAME} = final.callPackage ./. { inherit (inputs) prog_src; }; + ${APPNAME} = final.callPackage ./default.nix { + # Pass inputs as an argument to your package + inherit (prev) lib fetchFromGitHub buildGoModule; + # Or if you need all inputs: + # inherit inputs; + }; }; in { overlays.default = appOverlay; } // ( forAllSys (system: let - pkgs = import nixpkgs { inherit system; overlays = [ appOverlay ]; }; - in{ + pkgs = import nixpkgs { + inherit system; + overlays = [ appOverlay ]; + }; + in { packages = { default = pkgs.${APPNAME}; }; }) ); -} \ No newline at end of file +} diff --git a/makefile b/makefile index 96e3daa..302f3c4 100644 --- a/makefile +++ b/makefile @@ -1,5 +1,2 @@ build: go build -C src -o cocommit - -build-nix: - GOWORK=off go build -C src -o cocommit diff --git a/src/cmd/amend.go b/src/cmd/amend.go new file mode 100644 index 0000000..315c695 --- /dev/null +++ b/src/cmd/amend.go @@ -0,0 +1,75 @@ +/* +Copyright © 2025 NAME HERE +*/ +package cmd + +import ( + "os" + "strings" + + "github.com/Slug-Boi/cocommit/src/cmd/tui" + "github.com/Slug-Boi/cocommit/src/cmd/utils" + "github.com/spf13/cobra" +) + +// amendCmd represents the amend command +var amendCmd = &cobra.Command{ + Use: "amend", + Short: "Amend a commit message", + Long: `Ammend an existing commit message and add co-authors to it. + If ran without any arguments, it will open the TUI to select co-authors. + If ran with arguments, it will add the co-authors to the commit message.`, + Run: func(cmd *cobra.Command, args []string) { + // check if the print flag is set + pflag, _ := cmd.Flags().GetBool("print-output") + tflag, _ := cmd.Flags().GetBool("test_print") + git_flags, _ := cmd.Flags().GetString("git-flags") + edit, _ := cmd.Flags().GetBool("edit") + hash, _ := cmd.Flags().GetString("hash") + + + if hash != "" { + println("Hash based commit amendment is not yet implemented please use rebase option manually in git and then use this command to add co-authors.") + hash = "" + return + } + + if edit { + + } + + var authors string + if len(args) == 0 { + // open the TUI to select co-authors + list_authors := tui.Entry() + if list_authors == nil { + println("No authors selected, exiting.") + os.Exit(1) + } + authors = utils.Commit("", list_authors) + } else { + authors = utils.Commit("", args) + } + + git_flags_split := []string{} + if git_flags != "" { + git_flags_split = strings.Split(git_flags, " ") + } + + err, _ := utils.GitCommitAppender(authors, hash, git_flags_split, tflag, pflag) + if err != nil { + println("Error amending commit:", err.Error()) + os.Exit(1) + } + + }, +} + +func init() { + rootCmd.AddCommand(amendCmd) + 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().StringP("hash", "s", "", "Hash of the commit to amend") +} diff --git a/src/cmd/tui/tui_list.go b/src/cmd/tui/tui_list.go index e83368a..40dc242 100644 --- a/src/cmd/tui/tui_list.go +++ b/src/cmd/tui/tui_list.go @@ -488,6 +488,13 @@ func Entry() []string { } for i := range selected { short := dupProtect[i] + if short == "" { + split := strings.Split(i, " - ") + name := split[0] + email := split[1] + utils.TempAddUser(name, email) + short = name + } if negation { short = "^" + short } diff --git a/src/cmd/utils/commit.go b/src/cmd/utils/commit.go index 8e5b029..be7cbac 100644 --- a/src/cmd/utils/commit.go +++ b/src/cmd/utils/commit.go @@ -31,30 +31,30 @@ func Commit(message string, authors []string) string { return sb.String() } -// Loop that adds users -for _, committer := range authors { - if _, ok := Users[committer]; ok { - sb_author(committer, &sb) - } else if match := reg.MatchString(committer); match { - str := strings.Split(committer, ":") + // Loop that adds users + for _, committer := range authors { + if _, ok := Users[committer]; ok { + sb_author(committer, &sb) + } else if match := reg.MatchString(committer); match { + str := strings.Split(committer, ":") - sb.WriteString("\nCo-authored-by: ") - sb.WriteString(str[0]) - sb.WriteString(" <") - sb.WriteString(str[1]) - sb.WriteRune('>') + sb.WriteString("\nCo-authored-by: ") + sb.WriteString(str[0]) + sb.WriteString(" <") + sb.WriteString(str[1]) + sb.WriteRune('>') - } else if committer[0] == '^' { // Negations - excludeMode = append(excludeMode, Users[committer[1:]].Username) - } else { - println(committer, " was unknown. User either not defined or name typed wrong") + } else if committer[0] == '^' { // Negations + excludeMode = append(excludeMode, Users[committer[1:]].Username) + } else { + println(committer, " was unknown. User either not defined or name typed wrong") + } } -} -// Add excluded users after processing all authors -if len(excludeMode) > 0 { - add_x_users(excludeMode, &sb) -} + // Add excluded users after processing all authors + if len(excludeMode) > 0 { + add_x_users(excludeMode, &sb) + } return sb.String() } @@ -128,3 +128,53 @@ func group_selection(group []User, excludeMode []string) []string { return excludeMode } + +func GitCommitAppender(authors string, hash string, flags []string, t,p bool) (error, string) { + // Get old commit message + var cmd *exec.Cmd + + //TODO: Make the hash ammend work with rebase but its more complicated than orignally thought. + + // git log --format=%B -n1 + if hash == "" { + cmd = exec.Command("git", "log", "--format=%B", "-n1") + } else { + cmd = exec.Command("git", "log", "--format=%B", "-n1", hash) + } + + out, err := cmd.Output() + if err != nil { + return fmt.Errorf("error: %s", err), "" + } + + // Convert the output to a string + old_commit := string(out) + + // commit shell command + // specify git command1 + input := []string{"commit"} + input = append(input, flags...) + old_commit = strings.TrimSpace(old_commit) + input = append(input, "--amend", "-m", old_commit+"\n"+authors) + + if p { + println(old_commit + "\n" + authors) + if t { + return nil, old_commit + "\n" + authors + } + } + // append the message to the flags + // concat the git command and the flags + message + cmd = exec.Command("git", input...) + + // 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 { + return fmt.Errorf("error: %s : %s", err, string(cmd_output)), "" + } else { + println(string(cmd_output)) + } + return nil, old_commit + "\n" + authors +} diff --git a/src/cmd/utils/util_test.go b/src/cmd/utils/util_test.go index 5c1f5a5..d8a8db7 100644 --- a/src/cmd/utils/util_test.go +++ b/src/cmd/utils/util_test.go @@ -636,6 +636,88 @@ func Test_GitPush(t *testing.T) { } } +func Test_CommitAppender(t *testing.T) { + setup() + defer teardown() + utils.Define_users("author_file_test") + + // Test CommitAppender with a single author + authors := []string{"te"} + cmd := exec.Command("git", "log", "--format=%B", "-n1") + out, err := cmd.Output() + if err != nil { + t.Fatalf("Failed to get git log: %v", err) + } + + message := strings.TrimSpace(string(out)) + + commit := utils.Commit("", authors) + err, appendedMessage := utils.GitCommitAppender(commit, "", nil, true, true) + if err != nil { + t.Errorf("GitCommitAppender() returned error: %v", err) + } + + expectedMessage := message+"\n\n\nCo-authored-by: TestUser " + if appendedMessage != expectedMessage { + t.Errorf("CommitAppender() = %v;\nwant:\n%v", appendedMessage, expectedMessage) + } + + // check inverted commit + authors = []string{"^te"} + commit = utils.Commit("", authors) + err, appendedMessage = utils.GitCommitAppender(commit, "", nil, true, true) + if err != nil { + t.Errorf("GitCommitAppender() returned error: %v", err) + } + expectedMessage = message+"\n\n\nCo-authored-by: UserName2 " + + if appendedMessage != expectedMessage { + t.Errorf("CommitAppender() = %v;\nwant:\n%v", appendedMessage, expectedMessage) + } + + // Test CommitAppender with multiple authors + authors = []string{"te", "testtest"} + commit = utils.Commit("", authors) + err, appendedMessage = utils.GitCommitAppender(commit, "", nil, true, true) + if err != nil { + t.Errorf("GitCommitAppender() returned error: %v", err) + } + expectedMessage = message+"\n\n\nCo-authored-by: TestUser \nCo-authored-by: UserName2 " + + if appendedMessage != expectedMessage { + t.Errorf("CommitAppender() = %v;\nwant:\n%v", appendedMessage, expectedMessage) + } + // Test CommitAppender with all authors + authors = []string{"all"} + commit = utils.Commit("", authors) + err, appendedMessage = utils.GitCommitAppender(commit, "", nil, true, true) + if err != nil { + t.Errorf("GitCommitAppender() returned error: %v", err) + } + expectedMessage = message+"\n\n\nCo-authored-by: TestUser \nCo-authored-by: UserName2 " + expectedMessage2 := message+"\n\n\nCo-authored-by: UserName2 \nCo-authored-by: TestUser " + + if appendedMessage != expectedMessage && appendedMessage != expectedMessage2 { + t.Errorf("CommitAppender() = %v;\nwant:\n%v", appendedMessage, expectedMessage) + } + + // Test CommitAppender with group authors + authors = []string{"gr1"} + commit = utils.Commit("", authors) + err, appendedMessage = utils.GitCommitAppender(commit, "", nil, true, true) + if err != nil { + t.Errorf("GitCommitAppender() returned error: %v", err) + } + expectedMessage = message+"\n\n\nCo-authored-by: UserName2 " + + if appendedMessage != expectedMessage { + t.Errorf("CommitAppender() = %v;\nwant:\n%v", appendedMessage, expectedMessage) + } + + message = "" + +} + // Commit tests END // Github tests BEGIN