diff options
author | Dmitrii Naumenko <dmitrii.naumenko@jetbrains.com> | 2023-11-22 19:11:17 +0100 |
---|---|---|
committer | Matthias Sohn <matthias.sohn@sap.com> | 2024-01-28 16:13:32 +0100 |
commit | c646649257070cd1707b7e86887e50c5acafa86c (patch) | |
tree | c7211b1548a6e02bf36bb39bac542b20e2597793 /org.eclipse.jgit.test | |
parent | 74471b8d755bdfe15a0585e49e1449788b4fc843 (diff) | |
download | jgit-c646649257070cd1707b7e86887e50c5acafa86c.tar.gz jgit-c646649257070cd1707b7e86887e50c5acafa86c.zip |
CherryPick: add ability to customise cherry-picked commit message
Originally I wanted to support a feature similar to `-x` options from
https://git-scm.com/docs/git-cherry-pick#_options.
The idea was to append original commit hash in this format:
```
my original commit message
(cherry picked from commit 75355897dc28e9975afed028c1a6d8c6b97b2a3c)
```
This can be useful information in some integrations.
I decided to make it in a more generic way
and pass custom `CherryPickCommitMessageProvider` implementation.
One of the two default implementations can append original commit hash
Change-Id: Id664e8438b0b76c5cb9b58113887eec04aa6f611
Diffstat (limited to 'org.eclipse.jgit.test')
-rw-r--r-- | org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CherryPickCommandTest.java | 185 | ||||
-rw-r--r-- | org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FooterLineTest.java | 8 |
2 files changed, 193 insertions, 0 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CherryPickCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CherryPickCommandTest.java index 301d6be662..be3b33a9c5 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CherryPickCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CherryPickCommandTest.java @@ -9,6 +9,8 @@ */ package org.eclipse.jgit.api; +import static org.eclipse.jgit.api.CherryPickCommitMessageProvider.ORIGINAL; +import static org.eclipse.jgit.api.CherryPickCommitMessageProvider.ORIGINAL_WITH_REFERENCE; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -590,4 +592,187 @@ public class CherryPickCommandTest extends RepositoryTestCase { checkFile(new File(db.getWorkTree(), "file"), "a\n2\n3\n"); } } + + private void doCherryPickWithCustomProviderBaseTest(Git git, + CherryPickCommitMessageProvider commitMessageProvider) + throws Exception { + writeTrashFile("fileA", "line 1\nline 2\nline 3\n"); + git.add().addFilepattern("fileA").call(); + RevCommit commitFirst = git.commit().setMessage("create fileA").call(); + + writeTrashFile("fileB", "content from file B\n"); + git.add().addFilepattern("fileB").call(); + RevCommit commitCreateFileB = git.commit() + .setMessage("create fileB\n\nsome commit details").call(); + + writeTrashFile("fileA", "line 1\nline 2\nline 3\nline 4\n"); + git.add().addFilepattern("fileA").call(); + RevCommit commitEditFileA1 = git.commit().setMessage("patch fileA 1") + .call(); + + writeTrashFile("fileA", "line 1\nline 2\nline 3\nline 4\nline 5\n"); + git.add().addFilepattern("fileA").call(); + RevCommit commitEditFileA2 = git.commit().setMessage("patch fileA 2") + .call(); + + git.branchCreate().setName("side").setStartPoint(commitFirst).call(); + checkoutBranch("refs/heads/side"); + + CherryPickResult pickResult = git.cherryPick() + .setCherryPickCommitMessageProvider(commitMessageProvider) + .include(commitCreateFileB).include(commitEditFileA1) + .include(commitEditFileA2).call(); + + assertEquals(CherryPickStatus.OK, pickResult.getStatus()); + + assertTrue(new File(db.getWorkTree(), "fileA").exists()); + assertTrue(new File(db.getWorkTree(), "fileB").exists()); + + checkFile(new File(db.getWorkTree(), "fileA"), + "line 1\nline 2\nline 3\nline 4\nline 5\n"); + checkFile(new File(db.getWorkTree(), "fileB"), "content from file B\n"); + } + + @Test + public void testCherryPickWithCustomCommitMessageProvider() + throws Exception { + try (Git git = new Git(db)) { + @SuppressWarnings("boxing") + CherryPickCommitMessageProvider messageProvider = srcCommit -> { + String message = srcCommit.getFullMessage(); + return String.format("%s (message length: %d)", message, + message.length()); + }; + doCherryPickWithCustomProviderBaseTest(git, messageProvider); + + Iterator<RevCommit> history = git.log().call().iterator(); + assertEquals("patch fileA 2 (message length: 13)", + history.next().getFullMessage()); + assertEquals("patch fileA 1 (message length: 13)", + history.next().getFullMessage()); + assertEquals( + "create fileB\n\nsome commit details (message length: 33)", + history.next().getFullMessage()); + assertEquals("create fileA", history.next().getFullMessage()); + assertFalse(history.hasNext()); + } + } + + @Test + public void testCherryPickWithCustomCommitMessageProvider_ORIGINAL() + throws Exception { + try (Git git = new Git(db)) { + doCherryPickWithCustomProviderBaseTest(git, ORIGINAL); + + Iterator<RevCommit> history = git.log().call().iterator(); + assertEquals("patch fileA 2", history.next().getFullMessage()); + assertEquals("patch fileA 1", history.next().getFullMessage()); + assertEquals("create fileB\n\nsome commit details", + history.next().getFullMessage()); + assertEquals("create fileA", history.next().getFullMessage()); + assertFalse(history.hasNext()); + } + } + + @Test + public void testCherryPickWithCustomCommitMessageProvider_ORIGINAL_WITH_REFERENCE() + throws Exception { + try (Git git = new Git(db)) { + doCherryPickWithCustomProviderBaseTest(git, + ORIGINAL_WITH_REFERENCE); + + Iterator<RevCommit> history = git.log().call().iterator(); + assertEquals("patch fileA 2\n\n(cherry picked from commit 1ac121e90b0fb6fb18bbb4307e3e9731ceeba9e1)", history.next().getFullMessage()); + assertEquals("patch fileA 1\n\n(cherry picked from commit 71475239df59076e18564fa360e3a74280926c2a)", history.next().getFullMessage()); + assertEquals("create fileB\n\nsome commit details\n\n(cherry picked from commit 29b4501297ccf8de9de9f451e7beb384b51f5378)", + history.next().getFullMessage()); + assertEquals("create fileA", history.next().getFullMessage()); + assertFalse(history.hasNext()); + } + } + + @Test + public void testCherryPickWithCustomCommitMessageProvider_ORIGINAL_WITH_REFERENCE_DonNotAddNewLineAfterFooter() + throws Exception { + try (Git git = new Git(db)) { + CherryPickCommitMessageProvider commitMessageProvider = CherryPickCommitMessageProvider.ORIGINAL_WITH_REFERENCE; + + RevCommit commit1 = addFileAndCommit(git, "file1", "content 1", + "commit1: no footer line"); + RevCommit commit2 = addFileAndCommit(git, "file2", "content 2", + "commit2: simple single footer line" + + "\n\nSigned-off-by: Alice <alice@example.com>"); + RevCommit commit3 = addFileAndCommit(git, "file3", "content 3", + "commit3: multiple footer lines\n\n" + + "Signed-off-by: Alice <alice@example.com>\n" + + "Signed-off-by: Bob <bob@example.com>"); + RevCommit commit4 = addFileAndCommit(git, "file4", "content 4", + "commit4: extra commit text before footer line\n\n" + + "Commit message details\n\n" + + "Signed-off-by: Alice <alice@example.com>\n" + + "Signed-off-by: Bob <bob@example.com>"); + RevCommit commit5 = addFileAndCommit(git, "file5", "content 5", + "commit5: extra commit text after footer line\n\n" + + "Signed-off-by: Alice <alice@example.com>\n" + + "Signed-off-by: Bob <bob@example.com>\n\n" + + "some extra description after footer"); + + git.branchCreate().setName("side").setStartPoint(commit1).call(); + checkoutBranch("refs/heads/side"); + + CherryPickResult pickResult = git.cherryPick() + .setCherryPickCommitMessageProvider(commitMessageProvider) + .include(commit2).include(commit3).include(commit4) + .include(commit5).call(); + + assertEquals(CherryPickStatus.OK, pickResult.getStatus()); + + assertTrue(new File(db.getWorkTree(), "file1").exists()); + assertTrue(new File(db.getWorkTree(), "file2").exists()); + assertTrue(new File(db.getWorkTree(), "file3").exists()); + assertTrue(new File(db.getWorkTree(), "file4").exists()); + assertTrue(new File(db.getWorkTree(), "file5").exists()); + + Iterator<RevCommit> history = git.log().call().iterator(); + RevCommit cpCommit1 = history.next(); + RevCommit cpCommit2 = history.next(); + RevCommit cpCommit3 = history.next(); + RevCommit cpCommit4 = history.next(); + RevCommit cpCommitInit = history.next(); + assertFalse(history.hasNext()); + + assertEquals("commit5: extra commit text after footer line\n\n" + + "Signed-off-by: Alice <alice@example.com>\n" + + "Signed-off-by: Bob <bob@example.com>\n\n" + + "some extra description after footer\n\n" + + "(cherry picked from commit c3c9959207dc7ae7c83da5d36dc14ef2ca42d572)", + cpCommit1.getFullMessage()); + assertEquals("commit4: extra commit text before footer line\n\n" + + "Commit message details\n\n" + + "Signed-off-by: Alice <alice@example.com>\n" + + "Signed-off-by: Bob <bob@example.com>\n" + + "(cherry picked from commit af3e8106c12cb946a37b403ddb2dd6c11a883698)", + cpCommit2.getFullMessage()); + assertEquals("commit3: multiple footer lines\n\n" + + "Signed-off-by: Alice <alice@example.com>\n" + + "Signed-off-by: Bob <bob@example.com>\n" + + "(cherry picked from commit 6d60f1a70a11a32dff4402c157c4ac328c32ce6c)", + cpCommit3.getFullMessage()); + assertEquals("commit2: simple single footer line\n\n" + + "Signed-off-by: Alice <alice@example.com>\n" + + "(cherry picked from commit 92bf0ec458814ecc73da8e050e60547d2ea6cce5)", + cpCommit4.getFullMessage()); + + assertEquals("commit1: no footer line", + cpCommitInit.getFullMessage()); + } + } + + private RevCommit addFileAndCommit(Git git, String fileName, + String fileText, String commitMessage) + throws IOException, GitAPIException { + writeTrashFile(fileName, fileText); + git.add().addFilepattern(fileName).call(); + return git.commit().setMessage(commitMessage).call(); + } } diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FooterLineTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FooterLineTest.java index cac0743d68..657c3d242f 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FooterLineTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FooterLineTest.java @@ -291,18 +291,26 @@ public class FooterLineTest extends RepositoryTestCase { f = footers.get(0); assertEquals("Signed-off-by", f.getKey()); assertEquals("A. U. Thor <a@example.com>", f.getValue()); + assertEquals(217, f.getStartOffset()); + assertEquals(258, f.getEndOffset()); f = footers.get(1); assertEquals("CC", f.getKey()); assertEquals("<some.mailing.list@example.com>", f.getValue()); + assertEquals(259, f.getStartOffset()); + assertEquals(305, f.getEndOffset()); f = footers.get(2); assertEquals("Acked-by", f.getKey()); assertEquals("Some Reviewer <sr@example.com>", f.getValue()); + assertEquals(356, f.getStartOffset()); + assertEquals(396, f.getEndOffset()); f = footers.get(3); assertEquals("Signed-off-by", f.getKey()); assertEquals("Main Tain Er <mte@example.com>", f.getValue()); + assertEquals(397, f.getStartOffset()); + assertEquals(442, f.getEndOffset()); } @Test |