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); } } }
rev_list * rev_list_cvs (cvs_file *cvs) { rev_list *rl = calloc (1, sizeof (rev_list)); cvs_number trunk_number; rev_commit *trunk; rev_commit *branch; cvs_version *cv; cvs_branch *cb; rev_ref *t; cvs_version *ctrunk = NULL; build_branches(); /* * Locate first revision on trunk branch */ for (cv = cvs->versions; cv; cv = cv->next) { if (cvs_is_trunk (&cv->number) && (!ctrunk || cvs_number_compare (&cv->number, &ctrunk->number) < 0)) { ctrunk = cv; } } /* * Generate trunk branch */ if (ctrunk) trunk_number = ctrunk->number; else trunk_number = lex_number ("1.1"); trunk = rev_branch_cvs (cvs, &trunk_number); if (trunk) { t = rev_list_add_head (rl, trunk, atom ("master"), 2); t->number = trunk_number; } else fprintf(stderr, "warning - no master branch generated\n"); /* * Search for other branches */ #if DEBUG printf ("building branches for %s\n", cvs->name); #endif for (cv = cvs->versions; cv; cv = cv->next) { for (cb = cv->branches; cb; cb = cb->next) { branch = rev_branch_cvs (cvs, &cb->number); rev_list_add_head (rl, branch, NULL, 0); } } rev_list_patch_vendor_branch (rl, cvs); rev_list_graft_branches (rl, cvs); rev_list_set_refs (rl, cvs); rev_list_sort_heads (rl, cvs); rev_list_set_tail (rl); rev_list_free_dead_files (rl); rev_list_validate (rl); return rl; }
rev_list * rev_list_merge (rev_list *head) { int count = rev_list_count (head); rev_list *rl; rev_list *l; rev_ref *lh, *h; Tag *t; rev_ref **refs; int nref; ALLOC((rl = calloc (1, sizeof (rev_list))), "rev_list_merge"); ALLOC((refs = calloc (count, sizeof (rev_ref *))), "rev_list_merge"); /* * Find all of the heads across all of the incoming trees * Yes, this is currently very inefficient */ for (l = head; l; l = l->next) { for (lh = l->heads; lh; lh = lh->next) { h = rev_find_head (rl, lh->name); if (!h) rev_list_add_head (rl, NULL, lh->name, lh->degree); else if (lh->degree > h->degree) h->degree = lh->degree; } } /* * Sort by degree so that finding branch points always works */ // rl->heads = rev_ref_sel_sort (rl->heads); rl->heads = rev_ref_tsort (rl->heads, head); if (!rl->heads) return NULL; // for (h = rl->heads; h; h = h->next) // fprintf (stderr, "head %s (%d)\n", // h->name, h->degree); /* * Find branch parent relationships */ for (h = rl->heads; h; h = h->next) { rev_ref_set_parent (rl, h, head); // dump_ref_name (stderr, h); // fprintf (stderr, "\n"); } /* * Merge common branches */ for (h = rl->heads; h; h = h->next) { /* * Locate branch in every tree */ nref = 0; for (l = head; l; l = l->next) { lh = rev_find_head (l, h->name); if (lh) refs[nref++] = lh; } if (nref) rev_branch_merge (refs, nref, h, rl); } /* * Compute 'tail' values */ rev_list_set_tail (rl); free(refs); /* * Find tag locations */ for (t = all_tags; t; t = t->next) { rev_commit **commits = tagged(t); if (commits) rev_tag_search(t, commits, rl); else fprintf (stderr, "lost tag %s\n", t->name); free(commits); } rev_list_validate (rl); return rl; }