static void process_delta(Node *node, enum stringwork func) { long editline = 0, linecnt = 0, adjust = 0; int editor_command; struct diffcmd dc; uchar *ptr; Glog = node->p->log; in_buffer_init((uchar *)node->p->text, 1); Gversion = node->v; cvs_number_string(&Gversion->number, Gversion_number); switch (func) { case ENTER: while( (ptr=in_get_line()) ) insertline(editline++, ptr); case EDIT: dc.dafter = dc.adprev = 0; while ((editor_command = parse_next_delta_command(&dc)) >= 0) { if (editor_command) { editline = dc.line1 + adjust; linecnt = dc.nlines; while(linecnt--) insertline(editline++, in_get_line()); adjust += dc.nlines; } else { deletelines(dc.line1 - 1 + adjust, dc.nlines); adjust -= dc.nlines; } } break; } }
char * stringify_revision(const char *name, const char *sep, const cvs_number *number, char *buf, size_t bufsz) /* stringify a revision number */ { if (name != NULL) { if (strlen(name) >= bufsz - strlen(sep) - 1) fatal_error("filename too long"); strncpy(buf, name, bufsz - strlen(sep) - 1); strcat(buf, sep); } if (number) cvs_number_string(number, buf + strlen(buf), bufsz - strlen(buf)); return buf; }
static void rev_list_set_refs (rev_list *rl, cvs_file *cvs) { rev_ref *h; cvs_symbol *s; rev_commit *c; /* * Locate a symbolic name for this head */ for (s = cvs->symbols; s; s = s->next) { c = NULL; if (cvs_is_head (&s->number)) { for (h = rl->heads; h; h = h->next) { if (cvs_same_branch (&h->commit->file->number, &s->number)) break; } if (h) { if (!h->name) { h->name = s->name; h->degree = cvs_number_degree (&s->number); } else h = rev_list_add_head (rl, h->commit, s->name, cvs_number_degree (&s->number)); } else { cvs_number n; n = s->number; while (n.c >= 4) { n.c -= 2; c = rev_find_cvs_commit (rl, &n); if (c) break; } if (c) h = rev_list_add_head (rl, c, s->name, cvs_number_degree (&s->number)); } if (h) h->number = s->number; } else { c = rev_find_cvs_commit (rl, &s->number); if (c) tag_commit(c, s->name); } } /* * Fix up unnamed heads */ for (h = rl->heads; h; h = h->next) { cvs_number n; rev_commit *c; if (h->name) continue; for (c = h->commit; c; c = c->parent) { if (c->nfiles) break; } if (!c) continue; n = c->file->number; /* convert to branch form */ n.n[n.c-1] = n.n[n.c-2]; n.n[n.c-2] = 0; h->number = n; h->degree = cvs_number_degree (&n); /* compute name after patching parents */ } /* * Link heads together in a tree */ for (h = rl->heads; h; h = h->next) { cvs_number n; if (h->number.c >= 4) { n = h->number; n.c -= 2; h->parent = rev_list_find_branch (rl, &n); if (!h->parent && ! cvs_is_vendor (&h->number)) fprintf (stderr, "Warning: %s: branch %s has no parent\n", cvs->name, h->name); } if (h->parent && !h->name) { char name[1024]; char rev[CVS_MAX_REV_LEN]; cvs_number_string (&h->number, rev); fprintf (stderr, "Warning: %s: unnamed branch %s from %s\n", cvs->name, rev, h->parent->name); sprintf (name, "%s-UNNAMED-BRANCH", h->parent->name); h->name = atom (name); } } }
/* * "Vendor branches" (1.1.x) are created by importing sources from * an external source. In X.org, this was from XFree86 and DRI. When * these trees are imported, cvs sets the 'default' branch in each ,v file * to point along this branch. This means that tags made between * the time the vendor branch is imported and when a new revision * is committed to the head branch are placed on the vendor branch * In addition, any files without such a commit appear to adopt * the vendor branch as 'head'. We fix this by merging these two * branches together as if they were the same */ static void rev_list_patch_vendor_branch (rev_list *rl, cvs_file *cvs) { rev_ref *trunk = NULL; rev_ref *vendor = NULL; rev_ref *h; rev_commit *t, **tp, *v, **vp; rev_commit *vlast; rev_ref **h_p; int delete_head; trunk = rl->heads; for (h_p = &rl->heads; (h = *h_p);) { delete_head = 0; if (h->commit && cvs_is_vendor (&h->commit->file->number)) { /* * Find version 1.2 on the trunk. * This will reset the default branch set * when the initial import was done. * Subsequent imports will *not* set the default * branch, and should be on their own branch */ vendor = h; t = trunk->commit; v = vendor->commit; for (vlast = vendor->commit; vlast; vlast = vlast->parent) if (!vlast->parent) break; tp = &trunk->commit; /* * Find the latest trunk revision older than * the entire vendor branch */ while ((t = *tp)) { if (!t->parent || time_compare (vlast->file->date, t->parent->file->date) >= 0) { break; } tp = &t->parent; } if (t) { /* * If the first commit is older than the last element * of the vendor branch, paste them together and * nuke the vendor branch */ if (time_compare (vlast->file->date, t->file->date) >= 0) { delete_head = 1; } else { /* * Splice out any portion of the vendor branch * newer than a the next trunk commit after * the oldest branch commit. */ for (vp = &vendor->commit; (v = *vp); vp = &v->parent) if (time_compare (v->date, t->date) <= 0) break; if (vp == &vendor->commit) { /* * Nothing newer, nuke vendor branch */ delete_head = 1; } else { /* * Some newer stuff, patch parent */ *vp = NULL; } } } else delete_head = 1; /* * Patch up the remaining vendor branch pieces */ if (!delete_head) { rev_commit *vr; if (!vendor->name) { char rev[CVS_MAX_REV_LEN]; char name[MAXPATHLEN]; cvs_number branch; branch = vlast->file->number; branch.c--; cvs_number_string (&branch, rev); snprintf (name, sizeof (name), "import-%s", rev); vendor->name = atom (name); vendor->parent = trunk; vendor->degree = vlast->file->number.c; } for (vr = vendor->commit; vr; vr = vr->parent) { if (!vr->parent) { vr->tail = 1; vr->parent = v; break; } } } /* * Merge two branches based on dates */ while (t && v) { if (time_compare (v->file->date, t->file->date) >= 0) { *tp = v; tp = &v->parent; v = v->parent; } else { *tp = t; tp = &t->parent; t = t->parent; } } if (t) *tp = t; else *tp = v; } if (delete_head) { *h_p = h->next; free (h); } else { h_p = &(h->next); } } #if DEBUG fprintf (stderr, "%s spliced:\n", cvs->name); for (t = trunk->commit; t; t = t->parent) { dump_number_file (stderr, "\t", &t->file->number); fprintf (stderr, "\n"); } #endif }