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.
52
/// Inserts objects into an existing
53
/// <code>ObjectDatabase</code>
56
/// An inserter is not thread-safe. Individual threads should each obtain their
57
/// own unique inserter instance, or must arrange for locking at a higher level
58
/// to ensure the inserter is in use by no more than one thread at a time.
60
/// Objects written by an inserter may not be immediately visible for reading
61
/// after the insert method completes. Callers must invoke either
62
/// <see cref="Release()">Release()</see>
64
/// <see cref="Flush()">Flush()</see>
65
/// prior to updating references or
66
/// otherwise making the returned ObjectIds visible to other code.
68
public abstract class ObjectInserter
70
/// <summary>An inserter that can be used for formatting and id generation only.</summary>
71
/// <remarks>An inserter that can be used for formatting and id generation only.</remarks>
72
public class Formatter : ObjectInserter
74
/// <exception cref="System.IO.IOException"></exception>
75
public override ObjectId Insert(int objectType, long length, InputStream @in)
77
throw new NotSupportedException();
80
/// <exception cref="System.IO.IOException"></exception>
81
public override PackParser NewPackParser(InputStream @in)
83
throw new NotSupportedException();
86
/// <exception cref="System.IO.IOException"></exception>
87
public override void Flush()
92
public override void Release()
98
/// <summary>Digest to compute the name of an object.</summary>
99
/// <remarks>Digest to compute the name of an object.</remarks>
100
private readonly MessageDigest digest;
102
/// <summary>Temporary working buffer for streaming data through.</summary>
103
/// <remarks>Temporary working buffer for streaming data through.</remarks>
104
private byte[] tempBuffer;
106
/// <summary>Create a new inserter for a database.</summary>
107
/// <remarks>Create a new inserter for a database.</remarks>
108
public ObjectInserter()
110
digest = Constants.NewMessageDigest();
113
/// <returns>a temporary byte array for use by the caller.</returns>
114
protected internal virtual byte[] Buffer()
116
if (tempBuffer == null)
118
tempBuffer = new byte[8192];
123
/// <returns>digest to help compute an ObjectId</returns>
124
protected internal virtual MessageDigest Digest()
130
/// <summary>Compute the name of an object, without inserting it.</summary>
131
/// <remarks>Compute the name of an object, without inserting it.</remarks>
132
/// <param name="type">type code of the object to store.</param>
133
/// <param name="data">complete content of the object.</param>
134
/// <returns>the name of the object.</returns>
135
public virtual ObjectId IdFor(int type, byte[] data)
137
return IdFor(type, data, 0, data.Length);
140
/// <summary>Compute the name of an object, without inserting it.</summary>
141
/// <remarks>Compute the name of an object, without inserting it.</remarks>
142
/// <param name="type">type code of the object to store.</param>
143
/// <param name="data">complete content of the object.</param>
144
/// <param name="off">
145
/// first position within
146
/// <code>data</code>
149
/// <param name="len">
150
/// number of bytes to copy from
151
/// <code>data</code>
154
/// <returns>the name of the object.</returns>
155
public virtual ObjectId IdFor(int type, byte[] data, int off, int len)
157
MessageDigest md = Digest();
158
md.Update(Constants.EncodedTypeString(type));
159
md.Update(unchecked((byte)' '));
160
md.Update(Constants.EncodeASCII(len));
161
md.Update(unchecked((byte)0));
162
md.Update(data, off, len);
163
return ObjectId.FromRaw(md.Digest());
166
/// <summary>Compute the name of an object, without inserting it.</summary>
167
/// <remarks>Compute the name of an object, without inserting it.</remarks>
168
/// <param name="objectType">type code of the object to store.</param>
169
/// <param name="length">
170
/// number of bytes to scan from
174
/// <param name="in">
175
/// stream providing the object content. The caller is responsible
176
/// for closing the stream.
178
/// <returns>the name of the object.</returns>
179
/// <exception cref="System.IO.IOException">the source stream could not be read.</exception>
180
public virtual ObjectId IdFor(int objectType, long length, InputStream @in)
182
MessageDigest md = Digest();
183
md.Update(Constants.EncodedTypeString(objectType));
184
md.Update(unchecked((byte)' '));
185
md.Update(Constants.EncodeASCII(length));
186
md.Update(unchecked((byte)0));
187
byte[] buf = Buffer();
190
int n = @in.Read(buf, 0, (int)Math.Min(length, buf.Length));
193
throw new EOFException("Unexpected end of input");
195
md.Update(buf, 0, n);
198
return ObjectId.FromRaw(md.Digest());
201
/// <summary>Compute the ObjectId for the given tree without inserting it.</summary>
202
/// <remarks>Compute the ObjectId for the given tree without inserting it.</remarks>
203
/// <param name="formatter"></param>
204
/// <returns>the computed ObjectId</returns>
205
public virtual ObjectId IdFor(TreeFormatter formatter)
207
return formatter.ComputeId(this);
210
/// <summary>Insert a single tree into the store, returning its unique name.</summary>
211
/// <remarks>Insert a single tree into the store, returning its unique name.</remarks>
212
/// <param name="formatter">the formatter containing the proposed tree's data.</param>
213
/// <returns>the name of the tree object.</returns>
214
/// <exception cref="System.IO.IOException">the object could not be stored.</exception>
215
public ObjectId Insert(TreeFormatter formatter)
217
// Delegate to the formatter, as then it can pass the raw internal
218
// buffer back to this inserter, avoiding unnecessary data copying.
220
return formatter.InsertTo(this);
223
/// <summary>Insert a single commit into the store, returning its unique name.</summary>
224
/// <remarks>Insert a single commit into the store, returning its unique name.</remarks>
225
/// <param name="builder">the builder containing the proposed commit's data.</param>
226
/// <returns>the name of the commit object.</returns>
227
/// <exception cref="System.IO.IOException">the object could not be stored.</exception>
228
public ObjectId Insert(NGit.CommitBuilder builder)
230
return Insert(Constants.OBJ_COMMIT, builder.Build());
233
/// <summary>Insert a single annotated tag into the store, returning its unique name.
235
/// <remarks>Insert a single annotated tag into the store, returning its unique name.
237
/// <param name="builder">the builder containing the proposed tag's data.</param>
238
/// <returns>the name of the tag object.</returns>
239
/// <exception cref="System.IO.IOException">the object could not be stored.</exception>
240
public ObjectId Insert(TagBuilder builder)
242
return Insert(Constants.OBJ_TAG, builder.Build());
245
/// <summary>Insert a single object into the store, returning its unique name.</summary>
246
/// <remarks>Insert a single object into the store, returning its unique name.</remarks>
247
/// <param name="type">type code of the object to store.</param>
248
/// <param name="data">complete content of the object.</param>
249
/// <returns>the name of the object.</returns>
250
/// <exception cref="System.IO.IOException">the object could not be stored.</exception>
251
public virtual ObjectId Insert(int type, byte[] data)
253
return Insert(type, data, 0, data.Length);
256
/// <summary>Insert a single object into the store, returning its unique name.</summary>
257
/// <remarks>Insert a single object into the store, returning its unique name.</remarks>
258
/// <param name="type">type code of the object to store.</param>
259
/// <param name="data">complete content of the object.</param>
260
/// <param name="off">
261
/// first position within
262
/// <code>data</code>
265
/// <param name="len">
266
/// number of bytes to copy from
267
/// <code>data</code>
270
/// <returns>the name of the object.</returns>
271
/// <exception cref="System.IO.IOException">the object could not be stored.</exception>
272
public virtual ObjectId Insert(int type, byte[] data, int off, int len)
274
return Insert(type, len, new ByteArrayInputStream(data, off, len));
277
/// <summary>Insert a single object into the store, returning its unique name.</summary>
278
/// <remarks>Insert a single object into the store, returning its unique name.</remarks>
279
/// <param name="objectType">type code of the object to store.</param>
280
/// <param name="length">
281
/// number of bytes to copy from
285
/// <param name="in">
286
/// stream providing the object content. The caller is responsible
287
/// for closing the stream.
289
/// <returns>the name of the object.</returns>
290
/// <exception cref="System.IO.IOException">
291
/// the object could not be stored, or the source stream could
294
public abstract ObjectId Insert(int objectType, long length, InputStream @in);
296
/// <summary>Initialize a parser to read from a pack formatted stream.</summary>
297
/// <remarks>Initialize a parser to read from a pack formatted stream.</remarks>
298
/// <param name="in">
299
/// the input stream. The stream is not closed by the parser, and
300
/// must instead be closed by the caller once parsing is complete.
302
/// <returns>the pack parser.</returns>
303
/// <exception cref="System.IO.IOException">
304
/// the parser instance, which can be configured and then used to
305
/// parse objects into the ObjectDatabase.
307
public abstract PackParser NewPackParser(InputStream @in);
309
/// <summary>Make all inserted objects visible.</summary>
311
/// Make all inserted objects visible.
313
/// The flush may take some period of time to make the objects available to
316
/// <exception cref="System.IO.IOException">
317
/// the flush could not be completed; objects inserted thus far
318
/// are in an indeterminate state.
320
public abstract void Flush();
322
/// <summary>Release any resources used by this inserter.</summary>
324
/// Release any resources used by this inserter.
326
/// An inserter that has been released can be used again, but may need to be
327
/// released after the subsequent usage.
329
public abstract void Release();