Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

StashCreateCommandTest.java 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. /*
  2. * Copyright (C) 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.assertFalse;
  46. import static org.junit.Assert.assertNotNull;
  47. import static org.junit.Assert.assertNull;
  48. import static org.junit.Assert.assertTrue;
  49. import java.io.File;
  50. import java.io.IOException;
  51. import java.util.List;
  52. import org.eclipse.jgit.api.errors.UnmergedPathsException;
  53. import org.eclipse.jgit.diff.DiffEntry;
  54. import org.eclipse.jgit.internal.storage.file.ReflogEntry;
  55. import org.eclipse.jgit.internal.storage.file.ReflogReader;
  56. import org.eclipse.jgit.junit.RepositoryTestCase;
  57. import org.eclipse.jgit.lib.Constants;
  58. import org.eclipse.jgit.lib.ObjectId;
  59. import org.eclipse.jgit.lib.PersonIdent;
  60. import org.eclipse.jgit.lib.Ref;
  61. import org.eclipse.jgit.revwalk.RevCommit;
  62. import org.eclipse.jgit.revwalk.RevWalk;
  63. import org.eclipse.jgit.treewalk.TreeWalk;
  64. import org.eclipse.jgit.treewalk.filter.TreeFilter;
  65. import org.eclipse.jgit.util.FileUtils;
  66. import org.junit.Before;
  67. import org.junit.Test;
  68. /**
  69. * Unit tests of {@link StashCreateCommand}
  70. */
  71. public class StashCreateCommandTest extends RepositoryTestCase {
  72. private RevCommit head;
  73. private Git git;
  74. private File committedFile;
  75. @Before
  76. public void setUp() throws Exception {
  77. super.setUp();
  78. git = Git.wrap(db);
  79. committedFile = writeTrashFile("file.txt", "content");
  80. git.add().addFilepattern("file.txt").call();
  81. head = git.commit().setMessage("add file").call();
  82. assertNotNull(head);
  83. }
  84. /**
  85. * Core validation to be performed on all stashed commits
  86. *
  87. * @param commit
  88. * @throws IOException
  89. */
  90. private void validateStashedCommit(final RevCommit commit)
  91. throws IOException {
  92. assertNotNull(commit);
  93. Ref stashRef = db.getRef(Constants.R_STASH);
  94. assertNotNull(stashRef);
  95. assertEquals(commit, stashRef.getObjectId());
  96. assertNotNull(commit.getAuthorIdent());
  97. assertEquals(commit.getAuthorIdent(), commit.getCommitterIdent());
  98. assertEquals(2, commit.getParentCount());
  99. // Load parents
  100. RevWalk walk = new RevWalk(db);
  101. try {
  102. for (RevCommit parent : commit.getParents())
  103. walk.parseBody(parent);
  104. } finally {
  105. walk.release();
  106. }
  107. assertEquals(1, commit.getParent(1).getParentCount());
  108. assertEquals(head, commit.getParent(1).getParent(0));
  109. assertFalse("Head tree matches stashed commit tree", commit.getTree()
  110. .equals(head.getTree()));
  111. assertEquals(head, commit.getParent(0));
  112. assertFalse(commit.getFullMessage().equals(
  113. commit.getParent(1).getFullMessage()));
  114. }
  115. private TreeWalk createTreeWalk() {
  116. TreeWalk walk = new TreeWalk(db);
  117. walk.setRecursive(true);
  118. walk.setFilter(TreeFilter.ANY_DIFF);
  119. return walk;
  120. }
  121. private List<DiffEntry> diffWorkingAgainstHead(final RevCommit commit)
  122. throws IOException {
  123. TreeWalk walk = createTreeWalk();
  124. try {
  125. walk.addTree(commit.getParent(0).getTree());
  126. walk.addTree(commit.getTree());
  127. return DiffEntry.scan(walk);
  128. } finally {
  129. walk.release();
  130. }
  131. }
  132. private List<DiffEntry> diffIndexAgainstHead(final RevCommit commit)
  133. throws IOException {
  134. TreeWalk walk = createTreeWalk();
  135. try {
  136. walk.addTree(commit.getParent(0).getTree());
  137. walk.addTree(commit.getParent(1).getTree());
  138. return DiffEntry.scan(walk);
  139. } finally {
  140. walk.release();
  141. }
  142. }
  143. private List<DiffEntry> diffIndexAgainstWorking(final RevCommit commit)
  144. throws IOException {
  145. TreeWalk walk = createTreeWalk();
  146. try {
  147. walk.addTree(commit.getParent(1).getTree());
  148. walk.addTree(commit.getTree());
  149. return DiffEntry.scan(walk);
  150. } finally {
  151. walk.release();
  152. }
  153. }
  154. @Test
  155. public void noLocalChanges() throws Exception {
  156. assertNull(git.stashCreate().call());
  157. }
  158. @Test
  159. public void workingDirectoryDelete() throws Exception {
  160. deleteTrashFile("file.txt");
  161. RevCommit stashed = git.stashCreate().call();
  162. assertNotNull(stashed);
  163. assertEquals("content", read(committedFile));
  164. validateStashedCommit(stashed);
  165. assertEquals(head.getTree(), stashed.getParent(1).getTree());
  166. List<DiffEntry> diffs = diffWorkingAgainstHead(stashed);
  167. assertEquals(1, diffs.size());
  168. assertEquals(DiffEntry.ChangeType.DELETE, diffs.get(0).getChangeType());
  169. assertEquals("file.txt", diffs.get(0).getOldPath());
  170. }
  171. @Test
  172. public void indexAdd() throws Exception {
  173. File addedFile = writeTrashFile("file2.txt", "content2");
  174. git.add().addFilepattern("file2.txt").call();
  175. RevCommit stashed = Git.wrap(db).stashCreate().call();
  176. assertNotNull(stashed);
  177. assertFalse(addedFile.exists());
  178. validateStashedCommit(stashed);
  179. assertEquals(stashed.getTree(), stashed.getParent(1).getTree());
  180. List<DiffEntry> diffs = diffWorkingAgainstHead(stashed);
  181. assertEquals(1, diffs.size());
  182. assertEquals(DiffEntry.ChangeType.ADD, diffs.get(0).getChangeType());
  183. assertEquals("file2.txt", diffs.get(0).getNewPath());
  184. }
  185. @Test
  186. public void newFileInIndexThenModifiedInWorkTree() throws Exception {
  187. writeTrashFile("file", "content");
  188. git.add().addFilepattern("file").call();
  189. writeTrashFile("file", "content2");
  190. RevCommit stashedWorkTree = Git.wrap(db).stashCreate().call();
  191. validateStashedCommit(stashedWorkTree);
  192. RevWalk walk = new RevWalk(db);
  193. RevCommit stashedIndex = stashedWorkTree.getParent(1);
  194. walk.parseBody(stashedIndex);
  195. walk.parseBody(stashedIndex.getTree());
  196. walk.parseBody(stashedIndex.getParent(0));
  197. List<DiffEntry> workTreeStashAgainstWorkTree = diffWorkingAgainstHead(stashedWorkTree);
  198. assertEquals(1, workTreeStashAgainstWorkTree.size());
  199. List<DiffEntry> workIndexAgainstWorkTree = diffIndexAgainstHead(stashedWorkTree);
  200. assertEquals(1, workIndexAgainstWorkTree.size());
  201. List<DiffEntry> indexStashAgainstWorkTree = diffIndexAgainstWorking(stashedWorkTree);
  202. assertEquals(1, indexStashAgainstWorkTree.size());
  203. }
  204. @Test
  205. public void indexDelete() throws Exception {
  206. git.rm().addFilepattern("file.txt").call();
  207. RevCommit stashed = Git.wrap(db).stashCreate().call();
  208. assertNotNull(stashed);
  209. assertEquals("content", read(committedFile));
  210. validateStashedCommit(stashed);
  211. assertEquals(stashed.getTree(), stashed.getParent(1).getTree());
  212. List<DiffEntry> diffs = diffWorkingAgainstHead(stashed);
  213. assertEquals(1, diffs.size());
  214. assertEquals(DiffEntry.ChangeType.DELETE, diffs.get(0).getChangeType());
  215. assertEquals("file.txt", diffs.get(0).getOldPath());
  216. }
  217. @Test
  218. public void workingDirectoryModify() throws Exception {
  219. writeTrashFile("file.txt", "content2");
  220. RevCommit stashed = Git.wrap(db).stashCreate().call();
  221. assertNotNull(stashed);
  222. assertEquals("content", read(committedFile));
  223. validateStashedCommit(stashed);
  224. assertEquals(head.getTree(), stashed.getParent(1).getTree());
  225. List<DiffEntry> diffs = diffWorkingAgainstHead(stashed);
  226. assertEquals(1, diffs.size());
  227. assertEquals(DiffEntry.ChangeType.MODIFY, diffs.get(0).getChangeType());
  228. assertEquals("file.txt", diffs.get(0).getNewPath());
  229. }
  230. @Test
  231. public void workingDirectoryModifyInSubfolder() throws Exception {
  232. String path = "d1/d2/f.txt";
  233. File subfolderFile = writeTrashFile(path, "content");
  234. git.add().addFilepattern(path).call();
  235. head = git.commit().setMessage("add file").call();
  236. writeTrashFile(path, "content2");
  237. RevCommit stashed = Git.wrap(db).stashCreate().call();
  238. assertNotNull(stashed);
  239. assertEquals("content", read(subfolderFile));
  240. validateStashedCommit(stashed);
  241. assertEquals(head.getTree(), stashed.getParent(1).getTree());
  242. List<DiffEntry> diffs = diffWorkingAgainstHead(stashed);
  243. assertEquals(1, diffs.size());
  244. assertEquals(DiffEntry.ChangeType.MODIFY, diffs.get(0).getChangeType());
  245. assertEquals(path, diffs.get(0).getNewPath());
  246. }
  247. @Test
  248. public void workingDirectoryModifyIndexChanged() throws Exception {
  249. writeTrashFile("file.txt", "content2");
  250. git.add().addFilepattern("file.txt").call();
  251. writeTrashFile("file.txt", "content3");
  252. RevCommit stashed = Git.wrap(db).stashCreate().call();
  253. assertNotNull(stashed);
  254. assertEquals("content", read(committedFile));
  255. validateStashedCommit(stashed);
  256. assertFalse(stashed.getTree().equals(stashed.getParent(1).getTree()));
  257. List<DiffEntry> workingDiffs = diffWorkingAgainstHead(stashed);
  258. assertEquals(1, workingDiffs.size());
  259. assertEquals(DiffEntry.ChangeType.MODIFY, workingDiffs.get(0)
  260. .getChangeType());
  261. assertEquals("file.txt", workingDiffs.get(0).getNewPath());
  262. List<DiffEntry> indexDiffs = diffIndexAgainstHead(stashed);
  263. assertEquals(1, indexDiffs.size());
  264. assertEquals(DiffEntry.ChangeType.MODIFY, indexDiffs.get(0)
  265. .getChangeType());
  266. assertEquals("file.txt", indexDiffs.get(0).getNewPath());
  267. assertEquals(workingDiffs.get(0).getOldId(), indexDiffs.get(0)
  268. .getOldId());
  269. assertFalse(workingDiffs.get(0).getNewId()
  270. .equals(indexDiffs.get(0).getNewId()));
  271. }
  272. @Test
  273. public void workingDirectoryCleanIndexModify() throws Exception {
  274. writeTrashFile("file.txt", "content2");
  275. git.add().addFilepattern("file.txt").call();
  276. writeTrashFile("file.txt", "content");
  277. RevCommit stashed = Git.wrap(db).stashCreate().call();
  278. assertNotNull(stashed);
  279. assertEquals("content", read(committedFile));
  280. validateStashedCommit(stashed);
  281. assertEquals(stashed.getParent(1).getTree(), stashed.getTree());
  282. List<DiffEntry> workingDiffs = diffWorkingAgainstHead(stashed);
  283. assertEquals(1, workingDiffs.size());
  284. assertEquals(DiffEntry.ChangeType.MODIFY, workingDiffs.get(0)
  285. .getChangeType());
  286. assertEquals("file.txt", workingDiffs.get(0).getNewPath());
  287. List<DiffEntry> indexDiffs = diffIndexAgainstHead(stashed);
  288. assertEquals(1, indexDiffs.size());
  289. assertEquals(DiffEntry.ChangeType.MODIFY, indexDiffs.get(0)
  290. .getChangeType());
  291. assertEquals("file.txt", indexDiffs.get(0).getNewPath());
  292. assertEquals(workingDiffs.get(0).getOldId(), indexDiffs.get(0)
  293. .getOldId());
  294. assertTrue(workingDiffs.get(0).getNewId()
  295. .equals(indexDiffs.get(0).getNewId()));
  296. }
  297. @Test
  298. public void workingDirectoryDeleteIndexAdd() throws Exception {
  299. String path = "file2.txt";
  300. File added = writeTrashFile(path, "content2");
  301. assertTrue(added.exists());
  302. git.add().addFilepattern(path).call();
  303. FileUtils.delete(added);
  304. assertFalse(added.exists());
  305. RevCommit stashed = Git.wrap(db).stashCreate().call();
  306. assertNotNull(stashed);
  307. assertFalse(added.exists());
  308. validateStashedCommit(stashed);
  309. assertEquals(stashed.getParent(1).getTree(), stashed.getTree());
  310. List<DiffEntry> workingDiffs = diffWorkingAgainstHead(stashed);
  311. assertEquals(1, workingDiffs.size());
  312. assertEquals(DiffEntry.ChangeType.ADD, workingDiffs.get(0)
  313. .getChangeType());
  314. assertEquals(path, workingDiffs.get(0).getNewPath());
  315. List<DiffEntry> indexDiffs = diffIndexAgainstHead(stashed);
  316. assertEquals(1, indexDiffs.size());
  317. assertEquals(DiffEntry.ChangeType.ADD, indexDiffs.get(0)
  318. .getChangeType());
  319. assertEquals(path, indexDiffs.get(0).getNewPath());
  320. assertEquals(workingDiffs.get(0).getOldId(), indexDiffs.get(0)
  321. .getOldId());
  322. assertTrue(workingDiffs.get(0).getNewId()
  323. .equals(indexDiffs.get(0).getNewId()));
  324. }
  325. @Test
  326. public void workingDirectoryDeleteIndexEdit() throws Exception {
  327. File edited = writeTrashFile("file.txt", "content2");
  328. git.add().addFilepattern("file.txt").call();
  329. FileUtils.delete(edited);
  330. assertFalse(edited.exists());
  331. RevCommit stashed = Git.wrap(db).stashCreate().call();
  332. assertNotNull(stashed);
  333. assertEquals("content", read(committedFile));
  334. validateStashedCommit(stashed);
  335. assertFalse(stashed.getTree().equals(stashed.getParent(1).getTree()));
  336. List<DiffEntry> workingDiffs = diffWorkingAgainstHead(stashed);
  337. assertEquals(1, workingDiffs.size());
  338. assertEquals(DiffEntry.ChangeType.DELETE, workingDiffs.get(0)
  339. .getChangeType());
  340. assertEquals("file.txt", workingDiffs.get(0).getOldPath());
  341. List<DiffEntry> indexDiffs = diffIndexAgainstHead(stashed);
  342. assertEquals(1, indexDiffs.size());
  343. assertEquals(DiffEntry.ChangeType.MODIFY, indexDiffs.get(0)
  344. .getChangeType());
  345. assertEquals("file.txt", indexDiffs.get(0).getNewPath());
  346. assertEquals(workingDiffs.get(0).getOldId(), indexDiffs.get(0)
  347. .getOldId());
  348. assertFalse(workingDiffs.get(0).getNewId()
  349. .equals(indexDiffs.get(0).getNewId()));
  350. }
  351. @Test
  352. public void multipleEdits() throws Exception {
  353. git.rm().addFilepattern("file.txt").call();
  354. File addedFile = writeTrashFile("file2.txt", "content2");
  355. git.add().addFilepattern("file2.txt").call();
  356. RevCommit stashed = Git.wrap(db).stashCreate().call();
  357. assertNotNull(stashed);
  358. assertFalse(addedFile.exists());
  359. validateStashedCommit(stashed);
  360. assertEquals(stashed.getTree(), stashed.getParent(1).getTree());
  361. List<DiffEntry> diffs = diffWorkingAgainstHead(stashed);
  362. assertEquals(2, diffs.size());
  363. assertEquals(DiffEntry.ChangeType.DELETE, diffs.get(0).getChangeType());
  364. assertEquals("file.txt", diffs.get(0).getOldPath());
  365. assertEquals(DiffEntry.ChangeType.ADD, diffs.get(1).getChangeType());
  366. assertEquals("file2.txt", diffs.get(1).getNewPath());
  367. }
  368. @Test
  369. public void refLogIncludesCommitMessage() throws Exception {
  370. PersonIdent who = new PersonIdent("user", "user@email.com");
  371. deleteTrashFile("file.txt");
  372. RevCommit stashed = git.stashCreate().setPerson(who).call();
  373. assertNotNull(stashed);
  374. assertEquals("content", read(committedFile));
  375. validateStashedCommit(stashed);
  376. ReflogReader reader = new ReflogReader(git.getRepository(),
  377. Constants.R_STASH);
  378. ReflogEntry entry = reader.getLastEntry();
  379. assertNotNull(entry);
  380. assertEquals(ObjectId.zeroId(), entry.getOldId());
  381. assertEquals(stashed, entry.getNewId());
  382. assertEquals(who, entry.getWho());
  383. assertEquals(stashed.getFullMessage(), entry.getComment());
  384. }
  385. @Test(expected = UnmergedPathsException.class)
  386. public void unmergedPathsShouldCauseException() throws Exception {
  387. commitFile("file.txt", "master", "base");
  388. RevCommit side = commitFile("file.txt", "side", "side");
  389. commitFile("file.txt", "master", "master");
  390. git.merge().include(side).call();
  391. git.stashCreate().call();
  392. }
  393. }