Linus Torvalds | 9174026 | 2005-04-09 20:00:54 | [diff] [blame] | 1 | #include "cache.h" |
Junio C Hamano | 3ebfd4a | 2005-04-27 16:21:00 | [diff] [blame] | 2 | #include "diff.h" |
Linus Torvalds | e3bc7a3 | 2005-06-01 15:34:23 | [diff] [blame] | 3 | #include "commit.h" |
Linus Torvalds | 9174026 | 2005-04-09 20:00:54 | [diff] [blame] | 4 | |
Linus Torvalds | dc26bd8 | 2005-05-19 20:44:29 | [diff] [blame] | 5 | static int show_root_diff = 0; |
Linus Torvalds | cee99d2 | 2005-05-06 18:42:47 | [diff] [blame] | 6 | static int verbose_header = 0; |
Linus Torvalds | e0965d8 | 2005-05-06 17:03:17 | [diff] [blame] | 7 | static int ignore_merges = 1; |
Linus Torvalds | e0965d8 | 2005-05-06 17:03:17 | [diff] [blame] | 8 | static int read_stdin = 0; |
Junio C Hamano | 6b5ee13 | 2005-09-21 07:00:47 | [diff] [blame] | 9 | |
Linus Torvalds | f4f21ce | 2005-05-06 17:56:35 | [diff] [blame] | 10 | static const char *header = NULL; |
Linus Torvalds | cee99d2 | 2005-05-06 18:42:47 | [diff] [blame] | 11 | static const char *header_prefix = ""; |
Linus Torvalds | 000182e | 2005-06-05 16:02:03 | [diff] [blame] | 12 | static enum cmit_fmt commit_format = CMIT_FMT_RAW; |
Linus Torvalds | 9174026 | 2005-04-09 20:00:54 | [diff] [blame] | 13 | |
Linus Torvalds | ac1b3d1 | 2005-10-21 04:05:05 | [diff] [blame] | 14 | static struct diff_options diff_options; |
Linus Torvalds | 73134b6 | 2005-04-10 21:03:58 | [diff] [blame] | 15 | |
Junio C Hamano | 6b5ee13 | 2005-09-21 07:00:47 | [diff] [blame] | 16 | static void call_diff_setup_done(void) |
Junio C Hamano | 38c6f78 | 2005-05-22 02:40:36 | [diff] [blame] | 17 | { |
Junio C Hamano | 6b5ee13 | 2005-09-21 07:00:47 | [diff] [blame] | 18 | diff_setup_done(&diff_options); |
Junio C Hamano | 38c6f78 | 2005-05-22 02:40:36 | [diff] [blame] | 19 | } |
| 20 | |
Linus Torvalds | 09d74b3 | 2005-05-22 21:33:43 | [diff] [blame] | 21 | static int call_diff_flush(void) |
Junio C Hamano | 38c6f78 | 2005-05-22 02:40:36 | [diff] [blame] | 22 | { |
Junio C Hamano | 6b5ee13 | 2005-09-21 07:00:47 | [diff] [blame] | 23 | diffcore_std(&diff_options); |
Linus Torvalds | 9ab55bd | 2005-05-23 23:37:47 | [diff] [blame] | 24 | if (diff_queue_is_empty()) { |
Junio C Hamano | 6b5ee13 | 2005-09-21 07:00:47 | [diff] [blame] | 25 | int saved_fmt = diff_options.output_format; |
| 26 | diff_options.output_format = DIFF_FORMAT_NO_OUTPUT; |
| 27 | diff_flush(&diff_options); |
| 28 | diff_options.output_format = saved_fmt; |
Linus Torvalds | 9ab55bd | 2005-05-23 23:37:47 | [diff] [blame] | 29 | return 0; |
Junio C Hamano | 6b14d7f | 2005-05-22 17:04:37 | [diff] [blame] | 30 | } |
Junio C Hamano | 6b14d7f | 2005-05-22 17:04:37 | [diff] [blame] | 31 | if (header) { |
Junio C Hamano | 6b5ee13 | 2005-09-21 07:00:47 | [diff] [blame] | 32 | printf("%s%c", header, diff_options.line_termination); |
Junio C Hamano | 6b14d7f | 2005-05-22 17:04:37 | [diff] [blame] | 33 | header = NULL; |
| 34 | } |
Junio C Hamano | 6b5ee13 | 2005-09-21 07:00:47 | [diff] [blame] | 35 | diff_flush(&diff_options); |
Junio C Hamano | 6b14d7f | 2005-05-22 17:04:37 | [diff] [blame] | 36 | return 1; |
Junio C Hamano | 38c6f78 | 2005-05-22 02:40:36 | [diff] [blame] | 37 | } |
| 38 | |
Junio C Hamano | 5c97558 | 2005-05-19 10:32:35 | [diff] [blame] | 39 | static int diff_tree_sha1_top(const unsigned char *old, |
| 40 | const unsigned char *new, const char *base) |
| 41 | { |
| 42 | int ret; |
Junio C Hamano | 57fe64a | 2005-05-20 02:00:36 | [diff] [blame] | 43 | |
Junio C Hamano | 6b5ee13 | 2005-09-21 07:00:47 | [diff] [blame] | 44 | call_diff_setup_done(); |
Linus Torvalds | ac1b3d1 | 2005-10-21 04:05:05 | [diff] [blame] | 45 | ret = diff_tree_sha1(old, new, base, &diff_options); |
Junio C Hamano | 38c6f78 | 2005-05-22 02:40:36 | [diff] [blame] | 46 | call_diff_flush(); |
Junio C Hamano | 5c97558 | 2005-05-19 10:32:35 | [diff] [blame] | 47 | return ret; |
| 48 | } |
| 49 | |
Linus Torvalds | dc26bd8 | 2005-05-19 20:44:29 | [diff] [blame] | 50 | static int diff_root_tree(const unsigned char *new, const char *base) |
| 51 | { |
| 52 | int retval; |
| 53 | void *tree; |
Linus Torvalds | ac1b3d1 | 2005-10-21 04:05:05 | [diff] [blame] | 54 | struct tree_desc empty, real; |
Linus Torvalds | dc26bd8 | 2005-05-19 20:44:29 | [diff] [blame] | 55 | |
Junio C Hamano | 6b5ee13 | 2005-09-21 07:00:47 | [diff] [blame] | 56 | call_diff_setup_done(); |
Linus Torvalds | ac1b3d1 | 2005-10-21 04:05:05 | [diff] [blame] | 57 | tree = read_object_with_reference(new, "tree", &real.size, NULL); |
Linus Torvalds | dc26bd8 | 2005-05-19 20:44:29 | [diff] [blame] | 58 | if (!tree) |
| 59 | die("unable to read root tree (%s)", sha1_to_hex(new)); |
Linus Torvalds | ac1b3d1 | 2005-10-21 04:05:05 | [diff] [blame] | 60 | real.buf = tree; |
| 61 | |
| 62 | empty.buf = ""; |
| 63 | empty.size = 0; |
| 64 | retval = diff_tree(&empty, &real, base, &diff_options); |
Linus Torvalds | dc26bd8 | 2005-05-19 20:44:29 | [diff] [blame] | 65 | free(tree); |
Junio C Hamano | 38c6f78 | 2005-05-22 02:40:36 | [diff] [blame] | 66 | call_diff_flush(); |
Linus Torvalds | dc26bd8 | 2005-05-19 20:44:29 | [diff] [blame] | 67 | return retval; |
| 68 | } |
| 69 | |
Linus Torvalds | 1809266 | 2005-06-23 20:56:55 | [diff] [blame] | 70 | static const char *generate_header(const char *commit, const char *parent, const char *msg, unsigned long len) |
Linus Torvalds | cee99d2 | 2005-05-06 18:42:47 | [diff] [blame] | 71 | { |
Linus Torvalds | 3258c90 | 2005-05-21 18:04:19 | [diff] [blame] | 72 | static char this_header[16384]; |
Linus Torvalds | cee99d2 | 2005-05-06 18:42:47 | [diff] [blame] | 73 | int offset; |
| 74 | |
Linus Torvalds | 1809266 | 2005-06-23 20:56:55 | [diff] [blame] | 75 | if (!verbose_header) |
| 76 | return commit; |
Linus Torvalds | cee99d2 | 2005-05-06 18:42:47 | [diff] [blame] | 77 | |
Linus Torvalds | 1809266 | 2005-06-23 20:56:55 | [diff] [blame] | 78 | offset = sprintf(this_header, "%s%s (from %s)\n", header_prefix, commit, parent); |
| 79 | offset += pretty_print_commit(commit_format, msg, len, this_header + offset, sizeof(this_header) - offset); |
Linus Torvalds | cee99d2 | 2005-05-06 18:42:47 | [diff] [blame] | 80 | return this_header; |
| 81 | } |
| 82 | |
Linus Torvalds | b11645b | 2005-05-18 20:06:47 | [diff] [blame] | 83 | static int diff_tree_commit(const unsigned char *commit, const char *name) |
| 84 | { |
| 85 | unsigned long size, offset; |
| 86 | char *buf = read_object_with_reference(commit, "commit", &size, NULL); |
| 87 | |
| 88 | if (!buf) |
| 89 | return -1; |
| 90 | |
Linus Torvalds | 7384889 | 2005-05-18 20:43:58 | [diff] [blame] | 91 | if (!name) { |
| 92 | static char commit_name[60]; |
| 93 | strcpy(commit_name, sha1_to_hex(commit)); |
| 94 | name = commit_name; |
| 95 | } |
| 96 | |
Linus Torvalds | dc26bd8 | 2005-05-19 20:44:29 | [diff] [blame] | 97 | /* Root commit? */ |
| 98 | if (show_root_diff && memcmp(buf + 46, "parent ", 7)) { |
| 99 | header = generate_header(name, "root", buf, size); |
| 100 | diff_root_tree(commit, ""); |
| 101 | } |
| 102 | |
| 103 | /* More than one parent? */ |
| 104 | if (ignore_merges) { |
| 105 | if (!memcmp(buf + 46 + 48, "parent ", 7)) |
| 106 | return 0; |
| 107 | } |
| 108 | |
Linus Torvalds | b11645b | 2005-05-18 20:06:47 | [diff] [blame] | 109 | offset = 46; |
| 110 | while (offset + 48 < size && !memcmp(buf + offset, "parent ", 7)) { |
| 111 | unsigned char parent[20]; |
| 112 | if (get_sha1_hex(buf + offset + 7, parent)) |
| 113 | return -1; |
| 114 | header = generate_header(name, sha1_to_hex(parent), buf, size); |
Junio C Hamano | 5c97558 | 2005-05-19 10:32:35 | [diff] [blame] | 115 | diff_tree_sha1_top(parent, commit, ""); |
Linus Torvalds | d6db010 | 2005-05-21 22:42:53 | [diff] [blame] | 116 | if (!header && verbose_header) { |
Linus Torvalds | b11645b | 2005-05-18 20:06:47 | [diff] [blame] | 117 | header_prefix = "\ndiff-tree "; |
Linus Torvalds | d6db010 | 2005-05-21 22:42:53 | [diff] [blame] | 118 | /* |
| 119 | * Don't print multiple merge entries if we |
| 120 | * don't print the diffs. |
| 121 | */ |
Linus Torvalds | d6db010 | 2005-05-21 22:42:53 | [diff] [blame] | 122 | } |
Linus Torvalds | b11645b | 2005-05-18 20:06:47 | [diff] [blame] | 123 | offset += 48; |
| 124 | } |
Junio C Hamano | 5098baf | 2005-09-15 23:13:43 | [diff] [blame] | 125 | free(buf); |
Linus Torvalds | b11645b | 2005-05-18 20:06:47 | [diff] [blame] | 126 | return 0; |
| 127 | } |
| 128 | |
Linus Torvalds | e0965d8 | 2005-05-06 17:03:17 | [diff] [blame] | 129 | static int diff_tree_stdin(char *line) |
| 130 | { |
| 131 | int len = strlen(line); |
| 132 | unsigned char commit[20], parent[20]; |
Linus Torvalds | cee99d2 | 2005-05-06 18:42:47 | [diff] [blame] | 133 | static char this_header[1000]; |
Linus Torvalds | e0965d8 | 2005-05-06 17:03:17 | [diff] [blame] | 134 | |
| 135 | if (!len || line[len-1] != '\n') |
| 136 | return -1; |
| 137 | line[len-1] = 0; |
| 138 | if (get_sha1_hex(line, commit)) |
| 139 | return -1; |
| 140 | if (isspace(line[40]) && !get_sha1_hex(line+41, parent)) { |
Linus Torvalds | f4f21ce | 2005-05-06 17:56:35 | [diff] [blame] | 141 | line[40] = 0; |
Linus Torvalds | e0965d8 | 2005-05-06 17:03:17 | [diff] [blame] | 142 | line[81] = 0; |
Linus Torvalds | f4f21ce | 2005-05-06 17:56:35 | [diff] [blame] | 143 | sprintf(this_header, "%s (from %s)\n", line, line+41); |
| 144 | header = this_header; |
Junio C Hamano | 5c97558 | 2005-05-19 10:32:35 | [diff] [blame] | 145 | return diff_tree_sha1_top(parent, commit, ""); |
Linus Torvalds | e0965d8 | 2005-05-06 17:03:17 | [diff] [blame] | 146 | } |
Linus Torvalds | e0965d8 | 2005-05-06 17:03:17 | [diff] [blame] | 147 | line[40] = 0; |
Linus Torvalds | b11645b | 2005-05-18 20:06:47 | [diff] [blame] | 148 | return diff_tree_commit(commit, line); |
Linus Torvalds | e0965d8 | 2005-05-06 17:03:17 | [diff] [blame] | 149 | } |
| 150 | |
Petr Baudis | 4d1f119 | 2005-07-29 09:01:26 | [diff] [blame] | 151 | static const char diff_tree_usage[] = |
Chris Shoemaker | 50b8e35 | 2005-10-28 17:04:49 | [diff] [blame] | 152 | "git-diff-tree [--stdin] [-m] [-s] [-v] [--pretty] [-t] [-r] [--root] " |
| 153 | "[<common diff options>] <tree-ish> [<tree-ish>] [<path>...]\n" |
| 154 | " -r diff recursively\n" |
| 155 | " --root include the initial commit as diff against /dev/null\n" |
Junio C Hamano | dda2d79 | 2005-07-13 19:52:35 | [diff] [blame] | 156 | COMMON_DIFF_OPTIONS_HELP; |
Junio C Hamano | a8db165 | 2005-06-13 00:44:21 | [diff] [blame] | 157 | |
Junio C Hamano | 6b5ee13 | 2005-09-21 07:00:47 | [diff] [blame] | 158 | int main(int argc, const char **argv) |
Linus Torvalds | 73134b6 | 2005-04-10 21:03:58 | [diff] [blame] | 159 | { |
Linus Torvalds | 0a8365a | 2005-05-18 20:10:17 | [diff] [blame] | 160 | int nr_sha1; |
Linus Torvalds | e0965d8 | 2005-05-06 17:03:17 | [diff] [blame] | 161 | char line[1000]; |
Linus Torvalds | 0a8365a | 2005-05-18 20:10:17 | [diff] [blame] | 162 | unsigned char sha1[2][20]; |
Linus Torvalds | d288a70 | 2005-08-17 01:06:34 | [diff] [blame] | 163 | const char *prefix = setup_git_directory(); |
Linus Torvalds | 73134b6 | 2005-04-10 21:03:58 | [diff] [blame] | 164 | |
Linus Torvalds | 1771299 | 2005-10-10 23:31:08 | [diff] [blame] | 165 | git_config(git_default_config); |
Linus Torvalds | 0a8365a | 2005-05-18 20:10:17 | [diff] [blame] | 166 | nr_sha1 = 0; |
Junio C Hamano | 6b5ee13 | 2005-09-21 07:00:47 | [diff] [blame] | 167 | diff_setup(&diff_options); |
| 168 | |
Linus Torvalds | c5b4238 | 2005-04-24 05:08:00 | [diff] [blame] | 169 | for (;;) { |
Junio C Hamano | 6b5ee13 | 2005-09-21 07:00:47 | [diff] [blame] | 170 | int diff_opt_cnt; |
Junio C Hamano | 6b14d7f | 2005-05-22 17:04:37 | [diff] [blame] | 171 | const char *arg; |
Linus Torvalds | c5b4238 | 2005-04-24 05:08:00 | [diff] [blame] | 172 | |
Linus Torvalds | 73134b6 | 2005-04-10 21:03:58 | [diff] [blame] | 173 | argv++; |
| 174 | argc--; |
Linus Torvalds | e0965d8 | 2005-05-06 17:03:17 | [diff] [blame] | 175 | arg = *argv; |
Linus Torvalds | 0a8365a | 2005-05-18 20:10:17 | [diff] [blame] | 176 | if (!arg) |
Linus Torvalds | e0965d8 | 2005-05-06 17:03:17 | [diff] [blame] | 177 | break; |
| 178 | |
Linus Torvalds | 0a8365a | 2005-05-18 20:10:17 | [diff] [blame] | 179 | if (*arg != '-') { |
| 180 | if (nr_sha1 < 2 && !get_sha1(arg, sha1[nr_sha1])) { |
| 181 | nr_sha1++; |
| 182 | continue; |
| 183 | } |
| 184 | break; |
| 185 | } |
| 186 | |
Junio C Hamano | 6b5ee13 | 2005-09-21 07:00:47 | [diff] [blame] | 187 | diff_opt_cnt = diff_opt_parse(&diff_options, argv, argc); |
| 188 | if (diff_opt_cnt < 0) |
| 189 | usage(diff_tree_usage); |
| 190 | else if (diff_opt_cnt) { |
| 191 | argv += diff_opt_cnt - 1; |
| 192 | argc -= diff_opt_cnt - 1; |
| 193 | continue; |
| 194 | } |
| 195 | |
| 196 | |
Linus Torvalds | 0a8365a | 2005-05-18 20:10:17 | [diff] [blame] | 197 | if (!strcmp(arg, "--")) { |
Linus Torvalds | e0965d8 | 2005-05-06 17:03:17 | [diff] [blame] | 198 | argv++; |
| 199 | argc--; |
| 200 | break; |
| 201 | } |
Linus Torvalds | bf16c71 | 2005-04-11 15:37:17 | [diff] [blame] | 202 | if (!strcmp(arg, "-r")) { |
Linus Torvalds | ac1b3d1 | 2005-10-21 04:05:05 | [diff] [blame] | 203 | diff_options.recursive = 1; |
Linus Torvalds | 73134b6 | 2005-04-10 21:03:58 | [diff] [blame] | 204 | continue; |
| 205 | } |
Junio C Hamano | 4cae1a9 | 2005-05-25 06:24:22 | [diff] [blame] | 206 | if (!strcmp(arg, "-t")) { |
Linus Torvalds | ac1b3d1 | 2005-10-21 04:05:05 | [diff] [blame] | 207 | diff_options.recursive = 1; |
| 208 | diff_options.tree_in_recursive = 1; |
Junio C Hamano | 4cae1a9 | 2005-05-25 06:24:22 | [diff] [blame] | 209 | continue; |
| 210 | } |
Linus Torvalds | e0965d8 | 2005-05-06 17:03:17 | [diff] [blame] | 211 | if (!strcmp(arg, "-m")) { |
| 212 | ignore_merges = 0; |
| 213 | continue; |
| 214 | } |
Linus Torvalds | cee99d2 | 2005-05-06 18:42:47 | [diff] [blame] | 215 | if (!strcmp(arg, "-v")) { |
| 216 | verbose_header = 1; |
| 217 | header_prefix = "diff-tree "; |
| 218 | continue; |
| 219 | } |
Junio C Hamano | a8db165 | 2005-06-13 00:44:21 | [diff] [blame] | 220 | if (!strncmp(arg, "--pretty", 8)) { |
| 221 | verbose_header = 1; |
Linus Torvalds | ba88e54 | 2005-06-13 03:34:09 | [diff] [blame] | 222 | header_prefix = "diff-tree "; |
Junio C Hamano | a8db165 | 2005-06-13 00:44:21 | [diff] [blame] | 223 | commit_format = get_commit_format(arg+8); |
| 224 | continue; |
| 225 | } |
Linus Torvalds | e0965d8 | 2005-05-06 17:03:17 | [diff] [blame] | 226 | if (!strcmp(arg, "--stdin")) { |
| 227 | read_stdin = 1; |
| 228 | continue; |
| 229 | } |
Linus Torvalds | dc26bd8 | 2005-05-19 20:44:29 | [diff] [blame] | 230 | if (!strcmp(arg, "--root")) { |
| 231 | show_root_diff = 1; |
| 232 | continue; |
| 233 | } |
Junio C Hamano | c5bac17 | 2005-04-21 02:49:16 | [diff] [blame] | 234 | usage(diff_tree_usage); |
Linus Torvalds | 73134b6 | 2005-04-10 21:03:58 | [diff] [blame] | 235 | } |
Junio C Hamano | 6b5ee13 | 2005-09-21 07:00:47 | [diff] [blame] | 236 | if (diff_options.output_format == DIFF_FORMAT_PATCH) |
Linus Torvalds | ac1b3d1 | 2005-10-21 04:05:05 | [diff] [blame] | 237 | diff_options.recursive = 1; |
Linus Torvalds | 73134b6 | 2005-04-10 21:03:58 | [diff] [blame] | 238 | |
Linus Torvalds | ac1b3d1 | 2005-10-21 04:05:05 | [diff] [blame] | 239 | diff_tree_setup_paths(get_pathspec(prefix, argv)); |
Linus Torvalds | c5b4238 | 2005-04-24 05:08:00 | [diff] [blame] | 240 | |
Linus Torvalds | 0a8365a | 2005-05-18 20:10:17 | [diff] [blame] | 241 | switch (nr_sha1) { |
| 242 | case 0: |
| 243 | if (!read_stdin) |
| 244 | usage(diff_tree_usage); |
| 245 | break; |
| 246 | case 1: |
Linus Torvalds | 7384889 | 2005-05-18 20:43:58 | [diff] [blame] | 247 | diff_tree_commit(sha1[0], NULL); |
Linus Torvalds | 0a8365a | 2005-05-18 20:10:17 | [diff] [blame] | 248 | break; |
| 249 | case 2: |
Junio C Hamano | 5c97558 | 2005-05-19 10:32:35 | [diff] [blame] | 250 | diff_tree_sha1_top(sha1[0], sha1[1], ""); |
Linus Torvalds | 0a8365a | 2005-05-18 20:10:17 | [diff] [blame] | 251 | break; |
| 252 | } |
| 253 | |
Linus Torvalds | e0965d8 | 2005-05-06 17:03:17 | [diff] [blame] | 254 | if (!read_stdin) |
Linus Torvalds | 0a8365a | 2005-05-18 20:10:17 | [diff] [blame] | 255 | return 0; |
Linus Torvalds | e0965d8 | 2005-05-06 17:03:17 | [diff] [blame] | 256 | |
Junio C Hamano | 6b5ee13 | 2005-09-21 07:00:47 | [diff] [blame] | 257 | if (diff_options.detect_rename) |
| 258 | diff_options.setup |= (DIFF_SETUP_USE_SIZE_CACHE | |
| 259 | DIFF_SETUP_USE_CACHE); |
Linus Torvalds | e0965d8 | 2005-05-06 17:03:17 | [diff] [blame] | 260 | while (fgets(line, sizeof(line), stdin)) |
| 261 | diff_tree_stdin(line); |
| 262 | |
| 263 | return 0; |
Linus Torvalds | 9174026 | 2005-04-09 20:00:54 | [diff] [blame] | 264 | } |