Skip to content

Commit a7bfeca

Browse files
authored
Add option to copy commit body (#4274)
I based this off of the existing `CommitMessage` option in the copy commit attributes menu.
2 parents 01eece3 + ab23539 commit a7bfeca

File tree

8 files changed

+166
-45
lines changed

8 files changed

+166
-45
lines changed

pkg/gui/controllers/basic_commits_controller.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,24 @@ func (self *BasicCommitsController) GetKeybindings(opts types.KeybindingsOpts) [
122122
return bindings
123123
}
124124

125+
func (self *BasicCommitsController) getCommitMessageBody(hash string) string {
126+
commitMessageBody, err := self.c.Git().Commit.GetCommitMessage(hash)
127+
if err != nil {
128+
return ""
129+
}
130+
_, body := self.c.Helpers().Commits.SplitCommitMessageAndDescription(commitMessageBody)
131+
return body
132+
}
133+
125134
func (self *BasicCommitsController) copyCommitAttribute(commit *models.Commit) error {
135+
commitMessageBody := self.getCommitMessageBody(commit.Hash)
136+
var commitMessageBodyDisabled *types.DisabledReason
137+
if commitMessageBody == "" {
138+
commitMessageBodyDisabled = &types.DisabledReason{
139+
Text: self.c.Tr.CommitHasNoMessageBody,
140+
}
141+
}
142+
126143
items := []*types.MenuItem{
127144
{
128145
Label: self.c.Tr.CommitHash,
@@ -144,6 +161,14 @@ func (self *BasicCommitsController) copyCommitAttribute(commit *models.Commit) e
144161
},
145162
Key: 'm',
146163
},
164+
{
165+
Label: self.c.Tr.CommitMessageBody,
166+
DisabledReason: commitMessageBodyDisabled,
167+
OnPress: func() error {
168+
return self.copyCommitMessageBodyToClipboard(commitMessageBody)
169+
},
170+
Key: 'b',
171+
},
147172
{
148173
Label: self.c.Tr.CommitURL,
149174
OnPress: func() error {
@@ -259,6 +284,16 @@ func (self *BasicCommitsController) copyCommitMessageToClipboard(commit *models.
259284
return nil
260285
}
261286

287+
func (self *BasicCommitsController) copyCommitMessageBodyToClipboard(commitMessageBody string) error {
288+
self.c.LogAction(self.c.Tr.Actions.CopyCommitMessageBodyToClipboard)
289+
if err := self.c.OS().CopyToClipboard(commitMessageBody); err != nil {
290+
return err
291+
}
292+
293+
self.c.Toast(self.c.Tr.CommitMessageBodyCopiedToClipboard)
294+
return nil
295+
}
296+
262297
func (self *BasicCommitsController) copyCommitSubjectToClipboard(commit *models.Commit) error {
263298
message, err := self.c.Git().Commit.GetCommitSubject(commit.Hash)
264299
if err != nil {

pkg/i18n/english.go

Lines changed: 51 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,7 @@ type TranslationSet struct {
621621
PasteCommitMessageFromClipboard string
622622
SurePasteCommitMessage string
623623
CommitMessage string
624+
CommitMessageBody string
624625
CommitSubject string
625626
CommitAuthor string
626627
CommitTags string
@@ -685,10 +686,12 @@ type TranslationSet struct {
685686
CommitDiffCopiedToClipboard string
686687
CommitURLCopiedToClipboard string
687688
CommitMessageCopiedToClipboard string
689+
CommitMessageBodyCopiedToClipboard string
688690
CommitSubjectCopiedToClipboard string
689691
CommitAuthorCopiedToClipboard string
690692
CommitTagsCopiedToClipboard string
691693
CommitHasNoTags string
694+
CommitHasNoMessageBody string
692695
PatchCopiedToClipboard string
693696
CopiedToClipboard string
694697
ErrCannotEditDirectory string
@@ -914,6 +917,7 @@ type Actions struct {
914917
MoveCommitUp string
915918
MoveCommitDown string
916919
CopyCommitMessageToClipboard string
920+
CopyCommitMessageBodyToClipboard string
917921
CopyCommitSubjectToClipboard string
918922
CopyCommitDiffToClipboard string
919923
CopyCommitHashToClipboard string
@@ -1653,7 +1657,8 @@ func EnglishTranslationSet() *TranslationSet {
16531657
CopyCommitMessageToClipboard: "Copy commit message to clipboard",
16541658
PasteCommitMessageFromClipboard: "Paste commit message from clipboard",
16551659
SurePasteCommitMessage: "Pasting will overwrite the current commit message, continue?",
1656-
CommitMessage: "Commit message",
1660+
CommitMessage: "Commit message (subject and body)",
1661+
CommitMessageBody: "Commit message body",
16571662
CommitSubject: "Commit subject",
16581663
CommitAuthor: "Commit author",
16591664
CommitTags: "Commit tags",
@@ -1717,10 +1722,12 @@ func EnglishTranslationSet() *TranslationSet {
17171722
CommitDiffCopiedToClipboard: "Commit diff copied to clipboard",
17181723
CommitURLCopiedToClipboard: "Commit URL copied to clipboard",
17191724
CommitMessageCopiedToClipboard: "Commit message copied to clipboard",
1725+
CommitMessageBodyCopiedToClipboard: "Commit message body copied to clipboard",
17201726
CommitSubjectCopiedToClipboard: "Commit subject copied to clipboard",
17211727
CommitAuthorCopiedToClipboard: "Commit author copied to clipboard",
17221728
CommitTagsCopiedToClipboard: "Commit tags copied to clipboard",
17231729
CommitHasNoTags: "Commit has no tags",
1730+
CommitHasNoMessageBody: "Commit has no message body",
17241731
PatchCopiedToClipboard: "Patch copied to clipboard",
17251732
CopiedToClipboard: "copied to clipboard",
17261733
ErrCannotEditDirectory: "Cannot edit directories: you can only edit individual files",
@@ -1873,48 +1880,49 @@ func EnglishTranslationSet() *TranslationSet {
18731880

18741881
Actions: Actions{
18751882
// TODO: combine this with the original keybinding descriptions (those are all in lowercase atm)
1876-
CheckoutCommit: "Checkout commit",
1877-
CheckoutBranchAtCommit: "Checkout branch '%s'",
1878-
CheckoutCommitAsDetachedHead: "Checkout commit %s as detached head",
1879-
CheckoutTag: "Checkout tag",
1880-
CheckoutBranch: "Checkout branch",
1881-
ForceCheckoutBranch: "Force checkout branch",
1882-
CheckoutBranchOrCommit: "Checkout branch or commit",
1883-
DeleteLocalBranch: "Delete local branch",
1884-
Merge: "Merge",
1885-
SquashMerge: "Squash merge",
1886-
RebaseBranch: "Rebase branch",
1887-
RenameBranch: "Rename branch",
1888-
CreateBranch: "Create branch",
1889-
CherryPick: "(Cherry-pick) paste commits",
1890-
CheckoutFile: "Checkout file",
1891-
DiscardOldFileChange: "Discard old file change",
1892-
SquashCommitDown: "Squash commit down",
1893-
FixupCommit: "Fixup commit",
1894-
RewordCommit: "Reword commit",
1895-
DropCommit: "Drop commit",
1896-
EditCommit: "Edit commit",
1897-
AmendCommit: "Amend commit",
1898-
ResetCommitAuthor: "Reset commit author",
1899-
SetCommitAuthor: "Set commit author",
1900-
AddCommitCoAuthor: "Add commit co-author",
1901-
RevertCommit: "Revert commit",
1902-
CreateFixupCommit: "Create fixup commit",
1903-
SquashAllAboveFixupCommits: "Squash all above fixup commits",
1904-
CreateLightweightTag: "Create lightweight tag",
1905-
CreateAnnotatedTag: "Create annotated tag",
1906-
CopyCommitMessageToClipboard: "Copy commit message to clipboard",
1907-
CopyCommitSubjectToClipboard: "Copy commit subject to clipboard",
1908-
CopyCommitTagsToClipboard: "Copy commit tags to clipboard",
1909-
CopyCommitDiffToClipboard: "Copy commit diff to clipboard",
1910-
CopyCommitHashToClipboard: "Copy full commit hash to clipboard",
1911-
CopyCommitURLToClipboard: "Copy commit URL to clipboard",
1912-
CopyCommitAuthorToClipboard: "Copy commit author to clipboard",
1913-
CopyCommitAttributeToClipboard: "Copy to clipboard",
1914-
CopyPatchToClipboard: "Copy patch to clipboard",
1915-
MoveCommitUp: "Move commit up",
1916-
MoveCommitDown: "Move commit down",
1917-
CustomCommand: "Custom command",
1883+
CheckoutCommit: "Checkout commit",
1884+
CheckoutBranchAtCommit: "Checkout branch '%s'",
1885+
CheckoutCommitAsDetachedHead: "Checkout commit %s as detached head",
1886+
CheckoutTag: "Checkout tag",
1887+
CheckoutBranch: "Checkout branch",
1888+
ForceCheckoutBranch: "Force checkout branch",
1889+
CheckoutBranchOrCommit: "Checkout branch or commit",
1890+
DeleteLocalBranch: "Delete local branch",
1891+
Merge: "Merge",
1892+
SquashMerge: "Squash merge",
1893+
RebaseBranch: "Rebase branch",
1894+
RenameBranch: "Rename branch",
1895+
CreateBranch: "Create branch",
1896+
CherryPick: "(Cherry-pick) paste commits",
1897+
CheckoutFile: "Checkout file",
1898+
DiscardOldFileChange: "Discard old file change",
1899+
SquashCommitDown: "Squash commit down",
1900+
FixupCommit: "Fixup commit",
1901+
RewordCommit: "Reword commit",
1902+
DropCommit: "Drop commit",
1903+
EditCommit: "Edit commit",
1904+
AmendCommit: "Amend commit",
1905+
ResetCommitAuthor: "Reset commit author",
1906+
SetCommitAuthor: "Set commit author",
1907+
AddCommitCoAuthor: "Add commit co-author",
1908+
RevertCommit: "Revert commit",
1909+
CreateFixupCommit: "Create fixup commit",
1910+
SquashAllAboveFixupCommits: "Squash all above fixup commits",
1911+
CreateLightweightTag: "Create lightweight tag",
1912+
CreateAnnotatedTag: "Create annotated tag",
1913+
CopyCommitMessageToClipboard: "Copy commit message to clipboard",
1914+
CopyCommitMessageBodyToClipboard: "Copy commit message body to clipboard",
1915+
CopyCommitSubjectToClipboard: "Copy commit subject to clipboard",
1916+
CopyCommitTagsToClipboard: "Copy commit tags to clipboard",
1917+
CopyCommitDiffToClipboard: "Copy commit diff to clipboard",
1918+
CopyCommitHashToClipboard: "Copy full commit hash to clipboard",
1919+
CopyCommitURLToClipboard: "Copy commit URL to clipboard",
1920+
CopyCommitAuthorToClipboard: "Copy commit author to clipboard",
1921+
CopyCommitAttributeToClipboard: "Copy to clipboard",
1922+
CopyPatchToClipboard: "Copy patch to clipboard",
1923+
MoveCommitUp: "Move commit up",
1924+
MoveCommitDown: "Move commit down",
1925+
CustomCommand: "Custom command",
19181926

19191927
// TODO: remove
19201928
DiscardAllChangesInDirectory: "Discard all changes in directory",

pkg/integration/components/shell.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,10 @@ func (self *Shell) EmptyCommit(message string) *Shell {
174174
return self.RunCommand([]string{"git", "commit", "--allow-empty", "-m", message})
175175
}
176176

177+
func (self *Shell) EmptyCommitWithBody(subject string, body string) *Shell {
178+
return self.RunCommand([]string{"git", "commit", "--allow-empty", "-m", subject, "-m", body})
179+
}
180+
177181
func (self *Shell) EmptyCommitDaysAgo(message string, daysAgo int) *Shell {
178182
return self.RunCommand([]string{"git", "commit", "--allow-empty", "--date", fmt.Sprintf("%d days ago", daysAgo), "-m", message})
179183
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package commit
2+
3+
import (
4+
"github.com/jesseduffield/lazygit/pkg/config"
5+
. "github.com/jesseduffield/lazygit/pkg/integration/components"
6+
)
7+
8+
// We're emulating the clipboard by writing to a file called clipboard
9+
10+
var CopyMessageBodyToClipboard = NewIntegrationTest(NewIntegrationTestArgs{
11+
Description: "Copy a commit message body to the clipboard",
12+
ExtraCmdArgs: []string{},
13+
Skip: false,
14+
SetupConfig: func(config *config.AppConfig) {
15+
config.GetUserConfig().OS.CopyToClipboardCmd = "printf '%s' {{text}} > clipboard"
16+
},
17+
18+
SetupRepo: func(shell *Shell) {
19+
shell.EmptyCommitWithBody("My Subject", "My awesome commit message body")
20+
},
21+
22+
Run: func(t *TestDriver, keys config.KeybindingConfig) {
23+
t.Views().Commits().
24+
Focus().
25+
Lines(
26+
Contains("My Subject").IsSelected(),
27+
).
28+
Press(keys.Commits.CopyCommitAttributeToClipboard)
29+
30+
t.ExpectPopup().Menu().
31+
Title(Equals("Copy to clipboard")).
32+
Select(Contains("Commit message body")).
33+
Confirm()
34+
35+
t.ExpectToast(Equals("Commit message body copied to clipboard"))
36+
37+
t.FileSystem().FileContent("clipboard", Equals("My awesome commit message body"))
38+
},
39+
})
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package commit
2+
3+
import (
4+
"github.com/jesseduffield/lazygit/pkg/config"
5+
. "github.com/jesseduffield/lazygit/pkg/integration/components"
6+
)
7+
8+
var DisableCopyCommitMessageBody = NewIntegrationTest(NewIntegrationTestArgs{
9+
Description: "Disables copy commit message body when there is no body",
10+
ExtraCmdArgs: []string{},
11+
Skip: false,
12+
SetupConfig: func(config *config.AppConfig) {},
13+
14+
SetupRepo: func(shell *Shell) {
15+
shell.EmptyCommit("commit")
16+
},
17+
18+
Run: func(t *TestDriver, keys config.KeybindingConfig) {
19+
t.Views().Commits().
20+
Focus().
21+
Lines(
22+
Contains("commit").IsSelected(),
23+
).
24+
Press(keys.Commits.CopyCommitAttributeToClipboard)
25+
26+
t.ExpectPopup().Menu().
27+
Title(Equals("Copy to clipboard")).
28+
Select(Contains("Commit message body")).
29+
Confirm()
30+
31+
t.ExpectToast(Equals("Disabled: Commit has no message body"))
32+
},
33+
})

pkg/integration/tests/commit/paste_commit_message.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ var PasteCommitMessage = NewIntegrationTest(NewIntegrationTestArgs{
2626
Press(keys.Commits.CopyCommitAttributeToClipboard)
2727

2828
t.ExpectPopup().Menu().Title(Equals("Copy to clipboard")).
29-
Select(Contains("Commit message")).Confirm()
29+
Select(Contains("Commit message (subject and body)")).Confirm()
3030

3131
t.ExpectToast(Equals("Commit message copied to clipboard"))
3232

pkg/integration/tests/commit/paste_commit_message_over_existing.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ var PasteCommitMessageOverExisting = NewIntegrationTest(NewIntegrationTestArgs{
2626
Press(keys.Commits.CopyCommitAttributeToClipboard)
2727

2828
t.ExpectPopup().Menu().Title(Equals("Copy to clipboard")).
29-
Select(Contains("Commit message")).Confirm()
29+
Select(Contains("Commit message (subject and body)")).Confirm()
3030

3131
t.ExpectToast(Equals("Commit message copied to clipboard"))
3232

pkg/integration/tests/test_list.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,12 @@ var tests = []*components.IntegrationTest{
9797
commit.CommitWithNonMatchingBranchName,
9898
commit.CommitWithPrefix,
9999
commit.CopyAuthorToClipboard,
100+
commit.CopyMessageBodyToClipboard,
100101
commit.CopyTagToClipboard,
101102
commit.CreateAmendCommit,
102103
commit.CreateFixupCommitInBranchStack,
103104
commit.CreateTag,
105+
commit.DisableCopyCommitMessageBody,
104106
commit.DiscardOldFileChanges,
105107
commit.FindBaseCommitForFixup,
106108
commit.FindBaseCommitForFixupDisregardMainBranch,

0 commit comments

Comments
 (0)