1/* 2 * Copyright 2009, The Android Open Source Project 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include <map> 27#include <string> 28#include <vector> 29#include <cstdio> 30#include <stdlib.h> 31#include <string.h> 32 33using namespace std; 34 35string WEBKITLIB = "external/webkit"; 36 37string oldBaseStr; 38string oldCmdStr; 39string newBaseStr; 40string newCmdStr; 41string sandboxBaseStr; 42string sandboxCmdStr; 43string outputDir; 44string scratchDir; 45 46const char* oldBase; 47const char* oldCmd; 48const char* newBase; 49const char* newCmd; 50const char* sandboxBase; 51const char* sandboxCmd; 52 53bool assert_debug; 54 55#define myassert(a) do { \ 56 if (!(a)) { \ 57 fprintf(stderr, "%s %d %s\n", __FUNCTION__, __LINE__, #a); \ 58 fflush(stderr); \ 59 if (assert_debug) for(;;); else exit(0); \ 60 } \ 61} while(false) 62 63class Options { 64public: 65 Options() : emitGitCommands(false), emitPerforceCommands(false), 66 mergeMake(true), copyOther(true), mergeCore(true), 67 removeEmptyDirs(true), removeSVNDirs(true), debug(false), 68 execute(false), verbose(false), cleared(false) 69 { 70 } 71 72 bool finish(); 73 void clearOnce() 74 { 75 if (cleared) 76 return; 77 mergeMake = copyOther = mergeCore = removeEmptyDirs = removeSVNDirs = false; 78 cleared = true; 79 } 80 string androidWebKit; 81 string baseWebKit; 82 string newWebKit; 83 bool emitGitCommands; 84 bool emitPerforceCommands; 85 bool mergeMake; 86 bool copyOther; 87 bool mergeCore; 88 bool removeEmptyDirs; 89 bool removeSVNDirs; 90 bool debug; 91 bool execute; 92 bool verbose; 93private: 94 bool cleared; 95}; 96 97Options options; 98 99char* GetFile(string fileNameStr, size_t* sizePtr = NULL, int* lines = NULL) 100{ 101 const char* fileName = fileNameStr.c_str(); 102 FILE* file = fopen(fileName, "r"); 103 if (file == NULL) 104 { 105 fprintf(stderr, "can't read %s\n", fileName); 106 myassert(0); 107 return 0; 108 } 109 fseek(file, 0, SEEK_END); 110 size_t size = ftell(file); 111 if (sizePtr) 112 *sizePtr = size; 113 fseek(file, 0, SEEK_SET); 114 char* buffer = new char[size + 2]; 115 fread(buffer, size, 1, file); 116 buffer[size] = buffer[size + 1] = '\0'; 117 int lineCount = 0; 118 for (size_t index = 0; index < size; index++) { 119 if (buffer[index] == '\n') { 120 buffer[index] = '\0'; 121 lineCount++; 122 } 123 } 124 if (lines) 125 *lines = lineCount; 126 fclose(file); 127 return buffer; 128} 129 130bool Options::finish() 131{ 132 ::assert_debug = options.debug; 133 if (androidWebKit.size() == 0) { 134 fprintf(stderr, "missing --android parameter"); 135 return false; 136 } 137 if (baseWebKit.size() == 0) { 138 fprintf(stderr, "missing --basewebkit parameter"); 139 return false; 140 } 141 if (newWebKit.size() == 0) { 142 fprintf(stderr, "missing --newwebkit parameter"); 143 return false; 144 } 145 sandboxBaseStr = androidWebKit + "/" + WEBKITLIB; 146 sandboxCmdStr = sandboxBaseStr; 147 int err = system("pwd > pwd.txt"); 148 myassert(err != -1); 149 outputDir = string(GetFile("pwd.txt")); 150 system("rm pwd.txt"); 151 myassert(outputDir.size() > 0); 152 scratchDir = outputDir; 153 outputDir += "/scripts/"; 154 string outputMkdir = "test -d " + outputDir + " || mkdir " + outputDir; 155 system(outputMkdir.c_str()); 156 scratchDir += "/scratch/"; 157 string scratchMkdir = "test -d " + scratchDir + " || mkdir " + scratchDir; 158 system(scratchMkdir.c_str()); 159 oldBaseStr = baseWebKit; 160 oldCmdStr = oldBaseStr; 161 newBaseStr = newWebKit; 162 newCmdStr = newBaseStr; 163 oldBase = oldBaseStr.c_str(); 164 oldCmd = oldCmdStr.c_str(); 165 newBase = newBaseStr.c_str(); 166 newCmd = newCmdStr.c_str(); 167 sandboxBase = sandboxBaseStr.c_str(); 168 sandboxCmd = sandboxCmdStr.c_str(); 169 return true; 170} 171 172// scratch files 173string ScratchFile(const char* name) 174{ 175 return scratchDir + name + ".txt"; 176} 177 178FILE* commandFile; 179FILE* copyDirFile; 180FILE* oopsFile; 181 182string SedEscape(const char* str) 183{ 184 string result; 185 char ch; 186 while ((ch = *str++) != '\0') { 187 if (ch == '/' || ch == '\\' || ch == '$') 188 result += '\\'; 189 result += ch; 190 } 191 return result; 192} 193 194char* List(const char* base, char* name, const char* workingDir) 195{ 196 string listStr = "ls -F \""; 197 listStr += string(base) + "/" + workingDir + "\" > " + ScratchFile(name); 198 int err = system(listStr.c_str()); 199 myassert(err == 0); 200 return GetFile(ScratchFile(name)); 201} 202 203bool Merge(const char* oldDir, const char* oldFile, const char* newDir, const char* newFile, 204 const char* outFile) 205{ 206 char scratch[2048]; 207 208 sprintf(scratch, "merge -p -q \"%s/%s/%s\" \"%s/%s/%s\" \"%s/%s/%s\" > %s", 209 sandboxBase, oldDir, oldFile, oldBase, oldDir, oldFile, newBase, newDir, newFile, outFile); 210 int err = system(scratch); 211 myassert(err == 0 || err ==1 || err == 256); 212 return err == 0; 213} 214 215bool Merge(const char* dir, const char* file) 216{ 217 return Merge(dir, file, dir, file, "/dev/null"); 218} 219 220/* 221static const char* skipNonSpace(char** linePtr) { 222 char* line = *linePtr; 223 while (line[0] && isspace(line[0]) == false) 224 line++; 225 *linePtr = line; 226 return line; 227} 228*/ 229 230static bool endsWith(const char* str, const char* end) { 231 size_t endLen = strlen(end); 232 const char* endStr = str + strlen(str) - endLen; 233 return endStr >= str && strcmp(endStr, end) == 0; 234} 235 236static void skipSpace(char** linePtr) { 237 char* line = *linePtr; 238 while (isspace(line[0])) 239 line++; 240 *linePtr = line; 241} 242 243/* 244static void setTrimmed(string& str, char* loc, int len) { 245 char* start = loc; 246 skipSpace(&loc); 247 len -= loc - start; 248 while (len > 0 && isspace(loc[len - 1])) 249 len--; 250 str = string(loc, len); 251} 252*/ 253 254static bool skipText(char** linePtr, const char* text) { 255 skipSpace(linePtr); 256 size_t length = strlen(text); 257 bool result = strncmp(*linePtr, text, length) == 0; 258 if (result) 259 *linePtr += length; 260 skipSpace(linePtr); 261 return result; 262} 263 264static bool isTokenChar(char ch) { 265 return isalnum(ch) || ch == '_'; 266} 267 268struct Pair { 269 char* name; 270 int brace; 271}; 272 273class Parse { 274public: 275 char* m_text; 276 bool m_inComment; 277 bool m_inFunction; 278 bool m_inFindFunctionType; 279 vector<Pair> m_classes; 280 vector<Pair> m_namespaces; 281 vector<Pair> m_preprocessorConditions; 282 string m_functionName; 283 string m_functionDeclaration; 284 string m_classDeclaration; 285 int m_braceLevel; 286 int m_functionBrace; 287 288 Parse(char* text) : m_text(text), m_inComment(false), m_inFunction(false), m_inFindFunctionType(false), 289 m_braceLevel(0), m_functionBrace(0) {} 290 291 int CheckForBrace() 292 { 293 int indent = 0; 294 // don't count braces in strings, chars, comments 295 do { 296 char* openBrace = strchr(m_text, '{'); 297 char* closeBrace = strchr(m_text, '}'); 298 if (openBrace == NULL && closeBrace == NULL) 299 break; 300 char* brace = openBrace == NULL ? closeBrace : closeBrace == NULL ? openBrace : 301 openBrace < closeBrace ? openBrace : closeBrace; 302 char* doubleQ = strchr(m_text, '"'); 303 char* singleQ = strchr(m_text, '\''); 304 char* quote = doubleQ == NULL ? singleQ : singleQ == NULL ? doubleQ : 305 doubleQ < singleQ ? doubleQ : singleQ; 306 char quoteMark = quote == doubleQ ? '"' : '\''; 307 if (quote && quote < brace) { 308 myassert(quote[-1] != '\\'); 309 do { 310 quote = strchr(quote + 1, quoteMark); 311 myassert(doubleQ); 312 } while (quote[-1] == '\\'); 313 m_text = quote + 1; 314 continue; 315 } 316 indent += openBrace != NULL ? 1 : -1; 317 m_text = openBrace + 1; 318 } while (m_text[0] != '\0'); 319 return indent; 320 } 321 322int ParseLine() 323{ 324 size_t textLen = strlen(m_text); 325 char* lineStart = m_text; 326 char* commentStart; 327 if (m_text[0] == '\0') 328 goto nextLine; 329 if (m_inComment == false && m_text[0] == '/') { 330 m_inComment = m_text[1] == '*'; 331 if (m_text[1] == '/' || m_text[1] == '*') 332 goto nextLine; 333 } 334 commentStart = m_text; // before anything else, turn embedded comments into their own lines 335 if (m_inComment == false && skipText(&commentStart, "//")) { 336 if (commentStart < lineStart + textLen) 337 commentStart[0] = '/'; 338 else 339 commentStart[-1] = ' '; 340 commentStart -= 2; 341 commentStart[0] = '\0'; 342 textLen = commentStart - lineStart; 343 goto nextLine; 344 } 345 if (m_inComment || skipText(&commentStart, "/*")) { 346 char* commentEnd = commentStart; 347 if (skipText(&commentEnd, "*/")) { 348 if (commentEnd < lineStart + textLen) { 349 commentEnd[-1] = '\0'; 350 textLen = commentEnd - lineStart - 2; 351 } 352 if (m_inComment) { 353 m_inComment = false; 354 goto nextLine; 355 } 356 } 357 if (m_inComment) 358 goto nextLine; 359 memcpy(commentStart - 2, "\0/*", 3); 360 textLen = commentStart - lineStart - 2; 361 } 362 if (skipText(&m_text, "#include")) 363 goto nextLine; 364 if (skipText(&m_text, "#if") || skipText(&m_text, "#else")) { 365 Pair condition = { lineStart, m_braceLevel }; 366 m_preprocessorConditions.push_back(condition); 367 goto nextLine; 368 } 369 { 370 bool is_endif = false; 371 if (skipText(&m_text, "#elif") || (is_endif = skipText(&m_text, "#endif")) != false) { // pop prior elif, if 372 char* lastText; 373 do { 374 int last = m_preprocessorConditions.size() - 1; 375 myassert(last >= 0); 376 lastText = m_preprocessorConditions[last].name; 377 m_preprocessorConditions.pop_back(); 378 } while (is_endif && skipText(&lastText, "#else") == true); 379 goto nextLine; 380 } 381 } 382 if (skipText(&m_text, "namespace")) { 383 Pair space = { lineStart, m_braceLevel }; 384 m_namespaces.push_back(space); 385 goto checkForBrace; 386 } 387 if (m_inFunction) 388 goto checkForBrace; 389 // detect functions by looking for token preceding open-paren. 390 if (m_inFindFunctionType == false) { 391 char* openParen = strchr(m_text, '('); 392 if (openParen) { 393 char* last = openParen; 394 while (last > m_text && isspace(last[-1])) 395 --last; 396 while (last > m_text && ((isTokenChar(last[-1]) || last[-1] == ':') && last[-2] == ':')) 397 --last; 398 myassert(isdigit(last[0]) == false); 399 if (isTokenChar(last[0])) { 400 m_inFindFunctionType = true; 401 m_functionName = string(last); 402 } 403 } 404 } 405 { 406 char* openBrace = strchr(m_text, '{'); 407 char* semiColon = strchr(m_text, ';'); 408 if (semiColon != NULL && semiColon < openBrace) 409 openBrace = NULL; 410 // functions are of the form: type (class::)*function(parameter-list) { 411 // all of which may be on separate lines 412 // so keep track of returntype, class, function, paramlist, openbrace separately 413 if (m_inFindFunctionType == true) { // look ahead to see which comes first, a semicolon or an open brace 414 if (openBrace) { 415 m_functionBrace = ++m_braceLevel; 416 m_inFunction = true; 417 m_inFindFunctionType = false; 418 m_text = openBrace + 1; 419 goto checkForBrace; 420 } 421 if (semiColon != NULL) { // a function declaration 422 m_inFindFunctionType = false; 423 m_functionDeclaration = m_functionName; 424 m_functionName.erase(0, m_functionName.length()); 425 } else 426 goto nextLine; 427 } 428 // FIXME what if class line has neither brace nor semi? 429 if (skipText(&m_text, "class")) { 430 if (openBrace > m_text) { 431 Pair _class = { lineStart, m_braceLevel }; 432 m_classes.push_back(_class); 433 } else if (semiColon != NULL) { 434 m_classDeclaration = lineStart; // !!! FIXME should have function form as above 435 } 436 } 437 } 438checkForBrace: 439 m_braceLevel += CheckForBrace(); 440 if (m_functionBrace > 0 && m_braceLevel <= m_functionBrace) { 441 m_functionName.erase(0, m_functionName.length()); 442 m_functionBrace = 0; 443 } 444nextLine: 445 return textLen; 446} 447 448}; 449 450char* const GetAndroidDiffs(const char* dir, const char* filename) 451{ 452 char scratch[2048]; 453 string diffsFile = ScratchFile(__FUNCTION__); 454 sprintf(scratch, "diff \"%s/%s/%s\" \"%s/%s/%s\" > %s", sandboxBase, dir, 455 filename, oldBase, dir, filename, diffsFile.c_str()); 456 int err = system(scratch); 457 myassert(err == 0 || err == 256); 458 char* const diffs = GetFile(diffsFile); 459 return diffs; 460} 461 462void CheckForExec(const char* base1, const char* dir1, const char* file1, 463 const char* base2, const char* dir2, const char* file2, bool* ex1, bool* ex2) 464{ 465 size_t file1Len = strlen(file1); 466 size_t file2Len = strlen(file2); 467 bool file1Ex = file1[file1Len - 1] == '*'; 468 bool file2Ex = file2[file2Len - 1] == '*'; 469 if (file1Ex != file2Ex) { 470 fprintf(stderr, "warning: %s/%s/%s has %sexec bit set while" 471 " %s/%s/%s has %sexec bit set\n", 472 base1, dir1, file1, file1Ex ? "" : "no ", 473 base2, dir2, file2, file2Ex ? "" : "no "); 474 } 475 if (ex1) *ex1 = file1Ex; 476 if (ex2) *ex2 = file2Ex; 477} 478 479bool CompareFiles(const char* base1, const char* dir1, const char* file1, 480 const char* base2, const char* dir2, const char* file2) 481{ 482 char scratch[2048]; 483 bool file1Ex, file2Ex; 484 string compareFileStr = ScratchFile(__FUNCTION__); 485 CheckForExec(base1, dir1, file1, base2, dir2, file2, &file1Ex, &file2Ex); 486 sprintf(scratch, "diff --brief \"%s/%s/%.*s\" \"%s/%s/%.*s\" > %s", 487 base1, dir1, (int) strlen(file1) - (int) file1Ex, file1, 488 base2, dir2, (int) strlen(file2) - (int) file2Ex, file2, 489 compareFileStr.c_str()); 490 int err = system(scratch); 491 myassert(err == 0 || err == 256); 492 char* scratchText = GetFile(compareFileStr); 493 size_t len = strlen(scratchText); 494 delete[] scratchText; 495 return len > 0; 496} 497 498bool CompareFiles(const char* base1, const char* base2, const char* dir, const char* file) 499{ 500 return CompareFiles(base1, dir, file, base2, dir, file); 501} 502 503int Compare(char* one, size_t len1, char* two, size_t len2) 504{ 505 char* o_end = one + len1; 506 char* t_end = two + len2; 507 do { 508 if (one == o_end) 509 return two == t_end ? 0 : 1; 510 if (two == t_end) 511 return -1; 512 char o = *one++; 513 char t = *two++; 514 if (o == t) 515 continue; 516 if (o == '/') 517 return -1; 518 if (t == '/') 519 return 1; 520 return o < t ? -1 : 1; 521 } while (true); 522 myassert(0); 523 return 0; 524} 525 526string Find(const char* oldList) 527{ 528 string result; 529 char scratch[2048]; 530 // look in WebCore and JavaScriptCore 531 string findWebCore = ScratchFile("FindWebCore"); 532 sprintf(scratch, "cd %s%s ; find . -name \"%s\" > %s", 533 newBase, "/WebCore", oldList, findWebCore.c_str()); 534 int err = system(scratch); 535 myassert(err == 0 || err == 256); 536 int webCount; 537 char* foundInWebCore = GetFile(findWebCore, NULL, &webCount); 538 char* originalFoundInWebCore = foundInWebCore; 539 string findJavaScriptCore = ScratchFile("FindJavaScriptCore"); 540 sprintf(scratch, "cd %s%s ; find . -name \"%s\" > %s", 541 newBase, "/JavaScriptCore", oldList, findJavaScriptCore.c_str()); 542 err = system(scratch); 543 myassert(err == 0 || err == 256); 544 int javaScriptCount; 545 char* foundInJavaScriptCore = GetFile(findJavaScriptCore, NULL, &javaScriptCount); 546 char* originalFoundInJavaScriptCore = foundInJavaScriptCore; 547 if (webCount == 1 && javaScriptCount == 0) { 548 result = "WebCore/" + string(&foundInWebCore[2]); 549 } else if (webCount == 0 && javaScriptCount == 1) { 550 result = "JavaScriptCore/" + string(&foundInJavaScriptCore[2]); 551 } else if (webCount == 1 && javaScriptCount == 1 && 552 strncmp(&foundInWebCore[2], "ForwardingHeaders/", 18) == 0) { 553 result = "JavaScriptCore/" + string(&foundInJavaScriptCore[2]); 554 } else if (webCount == 1 && javaScriptCount == 1 && 555 strncmp(&foundInJavaScriptCore[2], "API/tests/", 10) == 0) { 556 result = "JavaScriptCore/" + string(&foundInJavaScriptCore[2]); 557 } else if (webCount + javaScriptCount > 0) { 558 fprintf(stderr, "deleted file \"%s\" has more than one possible rename:\n", oldList); 559 int index; 560 for (index = 0; index < webCount; index++) { 561 fprintf(stderr, "WebCore/%s\n", &foundInWebCore[2]); 562 foundInWebCore += strlen(foundInWebCore) + 1; 563 } 564 for (index = 0; index < javaScriptCount; index++) { 565 fprintf(stderr, "JavaScriptCore/%s\n", &foundInJavaScriptCore[2]); 566 foundInJavaScriptCore += strlen(foundInJavaScriptCore) + 1; 567 } 568 } 569 delete[] originalFoundInWebCore; 570 delete[] originalFoundInJavaScriptCore; 571 return result; 572} 573 574char* GetMakeAndExceptions(const char* dir, const char* filename, size_t* makeSize, 575 string* excludedFilesPtr, string* excludedGeneratedPtr, 576 string* excludedDirsPtr, string* androidFilesPtr, 577 char** startPtr, char** localStartPtr) 578{ 579 char scratch[1024]; 580 sprintf(scratch, "%s/%s/%s", sandboxBase, dir, filename); 581 char* makeFile = GetFile(scratch, makeSize); 582 char* start = makeFile; 583 do { // find first filename in makefile 584 if (strncmp(start, "# LOCAL_SRC_FILES_EXCLUDED := \\", 30) == 0) 585 break; 586 start += strlen(start) + 1; 587 } while (start < makeFile + *makeSize); 588 myassert(start[0] != '\0'); 589 start += strlen(start) + 1; 590 // construct one very large regular expression that looks like: 591 // echo '%s' | grep -v -E 'DerivedSources.cpp|WebCorePrefix.cpp...' 592 // to filter out matches that aren't allowed 593 // wildcards '*' in the original need to be expanded to '.*' 594 string excludedFiles = "grep -v -E '"; 595 while (strncmp(start, "#\t", 2) == 0) { 596 start += 2; 597 char ch; 598 while ((ch = *start++) != ' ') { 599 if (ch == '*') 600 excludedFiles += '.'; 601 else if (ch == '.') 602 excludedFiles += '\\'; 603 excludedFiles += ch; 604 } 605 excludedFiles += "|"; 606 myassert(*start == '\\'); 607 start += 2; 608 } 609 excludedFiles[excludedFiles.size() - 1] = '\''; 610 *excludedFilesPtr = excludedFiles; 611 do { 612 if (strncmp(start, "# LOCAL_GENERATED_FILES_EXCLUDED := \\", 37) == 0 || 613 strncmp(start, "# LOCAL_DIR_WILDCARD_EXCLUDED := \\", 34) == 0) 614 break; 615 start += strlen(start) + 1; 616 } while (start < makeFile + *makeSize); 617 if (strncmp(start, "# LOCAL_GENERATED_FILES_EXCLUDED := \\", 37) == 0) { 618 string excludedGenerated = "grep -v -E '"; 619 start += strlen(start) + 1; 620 while (strncmp(start, "#\t", 2) == 0) { 621 start += 2; 622 char ch; 623 while ((ch = *start++) != ' ') { 624 if (ch == '*') 625 excludedGenerated += '.'; 626 else if (ch == '.') 627 excludedGenerated += '\\'; 628 excludedGenerated += ch; 629 } 630 excludedGenerated += "|"; 631 myassert(*start == '\\'); 632 start += 2; 633 } 634 myassert(excludedGeneratedPtr); 635 excludedGenerated[excludedGenerated.size() - 1] = '\''; 636 *excludedGeneratedPtr = excludedGenerated; 637 } 638 do { // find first filename in makefile 639 if (strncmp(start, "# LOCAL_DIR_WILDCARD_EXCLUDED := \\", 34) == 0) 640 break; 641 start += strlen(start) + 1; 642 } while (start < makeFile + *makeSize); 643 if (start[0] != '\0') { 644 string excludedDirs = "-e '/\\.vcproj\\// d' -e '/\\.svn\\// d' "; 645 do { 646 start += strlen(start) + 1; 647 char* exceptionDirStart = start; 648 if (strncmp(exceptionDirStart, "#\t", 2) != 0) { 649 myassert(exceptionDirStart[0] == '\0'); 650 break; 651 } 652 exceptionDirStart += 2; 653 char* exceptionDirEnd = exceptionDirStart; 654 do { 655 exceptionDirEnd = strchr(exceptionDirEnd, '\\'); 656 } while (exceptionDirEnd && *++exceptionDirEnd == '/'); 657 myassert(exceptionDirEnd); 658 --exceptionDirEnd; 659 myassert(exceptionDirEnd[-1] == ' '); 660 myassert(exceptionDirEnd[-2] == '*'); 661 myassert(exceptionDirEnd[-3] == '/'); 662 exceptionDirEnd[-3] = '\0'; 663 excludedDirs += "-e '/"; 664 if (exceptionDirStart[0] == '/') 665 excludedDirs += "\\"; 666 excludedDirs += exceptionDirStart; 667 excludedDirs += "\\// d' "; 668 start = exceptionDirEnd; 669 } while (true); 670 *excludedDirsPtr = excludedDirs; 671 } 672 *startPtr = start; 673 // optionally look for android-specific files 674 char* makeEnd = makeFile + *makeSize; 675 do { // find first filename in makefile 676 if (strcmp(start, "# LOCAL_ANDROID_SRC_FILES_INCLUDED := \\") == 0) 677 break; 678 } while ((start += strlen(start) + 1), start < makeEnd); 679 if (start >= makeEnd) 680 return makeFile; 681 start += strlen(start) + 1; 682 string androidFiles = "grep -v -E '"; 683 do { 684 myassert(strncmp(start, "#\t", 2) == 0); 685 start += 2; 686 char ch; 687 bool isIdl = strstr(start, "idl \\") != 0; 688 char* lastSlash = strrchr(start, '/') + 1; 689 while ((ch = *start++) != ' ') { 690 if (ch == '*') 691 androidFiles += '.'; 692 else if (ch == '.') 693 androidFiles += '\\'; 694 androidFiles += ch; 695 if (!isIdl) 696 continue; 697 if (ch == '/' && start == lastSlash) 698 androidFiles += "JS"; 699 if (ch == '.') { 700 myassert(strcmp(start, "idl \\") == 0); 701 start += 4; 702 androidFiles += 'h'; 703 break; 704 } 705 } 706 androidFiles += "|"; 707 myassert(*start == '\\'); 708 start += 2; 709 } while (start[0] == '#'); 710 androidFiles[androidFiles.size() - 1] = '\''; 711 *androidFilesPtr = androidFiles; 712 return makeFile; 713} 714 715vector<char*> GetDerivedSourcesMake(const char* dir) 716{ 717 vector<char*> result; 718 char scratch[1024]; 719 sprintf(scratch, "%s/%s/%s", newBase, dir, "DerivedSources.make"); 720 size_t fileSize; 721 char* file = GetFile(scratch, &fileSize); 722 char* fileEnd = file + fileSize; 723 myassert(file); 724 size_t len; 725 do { // find first filename in makefile 726 len = strlen(file); 727 if (strcmp(file, "all : \\") == 0) 728 break; 729 file += len + 1; 730 } while (file < fileEnd); 731 myassert(strcmp(file, "all : \\") == 0); 732 file += len + 1; 733 while (file[0] != '#') { 734 len = strlen(file); 735 char* st = file; 736 skipSpace(&st); 737 if (st[0] != '\\' && st[0] != '$') 738 result.push_back(st); 739 file += len + 1; 740 } 741 return result; 742} 743 744bool MarkDerivedFound(vector<char*>& derived, char* check, size_t len) 745{ 746 bool found = false; 747 for (unsigned index = 0; index < derived.size(); index++) { 748 char* der = derived[index]; 749 if (strncmp(der, check, len) == 0) { 750 der[0] = '\0'; 751 found = true; 752 } 753 } 754 return found; 755} 756 757void UpdateDerivedMake() 758{ 759 const char* dir = "WebCore"; 760 int err; 761 vector<char*> derived = GetDerivedSourcesMake(dir); 762 size_t makeSize; 763 char* start, * localStart; 764 string excludedDirs, excludedFiles, excludedGenerated, androidFiles; 765 char* makeFile = GetMakeAndExceptions(dir, "Android.derived.mk", &makeSize, 766 &excludedFiles, &excludedGenerated, &excludedDirs, &androidFiles, 767 &start, &localStart); 768 if (options.emitPerforceCommands) 769 fprintf(commandFile, "p4 edit %s/%s/%s\n", sandboxCmd, dir, "Android.derived.mk"); 770 fprintf(commandFile, "cat %s/%s/%s | sed \\\n", sandboxCmd, dir, "Android.derived.mk"); 771 string updateDerivedMake = ScratchFile(__FUNCTION__); 772 string filelist = string("cd ") + newBase + "/" + dir + 773 " ; find . -name '*.idl' | " + excludedFiles + 774 " | sed -e 's/.\\///' " + excludedDirs + 775 " | sed 's@\\(.*\\)/\\(.*\\)\\.idl@ $(intermediates)/\\1/JS\\2.h@' " 776 " | sort -o " + updateDerivedMake; 777 err = system(filelist.c_str()); 778 myassert(err == 0 || err == 256); 779 char* bindings = GetFile(updateDerivedMake); 780 bool inGen = false; 781 char* fileEnd = makeFile + makeSize; 782 char* nextStart; 783 do { 784 size_t startLen = strlen(start); 785 nextStart = start + startLen + 1; 786 bool onGen = false; 787 char* st = start; 788 if (inGen == false) { 789 if (strncmp(st, "GEN", 3) != 0) 790 continue; 791 st += 3; 792 skipSpace(&st); 793 if (strncmp(st, ":=", 2) != 0) 794 continue; 795 st += 2; 796 onGen = true; 797 } 798 skipSpace(&st); 799 inGen = start[startLen - 1] == '\\'; 800 if (inGen) { 801 if (st[0] == '\\' && st[1] == '\0') 802 continue; 803 if (strcmp(st, "$(addprefix $(intermediates)/, \\") == 0) 804 continue; 805 } else if (st[0] == ')' && st[1] == '\0') 806 continue; 807 static const char bindHead[] = "bindings/js/"; 808 const size_t bindLen = sizeof(bindHead) - 1; 809 string escaped; 810 if (strncmp(st, bindHead, bindLen) == 0) { 811 st += bindLen; 812 if (MarkDerivedFound(derived, st, strlen(st)) == false) { 813 fprintf(stderr, "*** webkit removed js binding: %s" 814 " (must be removed manually)\n", st); 815 escaped = SedEscape(st); 816 fprintf(commandFile, "-e '/%s/ d' ", escaped.c_str()); 817 } 818 continue; 819 } 820 myassert(strncmp(st, "$(intermediates)", 16) == 0); 821 if (onGen && inGen == false) { // no continuation 822 char* lastSlash; 823 myassert(strrchr(st, '/') != NULL); 824 while ((lastSlash = strrchr(st, '/')) != NULL) { 825 char* lastEnd = strchr(lastSlash, ' '); 826 if (lastEnd == NULL) 827 lastEnd = lastSlash + strlen(lastSlash); 828 myassert(lastSlash != 0); 829 lastSlash++; 830 size_t lastLen = lastEnd - lastSlash; 831 if (MarkDerivedFound(derived, lastSlash, lastLen) == false) { 832 fprintf(stderr, "*** webkit removed generated file:" 833 " %.*s (must be removed manually)\n", (int) lastLen, 834 lastSlash); 835 // escaped = SedEscape(st); 836 // fprintf(commandFile, "-e '/%s/ d' \\\n", escaped.c_str()); 837 } 838 char* priorDollar = strrchr(st, '$'); 839 myassert(priorDollar != NULL); 840 char* nextDollar = strchr(st, '$'); 841 if (nextDollar == priorDollar) 842 break; 843 priorDollar[0] = '\0'; 844 } 845 continue; 846 } 847 char* nextSt = nextStart; 848 skipSpace(&nextSt); 849 myassert(strncmp(nextSt, "$(intermediates)", 16) != 0 || strcmp(st, nextSt) < 0); 850 // do { 851 char* bind = bindings; 852 myassert(bind); 853 skipSpace(&bind); 854 int compare = strncmp(bind, st, strlen(bind) - 2); 855 if (compare < 0) { // add a file 856 escaped = SedEscape(st); 857 char* filename = strrchr(bindings, '/'); 858 myassert(filename); 859 filename += 3; 860 // FIX ME: exclude items in DerivedSources.make all : $(filter-out ... 861 char* bi = bindings; 862 skipSpace(&bi); 863 char* bindName = strrchr(bi, '/'); 864 myassert(bindName != NULL); 865 bindName++; 866 string biStr = SedEscape(bi); 867 fprintf(commandFile, "-e '/%s/ i\\\n_TAB_%s \\\\\n' ", 868 escaped.c_str(), biStr.c_str()); 869 MarkDerivedFound(derived, bindName, strlen(bindName)); 870 nextStart = start; 871 bindings += strlen(bindings) + 1; 872 inGen = true; 873 } else if (compare > 0) { 874 // if file to be deleted is locally added by android, leave it alone 875 myassert(strncmp(st, "$(intermediates)/", 17) == 0); 876 string subst = string(st).substr(17, strlen(st) - 17 - (inGen ? 2 : 0)); 877 string localDerivedStr = ScratchFile("LocalDerived"); 878 string filter = string("echo '") + subst + "' | " + androidFiles + 879 " > " + localDerivedStr; 880 if (options.debug) 881 fprintf(stderr, "LocalDerived.txt : %s\n", filter.c_str()); 882 err = system(filter.c_str()); 883 myassert(err == 0 || err == 256); 884 char* localDerived = GetFile(localDerivedStr); 885 if (localDerived[0] != '\0') { 886 escaped = SedEscape(st); 887 fprintf(commandFile, "-e '/%s/ d' ", escaped.c_str()); 888 } 889 } else { 890 char* stName = strrchr(st, '/'); 891 myassert(stName); 892 stName++; 893 MarkDerivedFound(derived, stName, strlen(stName)); 894 bindings += strlen(bindings) + 1; 895 } 896 // } while (strstr(start, "$(intermediates)") != NULL); 897 // if changing directories, add any new files to the end of this directory first 898 if (bindings[0] != '\0' && strstr(nextStart, "$(intermediates)") == NULL) { 899 st = start; 900 skipSpace(&st); 901 escaped = SedEscape(st); 902 st = strchr(st, '/'); 903 char* stDirEnd = strchr(st + 1, '/'); 904 do { 905 bind = strchr(bindings, '/'); 906 if (!bind) 907 break; 908 char* bindEnd = strchr(bind + 1, '/'); 909 if (!bindEnd) 910 break; 911 if (bindEnd - bind != stDirEnd - st) 912 break; 913 if (strncmp(st, bind, stDirEnd - st) != 0) 914 break; 915 if (inGen == false) 916 fprintf(commandFile, "-e '/%s/ s/$/ \\\\/' ", escaped.c_str()); 917 char* bi = bindings; 918 skipSpace(&bi); 919 string biStr = SedEscape(bi); 920 fprintf(commandFile, "-e '/%s/ a\\\n_TAB_%s\n' ", 921 escaped.c_str(), biStr.c_str()); 922 MarkDerivedFound(derived, bindEnd + 1, strlen(bindEnd + 1)); 923 escaped = biStr; 924 inGen = false; 925 bindings += strlen(bindings) + 1; 926 } while (true); 927 } 928 } while (start = nextStart, start < fileEnd); 929 for (unsigned index = 0; index < derived.size(); index++) { 930 char* der = derived[index]; 931 if (der[0] == '\0') 932 continue; 933 string excludedGeneratedStr = ScratchFile("ExcludedGenerated"); 934 string filter = string("echo '") + der + "' | " + excludedGenerated + 935 " > " + excludedGeneratedStr; 936 err = system(filter.c_str()); 937 myassert(err == 0 || err == 256); 938 char* excluded = GetFile(excludedGeneratedStr); 939 if (excluded[0] != '\0') 940 fprintf(stderr, "*** missing rule to generate %s\n", der); 941 } 942 fprintf(commandFile, " | sed 's/^_TAB_/\t/' > %s/%s/%s\n", sandboxCmd, dir, "xAndroid.derived.mk"); 943 fprintf(commandFile, "mv %s/%s/%s %s/%s/%s\n", 944 sandboxCmd, dir, "xAndroid.derived.mk", sandboxCmd, dir, "Android.derived.mk"); 945 if (options.emitGitCommands) 946 fprintf(commandFile, "git add %s/%s\n", dir, "Android.derived.mk"); 947} 948 949int MatchLen(const char* one, const char* two, size_t len) 950{ 951 bool svgIn1 = strstr(one, "svg") || strstr(one, "SVG"); 952 bool svgIn2 = strstr(two, "svg") || strstr(two, "SVG"); 953 if (svgIn1 != svgIn2) 954 return 0; 955 int signedLen = (int) len; 956 int original = signedLen; 957 while (*one++ == *two++ && --signedLen >= 0) 958 ; 959 return original - signedLen; 960} 961 962// create the list of sed commands to update the WebCore Make file 963void UpdateMake(const char* dir) 964{ 965 // read in the makefile 966 size_t makeSize; 967 char* start, * localStart = NULL; 968 string excludedDirs, excludedFiles, androidFiles; 969 char* makeFile = GetMakeAndExceptions(dir, "Android.mk", &makeSize, 970 &excludedFiles, NULL, &excludedDirs, &androidFiles, &start, &localStart); 971 char* lastFileName = NULL; 972 size_t lastFileNameLen = 0; 973 int lastLineNumber = -1; 974 // get the actual list of files 975 string updateMakeStr = ScratchFile(__FUNCTION__); 976 string filelist = string("cd ") + newBase + "/" + dir + " ;" 977 " find . -name '*.cpp' -or -name '*.c' -or -name '*.y' | " + 978 excludedFiles + " | sed -e 's/.\\///' " + excludedDirs + 979 " | sort -o " + updateMakeStr; 980 if (options.debug) 981 fprintf(stderr, "make %s/%s filter: %s\n", dir, "Android.mk", filelist.c_str()); 982 int err = system(filelist.c_str()); 983 myassert(err == 0 || err == 256); 984 char* newList = GetFile(updateMakeStr); 985 do { // find first filename in makefile 986 if (strncmp(start, "LOCAL_SRC_FILES := \\", 20) == 0) 987 break; 988 start += strlen(start) + 1; 989 } while (start < makeFile + makeSize); 990 myassert(start[0] != '\0'); 991 if (options.emitPerforceCommands) 992 fprintf(commandFile, "p4 edit %s/%s/%s\n", sandboxCmd, dir, "Android.mk"); 993 fprintf(commandFile, "cat %s/%s/%s | sed ", sandboxCmd, dir, "Android.mk"); 994 int lineNumber = 0; 995 do { 996 start += strlen(start) + 1; 997 lineNumber++; 998 if (start - makeFile >= makeSize || start[0] == '$') 999 break; 1000 if (start[0] == '\0' || !isspace(start[0])) 1001 continue; 1002 skipSpace(&start); 1003 if (start[0] == '\0' || start[0] == '\\') 1004 continue; 1005 size_t startLen = strlen(start); 1006 if (start[startLen - 1] == '\\') 1007 --startLen; 1008 while (isspace(start[startLen - 1])) 1009 --startLen; 1010 size_t newListLen = strlen(newList); 1011 if (lastFileName != NULL) { 1012 myassert(strncmp(start, lastFileName, startLen) > 0 || 1013 startLen > lastFileNameLen); 1014 } 1015 if (strstr(start, "android") != NULL || strstr(start, "Android") != NULL) { 1016 if (startLen == newListLen && strncmp(newList, start, startLen) == 0) 1017 newList += newListLen + 1; 1018 lastFileName = start; 1019 lastFileNameLen = startLen; 1020 lastLineNumber = lineNumber; 1021 continue; 1022 } 1023 int compare; 1024 bool backslash = lastFileName && 1025 lastFileName[strlen(lastFileName) - 1] == '\\'; 1026 do { 1027 compare = strncmp(newList, start, startLen); 1028 if (compare == 0 && startLen != newListLen) 1029 compare = newListLen < startLen ? -1 : 1; 1030 if (newList[0] == '\0' || compare >= 0) 1031 break; 1032 // add a file 1033 if (lastFileName && lineNumber - lastLineNumber > 1 && 1034 MatchLen(lastFileName, newList, lastFileNameLen) > 1035 MatchLen(start, newList, startLen)) { 1036 string escaped = SedEscape(lastFileName); 1037 if (!backslash) 1038 fprintf(commandFile, "-e '/%s/ s/$/ \\\\/' ", escaped.c_str()); 1039 fprintf(commandFile, "-e '/%s/ a\\\n_TAB_%s%s\n' ", 1040 SedEscape(lastFileName).c_str(), newList, 1041 backslash ? " \\\\" : ""); 1042 lastFileName = newList; 1043 lastFileNameLen = newListLen; 1044 } else { 1045 fprintf(commandFile, "-e '/%s/ i\\\n_TAB_%s \\\\\n' ", 1046 SedEscape(start).c_str(), newList); 1047 } 1048 newList += newListLen + 1; 1049 newListLen = strlen(newList); 1050 } while (true); 1051 if (newList[0] == '\0' || compare > 0) { 1052 // don't delete files added by Android 1053 string localMakeStr = ScratchFile("LocalMake"); 1054 string filter = "echo '" + string(start).substr(0, startLen) + 1055 "' | " + androidFiles + " > " + localMakeStr; 1056 int err = system(filter.c_str()); 1057 myassert(err == 0 || err == 256); 1058 char* localMake = GetFile(localMakeStr); 1059 if (localMake[0] != '\0') { 1060 string escaped = SedEscape(start); 1061 fprintf(commandFile, "-e '/%s/ d' ", escaped.c_str()); 1062 } 1063 } else 1064 newList += newListLen + 1; 1065 lastFileName = start; 1066 lastFileNameLen = startLen; 1067 lastLineNumber = lineNumber; 1068 } while (true); 1069 fprintf(commandFile, " | sed 's/^_TAB_/\t/' > %s/%s/%s\n", sandboxCmd, dir, "xAndroid.mk"); 1070 fprintf(commandFile, "mv %s/%s/%s %s/%s/%s\n", 1071 sandboxCmd, dir, "xAndroid.mk", sandboxCmd, dir, "Android.mk"); 1072 if (options.emitGitCommands) 1073 fprintf(commandFile, "git add %s/%s\n", dir, "Android.mk"); 1074} 1075 1076static bool emptyDirectory(const char* base, const char* work, const char* dir) { 1077 string findEmptyStr = "find \""; 1078 string emptyDirStr = ScratchFile("emptyDirectory"); 1079 if (base[0] != '\0') 1080 findEmptyStr += string(base) + "/" + work + "/" + dir + "\""; 1081 else 1082 findEmptyStr += string(work) + "/" + dir + "\""; 1083 findEmptyStr += " -type f -print > " + emptyDirStr; 1084 int err = system(findEmptyStr.c_str()); 1085 if (err != 0) 1086 return true; 1087 FILE* file = fopen(emptyDirStr.c_str(), "r"); 1088 if (file == NULL) 1089 { 1090 fprintf(stderr, "can't read %s\n", emptyDirStr.c_str()); 1091 myassert(0); 1092 return true; 1093 } 1094 fseek(file, 0, SEEK_END); 1095 size_t size = ftell(file); 1096 fclose(file); 1097 return size == 0; 1098} 1099 1100static bool emptyDirectory(const char* work, const char* dir) { 1101 return emptyDirectory("", work, dir); 1102} 1103 1104void CompareDirs(const char* workingDir, bool renamePass) 1105{ 1106 map<string, string> renameMap; 1107 char* oldList = List(oldBase, "old", workingDir); 1108 char* newList = List(newBase, "new", workingDir); 1109 char* sandList = List(sandboxBase, "sandbox", workingDir); 1110 char* oldMem = oldList; 1111 char* newMem = newList; 1112 char* sandboxMem = sandList; 1113 // identify files to be added, removed by comparing old, new lists 1114 do { 1115 size_t oldLen = strlen(oldList); 1116 size_t newLen = strlen(newList); 1117 size_t sandLen = strlen(sandList); 1118 if (oldLen == 0 && newLen == 0 && sandLen == 0) 1119 break; 1120 bool oldDir = false; 1121 bool oldExecutable = false; 1122 if (oldLen > 0) { 1123 char last = oldList[oldLen - 1]; 1124 oldDir = last == '/'; 1125 oldExecutable = last == '*'; 1126 if (oldDir || oldExecutable) 1127 --oldLen; 1128 } 1129 bool newDir = false; 1130 bool newExecutable = false; 1131 if (newLen > 0) { 1132 char last = newList[newLen - 1]; 1133 newDir = last == '/'; 1134 newExecutable = last == '*'; 1135 if (newDir || newExecutable) 1136 --newLen; 1137 } 1138 bool sandDir = false; 1139 bool sandExecutable = false; 1140 if (sandLen > 0) { 1141 char last = sandList[sandLen - 1]; 1142 sandDir = last == '/'; 1143 sandExecutable = last == '*'; 1144 if (sandDir || sandExecutable) 1145 --sandLen; 1146 } 1147 string oldFileStr = string(oldList).substr(0, oldLen); 1148 const char* oldFile = oldFileStr.c_str(); 1149 string newFileStr = string(newList).substr(0, newLen); 1150 const char* newFile = newFileStr.c_str(); 1151 string sandFileStr = string(sandList).substr(0, sandLen); 1152 const char* sandFile = sandFileStr.c_str(); 1153 int order = Compare(oldList, oldLen, newList, newLen); 1154 int sandOrder = 0; 1155 if ((oldLen > 0 || sandLen > 0) && order <= 0) { 1156 sandOrder = Compare(sandList, sandLen, oldList, oldLen); 1157 if (sandOrder > 0 && renamePass == false) 1158 fprintf(stderr, "error: file in old webkit missing from sandbox: %s/%s\n", 1159 workingDir, oldFile); 1160 if (sandOrder < 0 && renamePass == false) { 1161 // file added by android -- should always have name 'android?' 1162 const char* android = strstr(sandFile, "ndroid"); 1163 if (android == NULL) 1164 fprintf(stderr, "warning: expect added %s to contain 'android': %s/%s\n", 1165 sandDir ? "directory" : "file" , workingDir, sandFile); 1166 } 1167 if (sandOrder == 0) { 1168 myassert(oldDir == sandDir); 1169 if (oldExecutable != sandExecutable) 1170 CheckForExec(oldBase, workingDir, oldList, 1171 sandboxBase, workingDir, sandList, 0, 0); 1172 } 1173 if (sandOrder <= 0) 1174 sandList += strlen(sandList) + 1; 1175 if (sandOrder < 0) 1176 continue; 1177 } 1178 if (order < 0) { // file in old list is not in new 1179 // check to see if file is read only ; if so, call p4 delete -- otherwise, just call delete 1180 if (oldDir == false) { 1181 bool modifiedFile = false; 1182 // check to see if android modified deleted file 1183 if (sandOrder == 0) { 1184 string rename(workingDir); 1185 rename.append("/"); 1186 rename.append(oldFile); 1187 if (renamePass) { 1188 string newName = Find(oldFile); 1189 if (newName.length() > 0) { 1190 map<string, string>::iterator iter = renameMap.find(rename); 1191 myassert(iter == renameMap.end()); // if I see the same file twice, must be a bug 1192 renameMap[rename] = newName; 1193 myassert(rename != newName); 1194 if (options.debug) 1195 fprintf(stderr, "map %s to %s\n", rename.c_str(), newName.c_str()); 1196 } 1197 } 1198 if (renamePass == false) { 1199 bool oldSandboxDiff = CompareFiles(oldBase, sandboxBase, workingDir, oldList); 1200 const char* renamedDir = workingDir; 1201 map<string, string>::iterator iter = renameMap.find(rename); 1202 if (iter != renameMap.end()) { 1203 string newName = renameMap[rename]; 1204 renamedDir = newName.c_str(); 1205 char* renamed = (char*) strrchr(renamedDir, '/'); 1206 *renamed++ = '\0'; // splits rename into two strings 1207 if (options.emitPerforceCommands) { 1208 fprintf(commandFile, "p4 integrate \"%s/%s/%s\" \"%s/%s/%s\"\n", sandboxCmd, workingDir, oldFile, 1209 sandboxCmd, renamedDir, renamed); 1210 fprintf(commandFile, "p4 resolve \"%s/%s/%s\"\n", sandboxCmd, renamedDir, renamed); 1211 } else if (options.emitGitCommands) { 1212 fprintf(commandFile, "git mv \"%s/%s\" \"%s/%s\"\n", workingDir, oldFile, 1213 renamedDir, renamed); 1214 } 1215 if (oldSandboxDiff) { 1216 if (options.emitPerforceCommands) 1217 fprintf(commandFile, "p4 open \"%s/%s/%s\"\n", sandboxCmd, renamedDir, renamed); 1218 fprintf(commandFile, "merge -q \"%s/%s/%s\" \"%s/%s/%s\" \"%s/%s/%s\"\n", 1219 sandboxCmd, renamedDir, renamed, oldCmd, workingDir, oldFile, newCmd, renamedDir, renamed); 1220 bool success = Merge(workingDir, oldFile, renamedDir, renamed, "/dev/null"); 1221 if (success == false) { 1222 fprintf(stderr, "*** Manual merge required: %s/%s\n", renamedDir, renamed); 1223 fprintf(commandFile, "cat \"%s/%s/%s\" | sed -e 's/^<<<<<<<.*$/#ifdef MANUAL_MERGE_REQUIRED/' " 1224 "-e 's/^=======$/#else \\/\\/ MANUAL_MERGE_REQUIRED/' " 1225 "-e 's/^>>>>>>>.*$/#endif \\/\\/ MANUAL_MERGE_REQUIRED/' > \"%s/%s/x%s\"\n", 1226 sandboxCmd, renamedDir, renamed, sandboxCmd, renamedDir, renamed); 1227 fprintf(commandFile, "mv \"%s/%s/x%s\" \"%s/%s/%s\"\n", 1228 sandboxCmd, renamedDir, renamed, sandboxCmd, renamedDir, renamed); 1229 } 1230 if (options.emitGitCommands) 1231 fprintf(commandFile, "git add \"%s/%s\"\n", renamedDir, renamed); 1232 } else { 1233 bool oldNewDiff = CompareFiles(oldBase, workingDir, oldList, newBase, renamedDir, renamed); 1234 if (oldNewDiff) { 1235 if (options.emitPerforceCommands) 1236 fprintf(oopsFile, "p4 open \"%s/%s/%s\"\n", sandboxCmd, renamedDir, renamed); 1237 fprintf(oopsFile, "cp \"%s/%s/%s\" \"%s/%s/%s\"\n", 1238 newCmd, renamedDir, renamed, sandboxCmd, renamedDir, renamed); 1239 if (options.emitGitCommands) 1240 fprintf(oopsFile, "git add \"%s/%s\"\n", renamedDir, renamed); 1241 } 1242 } 1243 } else if (oldSandboxDiff) { 1244 modifiedFile = true; 1245 fprintf(stderr, "*** Modified file deleted: %s/%s\n", workingDir, oldFile); 1246// FindDeletedAndroidChanges(workingDir, oldFile); 1247 } 1248 } // if renamePass == false 1249 } // if sandOrder == 0 1250 if (modifiedFile) { 1251 fprintf(commandFile, "cat \"%s/%s/%s\" | sed -e '1 i\\\n#ifdef MANUAL_MERGE_REQUIRED\n' " 1252 "-e '$ a\\\n#endif \\/\\/ MANUAL_MERGE_REQUIRED\n' > \"%s/%s/x%s\"\n", 1253 sandboxCmd, workingDir, oldFile, sandboxCmd, workingDir, oldFile); 1254 fprintf(commandFile, "mv \"%s/%s/x%s\" \"%s/%s/%s\"\n", 1255 sandboxCmd, workingDir, oldFile, sandboxCmd, workingDir, oldFile); 1256 } else if (options.emitPerforceCommands) 1257 fprintf(commandFile, "p4 delete \"%s/%s/%s\"\n", sandboxCmd, workingDir, oldFile); 1258 else if (options.emitGitCommands) 1259 fprintf(commandFile, "git rm \"%s/%s\"\n", workingDir, oldFile); 1260 else 1261 fprintf(commandFile, "rm \"%s/%s/%s\"\n", sandboxCmd, workingDir, oldFile); 1262 } else { // if oldDir != false 1263 // !!! FIXME start here; 1264 // check to see if old directory is empty ... (e.g., WebCore/doc) 1265 // ... and/or isn't in sandbox anyway (e.g., WebCore/LayoutTests) 1266 // if old directory is in sandbox (e.g. WebCore/kcanvas) that should work 1267 if (options.emitPerforceCommands) 1268 fprintf(commandFile, "p4 delete \"%s/%s/%s/...\"\n", sandboxCmd, workingDir, oldFile); 1269 else if (options.emitGitCommands) 1270 fprintf(commandFile, "git rm \"%s/%s/...\"\n", workingDir, oldFile); 1271 else 1272 fprintf(commandFile, "rm \"%s/%s/%s/...\"\n", sandboxCmd, workingDir, oldFile); 1273 if (renamePass == false) 1274 fprintf(stderr, "*** Directory deleted: %s/%s\n", workingDir, oldFile); 1275 } 1276 oldList += strlen(oldList) + 1; 1277 continue; 1278 } 1279 if (order > 0) { 1280 if (renamePass == false) { 1281 string rename(workingDir); 1282 rename.append("/"); 1283 rename.append(newFile); 1284 bool skip = false; 1285 for (map<string, string>::iterator iter = renameMap.begin(); iter != renameMap.end(); iter++) { 1286 if (iter->second == rename) { 1287 skip = true; 1288 break; 1289 } 1290 } 1291 if (skip == false) { 1292 if (newDir) { 1293 if (strcmp(sandFile, newFile) != 0 && 1294 emptyDirectory(newBase, workingDir, newFile) == false) { 1295 fprintf(copyDirFile, "find \"%s/%s/%s\" -type d -print | " 1296 "sed 's@%s/\\(.*\\)@mkdir %s/\\1@' | bash -s\n", 1297 newCmd, workingDir, newFile, newCmd, sandboxCmd); 1298 fprintf(copyDirFile, "find \"%s/%s/%s\" -type f -print | " 1299 "sed 's@%s/\\(.*\\)@cp %s/\\1 %s/\\1@' | bash -s\n", 1300 newCmd, workingDir, newFile, newCmd, newCmd, sandboxCmd); 1301 if (options.emitPerforceCommands) 1302 fprintf(copyDirFile, "find \"%s/%s/%s\" -type f -print | " 1303 "p4 -x - add\n", 1304 sandboxCmd, workingDir, newFile); 1305 else if (options.emitGitCommands) 1306 fprintf(copyDirFile, "git add \"%s/%s\"\n", 1307 workingDir, newFile); 1308 } 1309 } else { 1310// if (emptyDirectory(sandboxBase, workingDir)) { 1311// fprintf(commandFile, "mkdir \"%s/%s\"\n", sandboxCmd, workingDir); 1312// } 1313 bool edit = false; 1314 size_t newLen1 = strlen(newFile); 1315 for (map<string, string>::iterator iter = renameMap.begin(); iter != renameMap.end(); iter++) { 1316 if (strcmp(iter->second.c_str(), workingDir) == 0) { 1317 const char* first = iter->first.c_str(); 1318 size_t firstLen = strlen(first); 1319 if (firstLen > newLen1 && strcmp(newFile, 1320 &first[firstLen - newLen1]) == 0) { 1321 edit = true; 1322 break; 1323 } 1324 } 1325 } 1326 if (edit == false) { 1327 fprintf(commandFile, "cp \"%s/%s/%s\" \"%s/%s/%s\"\n", 1328 newCmd, workingDir, newFile, sandboxCmd, workingDir, newFile); 1329 if (options.emitPerforceCommands) 1330 fprintf(commandFile, "p4 add \"%s/%s/%s\"\n", sandboxCmd, workingDir, newFile); 1331 else if (options.emitGitCommands) 1332 fprintf(commandFile, "git add \"%s/%s\"\n", workingDir, newFile); 1333 } 1334 } 1335 } 1336 } 1337 newList += strlen(newList) + 1; 1338 continue; 1339 } 1340 if (oldDir) { 1341 myassert(newDir); 1342 size_t newLen1 = strlen(workingDir) + strlen(oldList); 1343 char* newFile = new char[newLen1 + 1]; 1344 sprintf(newFile, "%s/%.*s", workingDir, (int) strlen(oldList) - 1, 1345 oldList); 1346 if (sandOrder > 0) { // file is on old and new but not sandbox 1347 if (emptyDirectory(newBase, newFile) == false) { 1348 fprintf(copyDirFile, "find \"%s/%s\" -type d -print | " 1349 "sed 's@%s/\\(.*\\)@mkdir %s/\\1@' | bash -s\n", 1350 newCmd, newFile, newCmd, sandboxCmd); 1351 fprintf(copyDirFile, "find \"%s/%s\" -type f -print | " 1352 "sed 's@%s/\\(.*\\)@cp %s/\\1 %s/\\1@' | bash -s\n", 1353 newCmd, newFile, newCmd, newCmd, sandboxCmd); 1354 if (options.emitPerforceCommands) 1355 fprintf(copyDirFile, "find \"%s/%s\" -type f -print | " 1356 "p4 -x - add\n", 1357 sandboxCmd, newFile); 1358 else if (options.emitGitCommands) 1359 fprintf(copyDirFile, "git add \"%s\"", newFile); 1360 } 1361 } else 1362 CompareDirs(newFile, renamePass); 1363 delete[] newFile; 1364 } else { 1365 // at this point, the file is in both old and new webkits; see if it changed 1366 // ignore executables, different or not (or always copy, or do text compare? or find binary compare? ) 1367 if (oldExecutable != newExecutable) 1368 fprintf(stderr, "*** %s/%s differs in the execute bit (may cause problems for perforce)\n", workingDir, oldFile); 1369 // myassert(sandOrder != 0 || sandFile[sandLen - 1] == '*'); 1370 // Diff(oldBase, sandboxBase, workingDir, oldFile); 1371 bool oldNewDiff = CompareFiles(oldBase, newBase, workingDir, oldList); 1372 if (oldNewDiff && sandOrder == 0 && renamePass == false) { // if it changed, see if android also changed it 1373 if (options.emitPerforceCommands) 1374 fprintf(commandFile, "p4 edit \"%s/%s/%s\"\n", sandboxCmd, workingDir, oldFile); 1375 bool oldSandboxDiff = CompareFiles(oldBase, sandboxBase, workingDir, oldFile); 1376 if (oldSandboxDiff) { 1377 fprintf(commandFile, "merge -q \"%s/%s/%s\" \"%s/%s/%s\" \"%s/%s/%s\"\n", 1378 sandboxCmd, workingDir, oldFile, oldCmd, workingDir, oldFile, newCmd, workingDir, oldFile); 1379 bool success = Merge(workingDir, oldFile); 1380 if (success == false) { 1381 fprintf(stderr, "*** Manual merge required: %s/%s\n", workingDir, oldFile); 1382 fprintf(commandFile, "cat \"%s/%s/%s\" | sed -e 's/^<<<<<<<.*$/#ifdef MANUAL_MERGE_REQUIRED/' " 1383 "-e 's/^=======$/#else \\/\\/ MANUAL_MERGE_REQUIRED/' -e 's/^>>>>>>>.*$/#endif \\/\\/ MANUAL_MERGE_REQUIRED/' > \"%s/%s/x%s\"\n", 1384 sandboxCmd, workingDir, oldFile, sandboxCmd, workingDir, oldFile); 1385 fprintf(commandFile, "mv \"%s/%s/x%s\" \"%s/%s/%s\"\n", 1386 sandboxCmd, workingDir, oldFile, sandboxCmd, workingDir, oldFile); 1387 } 1388 } else fprintf(commandFile, "cp \"%s/%s/%s\" \"%s/%s/%s\"\n", newCmd, workingDir, oldFile , 1389 sandboxCmd, workingDir, oldFile); 1390 if (options.emitGitCommands) 1391 fprintf(commandFile, "git add \"%s/%s\"\n", workingDir, oldFile); 1392 } 1393 } 1394 myassert(oldLen == newLen); 1395 newList += strlen(newList) + 1; 1396 oldList += strlen(oldList) + 1; 1397 } while (true); 1398 delete[] oldMem; 1399 delete[] newMem; 1400 delete[] sandboxMem; 1401} 1402 1403bool Ignore(char* fileName, size_t len) 1404{ 1405 if (len == 0) 1406 return true; 1407 if (fileName[len - 1] =='/') 1408 return true; 1409 if (strcmp(fileName, ".DS_Store") == 0) 1410 return true; 1411 if (strcmp(fileName, ".ignoreSVN") == 0) 1412 return true; 1413 return false; 1414} 1415 1416void FixStar(char* fileName, size_t len) 1417{ 1418 if (fileName[len - 1] =='*') 1419 fileName[len - 1] = '\0'; 1420} 1421 1422void FixColon(char** fileNamePtr, size_t* lenPtr) 1423{ 1424 char* fileName = *fileNamePtr; 1425 size_t len = *lenPtr; 1426 if (fileName[len - 1] !=':') 1427 return; 1428 fileName[len - 1] = '\0'; 1429 if (strncmp(fileName ,"./", 2) != 0) 1430 return; 1431 fileName += 2; 1432 *fileNamePtr = fileName; 1433 len -= 2; 1434 *lenPtr = len; 1435} 1436 1437bool IgnoreDirectory(const char* dir, const char** dirList) 1438{ 1439 if (dirList == NULL) 1440 return false; 1441 const char* test; 1442 while ((test = *dirList++) != NULL) { 1443 if (strncmp(dir, test, strlen(test)) == 0) 1444 return true; 1445 } 1446 return false; 1447} 1448 1449static void doSystem(char* scratch) 1450{ 1451 if (false) printf("%s\n", scratch); 1452 int err = system(scratch); 1453 myassert(err == 0); 1454} 1455 1456static void copyToCommand(char* scratch, string file) 1457{ 1458 doSystem(scratch); 1459 char* diff = GetFile(file.c_str()); 1460 while (*diff) { 1461 fprintf(commandFile, "%s\n", diff); 1462 diff += strlen(diff) + 1; 1463 } 1464} 1465 1466#define WEBKIT_EXCLUDED_DIRECTORIES \ 1467 "-not -path \"*Tests\" " /* includes LayoutTests, PageLoadTests */ \ 1468 "-not -path \"*Tests/*\" " /* includes LayoutTests, PageLoadTests */ \ 1469 "-not -path \"*Site\" " /* includes BugsSite, WebKitSite */ \ 1470 "-not -path \"*Site/*\" " /* includes BugsSite, WebKitSite */ \ 1471 "-not -path \"./PlanetWebKit/*\" " \ 1472 "-not -path \"./PlanetWebKit\" " 1473 1474#define ANDROID_EXCLUDED_FILES \ 1475 "-e '/^Files .* differ/ d' " \ 1476 "-e '/^Only in .*/ d' " \ 1477 "-e '/Android.mk/ d' " \ 1478 "-e '/android$/ d' " 1479 1480#define ANDROID_EXCLUDED_DIRS \ 1481 "-e '/\\/JavaScriptCore\\// d' " \ 1482 "-e '/\\/WebCore\\// d' " 1483 1484#define ANDROID_EXCLUDED_DIRS_GIT \ 1485 "-e '/ JavaScriptCore\\// d' " \ 1486 "-e '/ WebCore\\// d' " 1487 1488void CopyOther() 1489{ 1490 string excludedFiles = ANDROID_EXCLUDED_FILES; 1491 if (options.emitGitCommands) 1492 excludedFiles += ANDROID_EXCLUDED_DIRS_GIT; 1493 else 1494 excludedFiles += ANDROID_EXCLUDED_DIRS; 1495 char scratch[1024]; 1496 // directories to ignore in webkit 1497 string copyOtherWebKit = ScratchFile("CopyOtherWebKit"); 1498 sprintf(scratch, "cd %s ; find . -type d -not -empty " 1499 WEBKIT_EXCLUDED_DIRECTORIES 1500 " > %s", newBase, copyOtherWebKit.c_str()); 1501 doSystem(scratch); 1502 // directories to ignore in android 1503 string copyOtherAndroid = ScratchFile("CopyOtherAndroid"); 1504 sprintf(scratch, "cd %s ; find . -type d -not -empty " 1505 "-not -path \"*.git*\" " 1506 "-not -path \"*android*\" " 1507 " > %s", sandboxBase, copyOtherAndroid.c_str()); 1508 doSystem(scratch); 1509 if (0) { 1510 string copyOtherMkDir = ScratchFile("CopyOtherMkDir"); 1511 sprintf(scratch, "diff %s %s | sed -e 's@< \\./\\(.*\\)$" 1512 "@mkdir %s/\\1@' " 1513 "-e '/^[0-9].*/ d' " 1514 "-e '/>.*/ d' " 1515 "-e '/---/ d' " 1516 "-e '/\\/JavaScriptCore\\// d' " 1517 "-e '/\\/WebCore\\// d' " 1518 "> %s", copyOtherWebKit.c_str(), copyOtherAndroid.c_str(), sandboxCmd, 1519 copyOtherMkDir.c_str()); 1520 if (options.debug) 1521 fprintf(stderr, "%s\n", scratch); 1522 copyToCommand(scratch, copyOtherMkDir); 1523 } 1524 string copyOtherDiff = ScratchFile("CopyOtherDiff"); 1525 int scratchLen = sprintf(scratch, "diff %s %s | sed -e 's@< \\./\\(.*\\)$" 1526 "@mkdir -p -v %s/\\1 ; find %s/\\1 -type f -depth 1 -exec cp {} %s/\\1 \";\"", 1527 copyOtherWebKit.c_str(), copyOtherAndroid.c_str(), sandboxCmd, newCmd, 1528 sandboxCmd); 1529 if (options.emitGitCommands) 1530 scratchLen += sprintf(&scratch[scratchLen], " ; cd %s ; find ", sandboxCmd); 1531 else 1532 scratchLen += sprintf(&scratch[scratchLen], " ; find %s/", sandboxCmd); 1533 scratchLen += sprintf(&scratch[scratchLen], "\\1 -type f -depth 1 | "); 1534 if (options.emitPerforceCommands) 1535 scratchLen += sprintf(&scratch[scratchLen], "p4 -x - add "); 1536 else if (options.emitGitCommands) 1537 scratchLen += sprintf(&scratch[scratchLen], "xargs git add "); 1538 scratchLen += sprintf(&scratch[scratchLen], 1539 "@' -e '/^[0-9].*/ d' " 1540 "-e '/>.*/ d' " 1541 "-e '/---/ d' " 1542 "-e '/\\/JavaScriptCore\\// d' " 1543 "-e '/\\/WebCore\\// d' " 1544 "> %s", copyOtherDiff.c_str()); 1545 if (options.debug) 1546 fprintf(stderr, "%s\n", scratch); 1547 copyToCommand(scratch, copyOtherDiff); 1548 string deleteOtherDiff = ScratchFile("DeleteOtherDiff"); 1549 scratchLen = sprintf(scratch, "diff -r -q %s %s | sed -e " 1550 "'s@Only in %s/\\(.*\\)\\: \\(.*\\)@", 1551 newBase, sandboxBase, sandboxBase); 1552 if (options.emitPerforceCommands) 1553 scratchLen += sprintf(&scratch[scratchLen], "p4 delete %s/", sandboxCmd); 1554 else if (options.emitGitCommands) 1555 scratchLen += sprintf(&scratch[scratchLen], "git rm "); 1556 else 1557 scratchLen += sprintf(&scratch[scratchLen], "rm %s/", sandboxCmd); 1558 scratchLen += sprintf(&scratch[scratchLen], "\\1/\\2@' %s > %s", 1559 excludedFiles.c_str(), deleteOtherDiff.c_str()); 1560 if (options.debug) 1561 fprintf(stderr, "%s\n", scratch); 1562 copyToCommand(scratch, deleteOtherDiff); 1563 string addOtherDiff = ScratchFile("AddOtherDiff"); 1564 scratchLen = sprintf(scratch, "diff -r -q %s %s | sed -e " 1565 "'s@Only in %s/\\(.*\\)\\: \\(.*\\)" 1566 "@mkdir -p -v %s/\\1 ; cp %s/\\1/\\2 %s/\\1/\\2 ; ", 1567 newBase, sandboxBase, newBase, sandboxCmd, newCmd, sandboxCmd); 1568 if (options.emitPerforceCommands) 1569 scratchLen += sprintf(&scratch[scratchLen], 1570 "p4 add %s/\\1/\\2", sandboxCmd); 1571 else if (options.emitGitCommands) 1572 scratchLen += sprintf(&scratch[scratchLen], 1573 "git add \\1/\\2"); 1574 scratchLen += sprintf(&scratch[scratchLen], "@' %s > %s", 1575 excludedFiles.c_str(), addOtherDiff.c_str()); 1576 if (options.debug) 1577 fprintf(stderr, "%s\n", scratch); 1578 copyToCommand(scratch, addOtherDiff); 1579 string editOtherDiff = ScratchFile("EditOtherDiff"); 1580 scratchLen = sprintf(scratch, "diff -r -q %s %s | sed -e " 1581 "'s@Files %s/\\(.*\\) and %s/\\(.*\\) differ@", 1582 newBase, sandboxBase, newBase, sandboxBase); 1583 if (options.emitPerforceCommands) 1584 scratchLen += sprintf(&scratch[scratchLen], 1585 "p4 edit %s/\\2 ; ", sandboxCmd); 1586 scratchLen += sprintf(&scratch[scratchLen], "cp %s/\\1 %s/\\2 ", 1587 newCmd, sandboxCmd); 1588 if (options.emitGitCommands) 1589 scratchLen += sprintf(&scratch[scratchLen], 1590 " ; git add \\2"); 1591 scratchLen += sprintf(&scratch[scratchLen], "@' %s > %s", 1592 excludedFiles.c_str(), editOtherDiff.c_str()); 1593 if (options.debug) 1594 fprintf(stderr, "%s\n", scratch); 1595 copyToCommand(scratch, editOtherDiff); 1596} 1597 1598void MakeExecutable(const string& filename) 1599{ 1600 string makeExScript = "chmod +x "; 1601 makeExScript += filename; 1602 int err = system(makeExScript.c_str()); 1603 myassert(err == 0); 1604} 1605 1606bool ReadArgs(char* const args[], int argCount) 1607{ 1608 int index = 0; 1609 const char* toolpath = args[index++]; 1610 // first arg is path to this executable 1611 // use this to build default paths 1612 1613 for (; index < argCount; index++) { 1614 const char* arg = args[index]; 1615 if (strncmp(arg, "-a", 2) == 0 || strcmp(arg, "--android") == 0) { 1616 index++; 1617 options.androidWebKit = args[index]; 1618 continue; 1619 } 1620 if (strncmp(arg, "-b", 2) == 0 || strcmp(arg, "--basewebkit") == 0) { 1621 index++; 1622 options.baseWebKit = args[index]; 1623 continue; 1624 } 1625 if (strncmp(arg, "-c", 2) == 0 || strcmp(arg, "--mergecore") == 0) { 1626 options.clearOnce(); 1627 options.mergeCore = true; 1628 continue; 1629 } 1630 if (strncmp(arg, "-d", 2) == 0 || strcmp(arg, "--debug") == 0) { 1631 options.debug = true; 1632 continue; 1633 } 1634 if (strncmp(arg, "-e", 2) == 0 || strcmp(arg, "--emptydirs") == 0) { 1635 options.clearOnce(); 1636 options.removeEmptyDirs = true; 1637 continue; 1638 } 1639 if (strncmp(arg, "-g", 2) == 0 || strcmp(arg, "--git") == 0) { 1640 options.emitGitCommands = true; 1641 if (options.emitPerforceCommands == false) 1642 continue; 1643 } 1644 if (strncmp(arg, "-m", 2) == 0 || strcmp(arg, "--mergemake") == 0) { 1645 options.clearOnce(); 1646 options.mergeMake = true; 1647 continue; 1648 } 1649 if (strncmp(arg, "-n", 2) == 0 || strcmp(arg, "--newwebkit") == 0) { 1650 index++; 1651 options.newWebKit = args[index]; 1652 continue; 1653 } 1654 if (strncmp(arg, "-o", 2) == 0 || strcmp(arg, "--copyother") == 0) { 1655 options.clearOnce(); 1656 options.copyOther = true; 1657 continue; 1658 } 1659 if (strncmp(arg, "-p", 2) == 0 || strcmp(arg, "--perforce") == 0) { 1660 options.emitPerforceCommands = true; 1661 if (options.emitGitCommands == false) 1662 continue; 1663 } 1664 if (strncmp(arg, "-s", 2) == 0 || strcmp(arg, "--removesvn") == 0) { 1665 options.clearOnce(); 1666 options.removeSVNDirs = true; 1667 continue; 1668 } 1669 if (strncmp(arg, "-v", 2) == 0 || strcmp(arg, "--verbose") == 0) { 1670 options.verbose = true; 1671 fprintf(stderr, "path: %s\n", toolpath); 1672 int err = system("pwd > pwd.txt"); 1673 myassert(err != -1); 1674 fprintf(stderr, "pwd: %s\n", GetFile("pwd.txt")); 1675 system("rm pwd.txt"); 1676 continue; 1677 } 1678 if (strncmp(arg, "-x", 2) == 0 || strcmp(arg, "--execute") == 0) { 1679 options.execute = true; 1680 continue; 1681 } 1682 if (options.emitGitCommands && options.emitPerforceCommands) 1683 printf("choose one of --git and --perforce\n"); 1684 else if (strncmp(arg, "-h", 2) != 0 && strcmp(arg, "--help") != 0 && strcmp(arg, "-?") != 0) 1685 printf("%s not understood\n", args[index]); 1686 printf( 1687"WebKit Merge for Android version 1.1\n" 1688"Usage: webkitmerge -a path -b path -n path [-g or -p] [-c -d -e -m -o -s -v -x]\n" 1689"Options -c -e -m -o -s are set unless one or more are passed.\n" 1690"Leave -g and -p unset to copy, merge, and delete files outside of source control.\n" 1691"-a --android path Set the Android webkit path to merge to.\n" 1692"-b --basewebkit path Set the common base for Android and the newer webkit.\n" 1693"-c --mergecore Create merge scripts for WebCore, JavaScriptCore .h .cpp.\n" 1694"-d --debug Show debugging printfs; loop forever on internal assert.\n" 1695"-e --emptydirs Remove empty directories from webkit trees.\n" 1696"-g --git Emit git commands.\n" 1697"-h --help Show this help.\n" 1698"-m --mergemake Create merge scripts for WebCore/Android.mk,\n" 1699" WebCore/Android.derived.mk, and JavaScriptCore/Android.mk.\n" 1700"-n --newwebkit path Set the webkit to merge from.\n" 1701"-o --copyother Create script to copy other webkit directories.\n" 1702"-p --perforce Emit perforce commands.\n" 1703"-s --removesvn Remove svn directories from webkit trees.\n" 1704"-v --verbose Show status printfs.\n" 1705"-x --execute Execute the merge scripts.\n" 1706 ); 1707 return false; 1708 } 1709 return options.finish(); 1710} 1711 1712int main (int argCount, char* const args[]) 1713{ 1714 if (ReadArgs(args, argCount) == false) 1715 return 0; 1716 int err; 1717 // First remove all .svn directories 1718 if (options.removeSVNDirs) { 1719 if (options.verbose) 1720 fprintf(stderr, "removing svn directories from %s\n", newBase); 1721 string removeSVNStr = string("find ") + newBase + 1722 " -type d -name \".svn\" -print0 | xargs -0 rm -rf"; 1723 err = system(removeSVNStr.c_str()); 1724 myassert(err == 0); 1725 } 1726 // Remove all empty directories 1727 if (options.removeEmptyDirs) { 1728 if (options.verbose) 1729 fprintf(stderr, "removing empty directories from %s, %s\n", 1730 oldBase, newBase); 1731 string removeEmpty = string("find ") + oldBase + " " + newBase + 1732 " -type d -empty -delete"; 1733 err = system(removeEmpty.c_str()); 1734 myassert(err == 0); 1735 } 1736 if (options.mergeCore /* || options.mergeMake */) { 1737 if (options.verbose) 1738 fprintf(stderr, "building rename map\n"); 1739 commandFile = fopen("/dev/null", "w"); 1740 copyDirFile = fopen("/dev/null", "w"); 1741 CompareDirs("WebCore", true); // build rename map 1742 CompareDirs("JavaScriptCore", true); 1743 fclose(copyDirFile); 1744 fclose(commandFile); 1745 } 1746 if (options.mergeMake) { 1747 if (options.verbose) 1748 fprintf(stderr, "building make.sh\n"); 1749 string makeShell = outputDir + "make.sh"; 1750 commandFile = fopen(makeShell.c_str(), "w"); 1751 if (options.emitGitCommands || options.emitPerforceCommands) 1752 fprintf(commandFile, "cd %s\n", sandboxCmd); 1753 UpdateMake("WebCore"); 1754 UpdateMake("JavaScriptCore"); 1755 UpdateDerivedMake(); 1756 fclose(commandFile); 1757 MakeExecutable(makeShell); 1758 } 1759 if (options.copyOther) { 1760 if (options.verbose) 1761 fprintf(stderr, "building copyOther.sh\n"); 1762 string copyOtherShell = outputDir + "copyOther.sh"; 1763 commandFile = fopen(copyOtherShell.c_str(), "w"); 1764 if (options.emitGitCommands || options.emitPerforceCommands) 1765 fprintf(commandFile, "cd %s\n", sandboxCmd); 1766 CopyOther(); 1767 fclose(commandFile); 1768 MakeExecutable(copyOtherShell); 1769 } 1770 if (options.mergeCore) { 1771 if (options.verbose) 1772 fprintf(stderr, "building command.sh copyDir.sh oops.sh\n"); 1773 string commandShell = outputDir + "command.sh"; 1774 commandFile = fopen(commandShell.c_str(), "w"); 1775 if (options.emitGitCommands || options.emitPerforceCommands) 1776 fprintf(commandFile, "cd %s\n", sandboxCmd); 1777 string copyDirShell = outputDir + "copyDir.sh"; 1778 copyDirFile = fopen(copyDirShell.c_str(), "w"); 1779 if (options.emitGitCommands || options.emitPerforceCommands) 1780 fprintf(copyDirFile, "cd %s\n", sandboxCmd); 1781 string oopsShell = outputDir + "oops.sh"; 1782 oopsFile = fopen(oopsShell.c_str(), "w"); 1783 if (options.emitGitCommands || options.emitPerforceCommands) 1784 fprintf(oopsFile, "cd %s\n", sandboxCmd); 1785 CompareDirs("WebCore", false); // generate command script 1786 CompareDirs("JavaScriptCore", false); 1787 fclose(oopsFile); 1788 fclose(copyDirFile); 1789 fclose(commandFile); 1790 MakeExecutable(oopsShell); 1791 MakeExecutable(copyDirShell); 1792 MakeExecutable(commandShell); 1793 } 1794 if (options.execute) { 1795 if (options.mergeCore) { 1796 if (options.verbose) 1797 fprintf(stderr, "executing command.sh\n"); 1798 string execCommand = "cd " + options.androidWebKit + "; . " + outputDir + "command.sh"; 1799 err = system(execCommand.c_str()); 1800 myassert(err == 0); 1801 if (options.verbose) 1802 fprintf(stderr, "executing copyDir.sh\n"); 1803 string execCopy = "cd " + options.androidWebKit + "; . " + outputDir + "copyDir.sh"; 1804 err = system(execCopy.c_str()); 1805 myassert(err == 0); 1806 } 1807 if (options.mergeMake) { 1808 if (options.verbose) 1809 fprintf(stderr, "executing make.sh\n"); 1810 string execMake = "cd " + options.androidWebKit + "; . " + outputDir + "make.sh"; 1811 err = system(execMake.c_str()); 1812 myassert(err == 0); 1813 } 1814 if (options.copyOther) { 1815 if (options.verbose) 1816 fprintf(stderr, "executing copyOther.sh\n"); 1817 string execCopyOther = "cd " + options.androidWebKit + "; . " + outputDir + "copyOther.sh"; 1818 err = system(execCopyOther.c_str()); 1819 myassert(err == 0); 1820 } 1821 } 1822 if (options.verbose) 1823 fprintf(stderr, "done!\n"); 1824 else { 1825 string rmAllCmd = "rm " + scratchDir + "* ; rmdir " + scratchDir; 1826 err = system(rmAllCmd.c_str()); 1827 myassert(err == 0); 1828 } 1829 return 0; 1830} 1831 1832/* things to do: 1833 when inserting MANUAL_MERGE_REQUIRED, if contents is #preprocessor, balance first? 1834*/ 1835