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; }