lanes.cpp

Go to the documentation of this file.
00001 /*
00002         Description: history graph computation
00003 
00004         Author: Marco Costalba (C) 2005-2006
00005 
00006         Copyright: See COPYING file that comes with this distribution
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 // changes the state so must be called as first one
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) // new branch case
00047                 return false;
00048 
00049         return (findNextSha(sha, pos + 1) != -1);
00050 /*
00051         int cnt = 0;
00052         while (pos != -1) {
00053                 cnt++;
00054                 pos = findNextSha(sha, pos + 1);
00055 //              if (isDiscontinuity)
00056 //                      isDiscontinuity = (activeLane != pos);
00057         }
00058         return (cnt > 1);
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 // setFork() must be called before setMerge()
00103 
00104         if (boundary)
00105                 return; // handle as a simple active line
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) { // skip first parent
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         // applied patches are not merges, nor forks
00181         typeVec[activeLane] = APPLIED; // TODO test with boundaries
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); // find first sha
00193         if (idx != -1)
00194                 typeVec[idx] = ACTIVE; // called before setBoundary()
00195         else
00196                 idx = add(BRANCH, sha, activeLane); // new branch
00197 
00198         activeLane = idx;
00199 }
00200 
00201 void Lanes::afterMerge() {
00202 
00203         if (boundary)
00204                 return; // will be reset by changeActiveLane()
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; // boundary will be reset by changeActiveLane()
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; // TODO test with boundaries
00250 }
00251 
00252 void Lanes::afterApplied() {
00253 
00254         typeVec[activeLane] = ACTIVE; // TODO test with boundaries
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         // first check empty lanes starting from pos
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         // if all lanes are occupied add a new lane
00290         typeVec.append(type);
00291         nextShaVec.append(next);
00292         return typeVec.count() - 1;
00293 }

Generated on Fri Dec 7 21:57:37 2007 for QGit by  doxygen 1.5.3