|
|
1.1 ! root 1: /* Copyright (C) 1982, 1988, 1989 Walter Tichy ! 2: * All rights reserved. ! 3: * ! 4: * Redistribution and use in source and binary forms are permitted ! 5: * provided that the above copyright notice and this paragraph are ! 6: * duplicated in all such forms and that any documentation, ! 7: * advertising materials, and other materials related to such ! 8: * distribution and use acknowledge that the software was developed ! 9: * by Walter Tichy. ! 10: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 11: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 12: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 13: * ! 14: * Report all problems and direct all questions to: ! 15: * [email protected] ! 16: * ! 17: ! 18: ! 19: ! 20: ! 21: ! 22: ! 23: ! 24: */ ! 25: ! 26: /* ! 27: * RCS checkout operation ! 28: */ ! 29: #ifndef lint ! 30: static char rcsid[]= ! 31: "$Header: /usr/src/local/bin/rcs/src/RCS/co.c,v 4.7 89/05/01 15:11:41 narten Exp $ Purdue CS"; ! 32: #endif ! 33: /***************************************************************************** ! 34: * check out revisions from RCS files ! 35: ***************************************************************************** ! 36: */ ! 37: ! 38: ! 39: /* $Log: co.c,v $ ! 40: * Revision 4.7 89/05/01 15:11:41 narten ! 41: * changed copyright header to reflect current distribution rules ! 42: * ! 43: * Revision 4.6 88/11/08 12:02:31 narten ! 44: * changes from [email protected] (Paul Eggert) ! 45: * ! 46: * Revision 4.6 88/08/09 19:12:15 eggert ! 47: * Fix "co -d" core dump; rawdate wasn't always initialized. ! 48: * Use execv(), not system(); fix putchar('\0') and diagnose() botches; remove lint ! 49: * ! 50: * Revision 4.5 87/12/18 11:35:40 narten ! 51: * lint cleanups (from Guy Harris) ! 52: * ! 53: * Revision 4.4 87/10/18 10:20:53 narten ! 54: * Updating version numbers changes relative to 1.1, are actually ! 55: * relative to 4.2 ! 56: * ! 57: * Revision 1.3 87/09/24 13:58:30 narten ! 58: * Sources now pass through lint (if you ignore printf/sprintf/fprintf ! 59: * warnings) ! 60: * ! 61: * Revision 1.2 87/03/27 14:21:38 jenkins ! 62: * Port to suns ! 63: * ! 64: * Revision 1.1 84/01/23 14:49:58 kcs ! 65: * Initial revision ! 66: * ! 67: * Revision 4.2 83/12/05 13:39:48 wft ! 68: * made rewriteflag external. ! 69: * ! 70: * Revision 4.1 83/05/10 16:52:55 wft ! 71: * Added option -u and -f. ! 72: * Added handling of default branch. ! 73: * Replaced getpwuid() with getcaller(). ! 74: * Removed calls to stat(); now done by pairfilenames(). ! 75: * Changed and renamed rmoldfile() to rmworkfile(). ! 76: * Replaced catchints() calls with restoreints(), unlink()--link() with rename(); ! 77: * ! 78: * Revision 3.7 83/02/15 15:27:07 wft ! 79: * Added call to fastcopy() to copy remainder of RCS file. ! 80: * ! 81: * Revision 3.6 83/01/15 14:37:50 wft ! 82: * Added ignoring of interrupts while RCS file is renamed; this avoids ! 83: * deletion of RCS files during the unlink/link window. ! 84: * ! 85: * Revision 3.5 82/12/08 21:40:11 wft ! 86: * changed processing of -d to use DATEFORM; removed actual from ! 87: * call to preparejoin; re-fixed printing of done at the end. ! 88: * ! 89: * Revision 3.4 82/12/04 18:40:00 wft ! 90: * Replaced getdelta() with gettree(), SNOOPDIR with SNOOPFILE. ! 91: * Fixed printing of "done". ! 92: * ! 93: * Revision 3.3 82/11/28 22:23:11 wft ! 94: * Replaced getlogin() with getpwuid(), flcose() with ffclose(), ! 95: * %02d with %.2d, mode generation for working file with WORKMODE. ! 96: * Fixed nil printing. Fixed -j combined with -l and -p, and exit ! 97: * for non-existing revisions in preparejoin(). ! 98: * ! 99: * Revision 3.2 82/10/18 20:47:21 wft ! 100: * Mode of working file is now maintained even for co -l, but write permission ! 101: * is removed. ! 102: * The working file inherits its mode from the RCS file, plus write permission ! 103: * for the owner. The write permission is not given if locking is strict and ! 104: * co does not lock. ! 105: * An existing working file without write permission is deleted automatically. ! 106: * Otherwise, co asks (empty answer: abort co). ! 107: * Call to getfullRCSname() added, check for write error added, call ! 108: * for getlogin() fixed. ! 109: * ! 110: * Revision 3.1 82/10/13 16:01:30 wft ! 111: * fixed type of variables receiving from getc() (char -> int). ! 112: * removed unused variables. ! 113: */ ! 114: ! 115: ! 116: ! 117: ! 118: #include "rcsbase.h" ! 119: #include "time.h" ! 120: #include <sys/types.h> ! 121: #include <sys/stat.h> ! 122: ! 123: #ifndef lint ! 124: static char rcsbaseid[] = RCSBASE; ! 125: #endif ! 126: static char co[] = CO; ! 127: static char merge[] = MERGE; ! 128: ! 129: extern FILE * fopen(); ! 130: extern int rename(); ! 131: extern char * getcaller(); /*get login of caller */ ! 132: extern struct hshentry * genrevs(); /*generate delta numbers */ ! 133: extern char * getancestor(); ! 134: extern int nextc; /*next input character */ ! 135: extern int nerror; /*counter for errors */ ! 136: extern char Kdesc[]; /*keyword for description */ ! 137: extern char * buildrevision(); /*constructs desired revision */ ! 138: extern int buildjoin(); /*join several revisions */ ! 139: extern char * mktempfile(); /*temporary file name generator */ ! 140: extern struct hshentry * findlock();/*find (and delete) a lock */ ! 141: extern struct lock * addlock(); /*add a new lock */ ! 142: extern long maketime(); /*convert parsed time to unix time. */ ! 143: extern struct tm * localtime(); /*convert unixtime into a tm-structure */ ! 144: extern FILE * finptr; /* RCS input file */ ! 145: extern FILE * frewrite; /* new RCS file */ ! 146: extern int rewriteflag; /* indicates whether input should be */ ! 147: /* echoed to frewrite */ ! 148: ! 149: char * newRCSfilename, * neworkfilename; ! 150: char * RCSfilename, * workfilename; ! 151: extern struct stat RCSstat, workstat; /* file status of RCS and work file */ ! 152: extern int haveRCSstat, haveworkstat;/* status indicators */ ! 153: ! 154: char * date, * rev, * state, * author, * join; ! 155: char finaldate[datelength]; ! 156: ! 157: int forceflag, lockflag, unlockflag, tostdout; ! 158: char * caller; /* caller's login; */ ! 159: extern quietflag; ! 160: ! 161: char numericrev[revlength]; /* holds expanded revision number */ ! 162: struct hshentry * gendeltas[hshsize]; /* stores deltas to be generated */ ! 163: struct hshentry * targetdelta; /* final delta to be generated */ ! 164: ! 165: char * joinlist[joinlength]; /* pointers to revisions to be joined */ ! 166: int lastjoin; /* index of last element in joinlist */ ! 167: ! 168: main (argc, argv) ! 169: int argc; ! 170: char * argv[]; ! 171: { ! 172: int killock; /* indicates whether a lock is removed*/ ! 173: char * cmdusage; ! 174: struct tm parseddate, *ftm; ! 175: char * rawdate; ! 176: long unixtime; ! 177: ! 178: catchints(); ! 179: cmdid = "co"; ! 180: cmdusage = "command format:\nco -f[rev] -l[rev] -p[rev] -q[rev] -r[rev] -ddate -sstate -w[login] -jjoinlist file ..."; ! 181: date = rev = state = author = join = nil; ! 182: forceflag = lockflag = unlockflag = tostdout = quietflag = false; ! 183: caller=getcaller(); ! 184: rawdate = ""; ! 185: ! 186: while (--argc,++argv, argc>=1 && ((*argv)[0] == '-')) { ! 187: switch ((*argv)[1]) { ! 188: ! 189: case 'r': ! 190: revno: if ((*argv)[2]!='\0') { ! 191: if (rev!=nil) warn("Redefinition of revision number"); ! 192: rev = (*argv)+2; ! 193: } ! 194: break; ! 195: ! 196: case 'f': ! 197: forceflag=true; ! 198: goto revno; ! 199: ! 200: case 'l': ! 201: lockflag=true; ! 202: if (unlockflag) { ! 203: warn("-l has precedence over -u"); ! 204: unlockflag=false; ! 205: } ! 206: goto revno; ! 207: ! 208: case 'u': ! 209: unlockflag=true; ! 210: if (lockflag) { ! 211: warn("-l has precedence over -u"); ! 212: unlockflag=false; ! 213: } ! 214: goto revno; ! 215: ! 216: case 'p': ! 217: tostdout=true; ! 218: goto revno; ! 219: ! 220: case 'q': ! 221: quietflag=true; ! 222: goto revno; ! 223: ! 224: case 'd': ! 225: if ((*argv)[2]!='\0') { ! 226: if (date!=nil) warn("Redefinition of -d option"); ! 227: rawdate=(*argv)+2; ! 228: } ! 229: /* process date/time */ ! 230: if (partime(rawdate,&parseddate)==0) ! 231: faterror("Can't parse date/time: %s",rawdate); ! 232: if ((unixtime=maketime(&parseddate))== 0L) ! 233: faterror("Inconsistent date/time: %s",rawdate); ! 234: ftm=localtime(&unixtime); ! 235: VOID sprintf(finaldate,DATEFORM, ! 236: ftm->tm_year,ftm->tm_mon+1,ftm->tm_mday,ftm->tm_hour,ftm->tm_min,ftm->tm_sec); ! 237: date=finaldate; ! 238: break; ! 239: ! 240: case 'j': ! 241: if ((*argv)[2]!='\0'){ ! 242: if (join!=nil)warn("Redefinition of -j option"); ! 243: join = (*argv)+2; ! 244: } ! 245: break; ! 246: ! 247: case 's': ! 248: if ((*argv)[2]!='\0'){ ! 249: if (state!=nil)warn("Redefinition of -s option"); ! 250: state = (*argv)+2; ! 251: } ! 252: break; ! 253: ! 254: case 'w': ! 255: if (author!=nil)warn("Redefinition of -w option"); ! 256: if ((*argv)[2]!='\0') ! 257: author = (*argv)+2; ! 258: else author = caller; ! 259: break; ! 260: ! 261: default: ! 262: faterror("unknown option: %s\n%s", *argv,cmdusage); ! 263: ! 264: }; ! 265: } /* end of option processing */ ! 266: ! 267: if (argc<1) faterror("No input file\n%s",cmdusage); ! 268: ! 269: /* now handle all filenames */ ! 270: do { ! 271: rewriteflag=false; ! 272: finptr=frewrite=NULL; ! 273: neworkfilename=nil; ! 274: ! 275: if (!pairfilenames(argc,argv,true,tostdout)) continue; ! 276: ! 277: /* now RCSfilename contains the name of the RCS file, and finptr ! 278: * the file descriptor. If tostdout is false, workfilename contains ! 279: * the name of the working file, otherwise undefined (not nil!). ! 280: * Also, RCSstat, workstat, and haveworkstat have been set. ! 281: */ ! 282: diagnose("%s --> %s", RCSfilename,tostdout?"stdout":workfilename); ! 283: ! 284: ! 285: if (!tostdout && !trydiraccess(workfilename)) continue; /* give up */ ! 286: if ((lockflag||unlockflag) && !checkaccesslist(caller)) continue; /* give up */ ! 287: if (!trysema(RCSfilename,lockflag||unlockflag)) continue; /* give up */ ! 288: ! 289: ! 290: gettree(); /* reads in the delta tree */ ! 291: ! 292: if (Head==nil) { ! 293: /* no revisions; create empty file */ ! 294: diagnose("no revisions present; generating empty revision 0.0"); ! 295: if (!tostdout) ! 296: if (!creatempty()) continue; ! 297: /* Can't reserve a delta, so don't call addlock */ ! 298: } else { ! 299: if (rev!=nil) { ! 300: /* expand symbolic revision number */ ! 301: if (!expandsym(rev,numericrev)) ! 302: continue; ! 303: } elsif (unlockflag && (targetdelta=findlock(caller,false))!=nil) { ! 304: VOID strcpy(numericrev,targetdelta->num); ! 305: } elsif (Dbranch!=nil) { ! 306: VOID strcpy(numericrev,Dbranch->num); ! 307: } else numericrev[0]='\0'; /* empty */ ! 308: /* get numbers of deltas to be generated */ ! 309: if (!(targetdelta=genrevs(numericrev,date,author,state,gendeltas))) ! 310: continue; ! 311: /* check reservations */ ! 312: if (lockflag && !addlock(targetdelta,caller)) ! 313: continue; ! 314: ! 315: if (unlockflag) { ! 316: if((killock=rmlock(caller,targetdelta))== -1) ! 317: continue; ! 318: } else { ! 319: killock=0; ! 320: } ! 321: ! 322: if (join && !preparejoin()) continue; ! 323: ! 324: diagnose("revision %s%s",targetdelta->num, ! 325: lockflag?" (locked)": ! 326: unlockflag?" (unlocked)":""); ! 327: ! 328: /* remove old working file if necessary */ ! 329: if (!tostdout) ! 330: if (!rmworkfile()) continue; ! 331: ! 332: /* prepare for rewriting the RCS file */ ! 333: if (lockflag||(killock==1)) { ! 334: newRCSfilename=mktempfile(RCSfilename,NEWRCSFILE); ! 335: if ((frewrite=fopen(newRCSfilename, "w"))==NULL) { ! 336: error("Can't open file %s",newRCSfilename); ! 337: continue; ! 338: } ! 339: putadmin(frewrite); ! 340: puttree(Head,frewrite); ! 341: VOID fprintf(frewrite, "\n\n%s%c",Kdesc,nextc); ! 342: rewriteflag=true; ! 343: } ! 344: ! 345: /* skip description */ ! 346: getdesc(false); /* don't echo*/ ! 347: ! 348: if (!(neworkfilename=buildrevision(gendeltas,targetdelta, ! 349: tostdout?(join!=nil?"/tmp/":(char *)nil):workfilename,true))) ! 350: continue; ! 351: ! 352: if ((lockflag||killock==1)&&nerror==0) { ! 353: /* rewrite the rest of the RCSfile */ ! 354: fastcopy(finptr,frewrite); ! 355: ffclose(frewrite); frewrite=NULL; ! 356: ignoreints(); ! 357: if (rename(newRCSfilename,RCSfilename)<0) { ! 358: error("Can't rewrite %s; saved in: %s", ! 359: RCSfilename, newRCSfilename); ! 360: newRCSfilename[0]='\0'; /* avoid deletion*/ ! 361: restoreints(); ! 362: break; ! 363: } ! 364: newRCSfilename[0]='\0'; /* avoid re-deletion by cleanup()*/ ! 365: if (chmod(RCSfilename,RCSstat.st_mode & ~0222)<0) ! 366: warn("Can't preserve mode of %s",RCSfilename); ! 367: restoreints(); ! 368: } ! 369: ! 370: # ifdef SNOOPFILE ! 371: logcommand("co",targetdelta,gendeltas,caller); ! 372: # endif ! 373: ! 374: if (join) { ! 375: rmsema(); /* kill semaphore file so other co's can proceed */ ! 376: if (!buildjoin(neworkfilename)) continue; ! 377: } ! 378: if (!tostdout) { ! 379: if (rename(neworkfilename,workfilename) <0) { ! 380: error("Can't create %s; see %s",workfilename,neworkfilename); ! 381: neworkfilename[0]= '\0'; /*avoid deletion*/ ! 382: continue; ! 383: } ! 384: neworkfilename[0]= '\0'; /*avoid re-deletion by cleanup()*/ ! 385: } ! 386: } ! 387: if (!tostdout) ! 388: if (chmod(workfilename, WORKMODE(RCSstat.st_mode))<0) ! 389: warn("Can't adjust mode of %s",workfilename); ! 390: ! 391: ! 392: if (!tostdout) diagnose("done"); ! 393: } while (cleanup(), ! 394: ++argv, --argc >=1); ! 395: ! 396: exit(nerror!=0); ! 397: ! 398: } /* end of main (co) */ ! 399: ! 400: ! 401: /***************************************************************** ! 402: * The following routines are auxiliary routines ! 403: *****************************************************************/ ! 404: ! 405: int rmworkfile() ! 406: /* Function: unlinks workfilename, if it exists, under the following conditions: ! 407: * If it is read-only, workfilename is unlinked. ! 408: * Otherwise (file writable): ! 409: * if !quietmode asks the user whether to really delete it (default: fail); ! 410: * otherwise failure. ! 411: * Returns false on failure to unlink, true otherwise. ! 412: */ ! 413: { ! 414: int response, c; /* holds user response to queries */ ! 415: ! 416: if (haveworkstat< 0) /* File doesn't exist; set by pairfilenames*/ ! 417: return (true); /* No problem */ ! 418: ! 419: if ((workstat.st_mode & 0222)&&!forceflag) { /* File is writable */ ! 420: if (!quietflag) { ! 421: VOID fprintf(stderr,"writable %s exists; overwrite? [ny](n): ",workfilename); ! 422: /* must be stderr in case of IO redirect */ ! 423: c=response=getchar(); ! 424: while (!(c==EOF || c=='\n')) c=getchar(); /*skip rest*/ ! 425: if (!(response=='y'||response=='Y')) { ! 426: warn("checkout aborted."); ! 427: return false; ! 428: } ! 429: } else { ! 430: error("writable %s exists; checkout aborted.",workfilename); ! 431: return false; ! 432: } ! 433: } ! 434: /* now unlink: either not writable, forceflag, or permission given */ ! 435: if (unlink(workfilename) != 0) { /* Remove failed */ ! 436: error("Can't unlink %s",workfilename); ! 437: return false; ! 438: } ! 439: return true; ! 440: } ! 441: ! 442: ! 443: creatempty() ! 444: /* Function: creates an empty working file. ! 445: * First, removes an existing working file with rmworkfile(). ! 446: */ ! 447: { ! 448: int fdesc; /* file descriptor */ ! 449: ! 450: if (!rmworkfile()) return false; ! 451: fdesc=creat(workfilename,0); ! 452: if (fdesc < 0) { ! 453: faterror("Cannot create %s",workfilename); ! 454: return false; ! 455: } else { ! 456: VOID close(fdesc); /* empty file */ ! 457: return true; ! 458: } ! 459: } ! 460: ! 461: ! 462: int rmlock(who,delta) ! 463: char * who; struct hshentry * delta; ! 464: /* Function: removes the lock held by who on delta. ! 465: * Returns -1 if someone else holds the lock, ! 466: * 0 if there is no lock on delta, ! 467: * and 1 if a lock was found and removed. ! 468: */ ! 469: { register struct lock * next, * trail; ! 470: char * num; ! 471: struct lock dummy; ! 472: int whomatch, nummatch; ! 473: ! 474: num=delta->num; ! 475: dummy.nextlock=next=Locks; ! 476: trail = &dummy; ! 477: while (next!=nil) { ! 478: whomatch=strcmp(who,next->login); ! 479: nummatch=strcmp(num,next->delta->num); ! 480: if ((whomatch==0) && (nummatch==0)) break; ! 481: /*found a lock on delta by who*/ ! 482: if ((whomatch!=0)&&(nummatch==0)) { ! 483: error("revision %s locked by %s; use co -r or rcs -u",num,next->login); ! 484: return -1; ! 485: } ! 486: trail=next; ! 487: next=next->nextlock; ! 488: } ! 489: if (next!=nil) { ! 490: /*found one; delete it */ ! 491: trail->nextlock=next->nextlock; ! 492: Locks=dummy.nextlock; ! 493: next->delta->lockedby=nil; /* reset locked-by */ ! 494: return 1; /*success*/ ! 495: } else return 0; /*no lock on delta*/ ! 496: } ! 497: ! 498: ! 499: ! 500: ! 501: /***************************************************************** ! 502: * The rest of the routines are for handling joins ! 503: *****************************************************************/ ! 504: ! 505: char * getrev(sp, tp, buffsize) ! 506: register char * sp, *tp; int buffsize; ! 507: /* Function: copies a symbolic revision number from sp to tp, ! 508: * appends a '\0', and returns a pointer to the character following ! 509: * the revision number; returns nil if the revision number is more than ! 510: * buffsize characters long. ! 511: * The revision number is terminated by space, tab, comma, colon, ! 512: * semicolon, newline, or '\0'. ! 513: * used for parsing the -j option. ! 514: */ ! 515: { ! 516: register char c; ! 517: register int length; ! 518: ! 519: length = 0; ! 520: while (((c= *sp)!=' ')&&(c!='\t')&&(c!='\n')&&(c!=':')&&(c!=',') ! 521: &&(c!=';')&&(c!='\0')) { ! 522: if (length>=buffsize) return false; ! 523: *tp++= *sp++; ! 524: length++; ! 525: } ! 526: *tp= '\0'; ! 527: return sp; ! 528: } ! 529: ! 530: ! 531: ! 532: int preparejoin() ! 533: /* Function: Parses a join list pointed to by join and places pointers to the ! 534: * revision numbers into joinlist. ! 535: */ ! 536: { ! 537: struct hshentry * * joindeltas; ! 538: struct hshentry * tmpdelta; ! 539: register char * j; ! 540: char symbolrev[revlength],numrev[revlength]; ! 541: ! 542: joindeltas = (struct hshentry * *)talloc(hshsize*sizeof(struct hshentry *)); ! 543: j=join; ! 544: lastjoin= -1; ! 545: for (;;) { ! 546: while ((*j==' ')||(*j=='\t')||(*j==',')) j++; ! 547: if (*j=='\0') break; ! 548: if (lastjoin>=joinlength-2) { ! 549: error("too many joins"); ! 550: return(false); ! 551: } ! 552: if(!(j=getrev(j,symbolrev,revlength))) return false; ! 553: if (!expandsym(symbolrev,numrev)) return false; ! 554: tmpdelta=genrevs(numrev,(char *)nil,(char *)nil,(char *)nil,(struct hshentry * *)joindeltas); ! 555: if (tmpdelta==nil) ! 556: return false; ! 557: else joinlist[++lastjoin]=tmpdelta->num; ! 558: while ((*j==' ') || (*j=='\t')) j++; ! 559: if (*j == ':') { ! 560: j++; ! 561: while((*j==' ') || (*j=='\t')) j++; ! 562: if (*j!='\0') { ! 563: if(!(j=getrev(j,symbolrev,revlength))) return false; ! 564: if (!expandsym(symbolrev,numrev)) return false; ! 565: tmpdelta=genrevs(numrev,(char *)nil,(char *)nil,(char *)nil, (struct hshentry * *) joindeltas); ! 566: if (tmpdelta==nil) ! 567: return false; ! 568: else joinlist[++lastjoin]=tmpdelta->num; ! 569: } else { ! 570: error("join pair incomplete"); ! 571: return false; ! 572: } ! 573: } else { ! 574: if (lastjoin==0) { /* first pair */ ! 575: /* common ancestor missing */ ! 576: joinlist[1]=joinlist[0]; ! 577: lastjoin=1; ! 578: /*derive common ancestor*/ ! 579: joinlist[0]=talloc(revlength); ! 580: if (!getancestor(targetdelta->num,joinlist[1],joinlist[0])) ! 581: return false; ! 582: } else { ! 583: error("join pair incomplete"); ! 584: return false; ! 585: } ! 586: } ! 587: } ! 588: if (lastjoin<1) { ! 589: error("empty join"); ! 590: return false; ! 591: } else return true; ! 592: } ! 593: ! 594: ! 595: ! 596: buildjoin(initialfile) ! 597: char * initialfile; ! 598: /* Function: merge pairs of elements in joinlist into initialfile ! 599: * If tostdout==true, copy result to stdout. ! 600: * All unlinking of initialfile, rev2, and rev3 should be done by cleanup(). ! 601: */ ! 602: { ! 603: char commarg[revlength+3]; ! 604: char subs[revlength]; ! 605: char * rev2, * rev3; ! 606: int i; ! 607: ! 608: rev2=mktempfile("/tmp/",JOINFIL2); ! 609: rev3=mktempfile("/tmp/",JOINFIL3); ! 610: ! 611: i=0; ! 612: while (i<lastjoin) { ! 613: /*prepare marker for merge*/ ! 614: if (i==0) ! 615: VOID strcpy(subs,targetdelta->num); ! 616: else VOID sprintf(subs, "merge%d",i/2); ! 617: diagnose("revision %s",joinlist[i]); ! 618: VOID sprintf(commarg,"-p%s",joinlist[i]); ! 619: if (run((char*)nil,rev2, co,commarg,"-q",RCSfilename,(char*)nil)) { ! 620: nerror++;return false; ! 621: } ! 622: diagnose("revision %s",joinlist[i+1]); ! 623: VOID sprintf(commarg,"-p%s",joinlist[i+1]); ! 624: if (run((char *)nil,rev3, co,commarg,"-q",RCSfilename,(char*)nil)) { ! 625: nerror++; return false; ! 626: } ! 627: diagnose("merging..."); ! 628: if ( ! 629: (i+2)>=lastjoin && tostdout ! 630: ? run((char*)nil,(char*)nil, merge,"-p",initialfile,rev2,rev3,subs,joinlist[i+1],(char*)nil) ! 631: : run((char*)nil,(char*)nil, merge, initialfile,rev2,rev3,subs,joinlist[i+1],(char*)nil)) { ! 632: nerror++; return false; ! 633: } ! 634: i=i+2; ! 635: } ! 636: return true; ! 637: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.