📄 rcs.c
字号:
} curstate = statelst; while( curstate ) { rcs_setstate(curstate->revno,curstate->status); curstate = curstate->nextstatus; } cuthead = cuttail = nil; if (delrev.strt && removerevs()) { /* rebuild delta tree if some deltas are deleted */ if ( cuttail ) VOID genrevs(cuttail->num, (char *)nil,(char *)nil, (char *)nil, &gendeltas); buildtree(); } if (nerror) continue; putadmin(frewrite); if ( Head ) puttree(Head, frewrite); putdesc(textflag,textfile); if ( Head) { if (!delrev.strt && !messagelst) { /* No revision was deleted and no message was changed. */ fastcopy(finptr, frewrite); } else { if (!cuttail || buildeltatext(gendeltas)) { advise_access(finptr, MADV_SEQUENTIAL); scanlogtext((struct hshentry *)nil, false); /* copy rest of delta text nodes that are not deleted */ } } } Izclose(&finptr); if ( ! nerror ) { /* move temporary file to RCS file if no error */ /* update mode */ ignoreints(); r = chnamemod(&frewrite, newRCSfilename, RCSfilename, RCSmode); e = errno; keepdirtemp(newRCSfilename); restoreints(); if (r != 0) { enerror(e, RCSfilename); error("saved in %s", newRCSfilename); dirtempunlink(); break; } diagnose("done\n"); } else { diagnose("%s aborted; %s unchanged.\n",cmdid,RCSfilename); } } while (cleanup(), ++argv, --argc >=1); tempunlink(); exitmain(exitstatus);} /* end of main (rcs) */ static voidcleanup(){ if (nerror) exitstatus = EXIT_FAILURE; Izclose(&finptr); Ozclose(&fcopy); Ozclose(&frewrite); dirtempunlink();} exiting voidexiterr(){ dirtempunlink(); tempunlink(); _exit(EXIT_FAILURE);} static voidgetassoclst(flag, sp)int flag;char * sp;/* Function: associate a symbolic name to a revision or branch, *//* and store in assoclst */{ struct Symrev * pt; char const *temp; int c; while( (c=(*++sp)) == ' ' || c == '\t' || c =='\n') ; temp = sp; sp = checkid(sp, ':'); /* check for invalid symbolic name */ c = *sp; *sp = '\0'; while( c == ' ' || c == '\t' || c == '\n') c = *++sp; if ( c != ':' && c != '\0') { error("invalid string %s after option -n or -N",sp); return; } pt = talloc(struct Symrev); pt->ssymbol = temp; pt->override = flag; if (c == '\0') /* delete symbol */ pt->revno = nil; else { while( (c = *++sp) == ' ' || c == '\n' || c == '\t') ; pt->revno = sp; } pt->nextsym = nil; if (lastassoc) lastassoc->nextsym = pt; else assoclst = pt; lastassoc = pt; return;} static voidgetchaccess(login, command) char const *login; enum changeaccess command;{ register struct chaccess *pt; *nextchaccess = pt = talloc(struct chaccess); pt->login = login; pt->command = command; pt->nextchaccess = nil; nextchaccess = &pt->nextchaccess;} static voidgetaccessor(opt, command) char *opt; enum changeaccess command;/* Function: get the accessor list of options -e and -a, *//* and store in chaccess */{ register c; register char *sp; sp = opt; while( ( c = *++sp) == ' ' || c == '\n' || c == '\t' || c == ',') ; if ( c == '\0') { if (command == erase && sp-opt == 1) { getchaccess((char const*)nil, command); return; } error("missing login name after option -a or -e"); return; } while( c != '\0') { getchaccess(sp, command); sp = checkid(sp,','); c = *sp; *sp = '\0'; while( c == ' ' || c == '\n' || c == '\t'|| c == ',')c =(*++sp); }} static voidgetmessage(option) char *option;{ struct Message *pt; struct cbuf cb; char *m; if (!(m = strchr(option, ':'))) { error("-m option lacks revision number"); return; } *m++ = 0; cb = cleanlogmsg(m, strlen(m)); if (!cb.size) { error("-m option lacks log message"); return; } pt = talloc(struct Message); pt->revno = option; pt->message = cb; pt->nextmessage = 0; if (lastmessage) lastmessage->nextmessage = pt; else messagelst = pt; lastmessage = pt;} static voidgetstates(sp)char *sp;/* Function: get one state attribute and the corresponding *//* revision and store in statelst */{ char const *temp; struct Status *pt; register c; while( (c=(*++sp)) ==' ' || c == '\t' || c == '\n') ; temp = sp; sp = checkid(sp,':'); /* check for invalid state attribute */ c = *sp; *sp = '\0'; while( c == ' ' || c == '\t' || c == '\n' ) c = *++sp; if ( c == '\0' ) { /* change state of def. branch or Head */ chgheadstate = true; headstate = temp; return; } else if ( c != ':' ) { error("missing ':' after state in option -s"); return; } while( (c = *++sp) == ' ' || c == '\t' || c == '\n') ; pt = talloc(struct Status); pt->status = temp; pt->revno = sp; pt->nextstatus = nil; if (laststate) laststate->nextstatus = pt; else statelst = pt; laststate = pt;} static voidgetdelrev(sp)char *sp;/* Function: get revision range or branch to be deleted, *//* and place in delrev */{ int c; struct delrevpair *pt; int separator; pt = &delrev; while((c = (*++sp)) == ' ' || c == '\n' || c == '\t') ; /* Support old ambiguous '-' syntax; this will go away. */ if (strchr(sp,':')) separator = ':'; else { if (strchr(sp,'-') && VERSION(5) <= RCSversion) warn("`-' is obsolete in `-o%s'; use `:' instead", sp); separator = '-'; } if (c == separator) { /* -o:rev */ while( (c = (*++sp)) == ' ' || c == '\n' || c == '\t') ; pt->strt = sp; pt->code = 1; while( c != ' ' && c != '\n' && c != '\t' && c != '\0') c =(*++sp); *sp = '\0'; pt->end = nil; return; } else { pt->strt = sp; while( c != ' ' && c != '\n' && c != '\t' && c != '\0' && c != separator ) c = *++sp; *sp = '\0'; while( c == ' ' || c == '\n' || c == '\t' ) c = *++sp; if ( c == '\0' ) { /* -o rev or branch */ pt->end = nil; pt->code = 0; return; } if (c != separator) { faterror("invalid range %s %s after -o", pt->strt, sp); } while( (c = *++sp) == ' ' || c == '\n' || c == '\t') ; if (!c) { /* -orev: */ pt->end = nil; pt->code = 2; return; } } /* -orev1:rev2 */ pt->end = sp; pt->code = 3; while( c!= ' ' && c != '\n' && c != '\t' && c != '\0') c = *++sp; *sp = '\0';} static voidscanlogtext(delta,edit) struct hshentry *delta; int edit;/* Function: Scans delta text nodes up to and including the one given * by delta, or up to last one present, if delta==nil. * For the one given by delta (if delta!=nil), the log message is saved into * delta->log if delta==cuttail; the text is edited if EDIT is set, else copied. * Assumes the initial lexeme must be read in first. * Does not advance nexttok after it is finished, except if delta==nil. */{ struct hshentry const *nextdelta; struct cbuf cb; for (;;) { foutptr = 0; if (eoflex()) { if(delta) faterror("can't find delta for revision %s", delta->num); return; /* no more delta text nodes */ } nextlex(); if (!(nextdelta=getnum())) faterror("delta number corrupted"); if (nextdelta->selector) { foutptr = frewrite; aprintf(frewrite,DELNUMFORM,nextdelta->num,Klog); } getkeystring(Klog); if (nextdelta == cuttail) { cb = savestring(&curlogbuf); if (!delta->log.string) delta->log = cleanlogmsg(curlogbuf.string, cb.size); } else if (nextdelta->log.string && nextdelta->selector) { foutptr = 0; readstring(); foutptr = frewrite; putstring(foutptr, false, nextdelta->log, true); afputc(nextc, foutptr); } else {readstring(); } nextlex(); while (nexttok==ID && strcmp(NextString,Ktext)!=0) ignorephrase(); getkeystring(Ktext); if (delta==nextdelta) break; readstring(); /* skip over it */ } /* got the one we're looking for */ if (edit) editstring((struct hshentry *)nil); else enterstring();} static struct Lockrev *rmnewlocklst(which) struct Lockrev const *which;/* Function: remove lock to revision which->revno from newlocklst */{ struct Lockrev * pt, *pre; while( newlocklst && (! strcmp(newlocklst->revno, which->revno))){ struct Lockrev *pn = newlocklst->nextrev; tfree(newlocklst); newlocklst = pn; } pt = pre = newlocklst; while( pt ) { if ( ! strcmp(pt->revno, which->revno) ) { pre->nextrev = pt->nextrev; tfree(pt); pt = pre->nextrev; } else { pre = pt; pt = pt->nextrev; } } return pre;} static voiddoaccess(){ register struct chaccess *ch; register struct access **p, *t; for (ch = chaccess; ch; ch = ch->nextchaccess) { switch (ch->command) { case erase: if (!ch->login) AccessList = nil; else for (p = &AccessList; (t = *p); ) if (strcmp(ch->login, t->login) == 0) *p = t->nextaccess; else p = &t->nextaccess; break; case append: for (p = &AccessList; ; p = &t->nextaccess) if (!(t = *p)) { *p = t = ftalloc(struct access); t->login = ch->login; t->nextaccess = nil; break; } else if (strcmp(ch->login, t->login) == 0) break; break; } }} static intsendmail(Delta, who) char const *Delta, *who;/* Function: mail to who, informing him that his lock on delta was * broken by caller. Ask first whether to go ahead. Return false on * error or if user decides not to break the lock. */{#ifdef SENDMAIL char const *messagefile; int old1, old2, c; FILE * mailmess;#endif aprintf(stderr, "Revision %s is already locked by %s.\n", Delta, who); if (!yesorno(false, "Do you want to break the lock? [ny](n): ")) return false; /* go ahead with breaking */#ifdef SENDMAIL messagefile = maketemp(0); if (!(mailmess = fopen(messagefile, "w"))) { efaterror(messagefile); } aprintf(mailmess, "Subject: Broken lock on %s\n\nYour lock on revision %s of file %s\nhas been broken by %s for the following reason:\n", basename(RCSfilename), Delta, getfullRCSname(), getcaller() ); aputs("State the reason for breaking the lock:\n(terminate with single '.' or end of file)\n>> ", stderr); old1 = '\n'; old2 = ' '; for (; ;) { c = getcstdin(); if (feof(stdin)) { aprintf(mailmess, "%c\n", old1); break; } else if ( c == '\n' && old1 == '.' && old2 == '\n') break; else { afputc(old1, mailmess); old2 = old1; old1 = c; if (c=='\n') aputs(">> ", stderr); } } Ozclose(&mailmess); if (run(messagefile, (char*)nil, SENDMAIL, who, (char*)nil)) warn("Mail may have failed."),#else warn("Mail notification of broken locks is not available."),#endif warn("Please tell `%s' why you broke the lock.", who); return(true);} static voidbreaklock(delta) struct hshentry const *delta;/* function: Finds the lock held by caller on delta, * and removes it. * Sends mail if a lock different from the caller's is broken. * Prints an error message if there is no such lock or error. */{ register struct lock * next, * trail; char const *num; struct lock dummy; num=delta->num; dummy.nextlock=next=Locks; trail = &dummy; while (next!=nil) { if (strcmp(num, next->delta->num) == 0) { if ( strcmp(getcaller(),next->login) != 0 && !sendmail(num, next->login) ) { error("%s still locked by %s", num, next->login); return; } break; /* exact match */ } trail=next; next=next->nextlock; } if (next!=nil) { /*found one */ diagnose("%s unlocked\n",next->delta->num); trail->nextlock=next->nextlock; next->delta->lockedby=nil; Locks=dummy.nextlock;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -