/* * Copyright (c) 2020, Google LLC and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * SPDX-License-Identifier: BSD-3-Clause */ package org.eclipse.jgit.internal.storage.dfs; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Collections; import java.util.Set; import org.eclipse.jgit.api.GarbageCollectCommand; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.junit.TestRepository; import org.eclipse.jgit.lib.NullProgressMonitor; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.transport.FetchResult; import org.eclipse.jgit.transport.RefSpec; import org.eclipse.jgit.transport.TransportBundleStream; import org.eclipse.jgit.transport.URIish; import org.junit.Before; import org.junit.Test; public class DfsBundleWriterTest { private TestRepository git; private InMemoryRepository repo; @Before public void setUp() throws IOException { DfsRepositoryDescription desc = new DfsRepositoryDescription("test"); git = new TestRepository<>(new InMemoryRepository(desc)); repo = git.getRepository(); } @Test public void makeBundle_containsUnreferencedObject() throws Exception { RevCommit commit0 = git.commit().message("0").create(); RevCommit commit1 = git.commit().message("1").parent(commit0).create(); git.update("master", commit1); RevCommit commit2 = git.commit().message("0").create(); byte[] bundle = makeBundle(); try (Repository newRepo = new InMemoryRepository( new DfsRepositoryDescription("copy"))) { fetchFromBundle(newRepo, bundle); Ref ref = newRepo.exactRef("refs/heads/master"); assertNotNull(ref); assertEquals(commit1.toObjectId(), ref.getObjectId()); // Unreferenced objects are included as well. assertTrue(newRepo.getObjectDatabase().has(commit2)); } } @Test public void makeBundle_containsObjectInGcRestPack() throws Exception { RevCommit commit0 = git.commit().message("0").create(); RevCommit commit1 = git.commit().message("1").parent(commit0).create(); git.update("master", commit1); RevCommit commit2 = git.commit().message("0").create(); // This moves unreachable commit2 to GC_REST pack. GarbageCollectCommand gc = Git.wrap(repo).gc(); gc.call(); byte[] bundle = makeBundle(); try (Repository newRepo = new InMemoryRepository( new DfsRepositoryDescription("copy"))) { fetchFromBundle(newRepo, bundle); Ref ref = newRepo.exactRef("refs/heads/master"); assertNotNull(ref); assertEquals(commit1.toObjectId(), ref.getObjectId()); // Unreferenced objects in GC_REST pack are included as well. assertTrue(newRepo.getObjectDatabase().has(commit2)); } } private byte[] makeBundle() throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); DfsBundleWriter.writeEntireRepositoryAsBundle( NullProgressMonitor.INSTANCE, out, repo); return out.toByteArray(); } private static FetchResult fetchFromBundle(Repository newRepo, byte[] bundle) throws Exception { URIish uri = new URIish("in-memory://"); ByteArrayInputStream in = new ByteArrayInputStream(bundle); RefSpec rs = new RefSpec("refs/heads/*:refs/heads/*"); Set refs = Collections.singleton(rs); try (TransportBundleStream transport = new TransportBundleStream( newRepo, uri, in)) { return transport.fetch(NullProgressMonitor.INSTANCE, refs); } } }