COOPY » Guide
version 0.6.5
|
00001 #include <coopy/Patcher.h> 00002 #include <coopy/MergeOutputSqlDiff.h> 00003 #include <coopy/MergeOutputHumanDiff.h> 00004 #include <coopy/MergeOutputVerboseDiff.h> 00005 #include <coopy/MergeOutputCsvDiff.h> 00006 #include <coopy/MergeOutputTdiff.h> 00007 #include <coopy/MergeOutputPatch.h> 00008 #include <coopy/MergeOutputIndex.h> 00009 #include <coopy/MergeOutputRowOps.h> 00010 #include <coopy/MergeOutputStats.h> 00011 #include <coopy/MergeOutputNovel.h> 00012 #include <coopy/MergeOutputEditList.h> 00013 #include <coopy/SheetPatcher.h> 00014 00015 #include <algorithm> 00016 00017 using namespace std; 00018 using namespace coopy::cmp; 00019 using namespace coopy::store; 00020 00021 00022 void RowChange::copy(const RowChange& alt) { 00023 mode = alt.mode; 00024 cond = alt.cond; 00025 val = alt.val; 00026 conflictingVal = alt.conflictingVal; 00027 conflictingParentVal = alt.conflictingParentVal; 00028 names = alt.names; 00029 allNames = alt.allNames; 00030 indexes = alt.indexes; 00031 sequential = alt.sequential; 00032 conflicted = alt.conflicted; 00033 pRow = alt.pRow; 00034 lRow = alt.lRow; 00035 rRow = alt.rRow; 00036 } 00037 00038 int OrderChange::identityToIndex(int id) const { 00039 //if (id==-1) return -1; 00040 vector<int>::const_iterator it = find(indicesBefore.begin(), 00041 indicesBefore.end(),id); 00042 if (it == indicesBefore.end()) { return -1; } 00043 return it-indicesBefore.begin(); 00044 } 00045 00046 int OrderChange::identityToIndexAfter(int id) const { 00047 //if (id==-1) return -1; 00048 vector<int>::const_iterator it = find(indicesAfter.begin(), 00049 indicesAfter.end(),id); 00050 if (it == indicesAfter.end()) { return -1; } 00051 return it-indicesAfter.begin(); 00052 } 00053 00054 Patcher *Patcher::createByName(const char *name, const char *version) { 00055 string mode(name); 00056 string _version; 00057 if (version!=NULL) _version = version; 00058 Patcher *result = NULL; 00059 #ifndef JUST_HIGHLIGHT 00060 if (mode=="sql") { 00061 result = new MergeOutputSqlDiff; 00062 } else if (mode=="human") { 00063 result = new MergeOutputHumanDiff; 00064 } else if (mode=="raw") { 00065 result = new MergeOutputVerboseDiff; 00066 } else if (mode=="tdiff"||mode=="default") { 00067 result = new MergeOutputTdiff; 00068 } else if (mode=="csv") { 00069 if (_version=="0.2") { 00070 result = new MergeOutputCsvDiffV0p2; 00071 } else if (_version=="0.4"||_version=="0.5"||_version=="") { 00072 result = new MergeOutputCsvDiff; 00073 } 00074 } else if (mode=="csv0") { 00075 result = new MergeOutputPatch; 00076 } else if (mode=="index") { 00077 result = new MergeOutputIndex; 00078 } else if (mode=="ops") { 00079 result = new MergeOutputRowOps; 00080 } else if (mode=="stats") { 00081 result = new MergeOutputStats; 00082 } else if (mode=="novel") { 00083 result = new MergeOutputNovel; 00084 } else if (mode=="edit") { 00085 result = new MergeOutputEditList; 00086 } else 00087 #endif 00088 if (mode=="apply") { 00089 result = SheetPatcher::createForApply(); 00090 } else if (mode=="sheet"||mode=="color"||mode=="hilite"||mode=="highlight"||mode=="hiliter"||mode=="highlighter"||mode=="default") { 00091 result = SheetPatcher::createForDescription(); 00092 } else if (mode=="review") { 00093 result = SheetPatcher::createForReview(); 00094 } else if (mode=="merge") { 00095 result = SheetPatcher::createForMerge(); 00096 } else { 00097 fprintf(stderr, "Format %s?\n", mode.c_str()); 00098 } 00099 return result; 00100 } 00101 00102 00103 00104 bool Patcher::startOutput(const std::string& output, CompareFlags& flags) { 00105 if (needOutputBook()) return true; 00106 if (output=="" || output=="-") { 00107 flags.out = stdout; 00108 return true; 00109 } 00110 FILE *fout = fopen(output.c_str(),"wb"); 00111 if (fout==NULL) { 00112 fprintf(stderr,"Could not open %s for writing\n", output.c_str()); 00113 exit(1); 00114 return false; 00115 } 00116 flags.out = fout; 00117 return true; 00118 } 00119 00120 bool Patcher::stopOutput(const std::string& output, CompareFlags& flags) { 00121 if (needOutputBook()) return true; 00122 if (flags.out!=stdout) { 00123 fclose(flags.out); 00124 flags.out = stdout; 00125 } 00126 return true; 00127 } 00128 00129 00130 bool Patcher::copyFile(const char *src, const char *dest) { 00131 FILE *fin = NULL; 00132 FILE *fout = NULL; 00133 fin = fopen(src,"rb"); 00134 if (fin==NULL) return false; 00135 fout = fopen(dest,"wb"); 00136 if (fout==NULL) { 00137 fclose(fin); 00138 return false; 00139 } 00140 char buf[32768]; 00141 int bytes_read = 0; 00142 while ((bytes_read=fread(buf,1,sizeof(buf),fin))>0) { 00143 fwrite(buf,1,bytes_read,fout); 00144 } 00145 fclose(fout); 00146 fclose(fin); 00147 return true; 00148 } 00149 00150 bool Patcher::setFlags(const CompareFlags& flags) { 00151 this->flags = flags; 00152 out = flags.out; 00153 return true; 00154 } 00155 00156 void Patcher::attachBook(coopy::store::TextBook& book) { 00157 patch_book = &book; 00158 pending = true; 00159 } 00160 00161 coopy::store::PolySheet Patcher::getSheetBase() { 00162 if (pending) { 00163 pending = false; 00164 coopy::store::TextBook *pbook = getBook(); 00165 if (pbook) { 00166 if (flags.tables.size()>0) { 00167 attachSheet(pbook->readSheet(flags.ordered_tables[0])); 00168 } else { 00169 attachSheet(pbook->readSheetByIndex(0)); 00170 } 00171 } 00172 } 00173 return patch_sheet; 00174 } 00175 00176 00177 coopy::store::PolySheet Patcher::getSheet() { 00178 PolySheet sheet = getSheetBase(); 00179 if (!sheet.isValid()) return sheet; 00180 if (!active_sheet.isValid()) { 00181 active_sheet = sheet; 00182 } 00183 if (&sheet.dataTail()!=&active_sheet.dataTail()) { 00184 active_sheet = sheet; 00185 } 00186 if (!getFlags().assume_header) { 00187 active_sheet.forbidSchema(); 00188 } 00189 return active_sheet; 00190 } 00191 00192 00193 bool Patcher::metaHint(const DataSheet& sheet) { 00194 getSheet(); 00195 if (!active_sheet.isValid()) return false; 00196 00197 if (!active_sheet.getMeta()) { 00198 if (sheet.getMeta()) { 00199 bool done = false; 00200 if (active_sheet.getSchema()) { 00201 dbg_printf("*** meta hint - was %s\n", 00202 active_sheet.getSchema()->toString().c_str()); 00203 done = active_sheet.getSchema()->copy(*sheet.getMeta()); 00204 } 00205 if (!done) { 00206 active_sheet.setSchema(sheet.getMeta()->clone(),true); 00207 } 00208 dbg_printf("*** meta hint - is now %s\n", 00209 active_sheet.getSchema()->toString().c_str()); 00210 if (sheet.hasRowOffset()&&!active_sheet.hasRowOffset()) { 00211 if (sheet.height()==active_sheet.height()) { 00212 active_sheet.getSchema()->setHeaderHeight(0); 00213 } 00214 } 00215 /* 00216 if (sheet.height()!=active_sheet.height()) { 00217 dbg_printf("Height mismatch? %d v %d\n", sheet.height(), active_sheet.height()); 00218 active_sheet.mustHaveSchema(); 00219 active_sheet.hideHeaders(); 00220 if (sheet.height()!=active_sheet.height()) { 00221 dbg_printf("Height mismatch persists\n"); 00222 } 00223 } 00224 */ 00225 setNames(true); 00226 } 00227 } 00228 return true; 00229 } 00230 00231 00232 bool Patcher::applyPool(const PoolChange& change) { 00233 if (flags.pool==NULL) { 00234 fprintf(stderr,"No storage available for pool information.\n"); 00235 return false; 00236 } 00237 std::string poolName = change.poolName; 00238 std::string tableName = change.tableName; 00239 for (std::vector<coopy::cmp::TableField>::const_iterator it=change.pool.begin(); it!=change.pool.end(); it++) { 00240 flags.pool->create(poolName,(it->tableName=="")?tableName:(it->tableName),it->fieldName,it->invented); 00241 } 00242 return true; 00243 } 00244 00245 00246 00247 void RowChange::show() { 00248 MergeOutputVerboseDiff diff; 00249 diff.changeRow(*this); 00250 } 00251 00252 00253 00254 00255 bool Patcher::addPoolsFromFlags(const DataSheet& sheet, bool msg) { 00256 if (flags.coined.size()>0) { 00257 00258 SheetSchema *ss = sheet.getSchema(); 00259 if (!ss) return false; 00260 00261 string name = ss->getSheetName(); 00262 00263 for (int j=0; j<(int)flags.coined.size(); j++) { 00264 string field = flags.coined[j]; 00265 for (int i=0; i<ss->getColumnCount(); i++) { 00266 string field2 = ss->getColumnInfo(i).getName(); 00267 if (field==field2) { 00268 PoolChange pc; 00269 pc.poolName = name; 00270 pc.tableName = name; 00271 pc.pool.push_back(TableField("",field,true)); 00272 changePool(pc); 00273 } 00274 } 00275 } 00276 } else { 00277 if (flags.pool!=NULL) { 00278 SheetSchema *ss = sheet.getSchema(); 00279 if (!ss) return false; 00280 string name = ss->getSheetName(); 00281 for (int i=0; i<ss->getColumnCount(); i++) { 00282 string field2 = ss->getColumnInfo(i).getName(); 00283 PoolColumnLink link = flags.pool->lookup(name,field2); 00284 if (link.isValid()) { 00285 PoolChange pc; 00286 pc.poolName = link.getPoolName(); 00287 pc.tableName = link.getTableName(); 00288 pc.pool.push_back(TableField("",link.getColumnName(),link.isInventor())); 00289 if (msg) { 00290 changePool(pc); 00291 } else { 00292 applyPool(pc); 00293 } 00294 } 00295 } 00296 } 00297 } 00298 return true; 00299 } 00300 00301 00302 bool Patcher::addPoolsFromSchema(const coopy::store::DataSheet& sheet, 00303 const coopy::store::NameSniffer& sniffer, 00304 const std::string& sheetName, 00305 bool msg) { 00306 const CompareFlags& flags = getFlags(); 00307 bool addedAuto = false; 00308 for (int i=0; i<sheet.width(); i++) { 00309 string name = sniffer.suggestColumnName(i); 00310 PoolColumnLink pc = flags.pool->lookup(sheetName,name); 00311 if (!pc.isValid()) { 00312 ColumnType t = sniffer.suggestColumnType(i); 00313 if (t.autoIncrement&&!addedAuto) { 00314 flags.pool->create(sheetName,sheetName,name,true); 00315 pc = flags.pool->lookup(sheetName,name); 00316 addedAuto = true; 00317 } 00318 if (t.foreignKey!="") { 00319 flags.pool->create(t.foreignTable,sheetName,name,false); 00320 pc = flags.pool->lookup(sheetName,name); 00321 } 00322 } 00323 if (pc.isValid()) { 00324 PoolChange c; 00325 c.poolName = pc.getPoolName(); 00326 c.tableName = pc.getTableName(); 00327 c.pool.push_back(TableField("",pc.getColumnName(),pc.isInventor())); 00328 if (msg) { 00329 changePool(c); 00330 } else { 00331 applyPool(c); 00332 } 00333 } 00334 } 00335 return addedAuto; 00336 } 00337 00338 00339