rev-list.con commit [PATCH] Tidy up some rev-list-related stuff (17ebe97)
   1#include "cache.h"
   2#include "commit.h"
   3#include "epoch.h"
   4
   5#define SEEN            (1u << 0)
   6#define INTERESTING     (1u << 1)
   7
   8static const char rev_list_usage[] =
   9        "usage: git-rev-list [OPTION] commit-id <commit-id>\n"
  10                      "  --max-count=nr\n"
  11                      "  --max-age=epoch\n"
  12                      "  --min-age=epoch\n"
  13                      "  --header\n"
  14                      "  --pretty\n"
  15                      "  --merge-order [ --show-breaks ]";
  16
  17static int verbose_header = 0;
  18static int show_parents = 0;
  19static int hdr_termination = 0;
  20static const char *prefix = "";
  21static unsigned long max_age = -1;
  22static unsigned long min_age = -1;
  23static int max_count = -1;
  24static enum cmit_fmt commit_format = CMIT_FMT_RAW;
  25static int merge_order = 0;
  26static int show_breaks = 0;
  27
  28static void show_commit(struct commit *commit)
  29{
  30        if (show_breaks) {
  31                prefix = "| ";
  32                if (commit->object.flags & DISCONTINUITY) {
  33                        prefix = "^ ";     
  34                } else if (commit->object.flags & BOUNDARY) {
  35                        prefix = "= ";
  36                } 
  37        }                       
  38        printf("%s%s", prefix, sha1_to_hex(commit->object.sha1));
  39        if (show_parents) {
  40                struct commit_list *parents = commit->parents;
  41                while (parents) {
  42                        printf(" %s", sha1_to_hex(parents->item->object.sha1));
  43                        parents = parents->next;
  44                }
  45        }
  46        putchar('\n');
  47        if (verbose_header) {
  48                static char pretty_header[16384];
  49                pretty_print_commit(commit_format, commit->buffer, ~0, pretty_header, sizeof(pretty_header));
  50                printf("%s%c", pretty_header, hdr_termination);
  51        }       
  52}
  53
  54static int filter_commit(struct commit * commit)
  55{
  56        if (commit->object.flags & UNINTERESTING)
  57                return CONTINUE;
  58        if (min_age != -1 && (commit->date > min_age))
  59                return CONTINUE;
  60        if (max_age != -1 && (commit->date < max_age))
  61                return STOP;
  62        if (max_count != -1 && !max_count--)
  63                return STOP;
  64
  65        return DO;
  66}
  67
  68static int process_commit(struct commit * commit)
  69{
  70        int action=filter_commit(commit);
  71
  72        if (action == STOP) {
  73                return STOP;
  74        }
  75
  76        if (action == CONTINUE) {
  77                return CONTINUE;
  78        }
  79
  80        show_commit(commit);
  81
  82        return CONTINUE;
  83}
  84
  85static void show_commit_list(struct commit_list *list)
  86{
  87        while (list) {
  88                struct commit *commit = pop_most_recent_commit(&list, SEEN);
  89
  90                if (process_commit(commit) == STOP)
  91                        break;
  92        }
  93}
  94
  95static void mark_parents_uninteresting(struct commit *commit)
  96{
  97        struct commit_list *parents = commit->parents;
  98
  99        while (parents) {
 100                struct commit *commit = parents->item;
 101                commit->object.flags |= UNINTERESTING;
 102                parents = parents->next;
 103        }
 104}
 105
 106static int everybody_uninteresting(struct commit_list *list)
 107{
 108        while (list) {
 109                struct commit *commit = list->item;
 110                list = list->next;
 111                if (commit->object.flags & UNINTERESTING)
 112                        continue;
 113                return 0;
 114        }
 115        return 1;
 116}
 117
 118struct commit_list *limit_list(struct commit_list *list)
 119{
 120        struct commit_list *newlist = NULL;
 121        struct commit_list **p = &newlist;
 122        do {
 123                struct commit *commit = pop_most_recent_commit(&list, SEEN);
 124                struct object *obj = &commit->object;
 125
 126                if (obj->flags & UNINTERESTING) {
 127                        mark_parents_uninteresting(commit);
 128                        if (everybody_uninteresting(list))
 129                                break;
 130                        continue;
 131                }
 132                p = &commit_list_insert(commit, p)->next;
 133        } while (list);
 134        return newlist;
 135}
 136
 137static enum cmit_fmt get_commit_format(const char *arg)
 138{
 139        if (!*arg)
 140                return CMIT_FMT_DEFAULT;
 141        if (!strcmp(arg, "=raw"))
 142                return CMIT_FMT_RAW;
 143        if (!strcmp(arg, "=medium"))
 144                return CMIT_FMT_MEDIUM;
 145        if (!strcmp(arg, "=short"))
 146                return CMIT_FMT_SHORT;
 147        usage(rev_list_usage);  
 148}                       
 149
 150
 151int main(int argc, char **argv)
 152{
 153        struct commit_list *list = NULL;
 154        int i, limited = 0;
 155
 156        for (i = 1 ; i < argc; i++) {
 157                int flags;
 158                char *arg = argv[i];
 159                unsigned char sha1[20];
 160                struct commit *commit;
 161
 162                if (!strncmp(arg, "--max-count=", 12)) {
 163                        max_count = atoi(arg + 12);
 164                        continue;
 165                }
 166                if (!strncmp(arg, "--max-age=", 10)) {
 167                        max_age = atoi(arg + 10);
 168                        continue;
 169                }
 170                if (!strncmp(arg, "--min-age=", 10)) {
 171                        min_age = atoi(arg + 10);
 172                        continue;
 173                }
 174                if (!strcmp(arg, "--header")) {
 175                        verbose_header = 1;
 176                        continue;
 177                }
 178                if (!strncmp(arg, "--pretty", 8)) {
 179                        commit_format = get_commit_format(arg+8);
 180                        verbose_header = 1;
 181                        hdr_termination = '\n';
 182                        prefix = "commit ";
 183                        continue;
 184                }
 185                if (!strcmp(arg, "--parents")) {
 186                        show_parents = 1;
 187                        continue;
 188                }
 189                if (!strncmp(arg, "--merge-order", 13)) {
 190                        merge_order = 1;
 191                        continue;
 192                }
 193                if (!strncmp(arg, "--show-breaks", 13)) {
 194                        show_breaks = 1;
 195                        continue;
 196                }
 197
 198                flags = 0;
 199                if (*arg == '^') {
 200                        flags = UNINTERESTING;
 201                        arg++;
 202                        limited = 1;
 203                }
 204                if (get_sha1(arg, sha1) || (show_breaks && !merge_order))
 205                        usage(rev_list_usage);
 206                commit = lookup_commit_reference(sha1);
 207                if (!commit || parse_commit(commit) < 0)
 208                        die("bad commit object %s", arg);
 209                commit->object.flags |= flags;
 210                commit_list_insert(commit, &list);
 211        }
 212
 213        if (!list)
 214                usage(rev_list_usage);
 215
 216        if (!merge_order) {             
 217                if (limited)
 218                        list = limit_list(list);
 219                show_commit_list(list);
 220        } else {
 221                if (sort_list_in_merge_order(list, &process_commit)) {
 222                          die("merge order sort failed\n");
 223                }
 224        }
 225
 226        return 0;
 227}