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.

DirCacheCheckoutTest.java 36KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200
  1. /*
  2. * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
  3. * Copyright (C) 2008-2011, Shawn O. Pearce <spearce@spearce.org>
  4. * Copyright (C) 2008-2011, Robin Rosenberg <robin.rosenberg@dewire.com>
  5. * Copyright (C) 2010-2011, Christian Halstrick <christian.halstrick@sap.com>
  6. * and other copyright owners as documented in the project's IP log.
  7. *
  8. * This program and the accompanying materials are made available under the
  9. * terms of the Eclipse Distribution License v1.0 which accompanies this
  10. * distribution, is reproduced below, and is available at
  11. * http://www.eclipse.org/org/documents/edl-v10.php
  12. *
  13. * All rights reserved.
  14. *
  15. * Redistribution and use in source and binary forms, with or without
  16. * modification, are permitted provided that the following conditions are met:
  17. *
  18. * - Redistributions of source code must retain the above copyright notice, this
  19. * list of conditions and the following disclaimer.
  20. *
  21. * - Redistributions in binary form must reproduce the above copyright notice,
  22. * this list of conditions and the following disclaimer in the documentation
  23. * and/or other materials provided with the distribution.
  24. *
  25. * - Neither the name of the Eclipse Foundation, Inc. nor the names of its
  26. * contributors may be used to endorse or promote products derived from this
  27. * software without specific prior written permission.
  28. *
  29. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  30. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  31. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  32. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  33. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  34. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  35. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  36. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  37. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  38. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  39. * POSSIBILITY OF SUCH DAMAGE.
  40. */
  41. package org.eclipse.jgit.lib;
  42. import static org.junit.Assert.assertArrayEquals;
  43. import static org.junit.Assert.assertEquals;
  44. import static org.junit.Assert.assertFalse;
  45. import static org.junit.Assert.assertNotNull;
  46. import static org.junit.Assert.assertTrue;
  47. import static org.junit.Assert.fail;
  48. import java.io.File;
  49. import java.io.FileInputStream;
  50. import java.io.IOException;
  51. import java.util.Arrays;
  52. import java.util.HashMap;
  53. import java.util.List;
  54. import java.util.Map;
  55. import org.eclipse.jgit.api.CheckoutCommand;
  56. import org.eclipse.jgit.api.CheckoutResult;
  57. import org.eclipse.jgit.api.Git;
  58. import org.eclipse.jgit.api.MergeResult.MergeStatus;
  59. import org.eclipse.jgit.api.ResetCommand.ResetType;
  60. import org.eclipse.jgit.api.Status;
  61. import org.eclipse.jgit.api.errors.GitAPIException;
  62. import org.eclipse.jgit.api.errors.NoFilepatternException;
  63. import org.eclipse.jgit.dircache.DirCache;
  64. import org.eclipse.jgit.dircache.DirCacheCheckout;
  65. import org.eclipse.jgit.dircache.DirCacheEditor;
  66. import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
  67. import org.eclipse.jgit.dircache.DirCacheEntry;
  68. import org.eclipse.jgit.errors.CheckoutConflictException;
  69. import org.eclipse.jgit.errors.CorruptObjectException;
  70. import org.eclipse.jgit.errors.NoWorkTreeException;
  71. import org.eclipse.jgit.junit.RepositoryTestCase;
  72. import org.eclipse.jgit.revwalk.RevCommit;
  73. import org.eclipse.jgit.treewalk.FileTreeIterator;
  74. import org.eclipse.jgit.treewalk.TreeWalk;
  75. import org.eclipse.jgit.util.FS;
  76. import org.junit.Test;
  77. public class DirCacheCheckoutTest extends RepositoryTestCase {
  78. private DirCacheCheckout dco;
  79. protected ObjectId theHead;
  80. protected ObjectId theMerge;
  81. private DirCache dirCache;
  82. private void prescanTwoTrees(ObjectId head, ObjectId merge)
  83. throws IllegalStateException, IOException {
  84. DirCache dc = db.lockDirCache();
  85. try {
  86. dco = new DirCacheCheckout(db, head, dc, merge);
  87. dco.preScanTwoTrees();
  88. } finally {
  89. dc.unlock();
  90. }
  91. }
  92. private void checkout() throws IOException {
  93. DirCache dc = db.lockDirCache();
  94. try {
  95. dco = new DirCacheCheckout(db, theHead, dc, theMerge);
  96. dco.checkout();
  97. } finally {
  98. dc.unlock();
  99. }
  100. }
  101. private List<String> getRemoved() {
  102. return dco.getRemoved();
  103. }
  104. private Map<String, ObjectId> getUpdated() {
  105. return dco.getUpdated();
  106. }
  107. private List<String> getConflicts() {
  108. return dco.getConflicts();
  109. }
  110. private static HashMap<String, String> mk(String a) {
  111. return mkmap(a, a);
  112. }
  113. private static HashMap<String, String> mkmap(String... args) {
  114. if ((args.length % 2) > 0)
  115. throw new IllegalArgumentException("needs to be pairs");
  116. HashMap<String, String> map = new HashMap<String, String>();
  117. for (int i = 0; i < args.length; i += 2) {
  118. map.put(args[i], args[i + 1]);
  119. }
  120. return map;
  121. }
  122. @Test
  123. public void testResetHard() throws IOException, NoFilepatternException,
  124. GitAPIException {
  125. Git git = new Git(db);
  126. writeTrashFile("f", "f()");
  127. writeTrashFile("D/g", "g()");
  128. git.add().addFilepattern(".").call();
  129. git.commit().setMessage("inital").call();
  130. assertIndex(mkmap("f", "f()", "D/g", "g()"));
  131. git.branchCreate().setName("topic").call();
  132. writeTrashFile("f", "f()\nmaster");
  133. writeTrashFile("D/g", "g()\ng2()");
  134. writeTrashFile("E/h", "h()");
  135. git.add().addFilepattern(".").call();
  136. RevCommit master = git.commit().setMessage("master-1").call();
  137. assertIndex(mkmap("f", "f()\nmaster", "D/g", "g()\ng2()", "E/h", "h()"));
  138. checkoutBranch("refs/heads/topic");
  139. assertIndex(mkmap("f", "f()", "D/g", "g()"));
  140. writeTrashFile("f", "f()\nside");
  141. assertTrue(new File(db.getWorkTree(), "D/g").delete());
  142. writeTrashFile("G/i", "i()");
  143. git.add().addFilepattern(".").call();
  144. git.add().addFilepattern(".").setUpdate(true).call();
  145. RevCommit topic = git.commit().setMessage("topic-1").call();
  146. assertIndex(mkmap("f", "f()\nside", "G/i", "i()"));
  147. writeTrashFile("untracked", "untracked");
  148. resetHard(master);
  149. assertIndex(mkmap("f", "f()\nmaster", "D/g", "g()\ng2()", "E/h", "h()"));
  150. resetHard(topic);
  151. assertIndex(mkmap("f", "f()\nside", "G/i", "i()"));
  152. assertWorkDir(mkmap("f", "f()\nside", "G/i", "i()", "untracked",
  153. "untracked"));
  154. assertEquals(MergeStatus.CONFLICTING, git.merge().include(master)
  155. .call().getMergeStatus());
  156. assertEquals(
  157. "[D/g, mode:100644, stage:1][D/g, mode:100644, stage:3][E/h, mode:100644][G/i, mode:100644][f, mode:100644, stage:1][f, mode:100644, stage:2][f, mode:100644, stage:3]",
  158. indexState(0));
  159. resetHard(master);
  160. assertIndex(mkmap("f", "f()\nmaster", "D/g", "g()\ng2()", "E/h", "h()"));
  161. assertWorkDir(mkmap("f", "f()\nmaster", "D/g", "g()\ng2()", "E/h",
  162. "h()", "untracked", "untracked"));
  163. }
  164. /**
  165. * Reset hard from unclean condition.
  166. * <p>
  167. * WorkDir: Empty <br/>
  168. * Index: f/g <br/>
  169. * Merge: x
  170. *
  171. * @throws Exception
  172. */
  173. @Test
  174. public void testResetHardFromIndexEntryWithoutFileToTreeWithoutFile()
  175. throws Exception {
  176. Git git = new Git(db);
  177. writeTrashFile("x", "x");
  178. git.add().addFilepattern("x").call();
  179. RevCommit id1 = git.commit().setMessage("c1").call();
  180. writeTrashFile("f/g", "f/g");
  181. git.rm().addFilepattern("x").call();
  182. git.add().addFilepattern("f/g").call();
  183. git.commit().setMessage("c2").call();
  184. deleteTrashFile("f/g");
  185. deleteTrashFile("f");
  186. // The actual test
  187. git.reset().setMode(ResetType.HARD).setRef(id1.getName()).call();
  188. assertIndex(mkmap("x", "x"));
  189. }
  190. private DirCacheCheckout resetHard(RevCommit commit)
  191. throws NoWorkTreeException,
  192. CorruptObjectException, IOException {
  193. DirCacheCheckout dc;
  194. dc = new DirCacheCheckout(db, null, db.lockDirCache(),
  195. commit.getTree());
  196. dc.setFailOnConflict(true);
  197. assertTrue(dc.checkout());
  198. return dc;
  199. }
  200. private void assertIndex(HashMap<String, String> i)
  201. throws CorruptObjectException, IOException {
  202. String expectedValue;
  203. String path;
  204. DirCache read = DirCache.read(db.getIndexFile(), db.getFS());
  205. assertEquals("Index has not the right size.", i.size(),
  206. read.getEntryCount());
  207. for (int j = 0; j < read.getEntryCount(); j++) {
  208. path = read.getEntry(j).getPathString();
  209. expectedValue = i.get(path);
  210. assertNotNull("found unexpected entry for path " + path
  211. + " in index", expectedValue);
  212. assertTrue("unexpected content for path " + path
  213. + " in index. Expected: <" + expectedValue + ">",
  214. Arrays.equals(db.open(read.getEntry(j).getObjectId())
  215. .getCachedBytes(), i.get(path).getBytes()));
  216. }
  217. }
  218. @Test
  219. public void testRules1thru3_NoIndexEntry() throws IOException {
  220. ObjectId head = buildTree(mk("foo"));
  221. TreeWalk tw = TreeWalk.forPath(db, "foo", head);
  222. ObjectId objectId = tw.getObjectId(0);
  223. ObjectId merge = db.newObjectInserter().insert(Constants.OBJ_TREE,
  224. new byte[0]);
  225. prescanTwoTrees(head, merge);
  226. assertTrue(getRemoved().contains("foo"));
  227. prescanTwoTrees(merge, head);
  228. assertEquals(objectId, getUpdated().get("foo"));
  229. merge = buildTree(mkmap("foo", "a"));
  230. tw = TreeWalk.forPath(db, "foo", merge);
  231. prescanTwoTrees(head, merge);
  232. assertConflict("foo");
  233. }
  234. void setupCase(HashMap<String, String> headEntries, HashMap<String, String> mergeEntries, HashMap<String, String> indexEntries) throws IOException {
  235. theHead = buildTree(headEntries);
  236. theMerge = buildTree(mergeEntries);
  237. buildIndex(indexEntries);
  238. }
  239. private void buildIndex(HashMap<String, String> indexEntries) throws IOException {
  240. dirCache = new DirCache(db.getIndexFile(), db.getFS());
  241. if (indexEntries != null) {
  242. assertTrue(dirCache.lock());
  243. DirCacheEditor editor = dirCache.editor();
  244. for (java.util.Map.Entry<String,String> e : indexEntries.entrySet()) {
  245. writeTrashFile(e.getKey(), e.getValue());
  246. ObjectInserter inserter = db.newObjectInserter();
  247. final ObjectId id = inserter.insert(Constants.OBJ_BLOB,
  248. Constants.encode(e.getValue()));
  249. editor.add(new DirCacheEditor.DeletePath(e.getKey()));
  250. editor.add(new DirCacheEditor.PathEdit(e.getKey()) {
  251. @Override
  252. public void apply(DirCacheEntry ent) {
  253. ent.setFileMode(FileMode.REGULAR_FILE);
  254. ent.setObjectId(id);
  255. ent.setUpdateNeeded(false);
  256. }
  257. });
  258. }
  259. assertTrue(editor.commit());
  260. }
  261. }
  262. static final class AddEdit extends PathEdit {
  263. private final ObjectId data;
  264. private final long length;
  265. public AddEdit(String entryPath, ObjectId data, long length) {
  266. super(entryPath);
  267. this.data = data;
  268. this.length = length;
  269. }
  270. @Override
  271. public void apply(DirCacheEntry ent) {
  272. ent.setFileMode(FileMode.REGULAR_FILE);
  273. ent.setLength(length);
  274. ent.setObjectId(data);
  275. }
  276. }
  277. private ObjectId buildTree(HashMap<String, String> headEntries)
  278. throws IOException {
  279. DirCache lockDirCache = DirCache.newInCore();
  280. // assertTrue(lockDirCache.lock());
  281. DirCacheEditor editor = lockDirCache.editor();
  282. if (headEntries != null) {
  283. for (java.util.Map.Entry<String, String> e : headEntries.entrySet()) {
  284. AddEdit addEdit = new AddEdit(e.getKey(),
  285. genSha1(e.getValue()), e.getValue().length());
  286. editor.add(addEdit);
  287. }
  288. }
  289. editor.finish();
  290. return lockDirCache.writeTree(db.newObjectInserter());
  291. }
  292. ObjectId genSha1(String data) {
  293. ObjectInserter w = db.newObjectInserter();
  294. try {
  295. ObjectId id = w.insert(Constants.OBJ_BLOB, data.getBytes());
  296. w.flush();
  297. return id;
  298. } catch (IOException e) {
  299. fail(e.toString());
  300. } finally {
  301. w.release();
  302. }
  303. return null;
  304. }
  305. protected void go() throws IllegalStateException, IOException {
  306. prescanTwoTrees(theHead, theMerge);
  307. }
  308. @Test
  309. public void testRules4thru13_IndexEntryNotInHead() throws IOException {
  310. // rules 4 and 5
  311. HashMap<String, String> idxMap;
  312. idxMap = new HashMap<String, String>();
  313. idxMap.put("foo", "foo");
  314. setupCase(null, null, idxMap);
  315. go();
  316. assertTrue(getUpdated().isEmpty());
  317. assertTrue(getRemoved().isEmpty());
  318. assertTrue(getConflicts().isEmpty());
  319. // rules 6 and 7
  320. idxMap = new HashMap<String, String>();
  321. idxMap.put("foo", "foo");
  322. setupCase(null, idxMap, idxMap);
  323. go();
  324. assertAllEmpty();
  325. // rules 8 and 9
  326. HashMap<String, String> mergeMap;
  327. mergeMap = new HashMap<String, String>();
  328. mergeMap.put("foo", "merge");
  329. setupCase(null, mergeMap, idxMap);
  330. go();
  331. assertTrue(getUpdated().isEmpty());
  332. assertTrue(getRemoved().isEmpty());
  333. assertTrue(getConflicts().contains("foo"));
  334. // rule 10
  335. HashMap<String, String> headMap = new HashMap<String, String>();
  336. headMap.put("foo", "foo");
  337. setupCase(headMap, null, idxMap);
  338. go();
  339. assertTrue(getRemoved().contains("foo"));
  340. assertTrue(getUpdated().isEmpty());
  341. assertTrue(getConflicts().isEmpty());
  342. // rule 11
  343. setupCase(headMap, null, idxMap);
  344. assertTrue(new File(trash, "foo").delete());
  345. writeTrashFile("foo", "bar");
  346. db.readDirCache().getEntry(0).setUpdateNeeded(true);
  347. go();
  348. assertTrue(getRemoved().isEmpty());
  349. assertTrue(getUpdated().isEmpty());
  350. assertTrue(getConflicts().contains("foo"));
  351. // rule 12 & 13
  352. headMap.put("foo", "head");
  353. setupCase(headMap, null, idxMap);
  354. go();
  355. assertTrue(getRemoved().isEmpty());
  356. assertTrue(getUpdated().isEmpty());
  357. assertTrue(getConflicts().contains("foo"));
  358. // rules 14 & 15
  359. setupCase(headMap, headMap, idxMap);
  360. go();
  361. assertAllEmpty();
  362. // rules 16 & 17
  363. setupCase(headMap, mergeMap, idxMap); go();
  364. assertTrue(getConflicts().contains("foo"));
  365. // rules 18 & 19
  366. setupCase(headMap, idxMap, idxMap); go();
  367. assertAllEmpty();
  368. // rule 20
  369. setupCase(idxMap, mergeMap, idxMap); go();
  370. assertTrue(getUpdated().containsKey("foo"));
  371. // rules 21
  372. setupCase(idxMap, mergeMap, idxMap);
  373. assertTrue(new File(trash, "foo").delete());
  374. writeTrashFile("foo", "bar");
  375. db.readDirCache().getEntry(0).setUpdateNeeded(true);
  376. go();
  377. assertTrue(getConflicts().contains("foo"));
  378. }
  379. private void assertAllEmpty() {
  380. assertTrue(getRemoved().isEmpty());
  381. assertTrue(getUpdated().isEmpty());
  382. assertTrue(getConflicts().isEmpty());
  383. }
  384. /*-
  385. * Directory/File Conflict cases:
  386. * It's entirely possible that in practice a number of these may be equivalent
  387. * to the cases described in git-read-tree.txt. As long as it does the right thing,
  388. * that's all I care about. These are basically reverse-engineered from
  389. * what git currently does. If there are tests for these in git, it's kind of
  390. * hard to track them all down...
  391. *
  392. * H I M Clean H==M H==I I==M Result
  393. * ------------------------------------------------------------------
  394. *1 D D F Y N Y N Update
  395. *2 D D F N N Y N Conflict
  396. *3 D F D Y N N Keep
  397. *4 D F D N N N Conflict
  398. *5 D F F Y N N Y Keep
  399. *5b D F F Y N N N Conflict
  400. *6 D F F N N N Y Keep
  401. *6b D F F N N N N Conflict
  402. *7 F D F Y Y N N Update
  403. *8 F D F N Y N N Conflict
  404. *9 F D F Y N N N Update
  405. *10 F D D N N Y Keep
  406. *11 F D D N N N Conflict
  407. *12 F F D Y N Y N Update
  408. *13 F F D N N Y N Conflict
  409. *14 F F D N N N Conflict
  410. *15 0 F D N N N Conflict
  411. *16 0 D F Y N N N Update
  412. *17 0 D F N N N Conflict
  413. *18 F 0 D Update
  414. *19 D 0 F Update
  415. */
  416. @Test
  417. public void testDirectoryFileSimple() throws IOException {
  418. ObjectId treeDF = buildTree(mkmap("DF", "DF"));
  419. ObjectId treeDFDF = buildTree(mkmap("DF/DF", "DF/DF"));
  420. buildIndex(mkmap("DF", "DF"));
  421. prescanTwoTrees(treeDF, treeDFDF);
  422. assertTrue(getRemoved().contains("DF"));
  423. assertTrue(getUpdated().containsKey("DF/DF"));
  424. recursiveDelete(new File(trash, "DF"));
  425. buildIndex(mkmap("DF/DF", "DF/DF"));
  426. prescanTwoTrees(treeDFDF, treeDF);
  427. assertTrue(getRemoved().contains("DF/DF"));
  428. assertTrue(getUpdated().containsKey("DF"));
  429. }
  430. @Test
  431. public void testDirectoryFileConflicts_1() throws Exception {
  432. // 1
  433. doit(mk("DF/DF"), mk("DF"), mk("DF/DF"));
  434. assertNoConflicts();
  435. assertUpdated("DF");
  436. assertRemoved("DF/DF");
  437. }
  438. @Test
  439. public void testDirectoryFileConflicts_2() throws Exception {
  440. // 2
  441. setupCase(mk("DF/DF"), mk("DF"), mk("DF/DF"));
  442. writeTrashFile("DF/DF", "different");
  443. go();
  444. assertConflict("DF/DF");
  445. }
  446. @Test
  447. public void testDirectoryFileConflicts_3() throws Exception {
  448. // 3
  449. doit(mk("DF/DF"), mk("DF/DF"), mk("DF"));
  450. assertNoConflicts();
  451. }
  452. @Test
  453. public void testDirectoryFileConflicts_4() throws Exception {
  454. // 4 (basically same as 3, just with H and M different)
  455. doit(mk("DF/DF"), mkmap("DF/DF", "foo"), mk("DF"));
  456. assertConflict("DF/DF");
  457. }
  458. @Test
  459. public void testDirectoryFileConflicts_5() throws Exception {
  460. // 5
  461. doit(mk("DF/DF"), mk("DF"), mk("DF"));
  462. assertRemoved("DF/DF");
  463. assertEquals(0, dco.getConflicts().size());
  464. assertEquals(0, dco.getUpdated().size());
  465. }
  466. @Test
  467. public void testDirectoryFileConflicts_5b() throws Exception {
  468. // 5
  469. doit(mk("DF/DF"), mkmap("DF", "different"), mk("DF"));
  470. assertRemoved("DF/DF");
  471. assertConflict("DF");
  472. assertEquals(0, dco.getUpdated().size());
  473. }
  474. @Test
  475. public void testDirectoryFileConflicts_6() throws Exception {
  476. // 6
  477. setupCase(mk("DF/DF"), mk("DF"), mk("DF"));
  478. writeTrashFile("DF", "different");
  479. go();
  480. assertRemoved("DF/DF");
  481. assertEquals(0, dco.getConflicts().size());
  482. assertEquals(0, dco.getUpdated().size());
  483. }
  484. @Test
  485. public void testDirectoryFileConflicts_6b() throws Exception {
  486. // 6
  487. setupCase(mk("DF/DF"), mk("DF"), mkmap("DF", "different"));
  488. writeTrashFile("DF", "again different");
  489. go();
  490. assertRemoved("DF/DF");
  491. assertConflict("DF");
  492. assertEquals(0, dco.getUpdated().size());
  493. }
  494. @Test
  495. public void testDirectoryFileConflicts_7() throws Exception {
  496. // 7
  497. doit(mk("DF"), mk("DF"), mk("DF/DF"));
  498. assertUpdated("DF");
  499. assertRemoved("DF/DF");
  500. cleanUpDF();
  501. setupCase(mk("DF/DF"), mk("DF/DF"), mk("DF/DF/DF/DF/DF"));
  502. go();
  503. assertRemoved("DF/DF/DF/DF/DF");
  504. assertUpdated("DF/DF");
  505. cleanUpDF();
  506. setupCase(mk("DF/DF"), mk("DF/DF"), mk("DF/DF/DF/DF/DF"));
  507. writeTrashFile("DF/DF/DF/DF/DF", "diff");
  508. go();
  509. assertConflict("DF/DF/DF/DF/DF");
  510. // assertUpdated("DF/DF");
  511. // Why do we expect an update on DF/DF. H==M,
  512. // H&M are files and index contains a dir, index
  513. // is dirty: that case is not in the table but
  514. // we cannot update DF/DF to a file, this would
  515. // require that we delete DF/DF/DF/DF/DF in workdir
  516. // throwing away unsaved contents.
  517. // This test would fail in DirCacheCheckoutTests.
  518. }
  519. @Test
  520. public void testDirectoryFileConflicts_8() throws Exception {
  521. // 8
  522. setupCase(mk("DF"), mk("DF"), mk("DF/DF"));
  523. recursiveDelete(new File(db.getWorkTree(), "DF"));
  524. writeTrashFile("DF", "xy");
  525. go();
  526. assertConflict("DF/DF");
  527. }
  528. @Test
  529. public void testDirectoryFileConflicts_9() throws Exception {
  530. // 9
  531. doit(mk("DF"), mkmap("DF", "QP"), mk("DF/DF"));
  532. assertRemoved("DF/DF");
  533. assertUpdated("DF");
  534. }
  535. @Test
  536. public void testDirectoryFileConflicts_10() throws Exception {
  537. // 10
  538. cleanUpDF();
  539. doit(mk("DF"), mk("DF/DF"), mk("DF/DF"));
  540. assertNoConflicts();
  541. }
  542. @Test
  543. public void testDirectoryFileConflicts_11() throws Exception {
  544. // 11
  545. doit(mk("DF"), mk("DF/DF"), mkmap("DF/DF", "asdf"));
  546. assertConflict("DF/DF");
  547. }
  548. @Test
  549. public void testDirectoryFileConflicts_12() throws Exception {
  550. // 12
  551. cleanUpDF();
  552. doit(mk("DF"), mk("DF/DF"), mk("DF"));
  553. assertRemoved("DF");
  554. assertUpdated("DF/DF");
  555. }
  556. @Test
  557. public void testDirectoryFileConflicts_13() throws Exception {
  558. // 13
  559. cleanUpDF();
  560. setupCase(mk("DF"), mk("DF/DF"), mk("DF"));
  561. writeTrashFile("DF", "asdfsdf");
  562. go();
  563. assertConflict("DF");
  564. assertUpdated("DF/DF");
  565. }
  566. @Test
  567. public void testDirectoryFileConflicts_14() throws Exception {
  568. // 14
  569. cleanUpDF();
  570. doit(mk("DF"), mk("DF/DF"), mkmap("DF", "Foo"));
  571. assertConflict("DF");
  572. assertUpdated("DF/DF");
  573. }
  574. @Test
  575. public void testDirectoryFileConflicts_15() throws Exception {
  576. // 15
  577. doit(mkmap(), mk("DF/DF"), mk("DF"));
  578. // This test would fail in DirCacheCheckoutTests. I think this test is wrong,
  579. // it should check for conflicts according to rule 15
  580. // assertRemoved("DF");
  581. assertUpdated("DF/DF");
  582. }
  583. @Test
  584. public void testDirectoryFileConflicts_15b() throws Exception {
  585. // 15, take 2, just to check multi-leveled
  586. doit(mkmap(), mk("DF/DF/DF/DF"), mk("DF"));
  587. // I think this test is wrong, it should
  588. // check for conflicts according to rule 15
  589. // This test would fail in DirCacheCheckouts
  590. // assertRemoved("DF");
  591. assertUpdated("DF/DF/DF/DF");
  592. }
  593. @Test
  594. public void testDirectoryFileConflicts_16() throws Exception {
  595. // 16
  596. cleanUpDF();
  597. doit(mkmap(), mk("DF"), mk("DF/DF/DF"));
  598. assertRemoved("DF/DF/DF");
  599. assertUpdated("DF");
  600. }
  601. @Test
  602. public void testDirectoryFileConflicts_17() throws Exception {
  603. // 17
  604. cleanUpDF();
  605. setupCase(mkmap(), mk("DF"), mk("DF/DF/DF"));
  606. writeTrashFile("DF/DF/DF", "asdf");
  607. go();
  608. assertConflict("DF/DF/DF");
  609. // Why do we expect an update on DF. If we really update
  610. // DF and update also the working tree we would have to
  611. // overwrite a dirty file in the work-tree DF/DF/DF
  612. // This test would fail in DirCacheCheckout
  613. // assertUpdated("DF");
  614. }
  615. @Test
  616. public void testDirectoryFileConflicts_18() throws Exception {
  617. // 18
  618. cleanUpDF();
  619. doit(mk("DF/DF"), mk("DF/DF/DF/DF"), null);
  620. assertRemoved("DF/DF");
  621. assertUpdated("DF/DF/DF/DF");
  622. }
  623. @Test
  624. public void testDirectoryFileConflicts_19() throws Exception {
  625. // 19
  626. cleanUpDF();
  627. doit(mk("DF/DF/DF/DF"), mk("DF/DF/DF"), null);
  628. assertRemoved("DF/DF/DF/DF");
  629. assertUpdated("DF/DF/DF");
  630. }
  631. protected void cleanUpDF() throws Exception {
  632. tearDown();
  633. setUp();
  634. recursiveDelete(new File(trash, "DF"));
  635. }
  636. protected void assertConflict(String s) {
  637. assertTrue(getConflicts().contains(s));
  638. }
  639. protected void assertUpdated(String s) {
  640. assertTrue(getUpdated().containsKey(s));
  641. }
  642. protected void assertRemoved(String s) {
  643. assertTrue(getRemoved().contains(s));
  644. }
  645. protected void assertNoConflicts() {
  646. assertTrue(getConflicts().isEmpty());
  647. }
  648. protected void doit(HashMap<String, String> h, HashMap<String, String> m, HashMap<String, String> i)
  649. throws IOException {
  650. setupCase(h, m, i);
  651. go();
  652. }
  653. @Test
  654. public void testUntrackedConflicts() throws IOException {
  655. setupCase(null, mk("foo"), null);
  656. writeTrashFile("foo", "foo");
  657. go();
  658. // test that we don't overwrite untracked files when there is a HEAD
  659. recursiveDelete(new File(trash, "foo"));
  660. setupCase(mk("other"), mkmap("other", "other", "foo", "foo"),
  661. mk("other"));
  662. writeTrashFile("foo", "bar");
  663. try {
  664. checkout();
  665. fail("didn't get the expected exception");
  666. } catch (CheckoutConflictException e) {
  667. assertConflict("foo");
  668. assertWorkDir(mkmap("foo", "bar", "other", "other"));
  669. assertIndex(mk("other"));
  670. }
  671. // test that we don't overwrite untracked files when there is no HEAD
  672. recursiveDelete(new File(trash, "other"));
  673. recursiveDelete(new File(trash, "foo"));
  674. setupCase(null, mk("foo"), null);
  675. writeTrashFile("foo", "bar");
  676. try {
  677. checkout();
  678. fail("didn't get the expected exception");
  679. } catch (CheckoutConflictException e) {
  680. assertConflict("foo");
  681. assertWorkDir(mkmap("foo", "bar"));
  682. assertIndex(mkmap("other", "other"));
  683. }
  684. // TODO: Why should we expect conflicts here?
  685. // H and M are empty and according to rule #5 of
  686. // the carry-over rules a dirty index is no reason
  687. // for a conflict. (I also feel it should be a
  688. // conflict because we are going to overwrite
  689. // unsaved content in the working tree
  690. // This test would fail in DirCacheCheckoutTest
  691. // assertConflict("foo");
  692. recursiveDelete(new File(trash, "foo"));
  693. recursiveDelete(new File(trash, "other"));
  694. setupCase(null, mk("foo"), null);
  695. writeTrashFile("foo/bar/baz", "");
  696. writeTrashFile("foo/blahblah", "");
  697. go();
  698. assertConflict("foo");
  699. assertConflict("foo/bar/baz");
  700. assertConflict("foo/blahblah");
  701. recursiveDelete(new File(trash, "foo"));
  702. setupCase(mkmap("foo/bar", "", "foo/baz", ""),
  703. mk("foo"), mkmap("foo/bar", "", "foo/baz", ""));
  704. assertTrue(new File(trash, "foo/bar").exists());
  705. go();
  706. assertNoConflicts();
  707. }
  708. @Test
  709. public void testCloseNameConflictsX0() throws IOException {
  710. setupCase(mkmap("a/a", "a/a-c"), mkmap("a/a","a/a", "b.b/b.b","b.b/b.bs"), mkmap("a/a", "a/a-c") );
  711. checkout();
  712. assertIndex(mkmap("a/a", "a/a", "b.b/b.b", "b.b/b.bs"));
  713. assertWorkDir(mkmap("a/a", "a/a", "b.b/b.b", "b.b/b.bs"));
  714. go();
  715. assertIndex(mkmap("a/a", "a/a", "b.b/b.b", "b.b/b.bs"));
  716. assertWorkDir(mkmap("a/a", "a/a", "b.b/b.b", "b.b/b.bs"));
  717. assertNoConflicts();
  718. }
  719. @Test
  720. public void testCloseNameConflicts1() throws IOException {
  721. setupCase(mkmap("a/a", "a/a-c"), mkmap("a/a","a/a", "a.a/a.a","a.a/a.a"), mkmap("a/a", "a/a-c") );
  722. checkout();
  723. assertIndex(mkmap("a/a", "a/a", "a.a/a.a", "a.a/a.a"));
  724. assertWorkDir(mkmap("a/a", "a/a", "a.a/a.a", "a.a/a.a"));
  725. go();
  726. assertIndex(mkmap("a/a", "a/a", "a.a/a.a", "a.a/a.a"));
  727. assertWorkDir(mkmap("a/a", "a/a", "a.a/a.a", "a.a/a.a"));
  728. assertNoConflicts();
  729. }
  730. @Test
  731. public void testCheckoutHierarchy() throws IOException {
  732. setupCase(
  733. mkmap("a", "a", "b/c", "b/c", "d", "d", "e/f", "e/f", "e/g",
  734. "e/g"),
  735. mkmap("a", "a2", "b/c", "b/c", "d", "d", "e/f", "e/f", "e/g",
  736. "e/g2"),
  737. mkmap("a", "a", "b/c", "b/c", "d", "d", "e/f", "e/f", "e/g",
  738. "e/g3"));
  739. try {
  740. checkout();
  741. } catch (CheckoutConflictException e) {
  742. assertWorkDir(mkmap("a", "a", "b/c", "b/c", "d", "d", "e/f",
  743. "e/f", "e/g", "e/g3"));
  744. assertConflict("e/g");
  745. }
  746. }
  747. @Test
  748. public void testCheckoutOutChanges() throws IOException {
  749. setupCase(mk("foo"), mk("foo/bar"), mk("foo"));
  750. checkout();
  751. assertIndex(mk("foo/bar"));
  752. assertWorkDir(mk("foo/bar"));
  753. assertFalse(new File(trash, "foo").isFile());
  754. assertTrue(new File(trash, "foo/bar").isFile());
  755. recursiveDelete(new File(trash, "foo"));
  756. assertWorkDir(mkmap());
  757. setupCase(mk("foo/bar"), mk("foo"), mk("foo/bar"));
  758. checkout();
  759. assertIndex(mk("foo"));
  760. assertWorkDir(mk("foo"));
  761. assertFalse(new File(trash, "foo/bar").isFile());
  762. assertTrue(new File(trash, "foo").isFile());
  763. setupCase(mk("foo"), mkmap("foo", "qux"), mkmap("foo", "bar"));
  764. assertIndex(mkmap("foo", "bar"));
  765. assertWorkDir(mkmap("foo", "bar"));
  766. try {
  767. checkout();
  768. fail("did not throw exception");
  769. } catch (CheckoutConflictException e) {
  770. assertIndex(mkmap("foo", "bar"));
  771. assertWorkDir(mkmap("foo", "bar"));
  772. }
  773. }
  774. @Test
  775. public void testCheckoutOutChangesAutoCRLFfalse() throws IOException {
  776. setupCase(mk("foo"), mkmap("foo/bar", "foo\nbar"), mk("foo"));
  777. checkout();
  778. assertIndex(mkmap("foo/bar", "foo\nbar"));
  779. assertWorkDir(mkmap("foo/bar", "foo\nbar"));
  780. }
  781. @Test
  782. public void testCheckoutOutChangesAutoCRLFInput() throws IOException {
  783. setupCase(mk("foo"), mkmap("foo/bar", "foo\nbar"), mk("foo"));
  784. db.getConfig().setString("core", null, "autocrlf", "input");
  785. checkout();
  786. assertIndex(mkmap("foo/bar", "foo\nbar"));
  787. assertWorkDir(mkmap("foo/bar", "foo\nbar"));
  788. }
  789. @Test
  790. public void testCheckoutOutChangesAutoCRLFtrue() throws IOException {
  791. setupCase(mk("foo"), mkmap("foo/bar", "foo\nbar"), mk("foo"));
  792. db.getConfig().setString("core", null, "autocrlf", "true");
  793. checkout();
  794. assertIndex(mkmap("foo/bar", "foo\nbar"));
  795. assertWorkDir(mkmap("foo/bar", "foo\r\nbar"));
  796. }
  797. @Test
  798. public void testCheckoutOutChangesAutoCRLFtrueBinary() throws IOException {
  799. setupCase(mk("foo"), mkmap("foo/bar", "foo\nb\u0000ar"), mk("foo"));
  800. db.getConfig().setString("core", null, "autocrlf", "true");
  801. checkout();
  802. assertIndex(mkmap("foo/bar", "foo\nb\u0000ar"));
  803. assertWorkDir(mkmap("foo/bar", "foo\nb\u0000ar"));
  804. }
  805. @Test
  806. public void testCheckoutUncachedChanges() throws IOException {
  807. setupCase(mk("foo"), mk("foo"), mk("foo"));
  808. writeTrashFile("foo", "otherData");
  809. checkout();
  810. assertIndex(mk("foo"));
  811. assertWorkDir(mkmap("foo", "otherData"));
  812. assertTrue(new File(trash, "foo").isFile());
  813. }
  814. @Test
  815. public void testDontOverwriteDirtyFile() throws IOException {
  816. setupCase(mk("foo"), mk("other"), mk("foo"));
  817. writeTrashFile("foo", "different");
  818. try {
  819. checkout();
  820. fail("Didn't got the expected conflict");
  821. } catch (CheckoutConflictException e) {
  822. assertIndex(mk("foo"));
  823. assertWorkDir(mkmap("foo", "different"));
  824. assertEquals(Arrays.asList("foo"), getConflicts());
  825. assertTrue(new File(trash, "foo").isFile());
  826. }
  827. }
  828. @Test
  829. public void testFileModeChangeWithNoContentChangeUpdate() throws Exception {
  830. if (!FS.DETECTED.supportsExecute())
  831. return;
  832. Git git = Git.wrap(db);
  833. // Add non-executable file
  834. File file = writeTrashFile("file.txt", "a");
  835. git.add().addFilepattern("file.txt").call();
  836. git.commit().setMessage("commit1").call();
  837. assertFalse(db.getFS().canExecute(file));
  838. // Create branch
  839. git.branchCreate().setName("b1").call();
  840. // Make file executable
  841. db.getFS().setExecute(file, true);
  842. git.add().addFilepattern("file.txt").call();
  843. git.commit().setMessage("commit2").call();
  844. // Verify executable and working directory is clean
  845. Status status = git.status().call();
  846. assertTrue(status.getModified().isEmpty());
  847. assertTrue(status.getChanged().isEmpty());
  848. assertTrue(db.getFS().canExecute(file));
  849. // Switch branches
  850. git.checkout().setName("b1").call();
  851. // Verify not executable and working directory is clean
  852. status = git.status().call();
  853. assertTrue(status.getModified().isEmpty());
  854. assertTrue(status.getChanged().isEmpty());
  855. assertFalse(db.getFS().canExecute(file));
  856. }
  857. @Test
  858. public void testFileModeChangeAndContentChangeConflict() throws Exception {
  859. if (!FS.DETECTED.supportsExecute())
  860. return;
  861. Git git = Git.wrap(db);
  862. // Add non-executable file
  863. File file = writeTrashFile("file.txt", "a");
  864. git.add().addFilepattern("file.txt").call();
  865. git.commit().setMessage("commit1").call();
  866. assertFalse(db.getFS().canExecute(file));
  867. // Create branch
  868. git.branchCreate().setName("b1").call();
  869. // Make file executable
  870. db.getFS().setExecute(file, true);
  871. git.add().addFilepattern("file.txt").call();
  872. git.commit().setMessage("commit2").call();
  873. // Verify executable and working directory is clean
  874. Status status = git.status().call();
  875. assertTrue(status.getModified().isEmpty());
  876. assertTrue(status.getChanged().isEmpty());
  877. assertTrue(db.getFS().canExecute(file));
  878. writeTrashFile("file.txt", "b");
  879. // Switch branches
  880. CheckoutCommand checkout = git.checkout().setName("b1");
  881. try {
  882. checkout.call();
  883. fail("Checkout exception not thrown");
  884. } catch (org.eclipse.jgit.api.errors.CheckoutConflictException e) {
  885. CheckoutResult result = checkout.getResult();
  886. assertNotNull(result);
  887. assertNotNull(result.getConflictList());
  888. assertEquals(1, result.getConflictList().size());
  889. assertTrue(result.getConflictList().contains("file.txt"));
  890. }
  891. }
  892. @Test
  893. public void testDirtyFileModeEqualHeadMerge()
  894. throws Exception {
  895. if (!FS.DETECTED.supportsExecute())
  896. return;
  897. Git git = Git.wrap(db);
  898. // Add non-executable file
  899. File file = writeTrashFile("file.txt", "a");
  900. git.add().addFilepattern("file.txt").call();
  901. git.commit().setMessage("commit1").call();
  902. assertFalse(db.getFS().canExecute(file));
  903. // Create branch
  904. git.branchCreate().setName("b1").call();
  905. // Create second commit and don't touch file
  906. writeTrashFile("file2.txt", "");
  907. git.add().addFilepattern("file2.txt").call();
  908. git.commit().setMessage("commit2").call();
  909. // stage a mode change
  910. writeTrashFile("file.txt", "a");
  911. db.getFS().setExecute(file, true);
  912. git.add().addFilepattern("file.txt").call();
  913. // dirty the file
  914. writeTrashFile("file.txt", "b");
  915. assertEquals(
  916. "[file.txt, mode:100755, content:a][file2.txt, mode:100644, content:]",
  917. indexState(CONTENT));
  918. assertWorkDir(mkmap("file.txt", "b", "file2.txt", ""));
  919. // Switch branches and check that the dirty file survived in worktree
  920. // and index
  921. git.checkout().setName("b1").call();
  922. assertEquals("[file.txt, mode:100755, content:a]", indexState(CONTENT));
  923. assertWorkDir(mkmap("file.txt", "b"));
  924. }
  925. @Test
  926. public void testDirtyFileModeEqualIndexMerge()
  927. throws Exception {
  928. if (!FS.DETECTED.supportsExecute())
  929. return;
  930. Git git = Git.wrap(db);
  931. // Add non-executable file
  932. File file = writeTrashFile("file.txt", "a");
  933. git.add().addFilepattern("file.txt").call();
  934. git.commit().setMessage("commit1").call();
  935. assertFalse(db.getFS().canExecute(file));
  936. // Create branch
  937. git.branchCreate().setName("b1").call();
  938. // Create second commit with executable file
  939. file = writeTrashFile("file.txt", "b");
  940. db.getFS().setExecute(file, true);
  941. git.add().addFilepattern("file.txt").call();
  942. git.commit().setMessage("commit2").call();
  943. // stage the same content as in the branch we want to switch to
  944. writeTrashFile("file.txt", "a");
  945. db.getFS().setExecute(file, false);
  946. git.add().addFilepattern("file.txt").call();
  947. // dirty the file
  948. writeTrashFile("file.txt", "c");
  949. db.getFS().setExecute(file, true);
  950. assertEquals("[file.txt, mode:100644, content:a]", indexState(CONTENT));
  951. assertWorkDir(mkmap("file.txt", "c"));
  952. // Switch branches and check that the dirty file survived in worktree
  953. // and index
  954. git.checkout().setName("b1").call();
  955. assertEquals("[file.txt, mode:100644, content:a]", indexState(CONTENT));
  956. assertWorkDir(mkmap("file.txt", "c"));
  957. }
  958. @Test
  959. public void testFileModeChangeAndContentChangeNoConflict() throws Exception {
  960. if (!FS.DETECTED.supportsExecute())
  961. return;
  962. Git git = Git.wrap(db);
  963. // Add first file
  964. File file1 = writeTrashFile("file1.txt", "a");
  965. git.add().addFilepattern("file1.txt").call();
  966. git.commit().setMessage("commit1").call();
  967. assertFalse(db.getFS().canExecute(file1));
  968. // Add second file
  969. File file2 = writeTrashFile("file2.txt", "b");
  970. git.add().addFilepattern("file2.txt").call();
  971. git.commit().setMessage("commit2").call();
  972. assertFalse(db.getFS().canExecute(file2));
  973. // Create branch from first commit
  974. assertNotNull(git.checkout().setCreateBranch(true).setName("b1")
  975. .setStartPoint(Constants.HEAD + "~1").call());
  976. // Change content and file mode in working directory and index
  977. file1 = writeTrashFile("file1.txt", "c");
  978. db.getFS().setExecute(file1, true);
  979. git.add().addFilepattern("file1.txt").call();
  980. // Switch back to 'master'
  981. assertNotNull(git.checkout().setName(Constants.MASTER).call());
  982. }
  983. public void assertWorkDir(HashMap<String, String> i) throws CorruptObjectException,
  984. IOException {
  985. TreeWalk walk = new TreeWalk(db);
  986. walk.setRecursive(true);
  987. walk.addTree(new FileTreeIterator(db));
  988. String expectedValue;
  989. String path;
  990. int nrFiles = 0;
  991. FileTreeIterator ft;
  992. while (walk.next()) {
  993. ft = walk.getTree(0, FileTreeIterator.class);
  994. path = ft.getEntryPathString();
  995. expectedValue = i.get(path);
  996. assertNotNull("found unexpected file for path " + path
  997. + " in workdir", expectedValue);
  998. File file = new File(db.getWorkTree(), path);
  999. assertTrue(file.exists());
  1000. if (file.isFile()) {
  1001. FileInputStream is = new FileInputStream(file);
  1002. byte[] buffer = new byte[(int) file.length()];
  1003. int offset = 0;
  1004. int numRead = 0;
  1005. while (offset < buffer.length
  1006. && (numRead = is.read(buffer, offset, buffer.length
  1007. - offset)) >= 0) {
  1008. offset += numRead;
  1009. }
  1010. is.close();
  1011. assertArrayEquals("unexpected content for path " + path
  1012. + " in workDir. ", buffer, i.get(path).getBytes());
  1013. nrFiles++;
  1014. }
  1015. }
  1016. assertEquals("WorkDir has not the right size.", i.size(), nrFiles);
  1017. }
  1018. }