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.internal.storage.pack.PackExt;
32 import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
33 import org.eclipse.jgit.junit.TestRepository;
34 import org.eclipse.jgit.lib.AbbreviatedObjectId;
35 import org.eclipse.jgit.lib.ObjectId;
36 import org.eclipse.jgit.lib.ObjectReader;
37 import org.eclipse.jgit.lib.Repository;
38 import org.eclipse.jgit.revwalk.RevBlob;
39 import org.eclipse.jgit.transport.PackedObjectInfo;
40 import org.eclipse.jgit.util.FileUtils;
41 import org.junit.After;
42 import org.junit.Before;
43 import org.junit.Test;
44
45 public class AbbreviationTest extends LocalDiskRepositoryTestCase {
46 private FileRepository db;
47
48 private ObjectReader reader;
49
50 private TestRepository<Repository> test;
51
52 @Override
53 @Before
54 public void setUp() throws Exception {
55 super.setUp();
56 db = createBareRepository();
57 reader = db.newObjectReader();
58 test = new TestRepository<>(db);
59 }
60
61 @Override
62 @After
63 public void tearDown() throws Exception {
64 if (reader != null) {
65 reader.close();
66 }
67 }
68
69 @Test
70 public void testAbbreviateOnEmptyRepository() throws IOException {
71 ObjectId id = id("9d5b926ed164e8ee88d3b8b1e525d699adda01ba");
72
73 assertEquals(id.abbreviate(2), reader.abbreviate(id, 2));
74 assertEquals(id.abbreviate(7), reader.abbreviate(id, 7));
75 assertEquals(id.abbreviate(8), reader.abbreviate(id, 8));
76 assertEquals(id.abbreviate(10), reader.abbreviate(id, 10));
77 assertEquals(id.abbreviate(16), reader.abbreviate(id, 16));
78
79 assertEquals(AbbreviatedObjectId.fromObjectId(id),
80 reader.abbreviate(id, OBJECT_ID_STRING_LENGTH));
81
82 Collection<ObjectId> matches;
83
84 matches = reader.resolve(reader.abbreviate(id, 8));
85 assertNotNull(matches);
86 assertEquals(0, matches.size());
87
88 matches = reader.resolve(AbbreviatedObjectId.fromObjectId(id));
89 assertNotNull(matches);
90 assertEquals(1, matches.size());
91 assertEquals(id, matches.iterator().next());
92 }
93
94 @Test
95 public void testAbbreviateLooseBlob() throws Exception {
96 ObjectId id = test.blob("test");
97
98 assertEquals(id.abbreviate(2), reader.abbreviate(id, 2));
99 assertEquals(id.abbreviate(7), reader.abbreviate(id, 7));
100 assertEquals(id.abbreviate(8), reader.abbreviate(id, 8));
101 assertEquals(id.abbreviate(10), reader.abbreviate(id, 10));
102 assertEquals(id.abbreviate(16), reader.abbreviate(id, 16));
103
104 Collection<ObjectId> matches = reader.resolve(reader.abbreviate(id, 8));
105 assertNotNull(matches);
106 assertEquals(1, matches.size());
107 assertEquals(id, matches.iterator().next());
108
109 assertEquals(id, db.resolve(reader.abbreviate(id, 8).name()));
110 }
111
112 @Test
113 public void testAbbreviatePackedBlob() throws Exception {
114 RevBlob id = test.blob("test");
115 test.branch("master").commit().add("test", id).child();
116 test.packAndPrune();
117 assertTrue(reader.has(id));
118
119 assertEquals(id.abbreviate(7), reader.abbreviate(id, 7));
120 assertEquals(id.abbreviate(8), reader.abbreviate(id, 8));
121 assertEquals(id.abbreviate(10), reader.abbreviate(id, 10));
122 assertEquals(id.abbreviate(16), reader.abbreviate(id, 16));
123
124 Collection<ObjectId> matches = reader.resolve(reader.abbreviate(id, 8));
125 assertNotNull(matches);
126 assertEquals(1, matches.size());
127 assertEquals(id, matches.iterator().next());
128
129 assertEquals(id, db.resolve(reader.abbreviate(id, 8).name()));
130 }
131
132 @Test
133 public void testAbbreviateIsActuallyUnique() throws Exception {
134
135
136
137
138
139
140 ObjectId id = id("9d5b926ed164e8ee88d3b8b1e525d699adda01ba");
141 byte[] idBuf = toByteArray(id);
142 List<PackedObjectInfo> objects = new ArrayList<>();
143 for (int i = 0; i < 256; i++) {
144 idBuf[9] = (byte) i;
145 objects.add(new PackedObjectInfo(ObjectId.fromRaw(idBuf)));
146 }
147
148 File packDir = db.getObjectDatabase().getPackDirectory();
149 PackFile idxFile = new PackFile(packDir, id, PackExt.INDEX);
150 PackFile packFile = idxFile.create(PackExt.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 }