00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "common.h"
00010 #include "lanes.h"
00011
00012 #define IS_NODE(x) (x == NODE || x == NODE_R || x == NODE_L)
00013
00014 using namespace QGit;
00015
00016 void Lanes::init(const QString& expectedSha) {
00017
00018 clear();
00019 activeLane = 0;
00020 setBoundary(false);
00021 add(BRANCH, expectedSha, activeLane);
00022 }
00023
00024 void Lanes::clear() {
00025
00026 typeVec.clear();
00027 nextShaVec.clear();
00028 }
00029
00030 void Lanes::setBoundary(bool b) {
00031
00032
00033 NODE = (b) ? BOUNDARY_C : MERGE_FORK;
00034 NODE_R = (b) ? BOUNDARY_R : MERGE_FORK_R;
00035 NODE_L = (b) ? BOUNDARY_L : MERGE_FORK_L;
00036 boundary = b;
00037
00038 if (boundary)
00039 typeVec[activeLane] = BOUNDARY;
00040 }
00041
00042 bool Lanes::isFork(const QString& sha, bool& isDiscontinuity) {
00043
00044 int pos = findNextSha(sha, 0);
00045 isDiscontinuity = (activeLane != pos);
00046 if (pos == -1)
00047 return false;
00048
00049 return (findNextSha(sha, pos + 1) != -1);
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 }
00061
00062 void Lanes::setFork(const QString& sha) {
00063
00064 int rangeStart, rangeEnd, idx;
00065 rangeStart = rangeEnd = idx = findNextSha(sha, 0);
00066
00067 while (idx != -1) {
00068 rangeEnd = idx;
00069 typeVec[idx] = TAIL;
00070 idx = findNextSha(sha, idx + 1);
00071 }
00072 typeVec[activeLane] = NODE;
00073
00074 int& startT = typeVec[rangeStart];
00075 int& endT = typeVec[rangeEnd];
00076
00077 if (startT == NODE)
00078 startT = NODE_L;
00079
00080 if (endT == NODE)
00081 endT = NODE_R;
00082
00083 if (startT == TAIL)
00084 startT = TAIL_L;
00085
00086 if (endT == TAIL)
00087 endT = TAIL_R;
00088
00089 for (int i = rangeStart + 1; i < rangeEnd; i++) {
00090
00091 int& t = typeVec[i];
00092
00093 if (t == NOT_ACTIVE)
00094 t = CROSS;
00095
00096 else if (t == EMPTY)
00097 t = CROSS_EMPTY;
00098 }
00099 }
00100
00101 void Lanes::setMerge(const QStringList& parents) {
00102
00103
00104 if (boundary)
00105 return;
00106
00107 int& t = typeVec[activeLane];
00108 bool wasFork = (t == NODE);
00109 bool wasFork_L = (t == NODE_L);
00110 bool wasFork_R = (t == NODE_R);
00111 bool joinWasACross = false;
00112
00113 t = NODE;
00114
00115 int rangeStart = activeLane, rangeEnd = activeLane;
00116 QStringList::const_iterator it(parents.constBegin());
00117 for (++it; it != parents.constEnd(); ++it) {
00118
00119 int idx = findNextSha(*it, 0);
00120 if (idx != -1) {
00121
00122 if (typeVec[idx] == CROSS)
00123 joinWasACross = true;
00124
00125 typeVec[idx] = JOIN;
00126
00127 if (idx > rangeEnd)
00128 rangeEnd = idx;
00129
00130 if (idx < rangeStart)
00131 rangeStart = idx;
00132 } else
00133 rangeEnd = add(HEAD, *it, rangeEnd + 1);
00134 }
00135 int& startT = typeVec[rangeStart];
00136 int& endT = typeVec[rangeEnd];
00137
00138 if (startT == NODE && !wasFork && !wasFork_R)
00139 startT = NODE_L;
00140
00141 if (endT == NODE && !wasFork && !wasFork_L)
00142 endT = NODE_R;
00143
00144 if (startT == JOIN && !joinWasACross)
00145 startT = JOIN_L;
00146
00147 if (endT == JOIN && !joinWasACross)
00148 endT = JOIN_R;
00149
00150 if (startT == HEAD)
00151 startT = HEAD_L;
00152
00153 if (endT == HEAD)
00154 endT = HEAD_R;
00155
00156 for (int i = rangeStart + 1; i < rangeEnd; i++) {
00157
00158 int& t = typeVec[i];
00159
00160 if (t == NOT_ACTIVE)
00161 t = CROSS;
00162
00163 else if (t == EMPTY)
00164 t = CROSS_EMPTY;
00165
00166 else if (t == TAIL_R || t == TAIL_L)
00167 t = TAIL;
00168 }
00169 }
00170
00171 void Lanes::setInitial() {
00172
00173 int& t = typeVec[activeLane];
00174 if (!IS_NODE(t) && t != APPLIED)
00175 t = (boundary ? BOUNDARY : INITIAL);
00176 }
00177
00178 void Lanes::setApplied() {
00179
00180
00181 typeVec[activeLane] = APPLIED;
00182 }
00183
00184 void Lanes::changeActiveLane(const QString& sha) {
00185
00186 int& t = typeVec[activeLane];
00187 if (t == INITIAL || isBoundary(t))
00188 t = EMPTY;
00189 else
00190 t = NOT_ACTIVE;
00191
00192 int idx = findNextSha(sha, 0);
00193 if (idx != -1)
00194 typeVec[idx] = ACTIVE;
00195 else
00196 idx = add(BRANCH, sha, activeLane);
00197
00198 activeLane = idx;
00199 }
00200
00201 void Lanes::afterMerge() {
00202
00203 if (boundary)
00204 return;
00205
00206 for (uint i = 0; i < typeVec.count(); i++) {
00207
00208 int& t = typeVec[i];
00209
00210 if (isHead(t) || isJoin(t) || t == CROSS)
00211 t = NOT_ACTIVE;
00212
00213 else if (t == CROSS_EMPTY)
00214 t = EMPTY;
00215
00216 else if (IS_NODE(t))
00217 t = ACTIVE;
00218 }
00219 }
00220
00221 void Lanes::afterFork() {
00222
00223 for (uint i = 0; i < typeVec.count(); i++) {
00224
00225 int& t = typeVec[i];
00226
00227 if (t == CROSS)
00228 t = NOT_ACTIVE;
00229
00230 else if (isTail(t) || t == CROSS_EMPTY)
00231 t = EMPTY;
00232
00233 if (!boundary && IS_NODE(t))
00234 t = ACTIVE;
00235 }
00236 while (typeVec.last() == EMPTY) {
00237 typeVec.pop_back();
00238 nextShaVec.pop_back();
00239 }
00240 }
00241
00242 bool Lanes::isBranch() {
00243
00244 return (typeVec[activeLane] == BRANCH);
00245 }
00246
00247 void Lanes::afterBranch() {
00248
00249 typeVec[activeLane] = ACTIVE;
00250 }
00251
00252 void Lanes::afterApplied() {
00253
00254 typeVec[activeLane] = ACTIVE;
00255 }
00256
00257 void Lanes::nextParent(const QString& sha) {
00258
00259 nextShaVec[activeLane] = (boundary ? "" : sha);
00260 }
00261
00262 int Lanes::findNextSha(const QString& next, int pos) {
00263
00264 for (uint i = pos; i < nextShaVec.count(); i++)
00265 if (nextShaVec[i] == next)
00266 return i;
00267 return -1;
00268 }
00269
00270 int Lanes::findType(int type, int pos) {
00271
00272 for (uint i = pos; i < typeVec.count(); i++)
00273 if (typeVec[i] == type)
00274 return i;
00275 return -1;
00276 }
00277
00278 int Lanes::add(int type, const QString& next, int pos) {
00279
00280
00281 if (pos < (int)typeVec.count()) {
00282 pos = findType(EMPTY, pos);
00283 if (pos != -1) {
00284 typeVec[pos] = type;
00285 nextShaVec[pos] = next;
00286 return pos;
00287 }
00288 }
00289
00290 typeVec.append(type);
00291 nextShaVec.append(next);
00292 return typeVec.count() - 1;
00293 }