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.

AddCommandTest.java 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. /*
  2. * Copyright (C) 2010, Stefan Lay <stefan.lay@sap.com>
  3. * Copyright (C) 2010, Christian Halstrick <christian.halstrick@sap.com>
  4. * and other copyright owners as documented in the project's IP log.
  5. *
  6. * This program and the accompanying materials are made available
  7. * under the terms of the Eclipse Distribution License v1.0 which
  8. * accompanies this distribution, is reproduced below, and is
  9. * available at http://www.eclipse.org/org/documents/edl-v10.php
  10. *
  11. * All rights reserved.
  12. *
  13. * Redistribution and use in source and binary forms, with or
  14. * without modification, are permitted provided that the following
  15. * conditions are met:
  16. *
  17. * - Redistributions of source code must retain the above copyright
  18. * notice, this list of conditions and the following disclaimer.
  19. *
  20. * - Redistributions in binary form must reproduce the above
  21. * copyright notice, this list of conditions and the following
  22. * disclaimer in the documentation and/or other materials provided
  23. * with the distribution.
  24. *
  25. * - Neither the name of the Eclipse Foundation, Inc. nor the
  26. * names of its contributors may be used to endorse or promote
  27. * products derived from this software without specific prior
  28. * written permission.
  29. *
  30. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  31. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  32. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  33. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  34. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  35. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  36. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  37. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  38. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  39. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  40. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  41. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  42. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  43. */
  44. package org.eclipse.jgit.api;
  45. import java.io.File;
  46. import java.io.FileInputStream;
  47. import java.io.IOException;
  48. import java.io.PrintWriter;
  49. import org.eclipse.jgit.api.errors.NoFilepatternException;
  50. import org.eclipse.jgit.dircache.DirCache;
  51. import org.eclipse.jgit.dircache.DirCacheBuilder;
  52. import org.eclipse.jgit.dircache.DirCacheEntry;
  53. import org.eclipse.jgit.lib.Constants;
  54. import org.eclipse.jgit.lib.FileMode;
  55. import org.eclipse.jgit.lib.ObjectId;
  56. import org.eclipse.jgit.lib.ObjectInserter;
  57. import org.eclipse.jgit.lib.RepositoryTestCase;
  58. public class AddCommandTest extends RepositoryTestCase {
  59. public void testAddNothing() {
  60. Git git = new Git(db);
  61. try {
  62. git.add().call();
  63. fail("Expected IllegalArgumentException");
  64. } catch (NoFilepatternException e) {
  65. // expected
  66. }
  67. }
  68. public void testAddNonExistingSingleFile() throws NoFilepatternException {
  69. Git git = new Git(db);
  70. DirCache dc = git.add().addFilepattern("a.txt").call();
  71. assertEquals(0, dc.getEntryCount());
  72. }
  73. public void testAddExistingSingleFile() throws IOException, NoFilepatternException {
  74. File file = new File(db.getWorkTree(), "a.txt");
  75. file.createNewFile();
  76. PrintWriter writer = new PrintWriter(file);
  77. writer.print("content");
  78. writer.close();
  79. Git git = new Git(db);
  80. git.add().addFilepattern("a.txt").call();
  81. assertEquals(
  82. "[a.txt, mode:100644, content:content]",
  83. indexState(CONTENT));
  84. }
  85. public void testAddExistingSingleFileInSubDir() throws IOException, NoFilepatternException {
  86. new File(db.getWorkTree(), "sub").mkdir();
  87. File file = new File(db.getWorkTree(), "sub/a.txt");
  88. file.createNewFile();
  89. PrintWriter writer = new PrintWriter(file);
  90. writer.print("content");
  91. writer.close();
  92. Git git = new Git(db);
  93. git.add().addFilepattern("sub/a.txt").call();
  94. assertEquals(
  95. "[sub/a.txt, mode:100644, content:content]",
  96. indexState(CONTENT));
  97. }
  98. public void testAddExistingSingleFileTwice() throws IOException, NoFilepatternException {
  99. File file = new File(db.getWorkTree(), "a.txt");
  100. file.createNewFile();
  101. PrintWriter writer = new PrintWriter(file);
  102. writer.print("content");
  103. writer.close();
  104. Git git = new Git(db);
  105. DirCache dc = git.add().addFilepattern("a.txt").call();
  106. dc.getEntry(0).getObjectId();
  107. writer = new PrintWriter(file);
  108. writer.print("other content");
  109. writer.close();
  110. dc = git.add().addFilepattern("a.txt").call();
  111. assertEquals(
  112. "[a.txt, mode:100644, content:other content]",
  113. indexState(CONTENT));
  114. }
  115. public void testAddExistingSingleFileTwiceWithCommit() throws Exception {
  116. File file = new File(db.getWorkTree(), "a.txt");
  117. file.createNewFile();
  118. PrintWriter writer = new PrintWriter(file);
  119. writer.print("content");
  120. writer.close();
  121. Git git = new Git(db);
  122. DirCache dc = git.add().addFilepattern("a.txt").call();
  123. dc.getEntry(0).getObjectId();
  124. git.commit().setMessage("commit a.txt").call();
  125. writer = new PrintWriter(file);
  126. writer.print("other content");
  127. writer.close();
  128. dc = git.add().addFilepattern("a.txt").call();
  129. assertEquals(
  130. "[a.txt, mode:100644, content:other content]",
  131. indexState(CONTENT));
  132. }
  133. public void testAddRemovedFile() throws Exception {
  134. File file = new File(db.getWorkTree(), "a.txt");
  135. file.createNewFile();
  136. PrintWriter writer = new PrintWriter(file);
  137. writer.print("content");
  138. writer.close();
  139. Git git = new Git(db);
  140. DirCache dc = git.add().addFilepattern("a.txt").call();
  141. dc.getEntry(0).getObjectId();
  142. file.delete();
  143. // is supposed to do nothing
  144. dc = git.add().addFilepattern("a.txt").call();
  145. assertEquals(
  146. "[a.txt, mode:100644, content:content]",
  147. indexState(CONTENT));
  148. }
  149. public void testAddRemovedCommittedFile() throws Exception {
  150. File file = new File(db.getWorkTree(), "a.txt");
  151. file.createNewFile();
  152. PrintWriter writer = new PrintWriter(file);
  153. writer.print("content");
  154. writer.close();
  155. Git git = new Git(db);
  156. DirCache dc = git.add().addFilepattern("a.txt").call();
  157. git.commit().setMessage("commit a.txt").call();
  158. dc.getEntry(0).getObjectId();
  159. file.delete();
  160. // is supposed to do nothing
  161. dc = git.add().addFilepattern("a.txt").call();
  162. assertEquals(
  163. "[a.txt, mode:100644, content:content]",
  164. indexState(CONTENT));
  165. }
  166. public void testAddWithConflicts() throws Exception {
  167. // prepare conflict
  168. File file = new File(db.getWorkTree(), "a.txt");
  169. file.createNewFile();
  170. PrintWriter writer = new PrintWriter(file);
  171. writer.print("content");
  172. writer.close();
  173. File file2 = new File(db.getWorkTree(), "b.txt");
  174. file2.createNewFile();
  175. writer = new PrintWriter(file2);
  176. writer.print("content b");
  177. writer.close();
  178. ObjectInserter newObjectInserter = db.newObjectInserter();
  179. DirCache dc = db.lockDirCache();
  180. DirCacheBuilder builder = dc.builder();
  181. addEntryToBuilder("b.txt", file2, newObjectInserter, builder, 0);
  182. addEntryToBuilder("a.txt", file, newObjectInserter, builder, 1);
  183. writer = new PrintWriter(file);
  184. writer.print("other content");
  185. writer.close();
  186. addEntryToBuilder("a.txt", file, newObjectInserter, builder, 3);
  187. writer = new PrintWriter(file);
  188. writer.print("our content");
  189. writer.close();
  190. addEntryToBuilder("a.txt", file, newObjectInserter, builder, 2)
  191. .getObjectId();
  192. builder.commit();
  193. assertEquals(
  194. "[a.txt, mode:100644, stage:1, content:content]" +
  195. "[a.txt, mode:100644, stage:2, content:our content]" +
  196. "[a.txt, mode:100644, stage:3, content:other content]" +
  197. "[b.txt, mode:100644, content:content b]",
  198. indexState(CONTENT));
  199. // now the test begins
  200. Git git = new Git(db);
  201. dc = git.add().addFilepattern("a.txt").call();
  202. assertEquals(
  203. "[a.txt, mode:100644, content:our content]" +
  204. "[b.txt, mode:100644, content:content b]",
  205. indexState(CONTENT));
  206. }
  207. public void testAddTwoFiles() throws Exception {
  208. File file = new File(db.getWorkTree(), "a.txt");
  209. file.createNewFile();
  210. PrintWriter writer = new PrintWriter(file);
  211. writer.print("content");
  212. writer.close();
  213. File file2 = new File(db.getWorkTree(), "b.txt");
  214. file2.createNewFile();
  215. writer = new PrintWriter(file2);
  216. writer.print("content b");
  217. writer.close();
  218. Git git = new Git(db);
  219. git.add().addFilepattern("a.txt").addFilepattern("b.txt").call();
  220. assertEquals(
  221. "[a.txt, mode:100644, content:content]" +
  222. "[b.txt, mode:100644, content:content b]",
  223. indexState(CONTENT));
  224. }
  225. public void testAddFolder() throws Exception {
  226. new File(db.getWorkTree(), "sub").mkdir();
  227. File file = new File(db.getWorkTree(), "sub/a.txt");
  228. file.createNewFile();
  229. PrintWriter writer = new PrintWriter(file);
  230. writer.print("content");
  231. writer.close();
  232. File file2 = new File(db.getWorkTree(), "sub/b.txt");
  233. file2.createNewFile();
  234. writer = new PrintWriter(file2);
  235. writer.print("content b");
  236. writer.close();
  237. Git git = new Git(db);
  238. git.add().addFilepattern("sub").call();
  239. assertEquals(
  240. "[sub/a.txt, mode:100644, content:content]" +
  241. "[sub/b.txt, mode:100644, content:content b]",
  242. indexState(CONTENT));
  243. }
  244. public void testAddIgnoredFile() throws Exception {
  245. new File(db.getWorkTree(), "sub").mkdir();
  246. File file = new File(db.getWorkTree(), "sub/a.txt");
  247. file.createNewFile();
  248. PrintWriter writer = new PrintWriter(file);
  249. writer.print("content");
  250. writer.close();
  251. File ignoreFile = new File(db.getWorkTree(), ".gitignore");
  252. ignoreFile.createNewFile();
  253. writer = new PrintWriter(ignoreFile);
  254. writer.print("sub/b.txt");
  255. writer.close();
  256. File file2 = new File(db.getWorkTree(), "sub/b.txt");
  257. file2.createNewFile();
  258. writer = new PrintWriter(file2);
  259. writer.print("content b");
  260. writer.close();
  261. Git git = new Git(db);
  262. git.add().addFilepattern("sub").call();
  263. assertEquals(
  264. "[sub/a.txt, mode:100644, content:content]",
  265. indexState(CONTENT));
  266. }
  267. public void testAddWholeRepo() throws Exception {
  268. new File(db.getWorkTree(), "sub").mkdir();
  269. File file = new File(db.getWorkTree(), "sub/a.txt");
  270. file.createNewFile();
  271. PrintWriter writer = new PrintWriter(file);
  272. writer.print("content");
  273. writer.close();
  274. File file2 = new File(db.getWorkTree(), "sub/b.txt");
  275. file2.createNewFile();
  276. writer = new PrintWriter(file2);
  277. writer.print("content b");
  278. writer.close();
  279. Git git = new Git(db);
  280. git.add().addFilepattern(".").call();
  281. assertEquals(
  282. "[sub/a.txt, mode:100644, content:content]" +
  283. "[sub/b.txt, mode:100644, content:content b]",
  284. indexState(CONTENT));
  285. }
  286. // the same three cases as in testAddWithParameterUpdate
  287. // file a exists in workdir and in index -> added
  288. // file b exists not in workdir but in index -> unchanged
  289. // file c exists in workdir but not in index -> added
  290. public void testAddWithoutParameterUpdate() throws Exception {
  291. new File(db.getWorkTree(), "sub").mkdir();
  292. File file = new File(db.getWorkTree(), "sub/a.txt");
  293. file.createNewFile();
  294. PrintWriter writer = new PrintWriter(file);
  295. writer.print("content");
  296. writer.close();
  297. File file2 = new File(db.getWorkTree(), "sub/b.txt");
  298. file2.createNewFile();
  299. writer = new PrintWriter(file2);
  300. writer.print("content b");
  301. writer.close();
  302. Git git = new Git(db);
  303. git.add().addFilepattern("sub").call();
  304. assertEquals(
  305. "[sub/a.txt, mode:100644, content:content]" +
  306. "[sub/b.txt, mode:100644, content:content b]",
  307. indexState(CONTENT));
  308. git.commit().setMessage("commit").call();
  309. // new unstaged file sub/c.txt
  310. File file3 = new File(db.getWorkTree(), "sub/c.txt");
  311. file3.createNewFile();
  312. writer = new PrintWriter(file3);
  313. writer.print("content c");
  314. writer.close();
  315. // file sub/a.txt is modified
  316. writer = new PrintWriter(file);
  317. writer.print("modified content");
  318. writer.close();
  319. // file sub/b.txt is deleted
  320. file2.delete();
  321. git.add().addFilepattern("sub").call();
  322. // change in sub/a.txt is staged
  323. // deletion of sub/b.txt is not staged
  324. // sub/c.txt is staged
  325. assertEquals(
  326. "[sub/a.txt, mode:100644, content:modified content]" +
  327. "[sub/b.txt, mode:100644, content:content b]" +
  328. "[sub/c.txt, mode:100644, content:content c]",
  329. indexState(CONTENT));
  330. }
  331. // file a exists in workdir and in index -> added
  332. // file b exists not in workdir but in index -> deleted
  333. // file c exists in workdir but not in index -> unchanged
  334. public void testAddWithParameterUpdate() throws Exception {
  335. new File(db.getWorkTree(), "sub").mkdir();
  336. File file = new File(db.getWorkTree(), "sub/a.txt");
  337. file.createNewFile();
  338. PrintWriter writer = new PrintWriter(file);
  339. writer.print("content");
  340. writer.close();
  341. File file2 = new File(db.getWorkTree(), "sub/b.txt");
  342. file2.createNewFile();
  343. writer = new PrintWriter(file2);
  344. writer.print("content b");
  345. writer.close();
  346. Git git = new Git(db);
  347. git.add().addFilepattern("sub").call();
  348. assertEquals(
  349. "[sub/a.txt, mode:100644, content:content]" +
  350. "[sub/b.txt, mode:100644, content:content b]",
  351. indexState(CONTENT));
  352. git.commit().setMessage("commit").call();
  353. // new unstaged file sub/c.txt
  354. File file3 = new File(db.getWorkTree(), "sub/c.txt");
  355. file3.createNewFile();
  356. writer = new PrintWriter(file3);
  357. writer.print("content c");
  358. writer.close();
  359. // file sub/a.txt is modified
  360. writer = new PrintWriter(file);
  361. writer.print("modified content");
  362. writer.close();
  363. file2.delete();
  364. // change in sub/a.txt is staged
  365. // deletion of sub/b.txt is staged
  366. // sub/c.txt is not staged
  367. git.add().addFilepattern("sub").setUpdate(true).call();
  368. // change in sub/a.txt is staged
  369. assertEquals(
  370. "[sub/a.txt, mode:100644, content:modified content]",
  371. indexState(CONTENT));
  372. }
  373. public void testAssumeUnchanged() throws Exception {
  374. Git git = new Git(db);
  375. String path = "a.txt";
  376. writeTrashFile(path, "content");
  377. git.add().addFilepattern(path).call();
  378. String path2 = "b.txt";
  379. writeTrashFile(path2, "content");
  380. git.add().addFilepattern(path2).call();
  381. git.commit().setMessage("commit").call();
  382. assertEquals("[a.txt, mode:100644, content:"
  383. + "content, assume-unchanged:false]"
  384. + "[b.txt, mode:100644, content:content, "
  385. + "assume-unchanged:false]", indexState(CONTENT
  386. | ASSUME_UNCHANGED));
  387. assumeUnchanged(path2);
  388. assertEquals("[a.txt, mode:100644, content:content, "
  389. + "assume-unchanged:false][b.txt, mode:100644, "
  390. + "content:content, assume-unchanged:true]", indexState(CONTENT
  391. | ASSUME_UNCHANGED));
  392. writeTrashFile(path, "more content");
  393. writeTrashFile(path2, "more content");
  394. git.add().addFilepattern(".").call();
  395. assertEquals("[a.txt, mode:100644, content:more content,"
  396. + " assume-unchanged:false][b.txt, mode:100644,"
  397. + "" + ""
  398. + " content:content, assume-unchanged:true]",
  399. indexState(CONTENT
  400. | ASSUME_UNCHANGED));
  401. }
  402. private DirCacheEntry addEntryToBuilder(String path, File file,
  403. ObjectInserter newObjectInserter, DirCacheBuilder builder, int stage)
  404. throws IOException {
  405. FileInputStream inputStream = new FileInputStream(file);
  406. ObjectId id = newObjectInserter.insert(
  407. Constants.OBJ_BLOB, file.length(), inputStream);
  408. inputStream.close();
  409. DirCacheEntry entry = new DirCacheEntry(path, stage);
  410. entry.setObjectId(id);
  411. entry.setFileMode(FileMode.REGULAR_FILE);
  412. entry.setLastModified(file.lastModified());
  413. entry.setLength((int) file.length());
  414. builder.add(entry);
  415. return entry;
  416. }
  417. private void assumeUnchanged(String path) throws IOException {
  418. final DirCache dirc = db.lockDirCache();
  419. final DirCacheEntry ent = dirc.getEntry(path);
  420. if (ent != null)
  421. ent.setAssumeValid(true);
  422. dirc.write();
  423. if (!dirc.commit())
  424. throw new IOException("could not commit");
  425. }
  426. }