int cvs_number_degree(const cvs_number *n) /* what is the degree of branchiness of the specified revision? */ { cvs_number four; if (n->c < 4) return n->c; four = *n; four.c = 4; /* * Place vendor branch between trunk and other branches */ if (cvs_is_vendor(&four)) return n->c - 1; return n->c; }
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); } } }
static void rev_list_graft_branches (rev_list *rl, cvs_file *cvs) { rev_ref *h; rev_commit *c; cvs_version *cv; cvs_branch *cb; /* * Glue branches together */ for (h = rl->heads; h; h = h->next) { /* * skip master branch; it "can't" join * any other branches and it may well end with a vendor * branch revision of the file, which will then create * a loop back to the recorded branch point */ if (h == rl->heads) continue; if (h->tail) continue; /* * Find last commit on branch */ for (c = h->commit; c && c->parent; c = c->parent) if (c->tail) { c = NULL; /* already been done, skip */ break; } if (c) { /* * Walk the version tree, looking for the branch location. * Note that in the presense of vendor branches, the * branch location may actually be out on that vendor branch */ for (cv = cvs->versions; cv; cv = cv->next) { for (cb = cv->branches; cb; cb = cb->next) { if (cvs_number_compare (&cb->number, &c->file->number) == 0) { c->parent = rev_find_cvs_commit (rl, &cv->number); c->tail = 1; break; } } if (c->parent) { #if 0 /* * check for a parallel vendor branch */ for (cb = cv->branches; cb; cb = cb->next) { if (cvs_is_vendor (&cb->number)) { cvs_number v_n; rev_commit *v_c, *n_v_c; fprintf (stderr, "Found merge into vendor branch\n"); v_n = cb->number; v_c = NULL; /* * Walk to head of vendor branch */ while ((n_v_c = rev_find_cvs_commit (rl, &v_n))) { /* * Stop if we reach a date after the * branch version date */ if (time_compare (n_v_c->date, c->date) > 0) break; v_c = n_v_c; v_n.n[v_n.c - 1]++; } if (v_c) { fprintf (stderr, "%s: rewrite branch", cvs->name); dump_number_file (stderr, " branch point", &v_c->file->number); dump_number_file (stderr, " branch version", &c->file->number); fprintf (stderr, "\n"); c->parent = v_c; } } } #endif break; } } } } }
/* * "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 }