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;