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.
47
namespace NGit.Revwalk
49
/// <summary>Replaces a RevCommit's parents until not colored with REWRITE.</summary>
51
/// Replaces a RevCommit's parents until not colored with REWRITE.
53
/// Before a RevCommit is returned to the caller its parents are updated to
54
/// create a dense DAG. Instead of reporting the actual parents as recorded when
55
/// the commit was created the returned commit will reflect the next closest
56
/// commit that matched the revision walker's filters.
58
/// This generator is the second phase of a path limited revision walk and
59
/// assumes it is receiving RevCommits from
60
/// <see cref="RewriteTreeFilter">RewriteTreeFilter</see>
62
/// after they have been fully buffered by
63
/// <see cref="AbstractRevQueue">AbstractRevQueue</see>
65
/// buffering is necessary to allow the simple loop used within our own
66
/// <see cref="Rewrite(RevCommit)">Rewrite(RevCommit)</see>
67
/// to pull completely through a strand of
68
/// <see cref="RevWalk.REWRITE">RevWalk.REWRITE</see>
69
/// colored commits and come up with a simplification
70
/// that makes the DAG dense. Not fully buffering the commits first would cause
71
/// this loop to abort early, due to commits not being parsed and colored
74
/// <seealso cref="RewriteTreeFilter">RewriteTreeFilter</seealso>
75
internal class RewriteGenerator : Generator
77
private const int REWRITE = RevWalk.REWRITE;
81
/// <see cref="Cleanup(RevCommit[])">Cleanup(RevCommit[])</see>
82
/// to remove duplicate parents.
84
private const int DUPLICATE = RevWalk.TEMP_MARK;
86
private readonly Generator source;
88
internal RewriteGenerator(Generator s)
93
internal override void ShareFreeList(BlockRevQueue q)
95
source.ShareFreeList(q);
98
internal override int OutputType()
100
return source.OutputType() & ~NEEDS_REWRITE;
103
/// <exception cref="NGit.Errors.MissingObjectException"></exception>
104
/// <exception cref="NGit.Errors.IncorrectObjectTypeException"></exception>
105
/// <exception cref="System.IO.IOException"></exception>
106
internal override RevCommit Next()
110
RevCommit c = source.Next();
115
bool rewrote = false;
116
RevCommit[] pList = c.parents;
117
int nParents = pList.Length;
118
for (int i = 0; i < nParents; i++)
120
RevCommit oldp = pList[i];
121
RevCommit newp = Rewrite(oldp);
130
c.parents = Cleanup(pList);
136
private RevCommit Rewrite(RevCommit p)
140
RevCommit[] pList = p.parents;
141
if (pList.Length > 1)
143
// This parent is a merge, so keep it.
147
if ((p.flags & RevWalk.UNINTERESTING) != 0)
149
// Retain uninteresting parents. They show where the
150
// DAG was cut off because it wasn't interesting.
154
if ((p.flags & REWRITE) == 0)
156
// This parent was not eligible for rewriting. We
157
// need to keep it in the DAG.
161
if (pList.Length == 0)
163
// We can't go back any further, other than to
164
// just delete the parent entirely.
172
private RevCommit[] Cleanup(RevCommit[] oldList)
174
// Remove any duplicate parents caused due to rewrites (e.g. a merge
175
// with two sides that both simplified back into the merge base).
176
// We also may have deleted a parent by marking it null.
179
for (int o = 0; o < oldList.Length; o++)
181
RevCommit p = oldList[o];
186
if ((p.flags & DUPLICATE) != 0)
191
p.flags |= DUPLICATE;
194
if (newCnt == oldList.Length)
196
foreach (RevCommit p in oldList)
198
p.flags &= ~DUPLICATE;
202
RevCommit[] newList = new RevCommit[newCnt];
204
foreach (RevCommit p_1 in oldList)
208
newList[newCnt++] = p_1;
209
p_1.flags &= ~DUPLICATE;