~ubuntu-branches/ubuntu/wily/monodevelop/wily

« back to all changes in this revision

Viewing changes to external/ngit/NGit/NGit.Blame/BlameResult.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2012-05-27 18:08:20 UTC
  • mfrom: (19.1.8 experimental)
  • Revision ID: package-import@ubuntu.com-20120527180820-fydl21qnbnfr8w2t
Tags: 3.0.2+dfsg-3
* [fcecfe7] Fix monodevelop-core-addins.pc.in to point to actual 
  installed location of assemblies.
* [26e1a07] DebSrc 3.0 does not support Quilt's -p parameter, so 
  manually adjust the path in the patch file.

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.Text;
 
45
using NGit;
 
46
using NGit.Blame;
 
47
using NGit.Diff;
 
48
using NGit.Revwalk;
 
49
using Sharpen;
 
50
 
 
51
namespace NGit.Blame
 
52
{
 
53
        /// <summary>Collects line annotations for inspection by applications.</summary>
 
54
        /// <remarks>
 
55
        /// Collects line annotations for inspection by applications.
 
56
        /// <p>
 
57
        /// A result is usually updated incrementally as the BlameGenerator digs back
 
58
        /// further through history. Applications that want to lay annotations down text
 
59
        /// to the original source file in a viewer may find the BlameResult structure an
 
60
        /// easy way to acquire the information, at the expense of keeping tables in
 
61
        /// memory tracking every line of the result file.
 
62
        /// <p>
 
63
        /// This class is not thread-safe.
 
64
        /// <p>
 
65
        /// During blame processing there are two files involved:
 
66
        /// <ul>
 
67
        /// <li>result - The file whose lines are being examined. This is the revision
 
68
        /// the user is trying to view blame/annotation information alongside of.</li>
 
69
        /// <li>source - The file that was blamed with supplying one or more lines of
 
70
        /// data into result. The source may be a different file path (due to copy or
 
71
        /// rename). Source line numbers may differ from result line numbers due to lines
 
72
        /// being added/removed in intermediate revisions.</li>
 
73
        /// </ul>
 
74
        /// </remarks>
 
75
        public class BlameResult
 
76
        {
 
77
                /// <summary>Construct a new BlameResult for a generator.</summary>
 
78
                /// <remarks>Construct a new BlameResult for a generator.</remarks>
 
79
                /// <param name="gen">the generator the result will consume records from.</param>
 
80
                /// <returns>
 
81
                /// the new result object. null if the generator cannot find the path
 
82
                /// it starts from.
 
83
                /// </returns>
 
84
                /// <exception cref="System.IO.IOException">the repository cannot be read.</exception>
 
85
                public static NGit.Blame.BlameResult Create(BlameGenerator gen)
 
86
                {
 
87
                        string path = gen.GetResultPath();
 
88
                        RawText contents = gen.GetResultContents();
 
89
                        if (contents == null)
 
90
                        {
 
91
                                gen.Release();
 
92
                                return null;
 
93
                        }
 
94
                        return new NGit.Blame.BlameResult(gen, path, contents);
 
95
                }
 
96
 
 
97
                private readonly string resultPath;
 
98
 
 
99
                private readonly RevCommit[] sourceCommits;
 
100
 
 
101
                private readonly PersonIdent[] sourceAuthors;
 
102
 
 
103
                private readonly PersonIdent[] sourceCommitters;
 
104
 
 
105
                private readonly string[] sourcePaths;
 
106
 
 
107
                /// <summary>Warning: these are actually 1-based.</summary>
 
108
                /// <remarks>Warning: these are actually 1-based.</remarks>
 
109
                private readonly int[] sourceLines;
 
110
 
 
111
                private RawText resultContents;
 
112
 
 
113
                private BlameGenerator generator;
 
114
 
 
115
                private int lastLength;
 
116
 
 
117
                internal BlameResult(BlameGenerator bg, string path, RawText text)
 
118
                {
 
119
                        generator = bg;
 
120
                        resultPath = path;
 
121
                        resultContents = text;
 
122
                        int cnt = text.Size();
 
123
                        sourceCommits = new RevCommit[cnt];
 
124
                        sourceAuthors = new PersonIdent[cnt];
 
125
                        sourceCommitters = new PersonIdent[cnt];
 
126
                        sourceLines = new int[cnt];
 
127
                        sourcePaths = new string[cnt];
 
128
                }
 
129
 
 
130
                /// <returns>path of the file this result annotates.</returns>
 
131
                public virtual string GetResultPath()
 
132
                {
 
133
                        return resultPath;
 
134
                }
 
135
 
 
136
                /// <returns>contents of the result file, available for display.</returns>
 
137
                public virtual RawText GetResultContents()
 
138
                {
 
139
                        return resultContents;
 
140
                }
 
141
 
 
142
                /// <summary>
 
143
                /// Throw away the
 
144
                /// <see cref="GetResultContents()">GetResultContents()</see>
 
145
                /// .
 
146
                /// </summary>
 
147
                public virtual void DiscardResultContents()
 
148
                {
 
149
                        resultContents = null;
 
150
                }
 
151
 
 
152
                /// <summary>Check if the given result line has been annotated yet.</summary>
 
153
                /// <remarks>Check if the given result line has been annotated yet.</remarks>
 
154
                /// <param name="idx">line to read data of, 0 based.</param>
 
155
                /// <returns>true if the data has been annotated, false otherwise.</returns>
 
156
                public virtual bool HasSourceData(int idx)
 
157
                {
 
158
                        return sourceLines[idx] != 0;
 
159
                }
 
160
 
 
161
                /// <summary>Check if the given result line has been annotated yet.</summary>
 
162
                /// <remarks>Check if the given result line has been annotated yet.</remarks>
 
163
                /// <param name="start">first index to examine.</param>
 
164
                /// <param name="end">last index to examine.</param>
 
165
                /// <returns>true if the data has been annotated, false otherwise.</returns>
 
166
                public virtual bool HasSourceData(int start, int end)
 
167
                {
 
168
                        for (; start < end; start++)
 
169
                        {
 
170
                                if (sourceLines[start] == 0)
 
171
                                {
 
172
                                        return false;
 
173
                                }
 
174
                        }
 
175
                        return true;
 
176
                }
 
177
 
 
178
                /// <summary>Get the commit that provided the specified line of the result.</summary>
 
179
                /// <remarks>
 
180
                /// Get the commit that provided the specified line of the result.
 
181
                /// <p>
 
182
                /// The source commit may be null if the line was blamed to an uncommitted
 
183
                /// revision, such as the working tree copy, or during a reverse blame if the
 
184
                /// line survives to the end revision (e.g. the branch tip).
 
185
                /// </remarks>
 
186
                /// <param name="idx">line to read data of, 0 based.</param>
 
187
                /// <returns>
 
188
                /// commit that provided line
 
189
                /// <code>idx</code>
 
190
                /// . May be null.
 
191
                /// </returns>
 
192
                public virtual RevCommit GetSourceCommit(int idx)
 
193
                {
 
194
                        return sourceCommits[idx];
 
195
                }
 
196
 
 
197
                /// <summary>Get the author that provided the specified line of the result.</summary>
 
198
                /// <remarks>Get the author that provided the specified line of the result.</remarks>
 
199
                /// <param name="idx">line to read data of, 0 based.</param>
 
200
                /// <returns>
 
201
                /// author that provided line
 
202
                /// <code>idx</code>
 
203
                /// . May be null.
 
204
                /// </returns>
 
205
                public virtual PersonIdent GetSourceAuthor(int idx)
 
206
                {
 
207
                        return sourceAuthors[idx];
 
208
                }
 
209
 
 
210
                /// <summary>Get the committer that provided the specified line of the result.</summary>
 
211
                /// <remarks>Get the committer that provided the specified line of the result.</remarks>
 
212
                /// <param name="idx">line to read data of, 0 based.</param>
 
213
                /// <returns>
 
214
                /// committer that provided line
 
215
                /// <code>idx</code>
 
216
                /// . May be null.
 
217
                /// </returns>
 
218
                public virtual PersonIdent GetSourceCommitter(int idx)
 
219
                {
 
220
                        return sourceCommitters[idx];
 
221
                }
 
222
 
 
223
                /// <summary>Get the file path that provided the specified line of the result.</summary>
 
224
                /// <remarks>Get the file path that provided the specified line of the result.</remarks>
 
225
                /// <param name="idx">line to read data of, 0 based.</param>
 
226
                /// <returns>
 
227
                /// source file path that provided line
 
228
                /// <code>idx</code>
 
229
                /// .
 
230
                /// </returns>
 
231
                public virtual string GetSourcePath(int idx)
 
232
                {
 
233
                        return sourcePaths[idx];
 
234
                }
 
235
 
 
236
                /// <summary>Get the corresponding line number in the source file.</summary>
 
237
                /// <remarks>Get the corresponding line number in the source file.</remarks>
 
238
                /// <param name="idx">line to read data of, 0 based.</param>
 
239
                /// <returns>matching line number in the source file.</returns>
 
240
                public virtual int GetSourceLine(int idx)
 
241
                {
 
242
                        return sourceLines[idx] - 1;
 
243
                }
 
244
 
 
245
                /// <summary>Compute all pending information.</summary>
 
246
                /// <remarks>Compute all pending information.</remarks>
 
247
                /// <exception cref="System.IO.IOException">the repository cannot be read.</exception>
 
248
                public virtual void ComputeAll()
 
249
                {
 
250
                        BlameGenerator gen = generator;
 
251
                        if (gen == null)
 
252
                        {
 
253
                                return;
 
254
                        }
 
255
                        try
 
256
                        {
 
257
                                while (gen.Next())
 
258
                                {
 
259
                                        LoadFrom(gen);
 
260
                                }
 
261
                        }
 
262
                        finally
 
263
                        {
 
264
                                gen.Release();
 
265
                                generator = null;
 
266
                        }
 
267
                }
 
268
 
 
269
                /// <summary>Compute the next available segment and return the first index.</summary>
 
270
                /// <remarks>
 
271
                /// Compute the next available segment and return the first index.
 
272
                /// <p>
 
273
                /// Computes one segment and returns to the caller the first index that is
 
274
                /// available. After return the caller can also inspect
 
275
                /// <see cref="LastLength()">LastLength()</see>
 
276
                /// to determine how many lines of the result were computed.
 
277
                /// </remarks>
 
278
                /// <returns>index that is now available. -1 if no more are available.</returns>
 
279
                /// <exception cref="System.IO.IOException">the repository cannot be read.</exception>
 
280
                public virtual int ComputeNext()
 
281
                {
 
282
                        BlameGenerator gen = generator;
 
283
                        if (gen == null)
 
284
                        {
 
285
                                return -1;
 
286
                        }
 
287
                        if (gen.Next())
 
288
                        {
 
289
                                LoadFrom(gen);
 
290
                                lastLength = gen.GetRegionLength();
 
291
                                return gen.GetResultStart();
 
292
                        }
 
293
                        else
 
294
                        {
 
295
                                gen.Release();
 
296
                                generator = null;
 
297
                                return -1;
 
298
                        }
 
299
                }
 
300
 
 
301
                /// <returns>
 
302
                /// length of the last segment found by
 
303
                /// <see cref="ComputeNext()">ComputeNext()</see>
 
304
                /// .
 
305
                /// </returns>
 
306
                public virtual int LastLength()
 
307
                {
 
308
                        return lastLength;
 
309
                }
 
310
 
 
311
                /// <summary>Compute until the entire range has been populated.</summary>
 
312
                /// <remarks>Compute until the entire range has been populated.</remarks>
 
313
                /// <param name="start">first index to examine.</param>
 
314
                /// <param name="end">last index to examine.</param>
 
315
                /// <exception cref="System.IO.IOException">the repository cannot be read.</exception>
 
316
                public virtual void ComputeRange(int start, int end)
 
317
                {
 
318
                        BlameGenerator gen = generator;
 
319
                        if (gen == null)
 
320
                        {
 
321
                                return;
 
322
                        }
 
323
                        while (start < end)
 
324
                        {
 
325
                                if (HasSourceData(start, end))
 
326
                                {
 
327
                                        return;
 
328
                                }
 
329
                                if (!gen.Next())
 
330
                                {
 
331
                                        gen.Release();
 
332
                                        generator = null;
 
333
                                        return;
 
334
                                }
 
335
                                LoadFrom(gen);
 
336
                                // If the result contains either end of our current range bounds,
 
337
                                // update the bounds to avoid scanning that section during the
 
338
                                // next loop iteration.
 
339
                                int resLine = gen.GetResultStart();
 
340
                                int resEnd = gen.GetResultEnd();
 
341
                                if (resLine <= start && start < resEnd)
 
342
                                {
 
343
                                        start = resEnd;
 
344
                                }
 
345
                                if (resLine <= end && end < resEnd)
 
346
                                {
 
347
                                        end = resLine;
 
348
                                }
 
349
                        }
 
350
                }
 
351
 
 
352
                public override string ToString()
 
353
                {
 
354
                        StringBuilder r = new StringBuilder();
 
355
                        r.Append("BlameResult: ");
 
356
                        r.Append(GetResultPath());
 
357
                        return r.ToString();
 
358
                }
 
359
 
 
360
                private void LoadFrom(BlameGenerator gen)
 
361
                {
 
362
                        RevCommit srcCommit = gen.GetSourceCommit();
 
363
                        PersonIdent srcAuthor = gen.GetSourceAuthor();
 
364
                        PersonIdent srcCommitter = gen.GetSourceCommitter();
 
365
                        string srcPath = gen.GetSourcePath();
 
366
                        int srcLine = gen.GetSourceStart();
 
367
                        int resLine = gen.GetResultStart();
 
368
                        int resEnd = gen.GetResultEnd();
 
369
                        for (; resLine < resEnd; resLine++)
 
370
                        {
 
371
                                // Reverse blame can generate multiple results for the same line.
 
372
                                // Favor the first one selected, as this is the oldest and most
 
373
                                // likely to be nearest to the inquiry made by the user.
 
374
                                if (sourceLines[resLine] != 0)
 
375
                                {
 
376
                                        continue;
 
377
                                }
 
378
                                sourceCommits[resLine] = srcCommit;
 
379
                                sourceAuthors[resLine] = srcAuthor;
 
380
                                sourceCommitters[resLine] = srcCommitter;
 
381
                                sourcePaths[resLine] = srcPath;
 
382
                                // Since sourceLines is 1-based to permit hasSourceData to use 0 to
 
383
                                // mean the line has not been annotated yet, pre-increment instead
 
384
                                // of the traditional post-increment when making the assignment.
 
385
                                sourceLines[resLine] = ++srcLine;
 
386
                        }
 
387
                }
 
388
        }
 
389
}