~ubuntu-branches/ubuntu/oneiric/monodevelop/oneiric

« back to all changes in this revision

Viewing changes to contrib/NGit/NGit.Diff/ContentSource.cs

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2011-06-27 17:03:13 UTC
  • mto: (1.8.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 54.
  • Revision ID: james.westby@ubuntu.com-20110627170313-6cvz3s19x6e9hqe9
ImportĀ upstreamĀ versionĀ 2.5.92+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
This code is derived from jgit (http://eclipse.org/jgit).
 
3
Copyright owners are documented in jgit's IP log.
 
4
 
 
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
 
9
 
 
10
All rights reserved.
 
11
 
 
12
Redistribution and use in source and binary forms, with or
 
13
without modification, are permitted provided that the following
 
14
conditions are met:
 
15
 
 
16
- Redistributions of source code must retain the above copyright
 
17
  notice, this list of conditions and the following disclaimer.
 
18
 
 
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.
 
23
 
 
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
 
27
  written permission.
 
28
 
 
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.
 
42
*/
 
43
 
 
44
using System;
 
45
using System.IO;
 
46
using NGit;
 
47
using NGit.Diff;
 
48
using NGit.Errors;
 
49
using NGit.Treewalk;
 
50
using NGit.Treewalk.Filter;
 
51
using Sharpen;
 
52
 
 
53
namespace NGit.Diff
 
54
{
 
55
        /// <summary>
 
56
        /// Supplies the content of a file for
 
57
        /// <see cref="DiffFormatter">DiffFormatter</see>
 
58
        /// .
 
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.
 
63
        /// </summary>
 
64
        public abstract class ContentSource
 
65
        {
 
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)
 
71
                {
 
72
                        return new ContentSource.ObjectReaderSource(reader);
 
73
                }
 
74
 
 
75
                /// <summary>Construct a content source for a working directory.</summary>
 
76
                /// <remarks>
 
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.
 
82
                /// </remarks>
 
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)
 
86
                {
 
87
                        if (iterator is FileTreeIterator)
 
88
                        {
 
89
                                FileTreeIterator i = (FileTreeIterator)iterator;
 
90
                                return new ContentSource.FileSource(i.GetDirectory());
 
91
                        }
 
92
                        return new ContentSource.WorkingTreeSource(iterator);
 
93
                }
 
94
 
 
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);
 
102
 
 
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>
 
107
                /// <returns>
 
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
 
110
                /// source.
 
111
                /// </returns>
 
112
                /// <exception cref="System.IO.IOException">the file cannot be accessed.</exception>
 
113
                public abstract ObjectLoader Open(string path, ObjectId id);
 
114
 
 
115
                private class ObjectReaderSource : ContentSource
 
116
                {
 
117
                        private readonly ObjectReader reader;
 
118
 
 
119
                        internal ObjectReaderSource(ObjectReader reader)
 
120
                        {
 
121
                                this.reader = reader;
 
122
                        }
 
123
 
 
124
                        /// <exception cref="System.IO.IOException"></exception>
 
125
                        public override long Size(string path, ObjectId id)
 
126
                        {
 
127
                                return reader.GetObjectSize(id, Constants.OBJ_BLOB);
 
128
                        }
 
129
 
 
130
                        /// <exception cref="System.IO.IOException"></exception>
 
131
                        public override ObjectLoader Open(string path, ObjectId id)
 
132
                        {
 
133
                                return reader.Open(id, Constants.OBJ_BLOB);
 
134
                        }
 
135
                }
 
136
 
 
137
                private class WorkingTreeSource : ContentSource
 
138
                {
 
139
                        private readonly TreeWalk tw;
 
140
 
 
141
                        private readonly WorkingTreeIterator iterator;
 
142
 
 
143
                        private string current;
 
144
 
 
145
                        private WorkingTreeIterator ptr;
 
146
 
 
147
                        internal WorkingTreeSource(WorkingTreeIterator iterator)
 
148
                        {
 
149
                                this.tw = new TreeWalk((ObjectReader)null);
 
150
                                this.iterator = iterator;
 
151
                        }
 
152
 
 
153
                        /// <exception cref="System.IO.IOException"></exception>
 
154
                        public override long Size(string path, ObjectId id)
 
155
                        {
 
156
                                Seek(path);
 
157
                                return ptr.GetEntryLength();
 
158
                        }
 
159
 
 
160
                        /// <exception cref="System.IO.IOException"></exception>
 
161
                        public override ObjectLoader Open(string path, ObjectId id)
 
162
                        {
 
163
                                Seek(path);
 
164
                                return new _ObjectLoader_173(this);
 
165
                        }
 
166
 
 
167
                        private sealed class _ObjectLoader_173 : ObjectLoader
 
168
                        {
 
169
                                public _ObjectLoader_173(WorkingTreeSource _enclosing)
 
170
                                {
 
171
                                        this._enclosing = _enclosing;
 
172
                                }
 
173
 
 
174
                                public override long GetSize()
 
175
                                {
 
176
                                        return this._enclosing.ptr.GetEntryLength();
 
177
                                }
 
178
 
 
179
                                public override int GetType()
 
180
                                {
 
181
                                        return this._enclosing.ptr.EntryFileMode.GetObjectType();
 
182
                                }
 
183
 
 
184
                                /// <exception cref="NGit.Errors.MissingObjectException"></exception>
 
185
                                /// <exception cref="System.IO.IOException"></exception>
 
186
                                public override ObjectStream OpenStream()
 
187
                                {
 
188
                                        InputStream @in = this._enclosing.ptr.OpenEntryStream();
 
189
                                        @in = new BufferedInputStream(@in);
 
190
                                        return new ObjectStream.Filter(this.GetType(), this.GetSize(), @in);
 
191
                                }
 
192
 
 
193
                                public override bool IsLarge()
 
194
                                {
 
195
                                        return true;
 
196
                                }
 
197
 
 
198
                                /// <exception cref="NGit.Errors.LargeObjectException"></exception>
 
199
                                public override byte[] GetCachedBytes()
 
200
                                {
 
201
                                        throw new LargeObjectException();
 
202
                                }
 
203
 
 
204
                                private readonly WorkingTreeSource _enclosing;
 
205
                        }
 
206
 
 
207
                        /// <exception cref="System.IO.IOException"></exception>
 
208
                        private void Seek(string path)
 
209
                        {
 
210
                                if (!path.Equals(current))
 
211
                                {
 
212
                                        iterator.Reset();
 
213
                                        tw.Reset();
 
214
                                        tw.AddTree(iterator);
 
215
                                        tw.Filter = PathFilter.Create(path);
 
216
                                        current = path;
 
217
                                        if (!tw.Next())
 
218
                                        {
 
219
                                                throw new FileNotFoundException(path);
 
220
                                        }
 
221
                                        ptr = tw.GetTree<WorkingTreeIterator>(0);
 
222
                                        if (ptr == null)
 
223
                                        {
 
224
                                                throw new FileNotFoundException(path);
 
225
                                        }
 
226
                                }
 
227
                        }
 
228
                }
 
229
 
 
230
                private class FileSource : ContentSource
 
231
                {
 
232
                        private readonly FilePath root;
 
233
 
 
234
                        internal FileSource(FilePath root)
 
235
                        {
 
236
                                this.root = root;
 
237
                        }
 
238
 
 
239
                        /// <exception cref="System.IO.IOException"></exception>
 
240
                        public override long Size(string path, ObjectId id)
 
241
                        {
 
242
                                return new FilePath(root, path).Length();
 
243
                        }
 
244
 
 
245
                        /// <exception cref="System.IO.IOException"></exception>
 
246
                        public override ObjectLoader Open(string path, ObjectId id)
 
247
                        {
 
248
                                FilePath p = new FilePath(root, path);
 
249
                                if (!p.IsFile())
 
250
                                {
 
251
                                        throw new FileNotFoundException(path);
 
252
                                }
 
253
                                return new _ObjectLoader_237(p);
 
254
                        }
 
255
 
 
256
                        private sealed class _ObjectLoader_237 : ObjectLoader
 
257
                        {
 
258
                                public _ObjectLoader_237(FilePath p)
 
259
                                {
 
260
                                        this.p = p;
 
261
                                }
 
262
 
 
263
                                public override long GetSize()
 
264
                                {
 
265
                                        return p.Length();
 
266
                                }
 
267
 
 
268
                                public override int GetType()
 
269
                                {
 
270
                                        return Constants.OBJ_BLOB;
 
271
                                }
 
272
 
 
273
                                /// <exception cref="NGit.Errors.MissingObjectException"></exception>
 
274
                                /// <exception cref="System.IO.IOException"></exception>
 
275
                                public override ObjectStream OpenStream()
 
276
                                {
 
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);
 
282
                                }
 
283
 
 
284
                                public override bool IsLarge()
 
285
                                {
 
286
                                        return true;
 
287
                                }
 
288
 
 
289
                                /// <exception cref="NGit.Errors.LargeObjectException"></exception>
 
290
                                public override byte[] GetCachedBytes()
 
291
                                {
 
292
                                        throw new LargeObjectException();
 
293
                                }
 
294
 
 
295
                                private readonly FilePath p;
 
296
                        }
 
297
                }
 
298
 
 
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
 
302
                {
 
303
                        private readonly ContentSource oldSource;
 
304
 
 
305
                        private readonly ContentSource newSource;
 
306
 
 
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)
 
312
                        {
 
313
                                this.oldSource = oldSource;
 
314
                                this.newSource = newSource;
 
315
                        }
 
316
 
 
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)
 
324
                        {
 
325
                                switch (side)
 
326
                                {
 
327
                                        case DiffEntry.Side.OLD:
 
328
                                        {
 
329
                                                return oldSource.Size(ent.oldPath, ent.oldId.ToObjectId());
 
330
                                        }
 
331
 
 
332
                                        case DiffEntry.Side.NEW:
 
333
                                        {
 
334
                                                return newSource.Size(ent.newPath, ent.newId.ToObjectId());
 
335
                                        }
 
336
 
 
337
                                        default:
 
338
                                        {
 
339
                                                throw new ArgumentException();
 
340
                                        }
 
341
                                }
 
342
                        }
 
343
 
 
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>
 
348
                        /// <returns>
 
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
 
351
                        /// same source.
 
352
                        /// </returns>
 
353
                        /// <exception cref="System.IO.IOException">the file cannot be accessed.</exception>
 
354
                        public ObjectLoader Open(DiffEntry.Side side, DiffEntry ent)
 
355
                        {
 
356
                                switch (side)
 
357
                                {
 
358
                                        case DiffEntry.Side.OLD:
 
359
                                        {
 
360
                                                return oldSource.Open(ent.oldPath, ent.oldId.ToObjectId());
 
361
                                        }
 
362
 
 
363
                                        case DiffEntry.Side.NEW:
 
364
                                        {
 
365
                                                return newSource.Open(ent.newPath, ent.newId.ToObjectId());
 
366
                                        }
 
367
 
 
368
                                        default:
 
369
                                        {
 
370
                                                throw new ArgumentException();
 
371
                                        }
 
372
                                }
 
373
                        }
 
374
                }
 
375
        }
 
376
}