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.
50
using NGit.Treewalk.Filter;
56
/// Supplies the content of a file for
57
/// <see cref="DiffFormatter">DiffFormatter</see>
59
/// A content source is not thread-safe. Sources may contain state, including
60
/// information about the last ObjectLoader they returned. Callers must be
61
/// careful to ensure there is no more than one ObjectLoader pending on any
62
/// source, at any time.
64
public abstract class ContentSource
66
/// <summary>Construct a content source for an ObjectReader.</summary>
67
/// <remarks>Construct a content source for an ObjectReader.</remarks>
68
/// <param name="reader">the reader to obtain blobs from.</param>
69
/// <returns>a source wrapping the reader.</returns>
70
public static ContentSource Create(ObjectReader reader)
72
return new ContentSource.ObjectReaderSource(reader);
75
/// <summary>Construct a content source for a working directory.</summary>
77
/// Construct a content source for a working directory.
78
/// If the iterator is a
79
/// <see cref="NGit.Treewalk.FileTreeIterator">NGit.Treewalk.FileTreeIterator</see>
80
/// an optimized version is
81
/// used that doesn't require seeking through a TreeWalk.
83
/// <param name="iterator">the iterator to obtain source files through.</param>
84
/// <returns>a content source wrapping the iterator.</returns>
85
public static ContentSource Create(WorkingTreeIterator iterator)
87
if (iterator is FileTreeIterator)
89
FileTreeIterator i = (FileTreeIterator)iterator;
90
return new ContentSource.FileSource(i.GetDirectory());
92
return new ContentSource.WorkingTreeSource(iterator);
95
/// <summary>Determine the size of the object.</summary>
96
/// <remarks>Determine the size of the object.</remarks>
97
/// <param name="path">the path of the file, relative to the root of the repository.</param>
98
/// <param name="id">blob id of the file, if known.</param>
99
/// <returns>the size in bytes.</returns>
100
/// <exception cref="System.IO.IOException">the file cannot be accessed.</exception>
101
public abstract long Size(string path, ObjectId id);
103
/// <summary>Open the object.</summary>
104
/// <remarks>Open the object.</remarks>
105
/// <param name="path">the path of the file, relative to the root of the repository.</param>
106
/// <param name="id">blob id of the file, if known.</param>
108
/// a loader that can supply the content of the file. The loader must
109
/// be used before another loader can be obtained from this same
112
/// <exception cref="System.IO.IOException">the file cannot be accessed.</exception>
113
public abstract ObjectLoader Open(string path, ObjectId id);
115
private class ObjectReaderSource : ContentSource
117
private readonly ObjectReader reader;
119
internal ObjectReaderSource(ObjectReader reader)
121
this.reader = reader;
124
/// <exception cref="System.IO.IOException"></exception>
125
public override long Size(string path, ObjectId id)
127
return reader.GetObjectSize(id, Constants.OBJ_BLOB);
130
/// <exception cref="System.IO.IOException"></exception>
131
public override ObjectLoader Open(string path, ObjectId id)
133
return reader.Open(id, Constants.OBJ_BLOB);
137
private class WorkingTreeSource : ContentSource
139
private readonly TreeWalk tw;
141
private readonly WorkingTreeIterator iterator;
143
private string current;
145
private WorkingTreeIterator ptr;
147
internal WorkingTreeSource(WorkingTreeIterator iterator)
149
this.tw = new TreeWalk((ObjectReader)null);
150
this.iterator = iterator;
153
/// <exception cref="System.IO.IOException"></exception>
154
public override long Size(string path, ObjectId id)
157
return ptr.GetEntryLength();
160
/// <exception cref="System.IO.IOException"></exception>
161
public override ObjectLoader Open(string path, ObjectId id)
164
return new _ObjectLoader_173(this);
167
private sealed class _ObjectLoader_173 : ObjectLoader
169
public _ObjectLoader_173(WorkingTreeSource _enclosing)
171
this._enclosing = _enclosing;
174
public override long GetSize()
176
return this._enclosing.ptr.GetEntryLength();
179
public override int GetType()
181
return this._enclosing.ptr.EntryFileMode.GetObjectType();
184
/// <exception cref="NGit.Errors.MissingObjectException"></exception>
185
/// <exception cref="System.IO.IOException"></exception>
186
public override ObjectStream OpenStream()
188
InputStream @in = this._enclosing.ptr.OpenEntryStream();
189
@in = new BufferedInputStream(@in);
190
return new ObjectStream.Filter(this.GetType(), this.GetSize(), @in);
193
public override bool IsLarge()
198
/// <exception cref="NGit.Errors.LargeObjectException"></exception>
199
public override byte[] GetCachedBytes()
201
throw new LargeObjectException();
204
private readonly WorkingTreeSource _enclosing;
207
/// <exception cref="System.IO.IOException"></exception>
208
private void Seek(string path)
210
if (!path.Equals(current))
214
tw.AddTree(iterator);
215
tw.Filter = PathFilter.Create(path);
219
throw new FileNotFoundException(path);
221
ptr = tw.GetTree<WorkingTreeIterator>(0);
224
throw new FileNotFoundException(path);
230
private class FileSource : ContentSource
232
private readonly FilePath root;
234
internal FileSource(FilePath root)
239
/// <exception cref="System.IO.IOException"></exception>
240
public override long Size(string path, ObjectId id)
242
return new FilePath(root, path).Length();
245
/// <exception cref="System.IO.IOException"></exception>
246
public override ObjectLoader Open(string path, ObjectId id)
248
FilePath p = new FilePath(root, path);
251
throw new FileNotFoundException(path);
253
return new _ObjectLoader_237(p);
256
private sealed class _ObjectLoader_237 : ObjectLoader
258
public _ObjectLoader_237(FilePath p)
263
public override long GetSize()
268
public override int GetType()
270
return Constants.OBJ_BLOB;
273
/// <exception cref="NGit.Errors.MissingObjectException"></exception>
274
/// <exception cref="System.IO.IOException"></exception>
275
public override ObjectStream OpenStream()
277
FileInputStream @in = new FileInputStream(p);
278
long sz = @in.GetChannel().Size();
279
int type = this.GetType();
280
BufferedInputStream b = new BufferedInputStream(@in);
281
return new ObjectStream.Filter(type, sz, b);
284
public override bool IsLarge()
289
/// <exception cref="NGit.Errors.LargeObjectException"></exception>
290
public override byte[] GetCachedBytes()
292
throw new LargeObjectException();
295
private readonly FilePath p;
299
/// <summary>A pair of sources to access the old and new sides of a DiffEntry.</summary>
300
/// <remarks>A pair of sources to access the old and new sides of a DiffEntry.</remarks>
301
public sealed class Pair
303
private readonly ContentSource oldSource;
305
private readonly ContentSource newSource;
307
/// <summary>Construct a pair of sources.</summary>
308
/// <remarks>Construct a pair of sources.</remarks>
309
/// <param name="oldSource">source to read the old side of a DiffEntry.</param>
310
/// <param name="newSource">source to read the new side of a DiffEntry.</param>
311
public Pair(ContentSource oldSource, ContentSource newSource)
313
this.oldSource = oldSource;
314
this.newSource = newSource;
317
/// <summary>Determine the size of the object.</summary>
318
/// <remarks>Determine the size of the object.</remarks>
319
/// <param name="side">which side of the entry to read (OLD or NEW).</param>
320
/// <param name="ent">the entry to examine.</param>
321
/// <returns>the size in bytes.</returns>
322
/// <exception cref="System.IO.IOException">the file cannot be accessed.</exception>
323
public long Size(DiffEntry.Side side, DiffEntry ent)
327
case DiffEntry.Side.OLD:
329
return oldSource.Size(ent.oldPath, ent.oldId.ToObjectId());
332
case DiffEntry.Side.NEW:
334
return newSource.Size(ent.newPath, ent.newId.ToObjectId());
339
throw new ArgumentException();
344
/// <summary>Open the object.</summary>
345
/// <remarks>Open the object.</remarks>
346
/// <param name="side">which side of the entry to read (OLD or NEW).</param>
347
/// <param name="ent">the entry to examine.</param>
349
/// a loader that can supply the content of the file. The loader
350
/// must be used before another loader can be obtained from this
353
/// <exception cref="System.IO.IOException">the file cannot be accessed.</exception>
354
public ObjectLoader Open(DiffEntry.Side side, DiffEntry ent)
358
case DiffEntry.Side.OLD:
360
return oldSource.Open(ent.oldPath, ent.oldId.ToObjectId());
363
case DiffEntry.Side.NEW:
365
return newSource.Open(ent.newPath, ent.newId.ToObjectId());
370
throw new ArgumentException();