static void rev_commit_dump (FILE *f, char *title, rev_commit *c, rev_commit *m) { fprintf (f, "\n%s\n", title); while (c) { int i; fprintf (f, "%c0x%x %s\n", c == m ? '>' : ' ', (int) c, ctime_nonl (&c->date)); for (i = 0; i < c->nfiles; i++) { fprintf (f, "\t%s", ctime_nonl (&c->files[i]->date)); dump_number_file (f, c->files[i]->name, &c->files[i]->number); fprintf (f, "\n"); } fprintf (f, "\n"); c = c->parent; } }
static void dot_commit_graph(git_commit *c, rev_ref *branch) { rev_file *f; printf("\""); if (branch) dot_ref_name(stdout, branch); // if (c->tail) // printf("*** TAIL"); printf("\\n"); printf("%s\\n", ctime_nonl(&c->date)); dump_log(stdout, c->log); printf("\\n"); if (difffiles) { rev_diff *diff = git_commit_diff(c->parent, c); rev_file_list *fl; for (fl = diff->add; fl; fl = fl->next) { if (!rev_file_list_has_filename(diff->del, fl->file->file_name)) { printf("+"); dump_number(fl->file->file_name, &fl->file->number); printf("\\n"); } } for (fl = diff->add; fl; fl = fl->next) { if (rev_file_list_has_filename(diff->del, fl->file->file_name)) { printf("|"); dump_number(fl->file->file_name, &fl->file->number); printf("\\n"); } } for (fl = diff->del; fl; fl = fl->next) { if (!rev_file_list_has_filename(diff->add, fl->file->file_name)) { printf("-"); dump_number(fl->file->file_name, &fl->file->number); printf("\\n"); } } rev_diff_free(diff); } else { int i, j; for (i = 0; i < c->ndirs; i++) { rev_dir *dir = c->dirs[i]; for (j = 0; j < dir->nfiles; j++) { f = dir->files[j]; dump_number(f->file_name, &f->number); printf("\\n"); } } } printf("%p", c); printf("\""); }
/* * Merge a set of per-file branches into a global branch */ static void rev_branch_merge (rev_ref **branches, int nbranch, rev_ref *branch, rev_list *rl) { int nlive; int n; rev_commit *prev = NULL; rev_commit *head = NULL, **tail = &head; rev_commit **commits; rev_commit *commit; rev_commit *latest; rev_commit **p; int lazy = 0; time_t start = 0; ALLOC((commits = calloc (nbranch, sizeof (rev_commit *))), "rev_branch_merge"); nlive = 0; // printf("rev_branch_merge: nbranch=%d\n", nbranch); for (n = 0; n < nbranch; n++) { rev_commit *c; /* * Initialize commits to head of each branch */ c = commits[n] = branches[n]->commit; /* * Compute number of branches with remaining entries */ if (!c) continue; if (branches[n]->tail) { c->tailed = 1; continue; } nlive++; while (c && !c->tail) { if (!start || time_compare(c->date, start) < 0) { // printf(" 1:setting start=%ld:%s (from %s)\n", start, ctime_nonl(&start), c->file->name); start = c->date; } c = c->parent; } if (c && (c->file || c->date != c->parent->date)) { if (!start || time_compare(c->date, start) < 0) { // printf(" 2:setting start=%ld:%s (from %s)\n", start, ctime_nonl(&start), c->file->name); start = c->date; } } } for (n = 0; n < nbranch; n++) { rev_commit *c = commits[n]; #if 0 printf("Doing commit %p: @ %ld\n", c, c->date); if (c->file) printf(" %s\n", c->file->name); #endif if (!c->tailed) continue; if (!start || time_compare(start, c->date) >= 0) continue; if (c->file) { /* This case can occur if files have been added to a branch since it's creation. */ printf( "Warning: %s too late date %s through branch %s (%ld:%ld=%ld)\n", c->file->name, ctime_nonl(&c->date), branch->name, start, c->date, start-c->date); continue; } commits[n] = NULL; } /* * Walk down branches until each one has merged with the * parent branch */ while (nlive > 0 && nbranch > 0) { for (n = 0, p = commits, latest = NULL; n < nbranch; n++) { rev_commit *c = commits[n]; if (!c) continue; *p++ = c; if (c->tailed) continue; if (!latest || time_compare(latest->date, c->date) < 0) latest = c; } nbranch = p - commits; /* * Construct current commit */ if (!lazy) { commit = rev_commit_build (commits, latest, nbranch); if (rev_mode == ExecuteGit) lazy = 1; } else { commit = create_tree(latest); } /* * Step each branch */ nlive = 0; for (n = 0; n < nbranch; n++) { rev_commit *c = commits[n]; rev_commit *to; /* already got to parent branch? */ if (c->tailed) continue; /* not affected? */ if (c != latest && !rev_commit_match(c, latest)) { if (c->parent || c->file) nlive++; continue; } to = c->parent; /* starts here? */ if (!to) goto Kill; if (c->tail) { /* * Adding file independently added on another * non-trunk branch. */ if (!to->parent && !to->file) goto Kill; /* * If the parent is at the beginning of trunk * and it is younger than some events on our * branch, we have old CVS adding file * independently * added on another branch. */ if (start && time_compare(start, to->date) < 0) goto Kill; /* * XXX: we still can't be sure that it's * not a file added on trunk after parent * branch had forked off it but before * our branch's creation. */ to->tailed = 1; } else if (to->file) { nlive++; } else { /* * See if it's recent CVS adding a file * independently added on another branch. */ if (!to->parent) goto Kill; if (to->tail && to->date == to->parent->date) goto Kill; nlive++; } if (to->file) set_commit(to); else delete_commit(c); commits[n] = to; continue; Kill: delete_commit(c); commits[n] = NULL; } *tail = commit; tail = &commit->parent; prev = commit; } /* * Connect to parent branch */ nbranch = rev_commit_date_sort (commits, nbranch); if (nbranch && branch->parent ) { rev_ref *lost; int present; // present = 0; for (present = 0; present < nbranch; present++) if (commits[present]->file) { /* * Skip files which appear in the repository after * the first commit along the branch */ if (prev && commits[present]->date > prev->date && commits[present]->date == rev_commit_first_date (commits[present])) { fprintf (stderr, "Warning: file %s appears after branch %s date\n", commits[present]->file->name, branch->name); continue; } break; } if (present == nbranch) *tail = NULL; else if ((*tail = rev_commit_locate_one (branch->parent, commits[present]))) { if (prev && time_compare ((*tail)->date, prev->date) > 0) { fprintf (stderr, "Warning: branch point %s -> %s later than branch\n", branch->name, branch->parent->name); fprintf (stderr, "\ttrunk(%3d): %s %s", n, ctime_nonl (&commits[present]->date), commits[present]->file ? " " : "D" ); if (commits[present]->file) dump_number_file (stderr, commits[present]->file->name, &commits[present]->file->number); fprintf (stderr, "\n"); fprintf (stderr, "\tbranch(%3d): %s ", n, prev->file?ctime_nonl (&prev->file->date):"no file"); if (prev->file) { dump_number_file (stderr, prev->file->name, &prev->file->number); } fprintf (stderr, "\n"); } } else if ((*tail = rev_commit_locate_date (branch->parent, commits[present]->date))) fprintf (stderr, "Warning: branch point %s -> %s matched by date\n", branch->name, branch->parent->name); else { fprintf (stderr, "Error: branch point %s -> %s not found.", branch->name, branch->parent->name); if ((lost = rev_branch_of_commit (rl, commits[present]))) fprintf (stderr, " Possible match on %s.", lost->name); fprintf (stderr, "\n"); } if (*tail) { if (prev) prev->tail = 1; } else *tail = rev_commit_build (commits, commits[0], nbranch); } for (n = 0; n < nbranch; n++) if (commits[n]) commits[n]->tailed = 0; free (commits); branch->commit = head; }