1
2
3
4
5
6
7
8
9
10
11 package org.eclipse.jgit.internal.storage.file;
12
13 import static org.eclipse.jgit.lib.Constants.OBJECT_ID_LENGTH;
14 import static org.eclipse.jgit.lib.Constants.OBJECT_ID_STRING_LENGTH;
15 import static org.junit.Assert.assertEquals;
16 import static org.junit.Assert.assertNotNull;
17 import static org.junit.Assert.assertTrue;
18 import static org.junit.Assert.fail;
19
20 import java.io.BufferedOutputStream;
21 import java.io.ByteArrayOutputStream;
22 import java.io.File;
23 import java.io.FileOutputStream;
24 import java.io.IOException;
25 import java.io.OutputStream;
26 import java.util.ArrayList;
27 import java.util.Collection;
28 import java.util.List;
29
30 import org.eclipse.jgit.errors.AmbiguousObjectException;
31 import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
32 import org.eclipse.jgit.junit.TestRepository;
33 import org.eclipse.jgit.lib.AbbreviatedObjectId;
34 import org.eclipse.jgit.lib.ObjectId;
35 import org.eclipse.jgit.lib.ObjectReader;
36 import org.eclipse.jgit.lib.Repository;
37 import org.eclipse.jgit.revwalk.RevBlob;
38 import org.eclipse.jgit.transport.PackedObjectInfo;
39 import org.eclipse.jgit.util.FileUtils;
40 import org.junit.After;
41 import org.junit.Before;
42 import org.junit.Test;
43
44 public class AbbreviationTest extends LocalDiskRepositoryTestCase {
45 private FileRepository db;
46
47 private ObjectReader reader;
48
49 private TestRepository<Repository> test;
50
51 @Override
52 @Before
53 public void setUp() throws Exception {
54 super.setUp();
55 db = createBareRepository();
56 reader = db.newObjectReader();
57 test = new TestRepository<>(db);
58 }
59
60 @Override
61 @After
62 public void tearDown() throws Exception {
63 if (reader != null) {
64 reader.close();
65 }
66 }
67
68 @Test
69 public void testAbbreviateOnEmptyRepository() throws IOException {
70 ObjectId id = id("9d5b926ed164e8ee88d3b8b1e525d699adda01ba");
71
72 assertEquals(id.abbreviate(2), reader.abbreviate(id, 2));
73 assertEquals(id.abbreviate(7), reader.abbreviate(id, 7));
74 assertEquals(id.abbreviate(8), reader.abbreviate(id, 8));
75 assertEquals(id.abbreviate(10), reader.abbreviate(id, 10));
76 assertEquals(id.abbreviate(16), reader.abbreviate(id, 16));
77
78 assertEquals(AbbreviatedObjectId.fromObjectId(id),
79 reader.abbreviate(id, OBJECT_ID_STRING_LENGTH));
80
81 Collection<ObjectId> matches;
82
83 matches = reader.resolve(reader.abbreviate(id, 8));
84 assertNotNull(matches);
85 assertEquals(0, matches.size());
86
87 matches = reader.resolve(AbbreviatedObjectId.fromObjectId(id));
88 assertNotNull(matches);
89 assertEquals(1, matches.size());
90 assertEquals(id, matches.iterator().next());
91 }
92
93 @Test
94 public void testAbbreviateLooseBlob() throws Exception {
95 ObjectId id = test.blob("test");
96
97 assertEquals(id.abbreviate(2), reader.abbreviate(id, 2));
98 assertEquals(id.abbreviate(7), reader.abbreviate(id, 7));
99 assertEquals(id.abbreviate(8), reader.abbreviate(id, 8));
100 assertEquals(id.abbreviate(10), reader.abbreviate(id, 10));
101 assertEquals(id.abbreviate(16), reader.abbreviate(id, 16));
102
103 Collection<ObjectId> matches = reader.resolve(reader.abbreviate(id, 8));
104 assertNotNull(matches);
105 assertEquals(1, matches.size());
106 assertEquals(id, matches.iterator().next());
107
108 assertEquals(id, db.resolve(reader.abbreviate(id, 8).name()));
109 }
110
111 @Test
112 public void testAbbreviatePackedBlob() throws Exception {
113 RevBlob id = test.blob("test");
114 test.branch("master").commit().add("test", id).child();
115 test.packAndPrune();
116 assertTrue(reader.has(id));
117
118 assertEquals(id.abbreviate(7), reader.abbreviate(id, 7));
119 assertEquals(id.abbreviate(8), reader.abbreviate(id, 8));
120 assertEquals(id.abbreviate(10), reader.abbreviate(id, 10));
121 assertEquals(id.abbreviate(16), reader.abbreviate(id, 16));
122
123 Collection<ObjectId> matches = reader.resolve(reader.abbreviate(id, 8));
124 assertNotNull(matches);
125 assertEquals(1, matches.size());
126 assertEquals(id, matches.iterator().next());
127
128 assertEquals(id, db.resolve(reader.abbreviate(id, 8).name()));
129 }
130
131 @Test
132 public void testAbbreviateIsActuallyUnique() throws Exception {
133
134
135
136
137
138
139 ObjectId id = id("9d5b926ed164e8ee88d3b8b1e525d699adda01ba");
140 byte[] idBuf = toByteArray(id);
141 List<PackedObjectInfo> objects = new ArrayList<>();
142 for (int i = 0; i < 256; i++) {
143 idBuf[9] = (byte) i;
144 objects.add(new PackedObjectInfo(ObjectId.fromRaw(idBuf)));
145 }
146
147 String packName = "pack-" + id.name();
148 File packDir = db.getObjectDatabase().getPackDirectory();
149 File idxFile = new File(packDir, packName + ".idx");
150 File packFile = new File(packDir, packName + ".pack");
151 FileUtils.mkdir(packDir, true);
152 try (OutputStream dst = new BufferedOutputStream(
153 new FileOutputStream(idxFile))) {
154 PackIndexWriter writer = new PackIndexWriterV2(dst);
155 writer.write(objects, new byte[OBJECT_ID_LENGTH]);
156 }
157
158 try (FileOutputStream unused = new FileOutputStream(packFile)) {
159
160 }
161
162 assertEquals(id.abbreviate(20), reader.abbreviate(id, 2));
163
164 AbbreviatedObjectId abbrev8 = id.abbreviate(8);
165 Collection<ObjectId> matches = reader.resolve(abbrev8);
166 assertNotNull(matches);
167 assertEquals(objects.size(), matches.size());
168 for (PackedObjectInfo info : objects)
169 assertTrue("contains " + info.name(), matches.contains(info));
170
171 try {
172 db.resolve(abbrev8.name());
173 fail("did not throw AmbiguousObjectException");
174 } catch (AmbiguousObjectException err) {
175 assertEquals(abbrev8, err.getAbbreviatedObjectId());
176 matches = err.getCandidates();
177 assertNotNull(matches);
178 assertEquals(objects.size(), matches.size());
179 for (PackedObjectInfo info : objects)
180 assertTrue("contains " + info.name(), matches.contains(info));
181 }
182
183 assertEquals(id, db.resolve(id.abbreviate(20).name()));
184 }
185
186 private static ObjectId id(String name) {
187 return ObjectId.fromString(name);
188 }
189
190 private static byte[] toByteArray(ObjectId id) throws IOException {
191 ByteArrayOutputStream buf = new ByteArrayOutputStream(OBJECT_ID_LENGTH);
192 id.copyRawTo(buf);
193 return buf.toByteArray();
194 }
195 }