You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CommitAndLogCommandTest.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /*
  2. * Copyright (C) 2010, Christian Halstrick <christian.halstrick@sap.com> and others
  3. *
  4. * This program and the accompanying materials are made available under the
  5. * terms of the Eclipse Distribution License v. 1.0 which is available at
  6. * https://www.eclipse.org/org/documents/edl-v10.php.
  7. *
  8. * SPDX-License-Identifier: BSD-3-Clause
  9. */
  10. package org.eclipse.jgit.api;
  11. import static java.nio.charset.StandardCharsets.UTF_8;
  12. import static org.junit.Assert.assertEquals;
  13. import static org.junit.Assert.assertFalse;
  14. import static org.junit.Assert.assertTrue;
  15. import static org.junit.Assert.fail;
  16. import static org.junit.Assume.assumeFalse;
  17. import java.io.File;
  18. import java.io.PrintWriter;
  19. import org.eclipse.jgit.api.errors.GitAPIException;
  20. import org.eclipse.jgit.api.errors.NoMessageException;
  21. import org.eclipse.jgit.junit.RepositoryTestCase;
  22. import org.eclipse.jgit.lib.Constants;
  23. import org.eclipse.jgit.lib.ObjectId;
  24. import org.eclipse.jgit.lib.PersonIdent;
  25. import org.eclipse.jgit.lib.RefUpdate;
  26. import org.eclipse.jgit.lib.ReflogReader;
  27. import org.eclipse.jgit.revwalk.RevCommit;
  28. import org.eclipse.jgit.treewalk.TreeWalk;
  29. import org.eclipse.jgit.util.FS;
  30. import org.eclipse.jgit.util.FileUtils;
  31. import org.eclipse.jgit.util.RawParseUtils;
  32. import org.junit.Test;
  33. /**
  34. * Testing the git commit and log commands
  35. */
  36. public class CommitAndLogCommandTest extends RepositoryTestCase {
  37. @Test
  38. public void testSomeCommits() throws Exception {
  39. // do 4 commits
  40. try (Git git = new Git(db)) {
  41. git.commit().setMessage("initial commit").call();
  42. git.commit().setMessage("second commit").setCommitter(committer)
  43. .call();
  44. git.commit().setMessage("third commit").setAuthor(author).call();
  45. git.commit().setMessage("fourth commit").setAuthor(author)
  46. .setCommitter(committer).call();
  47. Iterable<RevCommit> commits = git.log().call();
  48. // check that all commits came in correctly
  49. PersonIdent defaultCommitter = new PersonIdent(db);
  50. PersonIdent expectedAuthors[] = new PersonIdent[] {
  51. defaultCommitter, committer, author, author };
  52. PersonIdent expectedCommitters[] = new PersonIdent[] {
  53. defaultCommitter, committer, defaultCommitter, committer };
  54. String expectedMessages[] = new String[] { "initial commit",
  55. "second commit", "third commit", "fourth commit" };
  56. int l = expectedAuthors.length - 1;
  57. for (RevCommit c : commits) {
  58. assertEquals(expectedAuthors[l].getName(),
  59. c.getAuthorIdent().getName());
  60. assertEquals(expectedCommitters[l].getName(),
  61. c.getCommitterIdent().getName());
  62. assertEquals(c.getFullMessage(), expectedMessages[l]);
  63. l--;
  64. }
  65. assertEquals(l, -1);
  66. ReflogReader reader = db.getReflogReader(Constants.HEAD);
  67. assertTrue(
  68. reader.getLastEntry().getComment().startsWith("commit:"));
  69. reader = db.getReflogReader(db.getBranch());
  70. assertTrue(
  71. reader.getLastEntry().getComment().startsWith("commit:"));
  72. }
  73. }
  74. // try to do a commit without specifying a message. Should fail!
  75. @Test
  76. public void testWrongParams() throws GitAPIException {
  77. try (Git git = new Git(db)) {
  78. git.commit().setAuthor(author).call();
  79. fail("Didn't get the expected exception");
  80. } catch (NoMessageException e) {
  81. // expected
  82. }
  83. }
  84. // try to work with Commands after command has been invoked. Should throw
  85. // exceptions
  86. @Test
  87. public void testMultipleInvocations() throws GitAPIException {
  88. try (Git git = new Git(db)) {
  89. CommitCommand commitCmd = git.commit();
  90. commitCmd.setMessage("initial commit").call();
  91. try {
  92. // check that setters can't be called after invocation
  93. commitCmd.setAuthor(author);
  94. fail("didn't catch the expected exception");
  95. } catch (IllegalStateException e) {
  96. // expected
  97. }
  98. LogCommand logCmd = git.log();
  99. logCmd.call();
  100. try {
  101. // check that call can't be called twice
  102. logCmd.call();
  103. fail("didn't catch the expected exception");
  104. } catch (IllegalStateException e) {
  105. // expected
  106. }
  107. }
  108. }
  109. @Test
  110. public void testMergeEmptyBranches() throws Exception {
  111. try (Git git = new Git(db)) {
  112. git.commit().setMessage("initial commit").call();
  113. RefUpdate r = db.updateRef("refs/heads/side");
  114. r.setNewObjectId(db.resolve(Constants.HEAD));
  115. assertEquals(r.forceUpdate(), RefUpdate.Result.NEW);
  116. RevCommit second = git.commit().setMessage("second commit")
  117. .setCommitter(committer).call();
  118. db.updateRef(Constants.HEAD).link("refs/heads/side");
  119. RevCommit firstSide = git.commit().setMessage("first side commit")
  120. .setAuthor(author).call();
  121. write(new File(db.getDirectory(), Constants.MERGE_HEAD),
  122. ObjectId.toString(db.resolve("refs/heads/master")));
  123. write(new File(db.getDirectory(), Constants.MERGE_MSG), "merging");
  124. RevCommit commit = git.commit().call();
  125. RevCommit[] parents = commit.getParents();
  126. assertEquals(parents[0], firstSide);
  127. assertEquals(parents[1], second);
  128. assertEquals(2, parents.length);
  129. }
  130. }
  131. @Test
  132. public void testAddUnstagedChanges() throws Exception {
  133. File file = new File(db.getWorkTree(), "a.txt");
  134. FileUtils.createNewFile(file);
  135. try (PrintWriter writer = new PrintWriter(file, UTF_8.name())) {
  136. writer.print("content");
  137. }
  138. try (Git git = new Git(db)) {
  139. git.add().addFilepattern("a.txt").call();
  140. RevCommit commit = git.commit().setMessage("initial commit").call();
  141. TreeWalk tw = TreeWalk.forPath(db, "a.txt", commit.getTree());
  142. assertEquals("6b584e8ece562ebffc15d38808cd6b98fc3d97ea",
  143. tw.getObjectId(0).getName());
  144. try (PrintWriter writer = new PrintWriter(file, UTF_8.name())) {
  145. writer.print("content2");
  146. }
  147. commit = git.commit().setMessage("second commit").call();
  148. tw = TreeWalk.forPath(db, "a.txt", commit.getTree());
  149. assertEquals("6b584e8ece562ebffc15d38808cd6b98fc3d97ea",
  150. tw.getObjectId(0).getName());
  151. commit = git.commit().setAll(true).setMessage("third commit")
  152. .setAll(true).call();
  153. tw = TreeWalk.forPath(db, "a.txt", commit.getTree());
  154. assertEquals("db00fd65b218578127ea51f3dffac701f12f486a",
  155. tw.getObjectId(0).getName());
  156. }
  157. }
  158. @Test
  159. public void testModeChange() throws Exception {
  160. assumeFalse(System.getProperty("os.name").startsWith("Windows"));// SKIP
  161. try (Git git = new Git(db)) {
  162. // create file
  163. File file = new File(db.getWorkTree(), "a.txt");
  164. FileUtils.createNewFile(file);
  165. try (PrintWriter writer = new PrintWriter(file, UTF_8.name())) {
  166. writer.print("content1");
  167. }
  168. // First commit - a.txt file
  169. git.add().addFilepattern("a.txt").call();
  170. git.commit().setMessage("commit1").setCommitter(committer).call();
  171. // pure mode change should be committable
  172. FS fs = db.getFS();
  173. fs.setExecute(file, true);
  174. git.add().addFilepattern("a.txt").call();
  175. git.commit().setMessage("mode change").setCommitter(committer)
  176. .call();
  177. // pure mode change should be committable with -o option
  178. fs.setExecute(file, false);
  179. git.add().addFilepattern("a.txt").call();
  180. git.commit().setMessage("mode change").setCommitter(committer)
  181. .setOnly("a.txt").call();
  182. }
  183. }
  184. @Test
  185. public void testCommitRange() throws Exception {
  186. // do 4 commits and set the range to the second and fourth one
  187. try (Git git = new Git(db)) {
  188. git.commit().setMessage("first commit").call();
  189. RevCommit second = git.commit().setMessage("second commit")
  190. .setCommitter(committer).call();
  191. git.commit().setMessage("third commit").setAuthor(author).call();
  192. RevCommit last = git.commit().setMessage("fourth commit")
  193. .setAuthor(author).setCommitter(committer).call();
  194. Iterable<RevCommit> commits = git.log()
  195. .addRange(second.getId(), last.getId()).call();
  196. // check that we have the third and fourth commit
  197. PersonIdent defaultCommitter = new PersonIdent(db);
  198. PersonIdent expectedAuthors[] = new PersonIdent[] { author,
  199. author };
  200. PersonIdent expectedCommitters[] = new PersonIdent[] {
  201. defaultCommitter, committer };
  202. String expectedMessages[] = new String[] { "third commit",
  203. "fourth commit" };
  204. int l = expectedAuthors.length - 1;
  205. for (RevCommit c : commits) {
  206. assertEquals(expectedAuthors[l].getName(),
  207. c.getAuthorIdent().getName());
  208. assertEquals(expectedCommitters[l].getName(),
  209. c.getCommitterIdent().getName());
  210. assertEquals(c.getFullMessage(), expectedMessages[l]);
  211. l--;
  212. }
  213. assertEquals(l, -1);
  214. }
  215. }
  216. @Test
  217. public void testCommitAmend() throws Exception {
  218. try (Git git = new Git(db)) {
  219. git.commit().setMessage("first comit").call(); // typo
  220. git.commit().setAmend(true).setMessage("first commit").call();
  221. Iterable<RevCommit> commits = git.log().call();
  222. int c = 0;
  223. for (RevCommit commit : commits) {
  224. assertEquals("first commit", commit.getFullMessage());
  225. c++;
  226. }
  227. assertEquals(1, c);
  228. ReflogReader reader = db.getReflogReader(Constants.HEAD);
  229. assertTrue(reader.getLastEntry().getComment()
  230. .startsWith("commit (amend):"));
  231. reader = db.getReflogReader(db.getBranch());
  232. assertTrue(reader.getLastEntry().getComment()
  233. .startsWith("commit (amend):"));
  234. }
  235. }
  236. @Test
  237. public void testInsertChangeId() throws Exception {
  238. try (Git git = new Git(db)) {
  239. String messageHeader = "Some header line\n\nSome detail explanation\n";
  240. String changeIdTemplate = "\nChange-Id: I"
  241. + ObjectId.zeroId().getName() + "\n";
  242. String messageFooter = "Some foooter lines\nAnother footer line\n";
  243. RevCommit commit = git.commit()
  244. .setMessage(messageHeader + messageFooter)
  245. .setInsertChangeId(true).call();
  246. // we should find a real change id (at the end of the file)
  247. byte[] chars = commit.getFullMessage().getBytes(UTF_8);
  248. int lastLineBegin = RawParseUtils.prevLF(chars, chars.length - 2);
  249. String lastLine = RawParseUtils.decode(chars, lastLineBegin + 1,
  250. chars.length);
  251. assertTrue(lastLine.contains("Change-Id:"));
  252. assertFalse(lastLine
  253. .contains("Change-Id: I" + ObjectId.zeroId().getName()));
  254. commit = git.commit()
  255. .setMessage(
  256. messageHeader + changeIdTemplate + messageFooter)
  257. .setInsertChangeId(true).call();
  258. // we should find a real change id (in the line as dictated by the
  259. // template)
  260. chars = commit.getFullMessage().getBytes(UTF_8);
  261. int lineStart = 0;
  262. int lineEnd = 0;
  263. for (int i = 0; i < 4; i++) {
  264. lineStart = RawParseUtils.nextLF(chars, lineStart);
  265. }
  266. lineEnd = RawParseUtils.nextLF(chars, lineStart);
  267. String line = RawParseUtils.decode(chars, lineStart, lineEnd);
  268. assertTrue(line.contains("Change-Id:"));
  269. assertFalse(line
  270. .contains("Change-Id: I" + ObjectId.zeroId().getName()));
  271. commit = git.commit()
  272. .setMessage(
  273. messageHeader + changeIdTemplate + messageFooter)
  274. .setInsertChangeId(false).call();
  275. // we should find the untouched template
  276. chars = commit.getFullMessage().getBytes(UTF_8);
  277. lineStart = 0;
  278. lineEnd = 0;
  279. for (int i = 0; i < 4; i++) {
  280. lineStart = RawParseUtils.nextLF(chars, lineStart);
  281. }
  282. lineEnd = RawParseUtils.nextLF(chars, lineStart);
  283. line = RawParseUtils.decode(chars, lineStart, lineEnd);
  284. assertTrue(commit.getFullMessage()
  285. .contains("Change-Id: I" + ObjectId.zeroId().getName()));
  286. }
  287. }
  288. }