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.

ResetCommandTest.java 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670
  1. /*
  2. * Copyright (C) 2011-2018, Chris Aniszczyk <caniszczyk@gmail.com>
  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 java.time.Instant.EPOCH;
  45. import static org.eclipse.jgit.api.ResetCommand.ResetType.HARD;
  46. import static org.junit.Assert.assertEquals;
  47. import static org.junit.Assert.assertFalse;
  48. import static org.junit.Assert.assertNotNull;
  49. import static org.junit.Assert.assertNull;
  50. import static org.junit.Assert.assertTrue;
  51. import static org.junit.Assert.fail;
  52. import java.io.File;
  53. import java.io.IOException;
  54. import java.nio.file.Files;
  55. import java.nio.file.attribute.FileTime;
  56. import java.time.Instant;
  57. import org.eclipse.jgit.api.ResetCommand.ResetType;
  58. import org.eclipse.jgit.api.errors.GitAPIException;
  59. import org.eclipse.jgit.api.errors.JGitInternalException;
  60. import org.eclipse.jgit.dircache.DirCache;
  61. import org.eclipse.jgit.dircache.DirCacheBuilder;
  62. import org.eclipse.jgit.dircache.DirCacheEntry;
  63. import org.eclipse.jgit.errors.AmbiguousObjectException;
  64. import org.eclipse.jgit.junit.RepositoryTestCase;
  65. import org.eclipse.jgit.lib.Constants;
  66. import org.eclipse.jgit.lib.FileMode;
  67. import org.eclipse.jgit.lib.ObjectId;
  68. import org.eclipse.jgit.lib.Ref;
  69. import org.eclipse.jgit.revwalk.RevCommit;
  70. import org.eclipse.jgit.revwalk.RevWalk;
  71. import org.eclipse.jgit.treewalk.TreeWalk;
  72. import org.eclipse.jgit.util.FileUtils;
  73. import org.junit.Assert;
  74. import org.junit.Test;
  75. public class ResetCommandTest extends RepositoryTestCase {
  76. private Git git;
  77. private RevCommit initialCommit;
  78. private RevCommit secondCommit;
  79. private File indexFile;
  80. private File indexNestedFile;
  81. private File untrackedFile;
  82. private DirCacheEntry prestage;
  83. public void setupRepository() throws IOException, JGitInternalException,
  84. GitAPIException {
  85. // create initial commit
  86. git = new Git(db);
  87. initialCommit = git.commit().setMessage("initial commit").call();
  88. // create file
  89. indexFile = writeTrashFile("a.txt", "content");
  90. // create nested file
  91. indexNestedFile = writeTrashFile("dir/b.txt", "content");
  92. // add files and commit them
  93. git.add().addFilepattern("a.txt").addFilepattern("dir/b.txt").call();
  94. secondCommit = git.commit().setMessage("adding a.txt and dir/b.txt").call();
  95. prestage = DirCache.read(db.getIndexFile(), db.getFS()).getEntry(indexFile.getName());
  96. // modify files and add to index
  97. writeTrashFile("a.txt", "new content");
  98. writeTrashFile("dir/b.txt", "new content");
  99. git.add().addFilepattern("a.txt").addFilepattern("dir/b.txt").call();
  100. // create a file not added to the index
  101. untrackedFile = writeTrashFile("notAddedToIndex.txt", "content");
  102. }
  103. @Test
  104. public void testHardReset() throws JGitInternalException,
  105. AmbiguousObjectException, IOException, GitAPIException {
  106. setupRepository();
  107. ObjectId prevHead = db.resolve(Constants.HEAD);
  108. ResetCommand reset = git.reset();
  109. assertSameAsHead(reset.setMode(ResetType.HARD)
  110. .setRef(initialCommit.getName()).call());
  111. assertFalse("reflog should be enabled", reset.isReflogDisabled());
  112. // check if HEAD points to initial commit now
  113. ObjectId head = db.resolve(Constants.HEAD);
  114. assertEquals(initialCommit, head);
  115. // check if files were removed
  116. assertFalse(indexFile.exists());
  117. assertFalse(indexNestedFile.exists());
  118. assertTrue(untrackedFile.exists());
  119. // fileInIndex must no longer be in HEAD and in the index
  120. String fileInIndexPath = indexFile.getAbsolutePath();
  121. assertFalse(inHead(fileInIndexPath));
  122. assertFalse(inIndex(indexFile.getName()));
  123. assertReflog(prevHead, head);
  124. assertEquals(prevHead, db.readOrigHead());
  125. }
  126. @Test
  127. public void testHardResetReflogDisabled() throws Exception {
  128. setupRepository();
  129. ObjectId prevHead = db.resolve(Constants.HEAD);
  130. ResetCommand reset = git.reset();
  131. assertSameAsHead(reset.setMode(ResetType.HARD)
  132. .setRef(initialCommit.getName()).disableRefLog(true).call());
  133. assertTrue("reflog should be disabled", reset.isReflogDisabled());
  134. // check if HEAD points to initial commit now
  135. ObjectId head = db.resolve(Constants.HEAD);
  136. assertEquals(initialCommit, head);
  137. // check if files were removed
  138. assertFalse(indexFile.exists());
  139. assertFalse(indexNestedFile.exists());
  140. assertTrue(untrackedFile.exists());
  141. // fileInIndex must no longer be in HEAD and in the index
  142. String fileInIndexPath = indexFile.getAbsolutePath();
  143. assertFalse(inHead(fileInIndexPath));
  144. assertFalse(inIndex(indexFile.getName()));
  145. assertReflogDisabled(head);
  146. assertEquals(prevHead, db.readOrigHead());
  147. }
  148. @Test
  149. public void testHardResetWithConflicts_OverwriteUntrackedFile() throws Exception {
  150. setupRepository();
  151. git.rm().setCached(true).addFilepattern("a.txt").call();
  152. assertTrue(new File(db.getWorkTree(), "a.txt").exists());
  153. git.reset().setMode(ResetType.HARD).setRef(Constants.HEAD).call();
  154. assertTrue(new File(db.getWorkTree(), "a.txt").exists());
  155. assertEquals("content", read(new File(db.getWorkTree(), "a.txt")));
  156. }
  157. @Test
  158. public void testHardResetWithConflicts_DeleteFileFolderConflict() throws Exception {
  159. setupRepository();
  160. writeTrashFile("dir-or-file/c.txt", "content");
  161. git.add().addFilepattern("dir-or-file/c.txt").call();
  162. FileUtils.delete(new File(db.getWorkTree(), "dir-or-file"), FileUtils.RECURSIVE);
  163. writeTrashFile("dir-or-file", "content");
  164. git.reset().setMode(ResetType.HARD).setRef(Constants.HEAD).call();
  165. assertFalse(new File(db.getWorkTree(), "dir-or-file").exists());
  166. }
  167. @Test
  168. public void testHardResetWithConflicts_CreateFolder_UnstagedChanges() throws Exception {
  169. setupRepository();
  170. writeTrashFile("dir-or-file/c.txt", "content");
  171. git.add().addFilepattern("dir-or-file/c.txt").call();
  172. git.commit().setMessage("adding dir-or-file/c.txt").call();
  173. FileUtils.delete(new File(db.getWorkTree(), "dir-or-file"), FileUtils.RECURSIVE);
  174. writeTrashFile("dir-or-file", "content");
  175. // bug 479266: cannot create folder "dir-or-file"
  176. git.reset().setMode(ResetType.HARD).setRef(Constants.HEAD).call();
  177. assertTrue(new File(db.getWorkTree(), "dir-or-file/c.txt").exists());
  178. }
  179. @Test
  180. public void testHardResetWithConflicts_DeleteFolder_UnstagedChanges() throws Exception {
  181. setupRepository();
  182. ObjectId prevHead = db.resolve(Constants.HEAD);
  183. writeTrashFile("dir-or-file/c.txt", "content");
  184. git.add().addFilepattern("dir-or-file/c.txt").call();
  185. git.commit().setMessage("adding dir-or-file/c.txt").call();
  186. writeTrashFile("dir-or-file-2/d.txt", "content");
  187. git.add().addFilepattern("dir-or-file-2/d.txt").call();
  188. FileUtils.delete(new File(db.getWorkTree(), "dir-or-file-2"), FileUtils.RECURSIVE);
  189. writeTrashFile("dir-or-file-2", "content");
  190. // bug 479266: cannot delete folder "dir-or-file"
  191. git.reset().setMode(ResetType.HARD).setRef(prevHead.getName()).call();
  192. assertFalse(new File(db.getWorkTree(), "dir-or-file").exists());
  193. assertFalse(new File(db.getWorkTree(), "dir-or-file-2").exists());
  194. }
  195. @Test
  196. public void testResetToNonexistingHEAD() throws JGitInternalException,
  197. AmbiguousObjectException, IOException, GitAPIException {
  198. // create a file in the working tree of a fresh repo
  199. git = new Git(db);
  200. writeTrashFile("f", "content");
  201. try {
  202. git.reset().setRef(Constants.HEAD).call();
  203. fail("Expected JGitInternalException didn't occur");
  204. } catch (JGitInternalException e) {
  205. // got the expected exception
  206. }
  207. }
  208. @Test
  209. public void testSoftReset() throws JGitInternalException,
  210. AmbiguousObjectException, IOException, GitAPIException {
  211. setupRepository();
  212. ObjectId prevHead = db.resolve(Constants.HEAD);
  213. assertSameAsHead(git.reset().setMode(ResetType.SOFT)
  214. .setRef(initialCommit.getName()).call());
  215. // check if HEAD points to initial commit now
  216. ObjectId head = db.resolve(Constants.HEAD);
  217. assertEquals(initialCommit, head);
  218. // check if files still exist
  219. assertTrue(untrackedFile.exists());
  220. assertTrue(indexFile.exists());
  221. // fileInIndex must no longer be in HEAD but has to be in the index
  222. String fileInIndexPath = indexFile.getAbsolutePath();
  223. assertFalse(inHead(fileInIndexPath));
  224. assertTrue(inIndex(indexFile.getName()));
  225. assertReflog(prevHead, head);
  226. assertEquals(prevHead, db.readOrigHead());
  227. }
  228. @Test
  229. public void testMixedReset() throws JGitInternalException,
  230. AmbiguousObjectException, IOException, GitAPIException {
  231. setupRepository();
  232. ObjectId prevHead = db.resolve(Constants.HEAD);
  233. assertSameAsHead(git.reset().setMode(ResetType.MIXED)
  234. .setRef(initialCommit.getName()).call());
  235. // check if HEAD points to initial commit now
  236. ObjectId head = db.resolve(Constants.HEAD);
  237. assertEquals(initialCommit, head);
  238. // check if files still exist
  239. assertTrue(untrackedFile.exists());
  240. assertTrue(indexFile.exists());
  241. // fileInIndex must no longer be in HEAD and in the index
  242. String fileInIndexPath = indexFile.getAbsolutePath();
  243. assertFalse(inHead(fileInIndexPath));
  244. assertFalse(inIndex(indexFile.getName()));
  245. assertReflog(prevHead, head);
  246. assertEquals(prevHead, db.readOrigHead());
  247. }
  248. @Test
  249. public void testMixedResetRetainsSizeAndModifiedTime() throws Exception {
  250. git = new Git(db);
  251. Files.setLastModifiedTime(writeTrashFile("a.txt", "a").toPath(),
  252. FileTime.from(Instant.now().minusSeconds(60)));
  253. assertNotNull(git.add().addFilepattern("a.txt").call());
  254. assertNotNull(git.commit().setMessage("a commit").call());
  255. Files.setLastModifiedTime(writeTrashFile("b.txt", "b").toPath(),
  256. FileTime.from(Instant.now().minusSeconds(60)));
  257. assertNotNull(git.add().addFilepattern("b.txt").call());
  258. RevCommit commit2 = git.commit().setMessage("b commit").call();
  259. assertNotNull(commit2);
  260. DirCache cache = db.readDirCache();
  261. DirCacheEntry aEntry = cache.getEntry("a.txt");
  262. assertNotNull(aEntry);
  263. assertTrue(aEntry.getLength() > 0);
  264. assertTrue(aEntry.getLastModifiedInstant().compareTo(EPOCH) > 0);
  265. DirCacheEntry bEntry = cache.getEntry("b.txt");
  266. assertNotNull(bEntry);
  267. assertTrue(bEntry.getLength() > 0);
  268. assertTrue(bEntry.getLastModifiedInstant().compareTo(EPOCH) > 0);
  269. assertSameAsHead(git.reset().setMode(ResetType.MIXED)
  270. .setRef(commit2.getName()).call());
  271. cache = db.readDirCache();
  272. DirCacheEntry mixedAEntry = cache.getEntry("a.txt");
  273. assertNotNull(mixedAEntry);
  274. assertEquals(aEntry.getLastModifiedInstant(),
  275. mixedAEntry.getLastModifiedInstant());
  276. assertEquals(aEntry.getLastModifiedInstant(),
  277. mixedAEntry.getLastModifiedInstant());
  278. DirCacheEntry mixedBEntry = cache.getEntry("b.txt");
  279. assertNotNull(mixedBEntry);
  280. assertEquals(bEntry.getLastModifiedInstant(),
  281. mixedBEntry.getLastModifiedInstant());
  282. assertEquals(bEntry.getLastModifiedInstant(),
  283. mixedBEntry.getLastModifiedInstant());
  284. }
  285. @Test
  286. public void testMixedResetWithUnmerged() throws Exception {
  287. git = new Git(db);
  288. String file = "a.txt";
  289. writeTrashFile(file, "data");
  290. String file2 = "b.txt";
  291. writeTrashFile(file2, "data");
  292. git.add().addFilepattern(file).addFilepattern(file2).call();
  293. git.commit().setMessage("commit").call();
  294. DirCache index = db.lockDirCache();
  295. DirCacheBuilder builder = index.builder();
  296. builder.add(createEntry(file, FileMode.REGULAR_FILE, 1, ""));
  297. builder.add(createEntry(file, FileMode.REGULAR_FILE, 2, ""));
  298. builder.add(createEntry(file, FileMode.REGULAR_FILE, 3, ""));
  299. assertTrue(builder.commit());
  300. assertEquals("[a.txt, mode:100644, stage:1]"
  301. + "[a.txt, mode:100644, stage:2]"
  302. + "[a.txt, mode:100644, stage:3]",
  303. indexState(0));
  304. assertSameAsHead(git.reset().setMode(ResetType.MIXED).call());
  305. assertEquals("[a.txt, mode:100644]" + "[b.txt, mode:100644]",
  306. indexState(0));
  307. }
  308. @Test
  309. public void testPathsReset() throws Exception {
  310. setupRepository();
  311. DirCacheEntry preReset = DirCache.read(db.getIndexFile(), db.getFS())
  312. .getEntry(indexFile.getName());
  313. assertNotNull(preReset);
  314. git.add().addFilepattern(untrackedFile.getName()).call();
  315. // 'a.txt' has already been modified in setupRepository
  316. // 'notAddedToIndex.txt' has been added to repository
  317. assertSameAsHead(git.reset().addPath(indexFile.getName())
  318. .addPath(untrackedFile.getName()).call());
  319. DirCacheEntry postReset = DirCache.read(db.getIndexFile(), db.getFS())
  320. .getEntry(indexFile.getName());
  321. assertNotNull(postReset);
  322. Assert.assertNotSame(preReset.getObjectId(), postReset.getObjectId());
  323. Assert.assertEquals(prestage.getObjectId(), postReset.getObjectId());
  324. // check that HEAD hasn't moved
  325. ObjectId head = db.resolve(Constants.HEAD);
  326. assertEquals(secondCommit, head);
  327. // check if files still exist
  328. assertTrue(untrackedFile.exists());
  329. assertTrue(indexFile.exists());
  330. assertTrue(inHead(indexFile.getName()));
  331. assertTrue(inIndex(indexFile.getName()));
  332. assertFalse(inIndex(untrackedFile.getName()));
  333. }
  334. @Test
  335. public void testPathsResetOnDirs() throws Exception {
  336. setupRepository();
  337. DirCacheEntry preReset = DirCache.read(db.getIndexFile(), db.getFS())
  338. .getEntry("dir/b.txt");
  339. assertNotNull(preReset);
  340. git.add().addFilepattern(untrackedFile.getName()).call();
  341. // 'dir/b.txt' has already been modified in setupRepository
  342. assertSameAsHead(git.reset().addPath("dir").call());
  343. DirCacheEntry postReset = DirCache.read(db.getIndexFile(), db.getFS())
  344. .getEntry("dir/b.txt");
  345. assertNotNull(postReset);
  346. Assert.assertNotSame(preReset.getObjectId(), postReset.getObjectId());
  347. // check that HEAD hasn't moved
  348. ObjectId head = db.resolve(Constants.HEAD);
  349. assertEquals(secondCommit, head);
  350. // check if files still exist
  351. assertTrue(untrackedFile.exists());
  352. assertTrue(inHead("dir/b.txt"));
  353. assertTrue(inIndex("dir/b.txt"));
  354. }
  355. @Test
  356. public void testPathsResetWithRef() throws Exception {
  357. setupRepository();
  358. DirCacheEntry preReset = DirCache.read(db.getIndexFile(), db.getFS())
  359. .getEntry(indexFile.getName());
  360. assertNotNull(preReset);
  361. git.add().addFilepattern(untrackedFile.getName()).call();
  362. // 'a.txt' has already been modified in setupRepository
  363. // 'notAddedToIndex.txt' has been added to repository
  364. // reset to the inital commit
  365. assertSameAsHead(git.reset().setRef(initialCommit.getName())
  366. .addPath(indexFile.getName()).addPath(untrackedFile.getName())
  367. .call());
  368. // check that HEAD hasn't moved
  369. ObjectId head = db.resolve(Constants.HEAD);
  370. assertEquals(secondCommit, head);
  371. // check if files still exist
  372. assertTrue(untrackedFile.exists());
  373. assertTrue(indexFile.exists());
  374. assertTrue(inHead(indexFile.getName()));
  375. assertFalse(inIndex(indexFile.getName()));
  376. assertFalse(inIndex(untrackedFile.getName()));
  377. }
  378. @Test
  379. public void testPathsResetWithUnmerged() throws Exception {
  380. setupRepository();
  381. String file = "a.txt";
  382. writeTrashFile(file, "data");
  383. git.add().addFilepattern(file).call();
  384. git.commit().setMessage("commit").call();
  385. DirCache index = db.lockDirCache();
  386. DirCacheBuilder builder = index.builder();
  387. builder.add(createEntry(file, FileMode.REGULAR_FILE, 1, ""));
  388. builder.add(createEntry(file, FileMode.REGULAR_FILE, 2, ""));
  389. builder.add(createEntry(file, FileMode.REGULAR_FILE, 3, ""));
  390. builder.add(createEntry("b.txt", FileMode.REGULAR_FILE));
  391. assertTrue(builder.commit());
  392. assertEquals("[a.txt, mode:100644, stage:1]"
  393. + "[a.txt, mode:100644, stage:2]"
  394. + "[a.txt, mode:100644, stage:3]"
  395. + "[b.txt, mode:100644]",
  396. indexState(0));
  397. assertSameAsHead(git.reset().addPath(file).call());
  398. assertEquals("[a.txt, mode:100644]" + "[b.txt, mode:100644]",
  399. indexState(0));
  400. }
  401. @Test
  402. public void testPathsResetOnUnbornBranch() throws Exception {
  403. git = new Git(db);
  404. writeTrashFile("a.txt", "content");
  405. git.add().addFilepattern("a.txt").call();
  406. // Should assume an empty tree, like in C Git 1.8.2
  407. assertSameAsHead(git.reset().addPath("a.txt").call());
  408. DirCache cache = db.readDirCache();
  409. DirCacheEntry aEntry = cache.getEntry("a.txt");
  410. assertNull(aEntry);
  411. }
  412. @Test(expected = JGitInternalException.class)
  413. public void testPathsResetToNonexistingRef() throws Exception {
  414. git = new Git(db);
  415. writeTrashFile("a.txt", "content");
  416. git.add().addFilepattern("a.txt").call();
  417. assertSameAsHead(
  418. git.reset().setRef("doesnotexist").addPath("a.txt").call());
  419. }
  420. @Test
  421. public void testResetDefaultMode() throws Exception {
  422. git = new Git(db);
  423. writeTrashFile("a.txt", "content");
  424. git.add().addFilepattern("a.txt").call();
  425. writeTrashFile("a.txt", "modified");
  426. // should use default mode MIXED
  427. assertSameAsHead(git.reset().call());
  428. DirCache cache = db.readDirCache();
  429. DirCacheEntry aEntry = cache.getEntry("a.txt");
  430. assertNull(aEntry);
  431. assertEquals("modified", read("a.txt"));
  432. }
  433. @Test
  434. public void testHardResetOnTag() throws Exception {
  435. setupRepository();
  436. String tagName = "initialtag";
  437. git.tag().setName(tagName).setObjectId(secondCommit)
  438. .setMessage("message").call();
  439. DirCacheEntry preReset = DirCache.read(db.getIndexFile(), db.getFS())
  440. .getEntry(indexFile.getName());
  441. assertNotNull(preReset);
  442. git.add().addFilepattern(untrackedFile.getName()).call();
  443. assertSameAsHead(git.reset().setRef(tagName).setMode(HARD).call());
  444. ObjectId head = db.resolve(Constants.HEAD);
  445. assertEquals(secondCommit, head);
  446. }
  447. @Test
  448. public void testHardResetAfterSquashMerge() throws Exception {
  449. git = new Git(db);
  450. writeTrashFile("file1", "file1");
  451. git.add().addFilepattern("file1").call();
  452. RevCommit first = git.commit().setMessage("initial commit").call();
  453. assertTrue(new File(db.getWorkTree(), "file1").exists());
  454. createBranch(first, "refs/heads/branch1");
  455. checkoutBranch("refs/heads/branch1");
  456. writeTrashFile("file2", "file2");
  457. git.add().addFilepattern("file2").call();
  458. git.commit().setMessage("second commit").call();
  459. assertTrue(new File(db.getWorkTree(), "file2").exists());
  460. checkoutBranch("refs/heads/master");
  461. MergeResult result = git.merge()
  462. .include(db.exactRef("refs/heads/branch1"))
  463. .setSquash(true)
  464. .call();
  465. assertEquals(MergeResult.MergeStatus.FAST_FORWARD_SQUASHED,
  466. result.getMergeStatus());
  467. assertNotNull(db.readSquashCommitMsg());
  468. assertSameAsHead(git.reset().setMode(ResetType.HARD)
  469. .setRef(first.getName()).call());
  470. assertNull(db.readSquashCommitMsg());
  471. }
  472. @Test
  473. public void testHardResetOnUnbornBranch() throws Exception {
  474. git = new Git(db);
  475. File fileA = writeTrashFile("a.txt", "content");
  476. git.add().addFilepattern("a.txt").call();
  477. // Should assume an empty tree, like in C Git 1.8.2
  478. assertSameAsHead(git.reset().setMode(ResetType.HARD).call());
  479. DirCache cache = db.readDirCache();
  480. DirCacheEntry aEntry = cache.getEntry("a.txt");
  481. assertNull(aEntry);
  482. assertFalse(fileA.exists());
  483. assertNull(db.resolve(Constants.HEAD));
  484. }
  485. private void assertReflog(ObjectId prevHead, ObjectId head)
  486. throws IOException {
  487. // Check the reflog for HEAD
  488. String actualHeadMessage = db.getReflogReader(Constants.HEAD)
  489. .getLastEntry().getComment();
  490. String expectedHeadMessage = head.getName() + ": updating HEAD";
  491. assertEquals(expectedHeadMessage, actualHeadMessage);
  492. assertEquals(head.getName(), db.getReflogReader(Constants.HEAD)
  493. .getLastEntry().getNewId().getName());
  494. assertEquals(prevHead.getName(), db.getReflogReader(Constants.HEAD)
  495. .getLastEntry().getOldId().getName());
  496. // The reflog for master contains the same as the one for HEAD
  497. String actualMasterMessage = db.getReflogReader("refs/heads/master")
  498. .getLastEntry().getComment();
  499. String expectedMasterMessage = head.getName() + ": updating HEAD"; // yes!
  500. assertEquals(expectedMasterMessage, actualMasterMessage);
  501. assertEquals(head.getName(), db.getReflogReader(Constants.HEAD)
  502. .getLastEntry().getNewId().getName());
  503. assertEquals(prevHead.getName(), db
  504. .getReflogReader("refs/heads/master").getLastEntry().getOldId()
  505. .getName());
  506. }
  507. private void assertReflogDisabled(ObjectId head)
  508. throws IOException {
  509. // Check the reflog for HEAD
  510. String actualHeadMessage = db.getReflogReader(Constants.HEAD)
  511. .getLastEntry().getComment();
  512. String expectedHeadMessage = "commit: adding a.txt and dir/b.txt";
  513. assertEquals(expectedHeadMessage, actualHeadMessage);
  514. assertEquals(head.getName(), db.getReflogReader(Constants.HEAD)
  515. .getLastEntry().getOldId().getName());
  516. // The reflog for master contains the same as the one for HEAD
  517. String actualMasterMessage = db.getReflogReader("refs/heads/master")
  518. .getLastEntry().getComment();
  519. String expectedMasterMessage = "commit: adding a.txt and dir/b.txt";
  520. assertEquals(expectedMasterMessage, actualMasterMessage);
  521. assertEquals(head.getName(), db.getReflogReader(Constants.HEAD)
  522. .getLastEntry().getOldId().getName());
  523. }
  524. /**
  525. * Checks if a file with the given path exists in the HEAD tree
  526. *
  527. * @param path
  528. * @return true if the file exists
  529. * @throws IOException
  530. */
  531. private boolean inHead(String path) throws IOException {
  532. ObjectId headId = db.resolve(Constants.HEAD);
  533. try (RevWalk rw = new RevWalk(db);
  534. TreeWalk tw = TreeWalk.forPath(db, path,
  535. rw.parseTree(headId))) {
  536. return tw != null;
  537. }
  538. }
  539. /**
  540. * Checks if a file with the given path exists in the index
  541. *
  542. * @param path
  543. * @return true if the file exists
  544. * @throws IOException
  545. */
  546. private boolean inIndex(String path) throws IOException {
  547. DirCache dc = DirCache.read(db.getIndexFile(), db.getFS());
  548. return dc.getEntry(path) != null;
  549. }
  550. /**
  551. * Asserts that a certain ref is similar to repos HEAD.
  552. * @param ref
  553. * @throws IOException
  554. */
  555. private void assertSameAsHead(Ref ref) throws IOException {
  556. Ref headRef = db.exactRef(Constants.HEAD);
  557. assertEquals(headRef.getName(), ref.getName());
  558. assertEquals(headRef.getObjectId(), ref.getObjectId());
  559. }
  560. }