]>
Commit | Line | Data |
---|---|---|
40e88b95 | 1 | #define _XOPEN_SOURCE /* glibc2 needs this */ |
27de946d | 2 | #define _BSD_SOURCE /* for tm.tm_gmtoff */ |
40e88b95 LT |
3 | #include <time.h> |
4 | #include <ctype.h> | |
458754a9 | 5 | |
84fe9720 | 6 | #include "cache.h" |
5873b67e | 7 | #include "commit.h" |
84fe9720 | 8 | |
28258afe | 9 | /* |
458754a9 LT |
10 | * revision.h leaves the low 16 bits of the "flags" field of the |
11 | * revision data structure unused. We use it for a "reachable from | |
12 | * this commit <N>" bitmask. | |
28258afe | 13 | */ |
458754a9 | 14 | #define MAX_COMMITS 16 |
28258afe LT |
15 | |
16 | static int show_edges = 0; | |
727ff277 | 17 | static int basemask = 0; |
97d9c3cd | 18 | |
84fe9720 LT |
19 | static void read_cache_file(const char *path) |
20 | { | |
5873b67e | 21 | die("no revtree cache file yet"); |
84fe9720 LT |
22 | } |
23 | ||
24 | /* | |
28258afe LT |
25 | * Some revisions are less interesting than others. |
26 | * | |
27 | * For example, if we use a cache-file, that one may contain | |
28 | * revisions that were never used. They are never interesting. | |
29 | * | |
30 | * And sometimes we're only interested in "edge" commits, ie | |
31 | * places where the marking changes between parent and child. | |
32 | */ | |
5873b67e | 33 | static int interesting(struct commit *rev) |
28258afe | 34 | { |
5873b67e | 35 | unsigned mask = rev->object.flags; |
28258afe LT |
36 | |
37 | if (!mask) | |
38 | return 0; | |
39 | if (show_edges) { | |
5873b67e | 40 | struct commit_list *p = rev->parents; |
28258afe | 41 | while (p) { |
5873b67e | 42 | if (mask != p->item->object.flags) |
28258afe LT |
43 | return 1; |
44 | p = p->next; | |
45 | } | |
46 | return 0; | |
47 | } | |
727ff277 DW |
48 | if (mask & basemask) |
49 | return 0; | |
50 | ||
28258afe LT |
51 | return 1; |
52 | } | |
53 | ||
5873b67e DB |
54 | void process_commit(unsigned char *sha1) |
55 | { | |
56 | struct commit_list *parents; | |
57 | struct commit *obj = lookup_commit(sha1); | |
58 | parse_commit(obj); | |
59 | ||
60 | parents = obj->parents; | |
61 | while (parents) { | |
62 | process_commit(parents->item->object.sha1); | |
63 | parents = parents->next; | |
64 | } | |
65 | } | |
66 | ||
28258afe LT |
67 | /* |
68 | * Usage: rev-tree [--edges] [--cache <cache-file>] <commit-id> [<commit-id2>] | |
84fe9720 LT |
69 | * |
70 | * The cache-file can be quite important for big trees. This is an | |
71 | * expensive operation if you have to walk the whole chain of | |
72 | * parents in a tree with a long revision history. | |
73 | */ | |
74 | int main(int argc, char **argv) | |
75 | { | |
76 | int i; | |
28258afe LT |
77 | int nr = 0; |
78 | unsigned char sha1[MAX_COMMITS][20]; | |
84fe9720 | 79 | |
28258afe LT |
80 | /* |
81 | * First - pick up all the revisions we can (both from | |
82 | * caches and from commit file chains). | |
83 | */ | |
84 | for (i = 1; i < argc ; i++) { | |
85 | char *arg = argv[i]; | |
86 | ||
87 | if (!strcmp(arg, "--cache")) { | |
84fe9720 | 88 | read_cache_file(argv[2]); |
28258afe LT |
89 | i++; |
90 | continue; | |
91 | } | |
92 | ||
93 | if (!strcmp(arg, "--edges")) { | |
94 | show_edges = 1; | |
84fe9720 LT |
95 | continue; |
96 | } | |
28258afe | 97 | |
727ff277 DW |
98 | if (arg[0] == '^') { |
99 | arg++; | |
100 | basemask |= 1<<nr; | |
101 | } | |
28258afe LT |
102 | if (nr >= MAX_COMMITS || get_sha1_hex(arg, sha1[nr])) |
103 | usage("rev-tree [--edges] [--cache <cache-file>] <commit-id> [<commit-id>]"); | |
5873b67e | 104 | process_commit(sha1[nr]); |
28258afe | 105 | nr++; |
84fe9720 LT |
106 | } |
107 | ||
28258afe LT |
108 | /* |
109 | * Now we have the maximal tree. Walk the different sha files back to the root. | |
110 | */ | |
111 | for (i = 0; i < nr; i++) | |
5873b67e | 112 | mark_reachable(&lookup_commit(sha1[i])->object, 1 << i); |
28258afe LT |
113 | |
114 | /* | |
115 | * Now print out the results.. | |
116 | */ | |
5873b67e DB |
117 | for (i = 0; i < nr_objs; i++) { |
118 | struct object *obj = objs[i]; | |
119 | struct commit *commit; | |
120 | struct commit_list *p; | |
121 | ||
122 | if (obj->type != commit_type) | |
123 | continue; | |
124 | ||
125 | commit = (struct commit *) obj; | |
97d9c3cd | 126 | |
5873b67e | 127 | if (!interesting(commit)) |
28258afe LT |
128 | continue; |
129 | ||
5873b67e DB |
130 | printf("%lu %s:%d", commit->date, sha1_to_hex(obj->sha1), |
131 | obj->flags); | |
132 | p = commit->parents; | |
97d9c3cd | 133 | while (p) { |
5873b67e DB |
134 | printf(" %s:%d", sha1_to_hex(p->item->object.sha1), |
135 | p->item->object.flags); | |
97d9c3cd LT |
136 | p = p->next; |
137 | } | |
138 | printf("\n"); | |
84fe9720 LT |
139 | } |
140 | return 0; | |
141 | } |