📄 rcs.c
字号:
} else { error("no lock set on revision %s", num); }} static struct hshentry *searchcutpt(object, length, store) char const *object; unsigned length; struct hshentries *store;/* Function: Search store and return entry with number being object. *//* cuttail = nil, if the entry is Head; otherwise, cuttail *//* is the entry point to the one with number being object */{ cuthead = nil; while (compartial(store->first->num, object, length)) { cuthead = store->first; store = store->rest; } return store->first;} static intbranchpoint(strt, tail)struct hshentry *strt, *tail;/* Function: check whether the deltas between strt and tail *//* are locked or branch point, return 1 if any is *//* locked or branch point; otherwise, return 0 and *//* mark deleted */{ struct hshentry *pt; struct lock const *lockpt; int flag; pt = strt; flag = false; while( pt != tail) { if ( pt->branches ){ /* a branch point */ flag = true; error("can't remove branch point %s", pt->num); } lockpt = Locks; while(lockpt && lockpt->delta != pt) lockpt = lockpt->nextlock; if ( lockpt ) { flag = true; error("can't remove locked revision %s",pt->num); } pt = pt->next; } if ( ! flag ) { pt = strt; while( pt != tail ) { pt->selector = false; diagnose("deleting revision %s\n",pt->num); pt = pt->next; } } return flag;} static intremoverevs()/* Function: get the revision range to be removed, and place the *//* first revision removed in delstrt, the revision before *//* delstrt in cuthead( nil, if delstrt is head), and the *//* revision after the last removed revision in cuttail(nil *//* if the last is a leaf */{ struct hshentry *target, *target2, *temp; unsigned length; int flag; flag = false; if (!expandsym(delrev.strt, &numrev)) return 0; target = genrevs(numrev.string, (char*)nil, (char*)nil, (char*)nil, &gendeltas); if ( ! target ) return 0; if (cmpnum(target->num, numrev.string)) flag = true; length = countnumflds(numrev.string); if (delrev.code == 0) { /* -o rev or -o branch */ if (length & 1) temp=searchcutpt(target->num,length+1,gendeltas); else if (flag) { error("Revision %s doesn't exist.", numrev.string); return 0; } else temp = searchcutpt(numrev.string, length, gendeltas); cuttail = target->next; if ( branchpoint(temp, cuttail) ) { cuttail = nil; return 0; } delstrt = temp; /* first revision to be removed */ return 1; } if (length & 1) { /* invalid branch after -o */ error("invalid branch range %s after -o", numrev.string); return 0; } if (delrev.code == 1) { /* -o -rev */ if ( length > 2 ) { temp = searchcutpt( target->num, length-1, gendeltas); cuttail = target->next; } else { temp = searchcutpt(target->num, length, gendeltas); cuttail = target; while( cuttail && ! cmpnumfld(target->num,cuttail->num,1) ) cuttail = cuttail->next; } if ( branchpoint(temp, cuttail) ){ cuttail = nil; return 0; } delstrt = temp; return 1; } if (delrev.code == 2) { /* -o rev- */ if ( length == 2 ) { temp = searchcutpt(target->num, 1,gendeltas); if ( flag) cuttail = target; else cuttail = target->next; } else { if ( flag){ cuthead = target; if ( !(temp = target->next) ) return 0; } else temp = searchcutpt(target->num, length, gendeltas); getbranchno(temp->num, &numrev); /* get branch number */ target = genrevs(numrev.string, (char*)nil, (char*)nil, (char*)nil, &gendeltas); } if ( branchpoint( temp, cuttail ) ) { cuttail = nil; return 0; } delstrt = temp; return 1; } /* -o rev1-rev2 */ if (!expandsym(delrev.end, &numrev)) return 0; if ( length != countnumflds(numrev.string) || length>2 && compartial(numrev.string, target->num, length-1) ) { error("invalid revision range %s-%s", target->num, numrev.string); return 0; } target2 = genrevs(numrev.string,(char*)nil,(char*)nil,(char*)nil,&gendeltas); if ( ! target2 ) return 0; if ( length > 2) { /* delete revisions on branches */ if ( cmpnum(target->num, target2->num) > 0) { if (cmpnum(target2->num, numrev.string)) flag = true; else flag = false; temp = target; target = target2; target2 = temp; } if ( flag ) { if ( ! cmpnum(target->num, target2->num) ) { error("Revisions %s-%s don't exist.", delrev.strt,delrev.end); return 0; } cuthead = target; temp = target->next; } else temp = searchcutpt(target->num, length, gendeltas); cuttail = target2->next; } else { /* delete revisions on trunk */ if ( cmpnum( target->num, target2->num) < 0 ) { temp = target; target = target2; target2 = temp; } else if (cmpnum(target2->num, numrev.string)) flag = true; else flag = false; if ( flag ) { if ( ! cmpnum(target->num, target2->num) ) { error("Revisions %s-%s don't exist.", delrev.strt, delrev.end); return 0; } cuttail = target2; } else cuttail = target2->next; temp = searchcutpt(target->num, length, gendeltas); } if ( branchpoint(temp, cuttail) ) { cuttail = nil; return 0; } delstrt = temp; return 1;} static voiddoassoc()/* Function: add or delete(if revno is nil) association *//* which is stored in assoclst */{ char const *p; struct Symrev const *curassoc; struct assoc * pre, * pt; /* add new associations */ curassoc = assoclst; while( curassoc ) { if ( curassoc->revno == nil ) { /* delete symbol */ pre = pt = Symbols; while( pt && strcmp(pt->symbol,curassoc->ssymbol) ) { pre = pt; pt = pt->nextassoc; } if ( pt ) if ( pre == pt ) Symbols = pt->nextassoc; else pre->nextassoc = pt->nextassoc; else warn("can't delete nonexisting symbol %s",curassoc->ssymbol); } else { if (curassoc->revno[0]) { p = 0; if (expandsym(curassoc->revno, &numrev)) p = fstr_save(numrev.string); } else if (!(p = tiprev())) error("no latest revision to associate with symbol %s", curassoc->ssymbol ); if (p) VOID addsymbol(p, curassoc->ssymbol, curassoc->override); } curassoc = curassoc->nextsym; }} static voiddolocks()/* Function: remove lock for caller or first lock if unlockcaller is set; * remove locks which are stored in rmvlocklst, * add new locks which are stored in newlocklst, * add lock for Dbranch or Head if lockhead is set. */{ struct Lockrev const *lockpt; struct hshentry *target; if (unlockcaller) { /* find lock for caller */ if ( Head ) { if (Locks) { switch (findlock(true, &target)) { case 0: breaklock(Locks->delta); /* remove most recent lock */ break; case 1: diagnose("%s unlocked\n",target->num); break; } } else { warn("No locks are set."); } } else { warn("can't unlock an empty tree"); } } /* remove locks which are stored in rmvlocklst */ lockpt = rmvlocklst; while( lockpt ) { if (expandsym(lockpt->revno, &numrev)) { target = genrevs(numrev.string, (char *)nil, (char *)nil, (char *)nil, &gendeltas); if ( target ) if (!(countnumflds(numrev.string)&1) && cmpnum(target->num,numrev.string)) error("can't unlock nonexisting revision %s",lockpt->revno); else breaklock(target); /* breaklock does its own diagnose */ } lockpt = lockpt->nextrev; } /* add new locks which stored in newlocklst */ lockpt = newlocklst; while( lockpt ) { setlock(lockpt->revno); lockpt = lockpt->nextrev; } if (lockhead) { /* lock default branch or head */ if (Dbranch) { setlock(Dbranch); } else if (Head) { if (0 <= addlock(Head)) diagnose("%s locked\n",Head->num); } else { warn("can't lock an empty tree"); } }} static voidsetlock(rev) char const *rev;/* Function: Given a revision or branch number, finds the corresponding * delta and locks it for caller. */{ struct hshentry *target; if (expandsym(rev, &numrev)) { target = genrevs(numrev.string, (char*)nil, (char*)nil, (char*)nil, &gendeltas); if ( target ) if (!(countnumflds(numrev.string)&1) && cmpnum(target->num,numrev.string)) error("can't lock nonexisting revision %s", numrev.string); else if (0 <= addlock(target)) diagnose("%s locked\n", target->num); }} static voiddomessages(){ struct hshentry *target; struct Message *p; for (p = messagelst; p; p = p->nextmessage) if ( expandsym(p->revno, &numrev) && (target = genrevs( numrev.string, (char*)0, (char*)0, (char*)0, &gendeltas )) ) target->log = p->message;} static voidrcs_setstate(rev,status) char const *rev, *status;/* Function: Given a revision or branch number, finds the corresponding delta * and sets its state to status. */{ struct hshentry *target; if (expandsym(rev, &numrev)) { target = genrevs(numrev.string, (char*)nil, (char*)nil, (char*)nil, &gendeltas); if ( target ) if (!(countnumflds(numrev.string)&1) && cmpnum(target->num,numrev.string)) error("can't set state of nonexisting revision %s to %s", numrev.string, status); else target->state = status; }} static intbuildeltatext(deltas) struct hshentries const *deltas;/* Function: put the delta text on frewrite and make necessary *//* change to delta text */{ register FILE *fcut; /* temporary file to rebuild delta tree */ char const *cutfilename, *diffilename; cutfilename = nil; cuttail->selector = false; scanlogtext(deltas->first, false); if ( cuthead ) { cutfilename = maketemp(3); if (!(fcut = fopen(cutfilename, FOPEN_W_WORK))) { efaterror(cutfilename); } while (deltas->first != cuthead) { deltas = deltas->rest; scanlogtext(deltas->first, true); } snapshotedit(fcut); Ofclose(fcut); } while (deltas->first != cuttail) scanlogtext((deltas = deltas->rest)->first, true); finishedit((struct hshentry *)nil, (FILE*)0, true); Ozclose(&fcopy); if ( cuthead ) { diffilename = maketemp(0); switch (run((char*)nil,diffilename, DIFF DIFF_FLAGS, cutfilename, resultfile, (char*)nil )) { case DIFF_FAILURE: case DIFF_SUCCESS: break; default: faterror ("diff failed"); } return putdtext(cuttail->num,cuttail->log,diffilename,frewrite,true); } else return putdtext(cuttail->num,cuttail->log,resultfile,frewrite,false);} static voidbuildtree()/* Function: actually removes revisions whose selector field *//* is false, and rebuilds the linkage of deltas. *//* asks for reconfirmation if deleting last revision*/{ struct hshentry * Delta; struct branchhead *pt, *pre; if ( cuthead ) if ( cuthead->next == delstrt ) cuthead->next = cuttail; else { pre = pt = cuthead->branches; while( pt && pt->hsh != delstrt ) { pre = pt; pt = pt->nextbranch; } if ( cuttail ) pt->hsh = cuttail; else if ( pt == pre ) cuthead->branches = pt->nextbranch; else pre->nextbranch = pt->nextbranch; } else { if ( cuttail == nil && !quietflag) { if (!yesorno(false, "Do you really want to delete all revisions? [ny](n): ")) { error("No revision deleted"); Delta = delstrt; while( Delta) { Delta->selector = true; Delta = Delta->next; } return; } } Head = cuttail; } return;}#if lint/* This lets us lint everything all at once. */char const cmdid[] = "";#define go(p,e) {int p P((int,char**)); void e P((void)); if(*argv)return p(argc,argv);if(*argv[1])e();} intmain(argc, argv) int argc; char **argv;{ go(ciId, ciExit); go(coId, coExit); go(identId, identExit); go(mergeId, mergeExit); go(rcsId, exiterr); go(rcscleanId, rcscleanExit); go(rcsdiffId, rdiffExit); go(rcsmergeId, rmergeExit); go(rlogId, rlogExit); return 0;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -