Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

PackWriterTest.java 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604
  1. /*
  2. * Copyright (C) 2008, Marek Zawirski <marek.zawirski@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.storage.file;
  44. import static org.junit.Assert.assertEquals;
  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.ByteArrayInputStream;
  49. import java.io.ByteArrayOutputStream;
  50. import java.io.File;
  51. import java.io.FileOutputStream;
  52. import java.io.IOException;
  53. import java.util.ArrayList;
  54. import java.util.Arrays;
  55. import java.util.Collections;
  56. import java.util.Comparator;
  57. import java.util.HashSet;
  58. import java.util.List;
  59. import java.util.Set;
  60. import org.eclipse.jgit.errors.MissingObjectException;
  61. import org.eclipse.jgit.junit.JGitTestUtil;
  62. import org.eclipse.jgit.lib.NullProgressMonitor;
  63. import org.eclipse.jgit.lib.ObjectId;
  64. import org.eclipse.jgit.lib.ObjectInserter;
  65. import org.eclipse.jgit.lib.SampleDataRepositoryTestCase;
  66. import org.eclipse.jgit.revwalk.RevObject;
  67. import org.eclipse.jgit.revwalk.RevWalk;
  68. import org.eclipse.jgit.storage.file.PackIndex.MutableEntry;
  69. import org.eclipse.jgit.storage.pack.PackConfig;
  70. import org.eclipse.jgit.storage.pack.PackWriter;
  71. import org.eclipse.jgit.transport.PackParser;
  72. import org.junit.After;
  73. import org.junit.Before;
  74. import org.junit.Test;
  75. public class PackWriterTest extends SampleDataRepositoryTestCase {
  76. private static final Set<ObjectId> EMPTY_SET_OBJECT = Collections
  77. .<ObjectId> emptySet();
  78. private static final List<RevObject> EMPTY_LIST_REVS = Collections
  79. .<RevObject> emptyList();
  80. private PackConfig config;
  81. private PackWriter writer;
  82. private ByteArrayOutputStream os;
  83. private PackFile pack;
  84. private ObjectInserter inserter;
  85. private FileRepository dst;
  86. @Before
  87. public void setUp() throws Exception {
  88. super.setUp();
  89. os = new ByteArrayOutputStream();
  90. config = new PackConfig(db);
  91. dst = createBareRepository();
  92. File alt = new File(dst.getObjectDatabase().getDirectory(), "info/alternates");
  93. alt.getParentFile().mkdirs();
  94. write(alt, db.getObjectDatabase().getDirectory().getAbsolutePath() + "\n");
  95. }
  96. @After
  97. public void tearDown() throws Exception {
  98. if (writer != null) {
  99. writer.release();
  100. writer = null;
  101. }
  102. if (inserter != null) {
  103. inserter.release();
  104. inserter = null;
  105. }
  106. super.tearDown();
  107. }
  108. /**
  109. * Test constructor for exceptions, default settings, initialization.
  110. *
  111. * @throws IOException
  112. */
  113. @Test
  114. public void testContructor() throws IOException {
  115. writer = new PackWriter(config, db.newObjectReader());
  116. assertEquals(false, writer.isDeltaBaseAsOffset());
  117. assertEquals(true, config.isReuseDeltas());
  118. assertEquals(true, config.isReuseObjects());
  119. assertEquals(0, writer.getObjectCount());
  120. }
  121. /**
  122. * Change default settings and verify them.
  123. */
  124. @Test
  125. public void testModifySettings() {
  126. config.setReuseDeltas(false);
  127. config.setReuseObjects(false);
  128. config.setDeltaBaseAsOffset(false);
  129. assertEquals(false, config.isReuseDeltas());
  130. assertEquals(false, config.isReuseObjects());
  131. assertEquals(false, config.isDeltaBaseAsOffset());
  132. writer = new PackWriter(config, db.newObjectReader());
  133. writer.setDeltaBaseAsOffset(true);
  134. assertEquals(true, writer.isDeltaBaseAsOffset());
  135. assertEquals(false, config.isDeltaBaseAsOffset());
  136. }
  137. /**
  138. * Write empty pack by providing empty sets of interesting/uninteresting
  139. * objects and check for correct format.
  140. *
  141. * @throws IOException
  142. */
  143. @Test
  144. public void testWriteEmptyPack1() throws IOException {
  145. createVerifyOpenPack(EMPTY_SET_OBJECT, EMPTY_SET_OBJECT, false, false);
  146. assertEquals(0, writer.getObjectCount());
  147. assertEquals(0, pack.getObjectCount());
  148. assertEquals("da39a3ee5e6b4b0d3255bfef95601890afd80709", writer
  149. .computeName().name());
  150. }
  151. /**
  152. * Write empty pack by providing empty iterator of objects to write and
  153. * check for correct format.
  154. *
  155. * @throws IOException
  156. */
  157. @Test
  158. public void testWriteEmptyPack2() throws IOException {
  159. createVerifyOpenPack(EMPTY_LIST_REVS);
  160. assertEquals(0, writer.getObjectCount());
  161. assertEquals(0, pack.getObjectCount());
  162. }
  163. /**
  164. * Try to pass non-existing object as uninteresting, with non-ignoring
  165. * setting.
  166. *
  167. * @throws IOException
  168. */
  169. @Test
  170. public void testNotIgnoreNonExistingObjects() throws IOException {
  171. final ObjectId nonExisting = ObjectId
  172. .fromString("0000000000000000000000000000000000000001");
  173. try {
  174. createVerifyOpenPack(EMPTY_SET_OBJECT, Collections.singleton(
  175. nonExisting), false, false);
  176. fail("Should have thrown MissingObjectException");
  177. } catch (MissingObjectException x) {
  178. // expected
  179. }
  180. }
  181. /**
  182. * Try to pass non-existing object as uninteresting, with ignoring setting.
  183. *
  184. * @throws IOException
  185. */
  186. @Test
  187. public void testIgnoreNonExistingObjects() throws IOException {
  188. final ObjectId nonExisting = ObjectId
  189. .fromString("0000000000000000000000000000000000000001");
  190. createVerifyOpenPack(EMPTY_SET_OBJECT, Collections.singleton(
  191. nonExisting), false, true);
  192. // shouldn't throw anything
  193. }
  194. /**
  195. * Create pack basing on only interesting objects, then precisely verify
  196. * content. No delta reuse here.
  197. *
  198. * @throws IOException
  199. */
  200. @Test
  201. public void testWritePack1() throws IOException {
  202. config.setReuseDeltas(false);
  203. writeVerifyPack1();
  204. }
  205. /**
  206. * Test writing pack without object reuse. Pack content/preparation as in
  207. * {@link #testWritePack1()}.
  208. *
  209. * @throws IOException
  210. */
  211. @Test
  212. public void testWritePack1NoObjectReuse() throws IOException {
  213. config.setReuseDeltas(false);
  214. config.setReuseObjects(false);
  215. writeVerifyPack1();
  216. }
  217. /**
  218. * Create pack basing on both interesting and uninteresting objects, then
  219. * precisely verify content. No delta reuse here.
  220. *
  221. * @throws IOException
  222. */
  223. @Test
  224. public void testWritePack2() throws IOException {
  225. writeVerifyPack2(false);
  226. }
  227. /**
  228. * Test pack writing with deltas reuse, delta-base first rule. Pack
  229. * content/preparation as in {@link #testWritePack2()}.
  230. *
  231. * @throws IOException
  232. */
  233. @Test
  234. public void testWritePack2DeltasReuseRefs() throws IOException {
  235. writeVerifyPack2(true);
  236. }
  237. /**
  238. * Test pack writing with delta reuse. Delta bases referred as offsets. Pack
  239. * configuration as in {@link #testWritePack2DeltasReuseRefs()}.
  240. *
  241. * @throws IOException
  242. */
  243. @Test
  244. public void testWritePack2DeltasReuseOffsets() throws IOException {
  245. config.setDeltaBaseAsOffset(true);
  246. writeVerifyPack2(true);
  247. }
  248. /**
  249. * Test pack writing with delta reuse. Raw-data copy (reuse) is made on a
  250. * pack with CRC32 index. Pack configuration as in
  251. * {@link #testWritePack2DeltasReuseRefs()}.
  252. *
  253. * @throws IOException
  254. */
  255. @Test
  256. public void testWritePack2DeltasCRC32Copy() throws IOException {
  257. final File packDir = new File(db.getObjectDatabase().getDirectory(), "pack");
  258. final File crc32Pack = new File(packDir,
  259. "pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.pack");
  260. final File crc32Idx = new File(packDir,
  261. "pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.idx");
  262. copyFile(JGitTestUtil.getTestResourceFile(
  263. "pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.idxV2"),
  264. crc32Idx);
  265. db.openPack(crc32Pack, crc32Idx);
  266. writeVerifyPack2(true);
  267. }
  268. /**
  269. * Create pack basing on fixed objects list, then precisely verify content.
  270. * No delta reuse here.
  271. *
  272. * @throws IOException
  273. * @throws MissingObjectException
  274. *
  275. */
  276. @Test
  277. public void testWritePack3() throws MissingObjectException, IOException {
  278. config.setReuseDeltas(false);
  279. final ObjectId forcedOrder[] = new ObjectId[] {
  280. ObjectId.fromString("82c6b885ff600be425b4ea96dee75dca255b69e7"),
  281. ObjectId.fromString("c59759f143fb1fe21c197981df75a7ee00290799"),
  282. ObjectId.fromString("aabf2ffaec9b497f0950352b3e582d73035c2035"),
  283. ObjectId.fromString("902d5476fa249b7abc9d84c611577a81381f0327"),
  284. ObjectId.fromString("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259"),
  285. ObjectId.fromString("6ff87c4664981e4397625791c8ea3bbb5f2279a3") };
  286. final RevWalk parser = new RevWalk(db);
  287. final RevObject forcedOrderRevs[] = new RevObject[forcedOrder.length];
  288. for (int i = 0; i < forcedOrder.length; i++)
  289. forcedOrderRevs[i] = parser.parseAny(forcedOrder[i]);
  290. createVerifyOpenPack(Arrays.asList(forcedOrderRevs));
  291. assertEquals(forcedOrder.length, writer.getObjectCount());
  292. verifyObjectsOrder(forcedOrder);
  293. assertEquals("ed3f96b8327c7c66b0f8f70056129f0769323d86", writer
  294. .computeName().name());
  295. }
  296. /**
  297. * Another pack creation: basing on both interesting and uninteresting
  298. * objects. No delta reuse possible here, as this is a specific case when we
  299. * write only 1 commit, associated with 1 tree, 1 blob.
  300. *
  301. * @throws IOException
  302. */
  303. @Test
  304. public void testWritePack4() throws IOException {
  305. writeVerifyPack4(false);
  306. }
  307. /**
  308. * Test thin pack writing: 1 blob delta base is on objects edge. Pack
  309. * configuration as in {@link #testWritePack4()}.
  310. *
  311. * @throws IOException
  312. */
  313. @Test
  314. public void testWritePack4ThinPack() throws IOException {
  315. writeVerifyPack4(true);
  316. }
  317. /**
  318. * Compare sizes of packs created using {@link #testWritePack2()} and
  319. * {@link #testWritePack2DeltasReuseRefs()}. The pack using deltas should
  320. * be smaller.
  321. *
  322. * @throws Exception
  323. */
  324. @Test
  325. public void testWritePack2SizeDeltasVsNoDeltas() throws Exception {
  326. testWritePack2();
  327. final long sizePack2NoDeltas = os.size();
  328. tearDown();
  329. setUp();
  330. testWritePack2DeltasReuseRefs();
  331. final long sizePack2DeltasRefs = os.size();
  332. assertTrue(sizePack2NoDeltas > sizePack2DeltasRefs);
  333. }
  334. /**
  335. * Compare sizes of packs created using
  336. * {@link #testWritePack2DeltasReuseRefs()} and
  337. * {@link #testWritePack2DeltasReuseOffsets()}. The pack with delta bases
  338. * written as offsets should be smaller.
  339. *
  340. * @throws Exception
  341. */
  342. @Test
  343. public void testWritePack2SizeOffsetsVsRefs() throws Exception {
  344. testWritePack2DeltasReuseRefs();
  345. final long sizePack2DeltasRefs = os.size();
  346. tearDown();
  347. setUp();
  348. testWritePack2DeltasReuseOffsets();
  349. final long sizePack2DeltasOffsets = os.size();
  350. assertTrue(sizePack2DeltasRefs > sizePack2DeltasOffsets);
  351. }
  352. /**
  353. * Compare sizes of packs created using {@link #testWritePack4()} and
  354. * {@link #testWritePack4ThinPack()}. Obviously, the thin pack should be
  355. * smaller.
  356. *
  357. * @throws Exception
  358. */
  359. @Test
  360. public void testWritePack4SizeThinVsNoThin() throws Exception {
  361. testWritePack4();
  362. final long sizePack4 = os.size();
  363. tearDown();
  364. setUp();
  365. testWritePack4ThinPack();
  366. final long sizePack4Thin = os.size();
  367. assertTrue(sizePack4 > sizePack4Thin);
  368. }
  369. @Test
  370. public void testWriteIndex() throws Exception {
  371. config.setIndexVersion(2);
  372. writeVerifyPack4(false);
  373. File packFile = pack.getPackFile();
  374. String name = packFile.getName();
  375. String base = name.substring(0, name.lastIndexOf('.'));
  376. File indexFile = new File(packFile.getParentFile(), base + ".idx");
  377. // Validate that IndexPack came up with the right CRC32 value.
  378. final PackIndex idx1 = PackIndex.open(indexFile);
  379. assertTrue(idx1 instanceof PackIndexV2);
  380. assertEquals(0x4743F1E4L, idx1.findCRC32(ObjectId
  381. .fromString("82c6b885ff600be425b4ea96dee75dca255b69e7")));
  382. // Validate that an index written by PackWriter is the same.
  383. final File idx2File = new File(indexFile.getAbsolutePath() + ".2");
  384. final FileOutputStream is = new FileOutputStream(idx2File);
  385. try {
  386. writer.writeIndex(is);
  387. } finally {
  388. is.close();
  389. }
  390. final PackIndex idx2 = PackIndex.open(idx2File);
  391. assertTrue(idx2 instanceof PackIndexV2);
  392. assertEquals(idx1.getObjectCount(), idx2.getObjectCount());
  393. assertEquals(idx1.getOffset64Count(), idx2.getOffset64Count());
  394. for (int i = 0; i < idx1.getObjectCount(); i++) {
  395. final ObjectId id = idx1.getObjectId(i);
  396. assertEquals(id, idx2.getObjectId(i));
  397. assertEquals(idx1.findOffset(id), idx2.findOffset(id));
  398. assertEquals(idx1.findCRC32(id), idx2.findCRC32(id));
  399. }
  400. }
  401. // TODO: testWritePackDeltasCycle()
  402. // TODO: testWritePackDeltasDepth()
  403. private void writeVerifyPack1() throws IOException {
  404. final HashSet<ObjectId> interestings = new HashSet<ObjectId>();
  405. interestings.add(ObjectId
  406. .fromString("82c6b885ff600be425b4ea96dee75dca255b69e7"));
  407. createVerifyOpenPack(interestings, EMPTY_SET_OBJECT, false, false);
  408. final ObjectId expectedOrder[] = new ObjectId[] {
  409. ObjectId.fromString("82c6b885ff600be425b4ea96dee75dca255b69e7"),
  410. ObjectId.fromString("c59759f143fb1fe21c197981df75a7ee00290799"),
  411. ObjectId.fromString("540a36d136cf413e4b064c2b0e0a4db60f77feab"),
  412. ObjectId.fromString("aabf2ffaec9b497f0950352b3e582d73035c2035"),
  413. ObjectId.fromString("902d5476fa249b7abc9d84c611577a81381f0327"),
  414. ObjectId.fromString("4b825dc642cb6eb9a060e54bf8d69288fbee4904"),
  415. ObjectId.fromString("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259"),
  416. ObjectId.fromString("6ff87c4664981e4397625791c8ea3bbb5f2279a3") };
  417. assertEquals(expectedOrder.length, writer.getObjectCount());
  418. verifyObjectsOrder(expectedOrder);
  419. assertEquals("34be9032ac282b11fa9babdc2b2a93ca996c9c2f", writer
  420. .computeName().name());
  421. }
  422. private void writeVerifyPack2(boolean deltaReuse) throws IOException {
  423. config.setReuseDeltas(deltaReuse);
  424. final HashSet<ObjectId> interestings = new HashSet<ObjectId>();
  425. interestings.add(ObjectId
  426. .fromString("82c6b885ff600be425b4ea96dee75dca255b69e7"));
  427. final HashSet<ObjectId> uninterestings = new HashSet<ObjectId>();
  428. uninterestings.add(ObjectId
  429. .fromString("540a36d136cf413e4b064c2b0e0a4db60f77feab"));
  430. createVerifyOpenPack(interestings, uninterestings, false, false);
  431. final ObjectId expectedOrder[] = new ObjectId[] {
  432. ObjectId.fromString("82c6b885ff600be425b4ea96dee75dca255b69e7"),
  433. ObjectId.fromString("c59759f143fb1fe21c197981df75a7ee00290799"),
  434. ObjectId.fromString("aabf2ffaec9b497f0950352b3e582d73035c2035"),
  435. ObjectId.fromString("902d5476fa249b7abc9d84c611577a81381f0327"),
  436. ObjectId.fromString("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259"),
  437. ObjectId.fromString("6ff87c4664981e4397625791c8ea3bbb5f2279a3") };
  438. if (deltaReuse) {
  439. // objects order influenced (swapped) by delta-base first rule
  440. ObjectId temp = expectedOrder[4];
  441. expectedOrder[4] = expectedOrder[5];
  442. expectedOrder[5] = temp;
  443. }
  444. assertEquals(expectedOrder.length, writer.getObjectCount());
  445. verifyObjectsOrder(expectedOrder);
  446. assertEquals("ed3f96b8327c7c66b0f8f70056129f0769323d86", writer
  447. .computeName().name());
  448. }
  449. private void writeVerifyPack4(final boolean thin) throws IOException {
  450. final HashSet<ObjectId> interestings = new HashSet<ObjectId>();
  451. interestings.add(ObjectId
  452. .fromString("82c6b885ff600be425b4ea96dee75dca255b69e7"));
  453. final HashSet<ObjectId> uninterestings = new HashSet<ObjectId>();
  454. uninterestings.add(ObjectId
  455. .fromString("c59759f143fb1fe21c197981df75a7ee00290799"));
  456. createVerifyOpenPack(interestings, uninterestings, thin, false);
  457. final ObjectId writtenObjects[] = new ObjectId[] {
  458. ObjectId.fromString("82c6b885ff600be425b4ea96dee75dca255b69e7"),
  459. ObjectId.fromString("aabf2ffaec9b497f0950352b3e582d73035c2035"),
  460. ObjectId.fromString("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259") };
  461. assertEquals(writtenObjects.length, writer.getObjectCount());
  462. ObjectId expectedObjects[];
  463. if (thin) {
  464. expectedObjects = new ObjectId[4];
  465. System.arraycopy(writtenObjects, 0, expectedObjects, 0,
  466. writtenObjects.length);
  467. expectedObjects[3] = ObjectId
  468. .fromString("6ff87c4664981e4397625791c8ea3bbb5f2279a3");
  469. } else {
  470. expectedObjects = writtenObjects;
  471. }
  472. verifyObjectsOrder(expectedObjects);
  473. assertEquals("cded4b74176b4456afa456768b2b5aafb41c44fc", writer
  474. .computeName().name());
  475. }
  476. private void createVerifyOpenPack(final Set<ObjectId> interestings,
  477. final Set<ObjectId> uninterestings, final boolean thin,
  478. final boolean ignoreMissingUninteresting)
  479. throws MissingObjectException, IOException {
  480. NullProgressMonitor m = NullProgressMonitor.INSTANCE;
  481. writer = new PackWriter(config, db.newObjectReader());
  482. writer.setThin(thin);
  483. writer.setIgnoreMissingUninteresting(ignoreMissingUninteresting);
  484. writer.preparePack(m, interestings, uninterestings);
  485. writer.writePack(m, m, os);
  486. writer.release();
  487. verifyOpenPack(thin);
  488. }
  489. private void createVerifyOpenPack(final List<RevObject> objectSource)
  490. throws MissingObjectException, IOException {
  491. NullProgressMonitor m = NullProgressMonitor.INSTANCE;
  492. writer = new PackWriter(config, db.newObjectReader());
  493. writer.preparePack(objectSource.iterator());
  494. assertEquals(objectSource.size(), writer.getObjectCount());
  495. writer.writePack(m, m, os);
  496. writer.release();
  497. verifyOpenPack(false);
  498. }
  499. private void verifyOpenPack(final boolean thin) throws IOException {
  500. final byte[] packData = os.toByteArray();
  501. if (thin) {
  502. PackParser p = index(packData);
  503. try {
  504. p.parse(NullProgressMonitor.INSTANCE);
  505. fail("indexer should grumble about missing object");
  506. } catch (IOException x) {
  507. // expected
  508. }
  509. }
  510. ObjectDirectoryPackParser p = (ObjectDirectoryPackParser) index(packData);
  511. p.setKeepEmpty(true);
  512. p.setAllowThin(thin);
  513. p.setIndexVersion(2);
  514. p.parse(NullProgressMonitor.INSTANCE);
  515. pack = p.getPackFile();
  516. assertNotNull("have PackFile after parsing", pack);
  517. }
  518. private PackParser index(final byte[] packData) throws IOException {
  519. if (inserter == null)
  520. inserter = dst.newObjectInserter();
  521. return inserter.newPackParser(new ByteArrayInputStream(packData));
  522. }
  523. private void verifyObjectsOrder(final ObjectId objectsOrder[]) {
  524. final List<PackIndex.MutableEntry> entries = new ArrayList<PackIndex.MutableEntry>();
  525. for (MutableEntry me : pack) {
  526. entries.add(me.cloneEntry());
  527. }
  528. Collections.sort(entries, new Comparator<PackIndex.MutableEntry>() {
  529. public int compare(MutableEntry o1, MutableEntry o2) {
  530. return Long.signum(o1.getOffset() - o2.getOffset());
  531. }
  532. });
  533. int i = 0;
  534. for (MutableEntry me : entries) {
  535. assertEquals(objectsOrder[i++].toObjectId(), me.toObjectId());
  536. }
  537. }
  538. }