2 Description: history graph computation
4 Author: Marco Costalba (C) 2005-2007
6 Copyright: See COPYING file that comes with this distribution
12 #define IS_NODE(x) (x == NODE || x == NODE_R || x == NODE_L)
15 void Lanes::init(const QString
& expectedSha
) {
20 add(BRANCH
, expectedSha
, activeLane
);
29 void Lanes::setBoundary(bool b
) {
30 // changes the state so must be called as first one
32 NODE
= b
? BOUNDARY_C
: MERGE_FORK
;
33 NODE_R
= b
? BOUNDARY_R
: MERGE_FORK_R
;
34 NODE_L
= b
? BOUNDARY_L
: MERGE_FORK_L
;
38 typeVec
[activeLane
] = BOUNDARY
;
41 bool Lanes::isFork(const QString
& sha
, bool& isDiscontinuity
) {
43 int pos
= findNextSha(sha
, 0);
44 isDiscontinuity
= (activeLane
!= pos
);
45 if (pos
== -1) // new branch case
48 return (findNextSha(sha
, pos
+ 1) != -1);
53 pos = findNextSha(sha, pos + 1);
54 // if (isDiscontinuity)
55 // isDiscontinuity = (activeLane != pos);
61 void Lanes::setFork(const QString
& sha
) {
63 int rangeStart
, rangeEnd
, idx
;
64 rangeStart
= rangeEnd
= idx
= findNextSha(sha
, 0);
69 idx
= findNextSha(sha
, idx
+ 1);
71 typeVec
[activeLane
] = NODE
;
73 int& startT
= typeVec
[rangeStart
];
74 int& endT
= typeVec
[rangeEnd
];
88 for (int i
= rangeStart
+ 1; i
< rangeEnd
; i
++) {
100 void Lanes::setMerge(const QStringList
& parents
) {
101 // setFork() must be called before setMerge()
104 return; // handle as a simple active line
106 int& t
= typeVec
[activeLane
];
107 bool wasFork
= (t
== NODE
);
108 bool wasFork_L
= (t
== NODE_L
);
109 bool wasFork_R
= (t
== NODE_R
);
110 bool joinWasACross
= false;
114 int rangeStart
= activeLane
, rangeEnd
= activeLane
;
116 QStringList::const_iterator it
=parents
.begin();
118 for (++it
; it
!= parents
.end(); ++it
) { // skip first parent
120 int idx
= findNextSha(*it
, 0);
123 if (typeVec
[idx
] == CROSS
)
124 joinWasACross
= true;
131 if (idx
< rangeStart
)
134 rangeEnd
= add(HEAD
, *it
, rangeEnd
+ 1);
136 int& startT
= typeVec
[rangeStart
];
137 int& endT
= typeVec
[rangeEnd
];
139 if (startT
== NODE
&& !wasFork
&& !wasFork_R
)
142 if (endT
== NODE
&& !wasFork
&& !wasFork_L
)
145 if (startT
== JOIN
&& !joinWasACross
)
148 if (endT
== JOIN
&& !joinWasACross
)
157 for (int i
= rangeStart
+ 1; i
< rangeEnd
; i
++) {
167 else if (t
== TAIL_R
|| t
== TAIL_L
)
172 void Lanes::setInitial() {
174 int& t
= typeVec
[activeLane
];
175 if (!IS_NODE(t
) && t
!= APPLIED
)
176 t
= (boundary
? BOUNDARY
: INITIAL
);
179 void Lanes::setApplied() {
181 // applied patches are not merges, nor forks
182 typeVec
[activeLane
] = APPLIED
; // TODO test with boundaries
185 void Lanes::changeActiveLane(const QString
& sha
) {
187 int& t
= typeVec
[activeLane
];
188 if (t
== INITIAL
|| isBoundary(t
))
193 int idx
= findNextSha(sha
, 0); // find first sha
195 typeVec
[idx
] = ACTIVE
; // called before setBoundary()
197 idx
= add(BRANCH
, sha
, activeLane
); // new branch
202 void Lanes::afterMerge() {
205 return; // will be reset by changeActiveLane()
207 for (unsigned int i
= 0; i
< typeVec
.size(); i
++) {
211 if (isHead(t
) || isJoin(t
) || t
== CROSS
)
214 else if (t
== CROSS_EMPTY
)
222 void Lanes::afterFork() {
224 for (unsigned int i
= 0; i
< typeVec
.size(); i
++) {
231 else if (isTail(t
) || t
== CROSS_EMPTY
)
234 if (!boundary
&& IS_NODE(t
))
235 t
= ACTIVE
; // boundary will be reset by changeActiveLane()
237 while (typeVec
.back() == EMPTY
) {
239 nextShaVec
.pop_back();
243 bool Lanes::isBranch() {
245 return (typeVec
[activeLane
] == BRANCH
);
248 void Lanes::afterBranch() {
250 typeVec
[activeLane
] = ACTIVE
; // TODO test with boundaries
253 void Lanes::afterApplied() {
255 typeVec
[activeLane
] = ACTIVE
; // TODO test with boundaries
258 void Lanes::nextParent(const QString
& sha
) {
260 nextShaVec
[activeLane
] = (boundary
? QString(_T("")) : sha
);
263 int Lanes::findNextSha(const QString
& next
, int pos
) {
265 for (unsigned int i
= pos
; i
< nextShaVec
.size(); i
++)
266 if (nextShaVec
[i
] == next
)
271 int Lanes::findType(int type
, int pos
) {
273 for (unsigned int i
= pos
; i
< typeVec
.size(); i
++)
274 if (typeVec
[i
] == type
)
279 int Lanes::add(int type
, const QString
& next
, int pos
) {
281 // first check empty lanes starting from pos
282 if (pos
< (int)typeVec
.size()) {
283 pos
= findType(EMPTY
, pos
);
286 nextShaVec
[pos
] = next
;
290 // if all lanes are occupied add a new lane
291 typeVec
.push_back(type
);
292 nextShaVec
.push_back(next
);
293 return typeVec
.size() - 1;