|
26 | 26 | #include "argv-array.h"
|
27 | 27 | #include "commit-reach.h"
|
28 | 28 | #include "commit-graph.h"
|
| 29 | +#include "prio-queue.h" |
29 | 30 |
|
30 | 31 | volatile show_early_output_fn_t show_early_output;
|
31 | 32 |
|
@@ -2892,30 +2893,213 @@ static int mark_uninteresting(const struct object_id *oid,
|
2892 | 2893 | return 0;
|
2893 | 2894 | }
|
2894 | 2895 |
|
2895 |
| -struct topo_walk_info {}; |
| 2896 | +define_commit_slab(indegree_slab, int); |
| 2897 | + |
| 2898 | +struct topo_walk_info { |
| 2899 | + uint32_t min_generation; |
| 2900 | + struct prio_queue explore_queue; |
| 2901 | + struct prio_queue indegree_queue; |
| 2902 | + struct prio_queue topo_queue; |
| 2903 | + struct indegree_slab indegree; |
| 2904 | + struct author_date_slab author_date; |
| 2905 | +}; |
| 2906 | + |
| 2907 | +static inline void test_flag_and_insert(struct prio_queue *q, struct commit *c, int flag) |
| 2908 | +{ |
| 2909 | + if (c->object.flags & flag) |
| 2910 | + return; |
| 2911 | + |
| 2912 | + c->object.flags |= flag; |
| 2913 | + prio_queue_put(q, c); |
| 2914 | +} |
| 2915 | + |
| 2916 | +static void explore_walk_step(struct rev_info *revs) |
| 2917 | +{ |
| 2918 | + struct topo_walk_info *info = revs->topo_walk_info; |
| 2919 | + struct commit_list *p; |
| 2920 | + struct commit *c = prio_queue_get(&info->explore_queue); |
| 2921 | + |
| 2922 | + if (!c) |
| 2923 | + return; |
| 2924 | + |
| 2925 | + if (parse_commit_gently(c, 1) < 0) |
| 2926 | + return; |
| 2927 | + |
| 2928 | + if (revs->max_age != -1 && (c->date < revs->max_age)) |
| 2929 | + c->object.flags |= UNINTERESTING; |
| 2930 | + |
| 2931 | + if (add_parents_to_list(revs, c, NULL, NULL) < 0) |
| 2932 | + return; |
| 2933 | + |
| 2934 | + if (c->object.flags & UNINTERESTING) |
| 2935 | + mark_parents_uninteresting(c); |
| 2936 | + |
| 2937 | + for (p = c->parents; p; p = p->next) |
| 2938 | + test_flag_and_insert(&info->explore_queue, p->item, TOPO_WALK_EXPLORED); |
| 2939 | +} |
| 2940 | + |
| 2941 | +static void explore_to_depth(struct rev_info *revs, |
| 2942 | + uint32_t gen) |
| 2943 | +{ |
| 2944 | + struct topo_walk_info *info = revs->topo_walk_info; |
| 2945 | + struct commit *c; |
| 2946 | + while ((c = prio_queue_peek(&info->explore_queue)) && |
| 2947 | + c->generation >= gen) |
| 2948 | + explore_walk_step(revs); |
| 2949 | +} |
| 2950 | + |
| 2951 | +static void indegree_walk_step(struct rev_info *revs) |
| 2952 | +{ |
| 2953 | + struct commit_list *p; |
| 2954 | + struct topo_walk_info *info = revs->topo_walk_info; |
| 2955 | + struct commit *c = prio_queue_get(&info->indegree_queue); |
| 2956 | + |
| 2957 | + if (!c) |
| 2958 | + return; |
| 2959 | + |
| 2960 | + if (parse_commit_gently(c, 1) < 0) |
| 2961 | + return; |
| 2962 | + |
| 2963 | + explore_to_depth(revs, c->generation); |
| 2964 | + |
| 2965 | + if (parse_commit_gently(c, 1) < 0) |
| 2966 | + return; |
| 2967 | + |
| 2968 | + for (p = c->parents; p; p = p->next) { |
| 2969 | + struct commit *parent = p->item; |
| 2970 | + int *pi = indegree_slab_at(&info->indegree, parent); |
| 2971 | + |
| 2972 | + if (*pi) |
| 2973 | + (*pi)++; |
| 2974 | + else |
| 2975 | + *pi = 2; |
| 2976 | + |
| 2977 | + test_flag_and_insert(&info->indegree_queue, parent, TOPO_WALK_INDEGREE); |
| 2978 | + |
| 2979 | + if (revs->first_parent_only) |
| 2980 | + return; |
| 2981 | + } |
| 2982 | +} |
| 2983 | + |
| 2984 | +static void compute_indegrees_to_depth(struct rev_info *revs) |
| 2985 | +{ |
| 2986 | + struct topo_walk_info *info = revs->topo_walk_info; |
| 2987 | + struct commit *c; |
| 2988 | + while ((c = prio_queue_peek(&info->indegree_queue)) && |
| 2989 | + c->generation >= info->min_generation) |
| 2990 | + indegree_walk_step(revs); |
| 2991 | +} |
2896 | 2992 |
|
2897 | 2993 | static void init_topo_walk(struct rev_info *revs)
|
2898 | 2994 | {
|
2899 | 2995 | struct topo_walk_info *info;
|
| 2996 | + struct commit_list *list; |
2900 | 2997 | revs->topo_walk_info = xmalloc(sizeof(struct topo_walk_info));
|
2901 | 2998 | info = revs->topo_walk_info;
|
2902 | 2999 | memset(info, 0, sizeof(struct topo_walk_info));
|
2903 | 3000 |
|
2904 |
| - limit_list(revs); |
2905 |
| - sort_in_topological_order(&revs->commits, revs->sort_order); |
| 3001 | + init_indegree_slab(&info->indegree); |
| 3002 | + memset(&info->explore_queue, '\0', sizeof(info->explore_queue)); |
| 3003 | + memset(&info->indegree_queue, '\0', sizeof(info->indegree_queue)); |
| 3004 | + memset(&info->topo_queue, '\0', sizeof(info->topo_queue)); |
| 3005 | + |
| 3006 | + switch (revs->sort_order) { |
| 3007 | + default: /* REV_SORT_IN_GRAPH_ORDER */ |
| 3008 | + info->topo_queue.compare = NULL; |
| 3009 | + break; |
| 3010 | + case REV_SORT_BY_COMMIT_DATE: |
| 3011 | + info->topo_queue.compare = compare_commits_by_commit_date; |
| 3012 | + break; |
| 3013 | + case REV_SORT_BY_AUTHOR_DATE: |
| 3014 | + init_author_date_slab(&info->author_date); |
| 3015 | + info->topo_queue.compare = compare_commits_by_author_date; |
| 3016 | + info->topo_queue.cb_data = &info->author_date; |
| 3017 | + break; |
| 3018 | + } |
| 3019 | + |
| 3020 | + info->explore_queue.compare = compare_commits_by_gen_then_commit_date; |
| 3021 | + info->indegree_queue.compare = compare_commits_by_gen_then_commit_date; |
| 3022 | + |
| 3023 | + info->min_generation = GENERATION_NUMBER_INFINITY; |
| 3024 | + for (list = revs->commits; list; list = list->next) { |
| 3025 | + struct commit *c = list->item; |
| 3026 | + test_flag_and_insert(&info->explore_queue, c, TOPO_WALK_EXPLORED); |
| 3027 | + test_flag_and_insert(&info->indegree_queue, c, TOPO_WALK_INDEGREE); |
| 3028 | + |
| 3029 | + if (parse_commit_gently(c, 1)) |
| 3030 | + continue; |
| 3031 | + if (c->generation < info->min_generation) |
| 3032 | + info->min_generation = c->generation; |
| 3033 | + } |
| 3034 | + |
| 3035 | + for (list = revs->commits; list; list = list->next) { |
| 3036 | + struct commit *c = list->item; |
| 3037 | + *(indegree_slab_at(&info->indegree, c)) = 1; |
| 3038 | + |
| 3039 | + if (revs->sort_order == REV_SORT_BY_AUTHOR_DATE) |
| 3040 | + record_author_date(&info->author_date, c); |
| 3041 | + } |
| 3042 | + compute_indegrees_to_depth(revs); |
| 3043 | + |
| 3044 | + for (list = revs->commits; list; list = list->next) { |
| 3045 | + struct commit *c = list->item; |
| 3046 | + |
| 3047 | + if (*(indegree_slab_at(&info->indegree, c)) == 1) |
| 3048 | + prio_queue_put(&info->topo_queue, c); |
| 3049 | + } |
| 3050 | + |
| 3051 | + /* |
| 3052 | + * This is unfortunate; the initial tips need to be shown |
| 3053 | + * in the order given from the revision traversal machinery. |
| 3054 | + */ |
| 3055 | + if (revs->sort_order == REV_SORT_IN_GRAPH_ORDER) |
| 3056 | + prio_queue_reverse(&info->topo_queue); |
2906 | 3057 | }
|
2907 | 3058 |
|
2908 | 3059 | static struct commit *next_topo_commit(struct rev_info *revs)
|
2909 | 3060 | {
|
2910 |
| - return pop_commit(&revs->commits); |
| 3061 | + struct commit *c; |
| 3062 | + struct topo_walk_info *info = revs->topo_walk_info; |
| 3063 | + |
| 3064 | + /* pop next off of topo_queue */ |
| 3065 | + c = prio_queue_get(&info->topo_queue); |
| 3066 | + |
| 3067 | + if (c) |
| 3068 | + *(indegree_slab_at(&info->indegree, c)) = 0; |
| 3069 | + |
| 3070 | + return c; |
2911 | 3071 | }
|
2912 | 3072 |
|
2913 | 3073 | static void expand_topo_walk(struct rev_info *revs, struct commit *commit)
|
2914 | 3074 | {
|
2915 |
| - if (add_parents_to_list(revs, commit, &revs->commits, NULL) < 0) { |
| 3075 | + struct commit_list *p; |
| 3076 | + struct topo_walk_info *info = revs->topo_walk_info; |
| 3077 | + if (add_parents_to_list(revs, commit, NULL, NULL) < 0) { |
2916 | 3078 | if (!revs->ignore_missing_links)
|
2917 | 3079 | die("Failed to traverse parents of commit %s",
|
2918 |
| - oid_to_hex(&commit->object.oid)); |
| 3080 | + oid_to_hex(&commit->object.oid)); |
| 3081 | + } |
| 3082 | + |
| 3083 | + for (p = commit->parents; p; p = p->next) { |
| 3084 | + struct commit *parent = p->item; |
| 3085 | + int *pi; |
| 3086 | + |
| 3087 | + if (parse_commit_gently(parent, 1) < 0) |
| 3088 | + continue; |
| 3089 | + |
| 3090 | + if (parent->generation < info->min_generation) { |
| 3091 | + info->min_generation = parent->generation; |
| 3092 | + compute_indegrees_to_depth(revs); |
| 3093 | + } |
| 3094 | + |
| 3095 | + pi = indegree_slab_at(&info->indegree, parent); |
| 3096 | + |
| 3097 | + (*pi)--; |
| 3098 | + if (*pi == 1) |
| 3099 | + prio_queue_put(&info->topo_queue, parent); |
| 3100 | + |
| 3101 | + if (revs->first_parent_only) |
| 3102 | + return; |
2919 | 3103 | }
|
2920 | 3104 | }
|
2921 | 3105 |
|
|
0 commit comments