2
This code is derived from jgit (http://eclipse.org/jgit).
3
Copyright owners are documented in jgit's IP log.
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
12
Redistribution and use in source and binary forms, with or
13
without modification, are permitted provided that the following
16
- Redistributions of source code must retain the above copyright
17
notice, this list of conditions and the following disclaimer.
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.
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
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.
45
using System.Collections.Generic;
48
using NGit.Storage.File;
52
namespace NGit.Storage.File
55
/// Access path to locate objects by
56
/// <see cref="NGit.ObjectId">NGit.ObjectId</see>
58
/// <see cref="PackFile">PackFile</see>
61
/// Indexes are strictly redundant information in that we can rebuild all of the
62
/// data held in the index file from the on disk representation of the pack file
63
/// itself, but it is faster to access for random requests because data is stored
67
public abstract class PackIndex : Iterable<PackIndex.MutableEntry>
69
/// <summary>Open an existing pack <code>.idx</code> file for reading.</summary>
71
/// Open an existing pack <code>.idx</code> file for reading.
73
/// The format of the file will be automatically detected and a proper access
74
/// implementation for that format will be constructed and returned to the
75
/// caller. The file may or may not be held open by the returned instance.
78
/// <param name="idxFile">existing pack .idx to read.</param>
79
/// <returns>access implementation for the requested file.</returns>
80
/// <exception cref="System.IO.FileNotFoundException">the file does not exist.</exception>
81
/// <exception cref="System.IO.IOException">
82
/// the file exists but could not be read due to security errors,
83
/// unrecognized data version, or unexpected data corruption.
85
public static PackIndex Open(FilePath idxFile)
87
FileInputStream fd = new FileInputStream(idxFile);
90
byte[] hdr = new byte[8];
91
IOUtil.ReadFully(fd, hdr, 0, hdr.Length);
94
int v = NB.DecodeInt32(hdr, 4);
99
return new PackIndexV2(fd);
104
throw new IOException(MessageFormat.Format(JGitText.Get().unsupportedPackIndexVersion
109
return new PackIndexV1(fd, hdr);
111
catch (IOException ioe)
113
string path = idxFile.GetAbsolutePath();
115
err = new IOException(MessageFormat.Format(JGitText.Get().unreadablePackIndex, path
117
Sharpen.Extensions.InitCause(err, ioe);
133
private static bool IsTOC(byte[] h)
135
byte[] toc = PackIndexWriter.TOC;
136
for (int i = 0; i < toc.Length; i++)
146
/// <summary>Footer checksum applied on the bottom of the pack file.</summary>
147
/// <remarks>Footer checksum applied on the bottom of the pack file.</remarks>
148
protected internal byte[] packChecksum;
150
/// <summary>Determine if an object is contained within the pack file.</summary>
151
/// <remarks>Determine if an object is contained within the pack file.</remarks>
152
/// <param name="id">the object to look for. Must not be null.</param>
153
/// <returns>true if the object is listed in this index; false otherwise.</returns>
154
public virtual bool HasObject(AnyObjectId id)
156
return FindOffset(id) != -1;
159
/// <summary>Provide iterator that gives access to index entries.</summary>
161
/// Provide iterator that gives access to index entries. Note, that iterator
162
/// returns reference to mutable object, the same reference in each call -
163
/// for performance reason. If client needs immutable objects, it must copy
164
/// returned object on its own.
166
/// Iterator returns objects in SHA-1 lexicographical order.
169
/// <returns>iterator over pack index entries</returns>
170
public abstract override Sharpen.Iterator<PackIndex.MutableEntry> Iterator();
172
/// <summary>Obtain the total number of objects described by this index.</summary>
173
/// <remarks>Obtain the total number of objects described by this index.</remarks>
175
/// number of objects in this index, and likewise in the associated
176
/// pack that this index was generated from.
178
internal abstract long GetObjectCount();
180
/// <summary>Obtain the total number of objects needing 64 bit offsets.</summary>
181
/// <remarks>Obtain the total number of objects needing 64 bit offsets.</remarks>
183
/// number of objects in this index using a 64 bit offset; that is an
184
/// object positioned after the 2 GB position within the file.
186
internal abstract long GetOffset64Count();
189
/// Get ObjectId for the n-th object entry returned by
190
/// <see cref="Iterator()">Iterator()</see>
193
/// This method is a constant-time replacement for the following loop:
195
/// Iterator<MutableEntry> eItr = index.iterator();
196
/// int curPosition = 0;
197
/// while (eItr.hasNext() && curPosition++ < nthPosition)
199
/// ObjectId result = eItr.next().toObjectId();
202
/// <param name="nthPosition">
203
/// position within the traversal of
204
/// <see cref="Iterator()">Iterator()</see>
206
/// caller needs the object for. The first returned
207
/// <see cref="MutableEntry">MutableEntry</see>
208
/// is 0, the second is 1, etc.
210
/// <returns>the ObjectId for the corresponding entry.</returns>
211
internal abstract ObjectId GetObjectId(long nthPosition);
214
/// Get ObjectId for the n-th object entry returned by
215
/// <see cref="Iterator()">Iterator()</see>
218
/// This method is a constant-time replacement for the following loop:
220
/// Iterator<MutableEntry> eItr = index.iterator();
221
/// int curPosition = 0;
222
/// while (eItr.hasNext() && curPosition++ < nthPosition)
224
/// ObjectId result = eItr.next().toObjectId();
227
/// <param name="nthPosition">
228
/// unsigned 32 bit position within the traversal of
229
/// <see cref="Iterator()">Iterator()</see>
230
/// that the caller needs the object for. The
232
/// <see cref="MutableEntry">MutableEntry</see>
233
/// is 0, the second is 1,
234
/// etc. Positions past 2**31-1 are negative, but still valid.
236
/// <returns>the ObjectId for the corresponding entry.</returns>
237
internal ObjectId GetObjectId(int nthPosition)
239
if (nthPosition >= 0)
241
return GetObjectId((long)nthPosition);
243
int u31 = (int)(((uint)nthPosition) >> 1);
244
int one = nthPosition & 1;
245
return GetObjectId(((long)u31) << 1 | one);
248
/// <summary>Locate the file offset position for the requested object.</summary>
249
/// <remarks>Locate the file offset position for the requested object.</remarks>
250
/// <param name="objId">name of the object to locate within the pack.</param>
252
/// offset of the object's header and compressed content; -1 if the
253
/// object does not exist in this index and is thus not stored in the
256
internal abstract long FindOffset(AnyObjectId objId);
259
/// Retrieve stored CRC32 checksum of the requested object raw-data
260
/// (including header).
263
/// Retrieve stored CRC32 checksum of the requested object raw-data
264
/// (including header).
266
/// <param name="objId">id of object to look for</param>
267
/// <returns>CRC32 checksum of specified object (at 32 less significant bits)</returns>
268
/// <exception cref="NGit.Errors.MissingObjectException">when requested ObjectId was not found in this index
270
/// <exception cref="System.NotSupportedException">when this index doesn't support CRC32 checksum
272
internal abstract long FindCRC32(AnyObjectId objId);
274
/// <summary>Check whether this index supports (has) CRC32 checksums for objects.</summary>
275
/// <remarks>Check whether this index supports (has) CRC32 checksums for objects.</remarks>
276
/// <returns>true if CRC32 is stored, false otherwise</returns>
277
internal abstract bool HasCRC32Support();
279
/// <exception cref="System.IO.IOException"></exception>
280
internal abstract void Resolve(ICollection<ObjectId> matches, AbbreviatedObjectId
284
/// Represent mutable entry of pack index consisting of object id and offset
285
/// in pack (both mutable).
288
/// Represent mutable entry of pack index consisting of object id and offset
289
/// in pack (both mutable).
291
public class MutableEntry
293
internal readonly MutableObjectId idBuffer = new MutableObjectId();
295
internal long offset;
297
/// <summary>Returns offset for this index object entry</summary>
298
/// <returns>offset of this object in a pack file</returns>
299
public virtual long GetOffset()
304
/// <returns>hex string describing the object id of this entry.</returns>
305
public virtual string Name()
308
return idBuffer.Name;
311
/// <returns>a copy of the object id.</returns>
312
public virtual ObjectId ToObjectId()
315
return idBuffer.ToObjectId();
318
/// <returns>a complete copy of this entry, that won't modify</returns>
319
public virtual PackIndex.MutableEntry CloneEntry()
321
PackIndex.MutableEntry r = new PackIndex.MutableEntry();
323
r.idBuffer.FromObjectId(idBuffer);
328
internal virtual void EnsureId()
331
// Override in implementations.
334
internal abstract class EntriesIterator : Iterator<PackIndex.MutableEntry>
336
protected internal readonly PackIndex.MutableEntry entry;
338
protected internal long returnedNumber = 0;
340
protected internal abstract PackIndex.MutableEntry InitEntry();
342
public override bool HasNext()
344
return this.returnedNumber < this._enclosing.GetObjectCount();
348
/// Implementation must update
349
/// <see cref="returnedNumber">returnedNumber</see>
353
public abstract override PackIndex.MutableEntry Next();
355
public override void Remove()
357
throw new NotSupportedException();
360
internal EntriesIterator(PackIndex _enclosing)
363
this._enclosing = _enclosing;
366
private readonly PackIndex _enclosing;