View Javadoc
1   /*
2    * Copyright (c) 2020, Google LLC  and others
3    *
4    * This program and the accompanying materials are made available under the
5    * terms of the Eclipse Distribution License v. 1.0 which is available at
6    * http://www.eclipse.org/org/documents/edl-v10.php.
7    *
8    * SPDX-License-Identifier: BSD-3-Clause
9    */
10  package org.eclipse.jgit.internal.storage.dfs;
11  
12  import static org.junit.Assert.assertEquals;
13  import static org.junit.Assert.assertNotNull;
14  import static org.junit.Assert.assertTrue;
15  
16  import java.io.ByteArrayInputStream;
17  import java.io.ByteArrayOutputStream;
18  import java.io.IOException;
19  import java.util.Collections;
20  import java.util.Set;
21  
22  import org.eclipse.jgit.api.GarbageCollectCommand;
23  import org.eclipse.jgit.api.Git;
24  import org.eclipse.jgit.junit.TestRepository;
25  import org.eclipse.jgit.lib.NullProgressMonitor;
26  import org.eclipse.jgit.lib.Ref;
27  import org.eclipse.jgit.lib.Repository;
28  import org.eclipse.jgit.revwalk.RevCommit;
29  import org.eclipse.jgit.transport.FetchResult;
30  import org.eclipse.jgit.transport.RefSpec;
31  import org.eclipse.jgit.transport.TransportBundleStream;
32  import org.eclipse.jgit.transport.URIish;
33  import org.junit.Before;
34  import org.junit.Test;
35  
36  public class DfsBundleWriterTest {
37  	private TestRepository<InMemoryRepository> git;
38  
39  	private InMemoryRepository repo;
40  
41  	@Before
42  	public void setUp() throws IOException {
43  		DfsRepositoryDescription desc = new DfsRepositoryDescription("test");
44  		git = new TestRepository<>(new InMemoryRepository(desc));
45  		repo = git.getRepository();
46  	}
47  
48  	@Test
49  	public void makeBundle_containsUnreferencedObject() throws Exception {
50  		RevCommit commit0 = git.commit().message("0").create();
51  		RevCommit commit1 = git.commit().message("1").parent(commit0).create();
52  		git.update("master", commit1);
53  
54  		RevCommit commit2 = git.commit().message("0").create();
55  
56  		byte[] bundle = makeBundle();
57  		try (Repository newRepo = new InMemoryRepository(
58  				new DfsRepositoryDescription("copy"))) {
59  			fetchFromBundle(newRepo, bundle);
60  			Ref ref = newRepo.exactRef("refs/heads/master");
61  			assertNotNull(ref);
62  			assertEquals(commit1.toObjectId(), ref.getObjectId());
63  
64  			// Unreferenced objects are included as well.
65  			assertTrue(newRepo.getObjectDatabase().has(commit2));
66  		}
67  	}
68  
69  	@Test
70  	public void makeBundle_containsObjectInGcRestPack() throws Exception {
71  		RevCommit commit0 = git.commit().message("0").create();
72  		RevCommit commit1 = git.commit().message("1").parent(commit0).create();
73  		git.update("master", commit1);
74  
75  		RevCommit commit2 = git.commit().message("0").create();
76  
77  		// This moves unreachable commit2 to GC_REST pack.
78  		GarbageCollectCommand gc = Git.wrap(repo).gc();
79  		gc.call();
80  
81  		byte[] bundle = makeBundle();
82  		try (Repository newRepo = new InMemoryRepository(
83  				new DfsRepositoryDescription("copy"))) {
84  			fetchFromBundle(newRepo, bundle);
85  			Ref ref = newRepo.exactRef("refs/heads/master");
86  			assertNotNull(ref);
87  			assertEquals(commit1.toObjectId(), ref.getObjectId());
88  
89  			// Unreferenced objects in GC_REST pack are included as well.
90  			assertTrue(newRepo.getObjectDatabase().has(commit2));
91  		}
92  	}
93  
94  	private byte[] makeBundle() throws IOException {
95  		ByteArrayOutputStream out = new ByteArrayOutputStream();
96  		DfsBundleWriter.writeEntireRepositoryAsBundle(
97  				NullProgressMonitor.INSTANCE, out, repo);
98  		return out.toByteArray();
99  	}
100 
101 	private static FetchResult fetchFromBundle(Repository newRepo,
102 			byte[] bundle) throws Exception {
103 		URIish uri = new URIish("in-memory://");
104 		ByteArrayInputStream in = new ByteArrayInputStream(bundle);
105 		RefSpec rs = new RefSpec("refs/heads/*:refs/heads/*");
106 		Set<RefSpec> refs = Collections.singleton(rs);
107 		try (TransportBundleStream transport = new TransportBundleStream(
108 				newRepo, uri, in)) {
109 			return transport.fetch(NullProgressMonitor.INSTANCE, refs);
110 		}
111 	}
112 }