|
28 | 28 | #include "blob.h"
|
29 | 29 | #include "tree.h"
|
30 | 30 | #include "promisor-remote.h"
|
| 31 | +#include "refs.h" |
31 | 32 |
|
32 | 33 | #define FAILED_RUN "failed to run %s"
|
33 | 34 |
|
@@ -710,6 +711,86 @@ struct maintenance_run_opts {
|
710 | 711 | int quiet;
|
711 | 712 | };
|
712 | 713 |
|
| 714 | +/* Remember to update object flag allocation in object.h */ |
| 715 | +#define SEEN (1u<<0) |
| 716 | + |
| 717 | +struct cg_auto_data { |
| 718 | + int num_not_in_graph; |
| 719 | + int limit; |
| 720 | +}; |
| 721 | + |
| 722 | +static int dfs_on_ref(const char *refname, |
| 723 | + const struct object_id *oid, int flags, |
| 724 | + void *cb_data) |
| 725 | +{ |
| 726 | + struct cg_auto_data *data = (struct cg_auto_data *)cb_data; |
| 727 | + int result = 0; |
| 728 | + struct object_id peeled; |
| 729 | + struct commit_list *stack = NULL; |
| 730 | + struct commit *commit; |
| 731 | + |
| 732 | + if (!peel_ref(refname, &peeled)) |
| 733 | + oid = &peeled; |
| 734 | + if (oid_object_info(the_repository, oid, NULL) != OBJ_COMMIT) |
| 735 | + return 0; |
| 736 | + |
| 737 | + commit = lookup_commit(the_repository, oid); |
| 738 | + if (!commit) |
| 739 | + return 0; |
| 740 | + if (parse_commit(commit)) |
| 741 | + return 0; |
| 742 | + |
| 743 | + commit_list_append(commit, &stack); |
| 744 | + |
| 745 | + while (!result && stack) { |
| 746 | + struct commit_list *parent; |
| 747 | + |
| 748 | + commit = pop_commit(&stack); |
| 749 | + |
| 750 | + for (parent = commit->parents; parent; parent = parent->next) { |
| 751 | + if (parse_commit(parent->item) || |
| 752 | + commit_graph_position(parent->item) != COMMIT_NOT_FROM_GRAPH || |
| 753 | + parent->item->object.flags & SEEN) |
| 754 | + continue; |
| 755 | + |
| 756 | + parent->item->object.flags |= SEEN; |
| 757 | + data->num_not_in_graph++; |
| 758 | + |
| 759 | + if (data->num_not_in_graph >= data->limit) { |
| 760 | + result = 1; |
| 761 | + break; |
| 762 | + } |
| 763 | + |
| 764 | + commit_list_append(parent->item, &stack); |
| 765 | + } |
| 766 | + } |
| 767 | + |
| 768 | + free_commit_list(stack); |
| 769 | + return result; |
| 770 | +} |
| 771 | + |
| 772 | +static int should_write_commit_graph(void) |
| 773 | +{ |
| 774 | + int result; |
| 775 | + struct cg_auto_data data; |
| 776 | + |
| 777 | + data.num_not_in_graph = 0; |
| 778 | + data.limit = 100; |
| 779 | + git_config_get_int("maintenance.commit-graph.auto", |
| 780 | + &data.limit); |
| 781 | + |
| 782 | + if (!data.limit) |
| 783 | + return 0; |
| 784 | + if (data.limit < 0) |
| 785 | + return 1; |
| 786 | + |
| 787 | + result = for_each_ref(dfs_on_ref, &data); |
| 788 | + |
| 789 | + clear_commit_marks_all(SEEN); |
| 790 | + |
| 791 | + return result; |
| 792 | +} |
| 793 | + |
713 | 794 | static int run_write_commit_graph(struct maintenance_run_opts *opts)
|
714 | 795 | {
|
715 | 796 | struct child_process child = CHILD_PROCESS_INIT;
|
@@ -790,6 +871,7 @@ static struct maintenance_task tasks[] = {
|
790 | 871 | [TASK_COMMIT_GRAPH] = {
|
791 | 872 | "commit-graph",
|
792 | 873 | maintenance_task_commit_graph,
|
| 874 | + should_write_commit_graph, |
793 | 875 | },
|
794 | 876 | };
|
795 | 877 |
|
|
0 commit comments