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.

CommitCommandTest.java 31KB

Fix core.autocrlf for non-normalized index With text=auto or core.autocrlf=true, git does not normalize upon check-in if the file in the index contains already CR/LFs. The documentation says: "When text is set to "auto", the path is marked for automatic end-of-line conversion. If Git decides that the content is text, its line endings are converted to LF on checkin. When the file has been committed with CRLF, no conversion is done."[1] Implement the last bit as in canonical git: check the blob in the index for CR/LFs. For very large files, we check only the first 8000 bytes, like RawText.isBinary() and AutoLFInputStream do. In Auto(CR)LFInputStream, ensure that the buffer is filled as much as possible for the isBinary() check. Regarding these content checks, there are a number of inconsistencies: * Canonical git considers files containing lone CRs as binary. * RawText checks the first 8000 bytes. * Auto(CR)LFInputStream checks the first 8096 (not 8192!) bytes. None of these are changed with this commit. It appears that canonical git will check the whole blob, not just the first 8k bytes. Also note: the check for CR/LF text won't work with LFS (neither in JGit nor in git) since the blob data is not run through the smudge filter. C.f. [2]. Two tests in AddCommandTest actually tested that normalization was done even if the file was already committed with CR/LF.These tests had to be adapted. I find the git documentation unclear about the case where core.autocrlf=input, but from [3] it looks as if this non-normalization also applies in this case. Add new tests in CommitCommandTest testing this for the case where the index entry is for a merge conflict. In this case, canonical git uses the "ours" version.[4] Do the same. [1] https://git-scm.com/docs/gitattributes [2] https://github.com/git/git/blob/3434569fc/convert.c#L225 [3] https://github.com/git/git/blob/3434569fc/convert.c#L529 [4] https://github.com/git/git/blob/f2b6aa98b/read-cache.c#L3281 Bug: 470643 Change-Id: Ie7310539fbe6c737d78b1dcc29e34735d4616b88 Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
5 yıl önce
Fix core.autocrlf for non-normalized index With text=auto or core.autocrlf=true, git does not normalize upon check-in if the file in the index contains already CR/LFs. The documentation says: "When text is set to "auto", the path is marked for automatic end-of-line conversion. If Git decides that the content is text, its line endings are converted to LF on checkin. When the file has been committed with CRLF, no conversion is done."[1] Implement the last bit as in canonical git: check the blob in the index for CR/LFs. For very large files, we check only the first 8000 bytes, like RawText.isBinary() and AutoLFInputStream do. In Auto(CR)LFInputStream, ensure that the buffer is filled as much as possible for the isBinary() check. Regarding these content checks, there are a number of inconsistencies: * Canonical git considers files containing lone CRs as binary. * RawText checks the first 8000 bytes. * Auto(CR)LFInputStream checks the first 8096 (not 8192!) bytes. None of these are changed with this commit. It appears that canonical git will check the whole blob, not just the first 8k bytes. Also note: the check for CR/LF text won't work with LFS (neither in JGit nor in git) since the blob data is not run through the smudge filter. C.f. [2]. Two tests in AddCommandTest actually tested that normalization was done even if the file was already committed with CR/LF.These tests had to be adapted. I find the git documentation unclear about the case where core.autocrlf=input, but from [3] it looks as if this non-normalization also applies in this case. Add new tests in CommitCommandTest testing this for the case where the index entry is for a merge conflict. In this case, canonical git uses the "ours" version.[4] Do the same. [1] https://git-scm.com/docs/gitattributes [2] https://github.com/git/git/blob/3434569fc/convert.c#L225 [3] https://github.com/git/git/blob/3434569fc/convert.c#L529 [4] https://github.com/git/git/blob/f2b6aa98b/read-cache.c#L3281 Bug: 470643 Change-Id: Ie7310539fbe6c737d78b1dcc29e34735d4616b88 Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
5 yıl önce
Fix core.autocrlf for non-normalized index With text=auto or core.autocrlf=true, git does not normalize upon check-in if the file in the index contains already CR/LFs. The documentation says: "When text is set to "auto", the path is marked for automatic end-of-line conversion. If Git decides that the content is text, its line endings are converted to LF on checkin. When the file has been committed with CRLF, no conversion is done."[1] Implement the last bit as in canonical git: check the blob in the index for CR/LFs. For very large files, we check only the first 8000 bytes, like RawText.isBinary() and AutoLFInputStream do. In Auto(CR)LFInputStream, ensure that the buffer is filled as much as possible for the isBinary() check. Regarding these content checks, there are a number of inconsistencies: * Canonical git considers files containing lone CRs as binary. * RawText checks the first 8000 bytes. * Auto(CR)LFInputStream checks the first 8096 (not 8192!) bytes. None of these are changed with this commit. It appears that canonical git will check the whole blob, not just the first 8k bytes. Also note: the check for CR/LF text won't work with LFS (neither in JGit nor in git) since the blob data is not run through the smudge filter. C.f. [2]. Two tests in AddCommandTest actually tested that normalization was done even if the file was already committed with CR/LF.These tests had to be adapted. I find the git documentation unclear about the case where core.autocrlf=input, but from [3] it looks as if this non-normalization also applies in this case. Add new tests in CommitCommandTest testing this for the case where the index entry is for a merge conflict. In this case, canonical git uses the "ours" version.[4] Do the same. [1] https://git-scm.com/docs/gitattributes [2] https://github.com/git/git/blob/3434569fc/convert.c#L225 [3] https://github.com/git/git/blob/3434569fc/convert.c#L529 [4] https://github.com/git/git/blob/f2b6aa98b/read-cache.c#L3281 Bug: 470643 Change-Id: Ie7310539fbe6c737d78b1dcc29e34735d4616b88 Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
5 yıl önce
Fix core.autocrlf for non-normalized index With text=auto or core.autocrlf=true, git does not normalize upon check-in if the file in the index contains already CR/LFs. The documentation says: "When text is set to "auto", the path is marked for automatic end-of-line conversion. If Git decides that the content is text, its line endings are converted to LF on checkin. When the file has been committed with CRLF, no conversion is done."[1] Implement the last bit as in canonical git: check the blob in the index for CR/LFs. For very large files, we check only the first 8000 bytes, like RawText.isBinary() and AutoLFInputStream do. In Auto(CR)LFInputStream, ensure that the buffer is filled as much as possible for the isBinary() check. Regarding these content checks, there are a number of inconsistencies: * Canonical git considers files containing lone CRs as binary. * RawText checks the first 8000 bytes. * Auto(CR)LFInputStream checks the first 8096 (not 8192!) bytes. None of these are changed with this commit. It appears that canonical git will check the whole blob, not just the first 8k bytes. Also note: the check for CR/LF text won't work with LFS (neither in JGit nor in git) since the blob data is not run through the smudge filter. C.f. [2]. Two tests in AddCommandTest actually tested that normalization was done even if the file was already committed with CR/LF.These tests had to be adapted. I find the git documentation unclear about the case where core.autocrlf=input, but from [3] it looks as if this non-normalization also applies in this case. Add new tests in CommitCommandTest testing this for the case where the index entry is for a merge conflict. In this case, canonical git uses the "ours" version.[4] Do the same. [1] https://git-scm.com/docs/gitattributes [2] https://github.com/git/git/blob/3434569fc/convert.c#L225 [3] https://github.com/git/git/blob/3434569fc/convert.c#L529 [4] https://github.com/git/git/blob/f2b6aa98b/read-cache.c#L3281 Bug: 470643 Change-Id: Ie7310539fbe6c737d78b1dcc29e34735d4616b88 Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
5 yıl önce
Fix core.autocrlf for non-normalized index With text=auto or core.autocrlf=true, git does not normalize upon check-in if the file in the index contains already CR/LFs. The documentation says: "When text is set to "auto", the path is marked for automatic end-of-line conversion. If Git decides that the content is text, its line endings are converted to LF on checkin. When the file has been committed with CRLF, no conversion is done."[1] Implement the last bit as in canonical git: check the blob in the index for CR/LFs. For very large files, we check only the first 8000 bytes, like RawText.isBinary() and AutoLFInputStream do. In Auto(CR)LFInputStream, ensure that the buffer is filled as much as possible for the isBinary() check. Regarding these content checks, there are a number of inconsistencies: * Canonical git considers files containing lone CRs as binary. * RawText checks the first 8000 bytes. * Auto(CR)LFInputStream checks the first 8096 (not 8192!) bytes. None of these are changed with this commit. It appears that canonical git will check the whole blob, not just the first 8k bytes. Also note: the check for CR/LF text won't work with LFS (neither in JGit nor in git) since the blob data is not run through the smudge filter. C.f. [2]. Two tests in AddCommandTest actually tested that normalization was done even if the file was already committed with CR/LF.These tests had to be adapted. I find the git documentation unclear about the case where core.autocrlf=input, but from [3] it looks as if this non-normalization also applies in this case. Add new tests in CommitCommandTest testing this for the case where the index entry is for a merge conflict. In this case, canonical git uses the "ours" version.[4] Do the same. [1] https://git-scm.com/docs/gitattributes [2] https://github.com/git/git/blob/3434569fc/convert.c#L225 [3] https://github.com/git/git/blob/3434569fc/convert.c#L529 [4] https://github.com/git/git/blob/f2b6aa98b/read-cache.c#L3281 Bug: 470643 Change-Id: Ie7310539fbe6c737d78b1dcc29e34735d4616b88 Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
5 yıl önce
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902
  1. /*
  2. * Copyright (C) 2011-2012, GitHub Inc.
  3. * and other copyright owners as documented in the project's IP log.
  4. *
  5. * This program and the accompanying materials are made available
  6. * under the terms of the Eclipse Distribution License v1.0 which
  7. * accompanies this distribution, is reproduced below, and is
  8. * available at http://www.eclipse.org/org/documents/edl-v10.php
  9. *
  10. * All rights reserved.
  11. *
  12. * Redistribution and use in source and binary forms, with or
  13. * without modification, are permitted provided that the following
  14. * conditions are met:
  15. *
  16. * - Redistributions of source code must retain the above copyright
  17. * notice, this list of conditions and the following disclaimer.
  18. *
  19. * - Redistributions in binary form must reproduce the above
  20. * copyright notice, this list of conditions and the following
  21. * disclaimer in the documentation and/or other materials provided
  22. * with the distribution.
  23. *
  24. * - Neither the name of the Eclipse Foundation, Inc. nor the
  25. * names of its contributors may be used to endorse or promote
  26. * products derived from this software without specific prior
  27. * written permission.
  28. *
  29. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  30. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  31. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  32. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  33. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  34. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  35. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  36. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  37. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  38. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  40. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  41. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  42. */
  43. package org.eclipse.jgit.api;
  44. import static org.junit.Assert.assertEquals;
  45. import static org.junit.Assert.assertNotEquals;
  46. import static org.junit.Assert.assertNotNull;
  47. import static org.junit.Assert.assertNull;
  48. import static org.junit.Assert.assertSame;
  49. import static org.junit.Assert.assertTrue;
  50. import static org.junit.Assert.fail;
  51. import java.io.File;
  52. import java.util.Date;
  53. import java.util.List;
  54. import java.util.TimeZone;
  55. import java.util.concurrent.atomic.AtomicInteger;
  56. import org.eclipse.jgit.api.CherryPickResult.CherryPickStatus;
  57. import org.eclipse.jgit.api.errors.CanceledException;
  58. import org.eclipse.jgit.api.errors.EmptyCommitException;
  59. import org.eclipse.jgit.api.errors.WrongRepositoryStateException;
  60. import org.eclipse.jgit.diff.DiffEntry;
  61. import org.eclipse.jgit.dircache.DirCache;
  62. import org.eclipse.jgit.dircache.DirCacheBuilder;
  63. import org.eclipse.jgit.dircache.DirCacheEntry;
  64. import org.eclipse.jgit.junit.RepositoryTestCase;
  65. import org.eclipse.jgit.junit.time.TimeUtil;
  66. import org.eclipse.jgit.lib.CommitBuilder;
  67. import org.eclipse.jgit.lib.ConfigConstants;
  68. import org.eclipse.jgit.lib.Constants;
  69. import org.eclipse.jgit.lib.FileMode;
  70. import org.eclipse.jgit.lib.GpgSigner;
  71. import org.eclipse.jgit.lib.ObjectId;
  72. import org.eclipse.jgit.lib.PersonIdent;
  73. import org.eclipse.jgit.lib.RefUpdate;
  74. import org.eclipse.jgit.lib.RefUpdate.Result;
  75. import org.eclipse.jgit.lib.ReflogEntry;
  76. import org.eclipse.jgit.lib.Repository;
  77. import org.eclipse.jgit.lib.StoredConfig;
  78. import org.eclipse.jgit.revwalk.RevCommit;
  79. import org.eclipse.jgit.storage.file.FileBasedConfig;
  80. import org.eclipse.jgit.submodule.SubmoduleWalk;
  81. import org.eclipse.jgit.transport.CredentialsProvider;
  82. import org.eclipse.jgit.treewalk.TreeWalk;
  83. import org.eclipse.jgit.treewalk.filter.TreeFilter;
  84. import org.eclipse.jgit.util.FS;
  85. import org.junit.Ignore;
  86. import org.junit.Test;
  87. /**
  88. * Unit tests of {@link CommitCommand}.
  89. */
  90. public class CommitCommandTest extends RepositoryTestCase {
  91. @Test
  92. public void testExecutableRetention() throws Exception {
  93. StoredConfig config = db.getConfig();
  94. config.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
  95. ConfigConstants.CONFIG_KEY_FILEMODE, true);
  96. config.save();
  97. FS executableFs = new FS() {
  98. @Override
  99. public boolean supportsExecute() {
  100. return true;
  101. }
  102. @Override
  103. public boolean setExecute(File f, boolean canExec) {
  104. return true;
  105. }
  106. @Override
  107. public ProcessBuilder runInShell(String cmd, String[] args) {
  108. return null;
  109. }
  110. @Override
  111. public boolean retryFailedLockFileCommit() {
  112. return false;
  113. }
  114. @Override
  115. public FS newInstance() {
  116. return this;
  117. }
  118. @Override
  119. protected File discoverGitExe() {
  120. return null;
  121. }
  122. @Override
  123. public boolean canExecute(File f) {
  124. return true;
  125. }
  126. @Override
  127. public boolean isCaseSensitive() {
  128. return true;
  129. }
  130. };
  131. Git git = Git.open(db.getDirectory(), executableFs);
  132. String path = "a.txt";
  133. writeTrashFile(path, "content");
  134. git.add().addFilepattern(path).call();
  135. RevCommit commit1 = git.commit().setMessage("commit").call();
  136. TreeWalk walk = TreeWalk.forPath(db, path, commit1.getTree());
  137. assertNotNull(walk);
  138. assertEquals(FileMode.EXECUTABLE_FILE, walk.getFileMode(0));
  139. FS nonExecutableFs = new FS() {
  140. @Override
  141. public boolean supportsExecute() {
  142. return false;
  143. }
  144. @Override
  145. public boolean setExecute(File f, boolean canExec) {
  146. return false;
  147. }
  148. @Override
  149. public ProcessBuilder runInShell(String cmd, String[] args) {
  150. return null;
  151. }
  152. @Override
  153. public boolean retryFailedLockFileCommit() {
  154. return false;
  155. }
  156. @Override
  157. public FS newInstance() {
  158. return this;
  159. }
  160. @Override
  161. protected File discoverGitExe() {
  162. return null;
  163. }
  164. @Override
  165. public boolean canExecute(File f) {
  166. return false;
  167. }
  168. @Override
  169. public boolean isCaseSensitive() {
  170. return true;
  171. }
  172. };
  173. config = db.getConfig();
  174. config.setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
  175. ConfigConstants.CONFIG_KEY_FILEMODE, false);
  176. config.save();
  177. Git git2 = Git.open(db.getDirectory(), nonExecutableFs);
  178. writeTrashFile(path, "content2");
  179. RevCommit commit2 = git2.commit().setOnly(path).setMessage("commit2")
  180. .call();
  181. walk = TreeWalk.forPath(db, path, commit2.getTree());
  182. assertNotNull(walk);
  183. assertEquals(FileMode.EXECUTABLE_FILE, walk.getFileMode(0));
  184. }
  185. @Test
  186. public void commitNewSubmodule() throws Exception {
  187. try (Git git = new Git(db)) {
  188. writeTrashFile("file.txt", "content");
  189. git.add().addFilepattern("file.txt").call();
  190. RevCommit commit = git.commit().setMessage("create file").call();
  191. SubmoduleAddCommand command = new SubmoduleAddCommand(db);
  192. String path = "sub";
  193. command.setPath(path);
  194. String uri = db.getDirectory().toURI().toString();
  195. command.setURI(uri);
  196. Repository repo = command.call();
  197. assertNotNull(repo);
  198. addRepoToClose(repo);
  199. SubmoduleWalk generator = SubmoduleWalk.forIndex(db);
  200. assertTrue(generator.next());
  201. assertEquals(path, generator.getPath());
  202. assertEquals(commit, generator.getObjectId());
  203. assertEquals(uri, generator.getModulesUrl());
  204. assertEquals(path, generator.getModulesPath());
  205. assertEquals(uri, generator.getConfigUrl());
  206. try (Repository subModRepo = generator.getRepository()) {
  207. assertNotNull(subModRepo);
  208. }
  209. assertEquals(commit, repo.resolve(Constants.HEAD));
  210. RevCommit submoduleCommit = git.commit().setMessage("submodule add")
  211. .setOnly(path).call();
  212. assertNotNull(submoduleCommit);
  213. try (TreeWalk walk = new TreeWalk(db)) {
  214. walk.addTree(commit.getTree());
  215. walk.addTree(submoduleCommit.getTree());
  216. walk.setFilter(TreeFilter.ANY_DIFF);
  217. List<DiffEntry> diffs = DiffEntry.scan(walk);
  218. assertEquals(1, diffs.size());
  219. DiffEntry subDiff = diffs.get(0);
  220. assertEquals(FileMode.MISSING, subDiff.getOldMode());
  221. assertEquals(FileMode.GITLINK, subDiff.getNewMode());
  222. assertEquals(ObjectId.zeroId(), subDiff.getOldId().toObjectId());
  223. assertEquals(commit, subDiff.getNewId().toObjectId());
  224. assertEquals(path, subDiff.getNewPath());
  225. }
  226. }
  227. }
  228. @Test
  229. public void commitSubmoduleUpdate() throws Exception {
  230. try (Git git = new Git(db)) {
  231. writeTrashFile("file.txt", "content");
  232. git.add().addFilepattern("file.txt").call();
  233. RevCommit commit = git.commit().setMessage("create file").call();
  234. writeTrashFile("file.txt", "content2");
  235. git.add().addFilepattern("file.txt").call();
  236. RevCommit commit2 = git.commit().setMessage("edit file").call();
  237. SubmoduleAddCommand command = new SubmoduleAddCommand(db);
  238. String path = "sub";
  239. command.setPath(path);
  240. String uri = db.getDirectory().toURI().toString();
  241. command.setURI(uri);
  242. Repository repo = command.call();
  243. assertNotNull(repo);
  244. addRepoToClose(repo);
  245. SubmoduleWalk generator = SubmoduleWalk.forIndex(db);
  246. assertTrue(generator.next());
  247. assertEquals(path, generator.getPath());
  248. assertEquals(commit2, generator.getObjectId());
  249. assertEquals(uri, generator.getModulesUrl());
  250. assertEquals(path, generator.getModulesPath());
  251. assertEquals(uri, generator.getConfigUrl());
  252. try (Repository subModRepo = generator.getRepository()) {
  253. assertNotNull(subModRepo);
  254. }
  255. assertEquals(commit2, repo.resolve(Constants.HEAD));
  256. RevCommit submoduleAddCommit = git.commit().setMessage("submodule add")
  257. .setOnly(path).call();
  258. assertNotNull(submoduleAddCommit);
  259. RefUpdate update = repo.updateRef(Constants.HEAD);
  260. update.setNewObjectId(commit);
  261. assertEquals(Result.FORCED, update.forceUpdate());
  262. RevCommit submoduleEditCommit = git.commit()
  263. .setMessage("submodule add").setOnly(path).call();
  264. assertNotNull(submoduleEditCommit);
  265. try (TreeWalk walk = new TreeWalk(db)) {
  266. walk.addTree(submoduleAddCommit.getTree());
  267. walk.addTree(submoduleEditCommit.getTree());
  268. walk.setFilter(TreeFilter.ANY_DIFF);
  269. List<DiffEntry> diffs = DiffEntry.scan(walk);
  270. assertEquals(1, diffs.size());
  271. DiffEntry subDiff = diffs.get(0);
  272. assertEquals(FileMode.GITLINK, subDiff.getOldMode());
  273. assertEquals(FileMode.GITLINK, subDiff.getNewMode());
  274. assertEquals(commit2, subDiff.getOldId().toObjectId());
  275. assertEquals(commit, subDiff.getNewId().toObjectId());
  276. assertEquals(path, subDiff.getNewPath());
  277. assertEquals(path, subDiff.getOldPath());
  278. }
  279. }
  280. }
  281. @Ignore("very flaky when run with Hudson")
  282. @Test
  283. public void commitUpdatesSmudgedEntries() throws Exception {
  284. try (Git git = new Git(db)) {
  285. File file1 = writeTrashFile("file1.txt", "content1");
  286. TimeUtil.setLastModifiedWithOffset(file1.toPath(), -5000L);
  287. File file2 = writeTrashFile("file2.txt", "content2");
  288. TimeUtil.setLastModifiedWithOffset(file2.toPath(), -5000L);
  289. File file3 = writeTrashFile("file3.txt", "content3");
  290. TimeUtil.setLastModifiedWithOffset(file3.toPath(), -5000L);
  291. assertNotNull(git.add().addFilepattern("file1.txt")
  292. .addFilepattern("file2.txt").addFilepattern("file3.txt").call());
  293. RevCommit commit = git.commit().setMessage("add files").call();
  294. assertNotNull(commit);
  295. DirCache cache = DirCache.read(db.getIndexFile(), db.getFS());
  296. int file1Size = cache.getEntry("file1.txt").getLength();
  297. int file2Size = cache.getEntry("file2.txt").getLength();
  298. int file3Size = cache.getEntry("file3.txt").getLength();
  299. ObjectId file2Id = cache.getEntry("file2.txt").getObjectId();
  300. ObjectId file3Id = cache.getEntry("file3.txt").getObjectId();
  301. assertTrue(file1Size > 0);
  302. assertTrue(file2Size > 0);
  303. assertTrue(file3Size > 0);
  304. // Smudge entries
  305. cache = DirCache.lock(db.getIndexFile(), db.getFS());
  306. cache.getEntry("file1.txt").setLength(0);
  307. cache.getEntry("file2.txt").setLength(0);
  308. cache.getEntry("file3.txt").setLength(0);
  309. cache.write();
  310. assertTrue(cache.commit());
  311. // Verify entries smudged
  312. cache = DirCache.read(db.getIndexFile(), db.getFS());
  313. assertEquals(0, cache.getEntry("file1.txt").getLength());
  314. assertEquals(0, cache.getEntry("file2.txt").getLength());
  315. assertEquals(0, cache.getEntry("file3.txt").getLength());
  316. TimeUtil.setLastModifiedWithOffset(db.getIndexFile().toPath(),
  317. -5000L);
  318. write(file1, "content4");
  319. TimeUtil.setLastModifiedWithOffset(file1.toPath(), 2500L);
  320. assertNotNull(git.commit().setMessage("edit file").setOnly("file1.txt")
  321. .call());
  322. cache = db.readDirCache();
  323. assertEquals(file1Size, cache.getEntry("file1.txt").getLength());
  324. assertEquals(file2Size, cache.getEntry("file2.txt").getLength());
  325. assertEquals(file3Size, cache.getEntry("file3.txt").getLength());
  326. assertEquals(file2Id, cache.getEntry("file2.txt").getObjectId());
  327. assertEquals(file3Id, cache.getEntry("file3.txt").getObjectId());
  328. }
  329. }
  330. @Ignore("very flaky when run with Hudson")
  331. @Test
  332. public void commitIgnoresSmudgedEntryWithDifferentId() throws Exception {
  333. try (Git git = new Git(db)) {
  334. File file1 = writeTrashFile("file1.txt", "content1");
  335. TimeUtil.setLastModifiedWithOffset(file1.toPath(), -5000L);
  336. File file2 = writeTrashFile("file2.txt", "content2");
  337. TimeUtil.setLastModifiedWithOffset(file2.toPath(), -5000L);
  338. assertNotNull(git.add().addFilepattern("file1.txt")
  339. .addFilepattern("file2.txt").call());
  340. RevCommit commit = git.commit().setMessage("add files").call();
  341. assertNotNull(commit);
  342. DirCache cache = DirCache.read(db.getIndexFile(), db.getFS());
  343. int file1Size = cache.getEntry("file1.txt").getLength();
  344. int file2Size = cache.getEntry("file2.txt").getLength();
  345. assertTrue(file1Size > 0);
  346. assertTrue(file2Size > 0);
  347. writeTrashFile("file2.txt", "content3");
  348. assertNotNull(git.add().addFilepattern("file2.txt").call());
  349. writeTrashFile("file2.txt", "content4");
  350. // Smudge entries
  351. cache = DirCache.lock(db.getIndexFile(), db.getFS());
  352. cache.getEntry("file1.txt").setLength(0);
  353. cache.getEntry("file2.txt").setLength(0);
  354. cache.write();
  355. assertTrue(cache.commit());
  356. // Verify entries smudged
  357. cache = db.readDirCache();
  358. assertEquals(0, cache.getEntry("file1.txt").getLength());
  359. assertEquals(0, cache.getEntry("file2.txt").getLength());
  360. TimeUtil.setLastModifiedWithOffset(db.getIndexFile().toPath(),
  361. -5000L);
  362. write(file1, "content5");
  363. TimeUtil.setLastModifiedWithOffset(file1.toPath(), 1000L);
  364. assertNotNull(git.commit().setMessage("edit file").setOnly("file1.txt")
  365. .call());
  366. cache = db.readDirCache();
  367. assertEquals(file1Size, cache.getEntry("file1.txt").getLength());
  368. assertEquals(0, cache.getEntry("file2.txt").getLength());
  369. }
  370. }
  371. @Test
  372. public void commitAfterSquashMerge() throws Exception {
  373. try (Git git = new Git(db)) {
  374. writeTrashFile("file1", "file1");
  375. git.add().addFilepattern("file1").call();
  376. RevCommit first = git.commit().setMessage("initial commit").call();
  377. assertTrue(new File(db.getWorkTree(), "file1").exists());
  378. createBranch(first, "refs/heads/branch1");
  379. checkoutBranch("refs/heads/branch1");
  380. writeTrashFile("file2", "file2");
  381. git.add().addFilepattern("file2").call();
  382. git.commit().setMessage("second commit").call();
  383. assertTrue(new File(db.getWorkTree(), "file2").exists());
  384. checkoutBranch("refs/heads/master");
  385. MergeResult result = git.merge()
  386. .include(db.exactRef("refs/heads/branch1"))
  387. .setSquash(true)
  388. .call();
  389. assertTrue(new File(db.getWorkTree(), "file1").exists());
  390. assertTrue(new File(db.getWorkTree(), "file2").exists());
  391. assertEquals(MergeResult.MergeStatus.FAST_FORWARD_SQUASHED,
  392. result.getMergeStatus());
  393. // comment not set, should be inferred from SQUASH_MSG
  394. RevCommit squashedCommit = git.commit().call();
  395. assertEquals(1, squashedCommit.getParentCount());
  396. assertNull(db.readSquashCommitMsg());
  397. assertEquals("commit: Squashed commit of the following:", db
  398. .getReflogReader(Constants.HEAD).getLastEntry().getComment());
  399. assertEquals("commit: Squashed commit of the following:", db
  400. .getReflogReader(db.getBranch()).getLastEntry().getComment());
  401. }
  402. }
  403. @Test
  404. public void testReflogs() throws Exception {
  405. try (Git git = new Git(db)) {
  406. writeTrashFile("f", "1");
  407. git.add().addFilepattern("f").call();
  408. git.commit().setMessage("c1").call();
  409. writeTrashFile("f", "2");
  410. git.commit().setMessage("c2").setAll(true).setReflogComment(null)
  411. .call();
  412. writeTrashFile("f", "3");
  413. git.commit().setMessage("c3").setAll(true)
  414. .setReflogComment("testRl").call();
  415. db.getReflogReader(Constants.HEAD).getReverseEntries();
  416. assertEquals("testRl;commit (initial): c1;", reflogComments(
  417. db.getReflogReader(Constants.HEAD).getReverseEntries()));
  418. assertEquals("testRl;commit (initial): c1;", reflogComments(
  419. db.getReflogReader(db.getBranch()).getReverseEntries()));
  420. }
  421. }
  422. private static String reflogComments(List<ReflogEntry> entries) {
  423. StringBuilder b = new StringBuilder();
  424. for (ReflogEntry e : entries) {
  425. b.append(e.getComment()).append(";");
  426. }
  427. return b.toString();
  428. }
  429. @Test(expected = WrongRepositoryStateException.class)
  430. public void commitAmendOnInitialShouldFail() throws Exception {
  431. try (Git git = new Git(db)) {
  432. git.commit().setAmend(true).setMessage("initial commit").call();
  433. }
  434. }
  435. @Test
  436. public void commitAmendWithoutAuthorShouldSetOriginalAuthorAndAuthorTime()
  437. throws Exception {
  438. try (Git git = new Git(db)) {
  439. writeTrashFile("file1", "file1");
  440. git.add().addFilepattern("file1").call();
  441. final String authorName = "First Author";
  442. final String authorEmail = "author@example.org";
  443. final Date authorDate = new Date(1349621117000L);
  444. PersonIdent firstAuthor = new PersonIdent(authorName, authorEmail,
  445. authorDate, TimeZone.getTimeZone("UTC"));
  446. git.commit().setMessage("initial commit").setAuthor(firstAuthor).call();
  447. RevCommit amended = git.commit().setAmend(true)
  448. .setMessage("amend commit").call();
  449. PersonIdent amendedAuthor = amended.getAuthorIdent();
  450. assertEquals(authorName, amendedAuthor.getName());
  451. assertEquals(authorEmail, amendedAuthor.getEmailAddress());
  452. assertEquals(authorDate.getTime(), amendedAuthor.getWhen().getTime());
  453. }
  454. }
  455. @Test
  456. public void commitAmendWithAuthorShouldUseIt() throws Exception {
  457. try (Git git = new Git(db)) {
  458. writeTrashFile("file1", "file1");
  459. git.add().addFilepattern("file1").call();
  460. git.commit().setMessage("initial commit").call();
  461. RevCommit amended = git.commit().setAmend(true)
  462. .setAuthor("New Author", "newauthor@example.org")
  463. .setMessage("amend commit").call();
  464. PersonIdent amendedAuthor = amended.getAuthorIdent();
  465. assertEquals("New Author", amendedAuthor.getName());
  466. assertEquals("newauthor@example.org", amendedAuthor.getEmailAddress());
  467. }
  468. }
  469. @Test
  470. public void commitEmptyCommits() throws Exception {
  471. try (Git git = new Git(db)) {
  472. writeTrashFile("file1", "file1");
  473. git.add().addFilepattern("file1").call();
  474. RevCommit initial = git.commit().setMessage("initial commit")
  475. .call();
  476. RevCommit emptyFollowUp = git.commit()
  477. .setAuthor("New Author", "newauthor@example.org")
  478. .setMessage("no change").call();
  479. assertNotEquals(initial.getId(), emptyFollowUp.getId());
  480. assertEquals(initial.getTree().getId(),
  481. emptyFollowUp.getTree().getId());
  482. try {
  483. git.commit().setAuthor("New Author", "newauthor@example.org")
  484. .setMessage("again no change").setAllowEmpty(false)
  485. .call();
  486. fail("Didn't get the expected EmptyCommitException");
  487. } catch (EmptyCommitException e) {
  488. // expect this exception
  489. }
  490. // Allow empty commits also when setOnly was set
  491. git.commit().setAuthor("New Author", "newauthor@example.org")
  492. .setMessage("again no change").setOnly("file1")
  493. .setAllowEmpty(true).call();
  494. }
  495. }
  496. @Test
  497. public void commitOnlyShouldCommitUnmergedPathAndNotAffectOthers()
  498. throws Exception {
  499. DirCache index = db.lockDirCache();
  500. DirCacheBuilder builder = index.builder();
  501. addUnmergedEntry("unmerged1", builder);
  502. addUnmergedEntry("unmerged2", builder);
  503. DirCacheEntry other = new DirCacheEntry("other");
  504. other.setFileMode(FileMode.REGULAR_FILE);
  505. builder.add(other);
  506. builder.commit();
  507. writeTrashFile("unmerged1", "unmerged1 data");
  508. writeTrashFile("unmerged2", "unmerged2 data");
  509. writeTrashFile("other", "other data");
  510. assertEquals("[other, mode:100644]"
  511. + "[unmerged1, mode:100644, stage:1]"
  512. + "[unmerged1, mode:100644, stage:2]"
  513. + "[unmerged1, mode:100644, stage:3]"
  514. + "[unmerged2, mode:100644, stage:1]"
  515. + "[unmerged2, mode:100644, stage:2]"
  516. + "[unmerged2, mode:100644, stage:3]",
  517. indexState(0));
  518. try (Git git = new Git(db)) {
  519. RevCommit commit = git.commit().setOnly("unmerged1")
  520. .setMessage("Only one file").call();
  521. assertEquals("[other, mode:100644]" + "[unmerged1, mode:100644]"
  522. + "[unmerged2, mode:100644, stage:1]"
  523. + "[unmerged2, mode:100644, stage:2]"
  524. + "[unmerged2, mode:100644, stage:3]",
  525. indexState(0));
  526. try (TreeWalk walk = TreeWalk.forPath(db, "unmerged1", commit.getTree())) {
  527. assertEquals(FileMode.REGULAR_FILE, walk.getFileMode(0));
  528. }
  529. }
  530. }
  531. @Test
  532. public void commitOnlyShouldHandleIgnored() throws Exception {
  533. try (Git git = new Git(db)) {
  534. writeTrashFile("subdir/foo", "Hello World");
  535. writeTrashFile("subdir/bar", "Hello World");
  536. writeTrashFile(".gitignore", "bar");
  537. git.add().addFilepattern("subdir").call();
  538. git.commit().setOnly("subdir").setMessage("first commit").call();
  539. assertEquals("[subdir/foo, mode:100644, content:Hello World]",
  540. indexState(CONTENT));
  541. }
  542. }
  543. @Test
  544. public void commitWithAutoCrlfAndNonNormalizedIndex() throws Exception {
  545. try (Git git = new Git(db)) {
  546. // Commit a file with CR/LF into the index
  547. FileBasedConfig config = db.getConfig();
  548. config.setString("core", null, "autocrlf", "false");
  549. config.save();
  550. writeTrashFile("file.txt", "line 1\r\nline 2\r\n");
  551. git.add().addFilepattern("file.txt").call();
  552. git.commit().setMessage("Initial").call();
  553. assertEquals(
  554. "[file.txt, mode:100644, content:line 1\r\nline 2\r\n]",
  555. indexState(CONTENT));
  556. config.setString("core", null, "autocrlf", "true");
  557. config.save();
  558. writeTrashFile("file.txt", "line 1\r\nline 1.5\r\nline 2\r\n");
  559. writeTrashFile("file2.txt", "new\r\nfile\r\n");
  560. git.add().addFilepattern("file.txt").addFilepattern("file2.txt")
  561. .call();
  562. git.commit().setMessage("Second").call();
  563. assertEquals(
  564. "[file.txt, mode:100644, content:line 1\r\nline 1.5\r\nline 2\r\n]"
  565. + "[file2.txt, mode:100644, content:new\nfile\n]",
  566. indexState(CONTENT));
  567. writeTrashFile("file2.txt", "new\r\nfile\r\ncontent\r\n");
  568. git.add().addFilepattern("file2.txt").call();
  569. git.commit().setMessage("Third").call();
  570. assertEquals(
  571. "[file.txt, mode:100644, content:line 1\r\nline 1.5\r\nline 2\r\n]"
  572. + "[file2.txt, mode:100644, content:new\nfile\ncontent\n]",
  573. indexState(CONTENT));
  574. }
  575. }
  576. @Test
  577. public void testDeletionConflictWithAutoCrlf() throws Exception {
  578. try (Git git = new Git(db)) {
  579. // Commit a file with CR/LF into the index
  580. FileBasedConfig config = db.getConfig();
  581. config.setString("core", null, "autocrlf", "false");
  582. config.save();
  583. File file = writeTrashFile("file.txt", "foo\r\n");
  584. git.add().addFilepattern("file.txt").call();
  585. git.commit().setMessage("Initial").call();
  586. // Switch to side branch
  587. git.checkout().setCreateBranch(true).setName("side").call();
  588. assertTrue(file.delete());
  589. git.rm().addFilepattern("file.txt").call();
  590. git.commit().setMessage("Side").call();
  591. // Switch on autocrlf=true
  592. config.setString("core", null, "autocrlf", "true");
  593. config.save();
  594. // Switch back to master and commit a conflict
  595. git.checkout().setName("master").call();
  596. writeTrashFile("file.txt", "foob\r\n");
  597. git.add().addFilepattern("file.txt").call();
  598. assertEquals("[file.txt, mode:100644, content:foob\r\n]",
  599. indexState(CONTENT));
  600. writeTrashFile("g", "file2.txt", "anything");
  601. git.add().addFilepattern("g/file2.txt");
  602. RevCommit master = git.commit().setMessage("Second").call();
  603. // Switch to side branch again so that the deletion is "ours"
  604. git.checkout().setName("side").call();
  605. // Cherry pick master: produces a delete-modify conflict.
  606. CherryPickResult pick = git.cherryPick().include(master).call();
  607. assertEquals("Expected a cherry-pick conflict",
  608. CherryPickStatus.CONFLICTING, pick.getStatus());
  609. // XXX: g/file2.txt should actually be staged already, but isn't.
  610. git.add().addFilepattern("g/file2.txt").call();
  611. // Resolve the conflict by taking the master version
  612. writeTrashFile("file.txt", "foob\r\n");
  613. git.add().addFilepattern("file.txt").call();
  614. git.commit().setMessage("Cherry").call();
  615. // We expect this to be committed with a single LF since there is no
  616. // "ours" stage.
  617. assertEquals(
  618. "[file.txt, mode:100644, content:foob\n]"
  619. + "[g/file2.txt, mode:100644, content:anything]",
  620. indexState(CONTENT));
  621. }
  622. }
  623. private void testConflictWithAutoCrlf(String baseLf, String lf)
  624. throws Exception {
  625. try (Git git = new Git(db)) {
  626. // Commit a file with CR/LF into the index
  627. FileBasedConfig config = db.getConfig();
  628. config.setString("core", null, "autocrlf", "false");
  629. config.save();
  630. writeTrashFile("file.txt", "foo" + baseLf);
  631. git.add().addFilepattern("file.txt").call();
  632. git.commit().setMessage("Initial").call();
  633. // Switch to side branch
  634. git.checkout().setCreateBranch(true).setName("side").call();
  635. writeTrashFile("file.txt", "bar\r\n");
  636. git.add().addFilepattern("file.txt").call();
  637. RevCommit side = git.commit().setMessage("Side").call();
  638. // Switch back to master and commit a conflict with the given lf
  639. git.checkout().setName("master");
  640. writeTrashFile("file.txt", "foob" + lf);
  641. git.add().addFilepattern("file.txt").call();
  642. git.commit().setMessage("Second").call();
  643. // Switch on autocrlf=true
  644. config.setString("core", null, "autocrlf", "true");
  645. config.save();
  646. // Cherry pick side: conflict. Resolve with CR-LF and commit.
  647. CherryPickResult pick = git.cherryPick().include(side).call();
  648. assertEquals("Expected a cherry-pick conflict",
  649. CherryPickStatus.CONFLICTING, pick.getStatus());
  650. writeTrashFile("file.txt", "foobar\r\n");
  651. git.add().addFilepattern("file.txt").call();
  652. git.commit().setMessage("Second").call();
  653. assertEquals("[file.txt, mode:100644, content:foobar" + lf + "]",
  654. indexState(CONTENT));
  655. }
  656. }
  657. @Test
  658. public void commitConflictWithAutoCrlfBaseCrLfOursLf() throws Exception {
  659. testConflictWithAutoCrlf("\r\n", "\n");
  660. }
  661. @Test
  662. public void commitConflictWithAutoCrlfBaseLfOursLf() throws Exception {
  663. testConflictWithAutoCrlf("\n", "\n");
  664. }
  665. @Test
  666. public void commitConflictWithAutoCrlfBasCrLfOursCrLf() throws Exception {
  667. testConflictWithAutoCrlf("\r\n", "\r\n");
  668. }
  669. @Test
  670. public void commitConflictWithAutoCrlfBaseLfOursCrLf() throws Exception {
  671. testConflictWithAutoCrlf("\n", "\r\n");
  672. }
  673. private static void addUnmergedEntry(String file, DirCacheBuilder builder) {
  674. DirCacheEntry stage1 = new DirCacheEntry(file, DirCacheEntry.STAGE_1);
  675. DirCacheEntry stage2 = new DirCacheEntry(file, DirCacheEntry.STAGE_2);
  676. DirCacheEntry stage3 = new DirCacheEntry(file, DirCacheEntry.STAGE_3);
  677. stage1.setFileMode(FileMode.REGULAR_FILE);
  678. stage2.setFileMode(FileMode.REGULAR_FILE);
  679. stage3.setFileMode(FileMode.REGULAR_FILE);
  680. builder.add(stage1);
  681. builder.add(stage2);
  682. builder.add(stage3);
  683. }
  684. @Test
  685. public void callSignerWithProperSigningKey() throws Exception {
  686. try (Git git = new Git(db)) {
  687. writeTrashFile("file1", "file1");
  688. git.add().addFilepattern("file1").call();
  689. String[] signingKey = new String[1];
  690. PersonIdent[] signingCommitters = new PersonIdent[1];
  691. AtomicInteger callCount = new AtomicInteger();
  692. GpgSigner.setDefault(new GpgSigner() {
  693. @Override
  694. public void sign(CommitBuilder commit, String gpgSigningKey,
  695. PersonIdent signingCommitter, CredentialsProvider credentialsProvider) {
  696. signingKey[0] = gpgSigningKey;
  697. signingCommitters[0] = signingCommitter;
  698. callCount.incrementAndGet();
  699. }
  700. @Override
  701. public boolean canLocateSigningKey(String gpgSigningKey,
  702. PersonIdent signingCommitter,
  703. CredentialsProvider credentialsProvider)
  704. throws CanceledException {
  705. return false;
  706. }
  707. });
  708. // first call should use config, which is expected to be null at
  709. // this time
  710. git.commit().setCommitter(committer).setSign(Boolean.TRUE)
  711. .setMessage("initial commit")
  712. .call();
  713. assertNull(signingKey[0]);
  714. assertEquals(1, callCount.get());
  715. assertSame(committer, signingCommitters[0]);
  716. writeTrashFile("file2", "file2");
  717. git.add().addFilepattern("file2").call();
  718. // second commit applies config value
  719. String expectedConfigSigningKey = "config-" + System.nanoTime();
  720. StoredConfig config = git.getRepository().getConfig();
  721. config.setString("user", null, "signingKey",
  722. expectedConfigSigningKey);
  723. config.save();
  724. git.commit().setCommitter(committer).setSign(Boolean.TRUE)
  725. .setMessage("initial commit")
  726. .call();
  727. assertEquals(expectedConfigSigningKey, signingKey[0]);
  728. assertEquals(2, callCount.get());
  729. assertSame(committer, signingCommitters[0]);
  730. writeTrashFile("file3", "file3");
  731. git.add().addFilepattern("file3").call();
  732. // now use specific on api
  733. String expectedSigningKey = "my-" + System.nanoTime();
  734. git.commit().setCommitter(committer).setSign(Boolean.TRUE)
  735. .setSigningKey(expectedSigningKey)
  736. .setMessage("initial commit").call();
  737. assertEquals(expectedSigningKey, signingKey[0]);
  738. assertEquals(3, callCount.get());
  739. assertSame(committer, signingCommitters[0]);
  740. }
  741. }
  742. @Test
  743. public void callSignerOnlyWhenSigning() throws Exception {
  744. try (Git git = new Git(db)) {
  745. writeTrashFile("file1", "file1");
  746. git.add().addFilepattern("file1").call();
  747. AtomicInteger callCount = new AtomicInteger();
  748. GpgSigner.setDefault(new GpgSigner() {
  749. @Override
  750. public void sign(CommitBuilder commit, String gpgSigningKey,
  751. PersonIdent signingCommitter, CredentialsProvider credentialsProvider) {
  752. callCount.incrementAndGet();
  753. }
  754. @Override
  755. public boolean canLocateSigningKey(String gpgSigningKey,
  756. PersonIdent signingCommitter,
  757. CredentialsProvider credentialsProvider)
  758. throws CanceledException {
  759. return false;
  760. }
  761. });
  762. // first call should use config, which is expected to be null at
  763. // this time
  764. git.commit().setMessage("initial commit").call();
  765. assertEquals(0, callCount.get());
  766. writeTrashFile("file2", "file2");
  767. git.add().addFilepattern("file2").call();
  768. // now force signing
  769. git.commit().setSign(Boolean.TRUE).setMessage("commit").call();
  770. assertEquals(1, callCount.get());
  771. writeTrashFile("file3", "file3");
  772. git.add().addFilepattern("file3").call();
  773. // now rely on config
  774. StoredConfig config = git.getRepository().getConfig();
  775. config.setBoolean("commit", null, "gpgSign", true);
  776. config.save();
  777. git.commit().setMessage("commit").call();
  778. assertEquals(2, callCount.get());
  779. writeTrashFile("file4", "file4");
  780. git.add().addFilepattern("file4").call();
  781. // now force "no-sign" (even though config is true)
  782. git.commit().setSign(Boolean.FALSE).setMessage("commit").call();
  783. assertEquals(2, callCount.get());
  784. }
  785. }
  786. }