blob: 0b591c87169ff4b8c2173bedb26d6ed1a8a84b68 [file] [log] [blame]
Linus Torvalds91740262005-04-09 13:00:54 -07001#include "cache.h"
Junio C Hamano3ebfd4a2005-04-27 09:21:00 -07002#include "diff.h"
Linus Torvaldse3bc7a32005-06-01 08:34:23 -07003#include "commit.h"
Junio C Hamano5f1c3f02006-04-09 01:11:11 -07004#include "log-tree.h"
Peter Eriksene8cc9cd2006-05-23 14:15:36 +02005#include "builtin.h"
Linus Torvalds91740262005-04-09 13:00:54 -07006
Linus Torvaldscd2bdc52006-04-14 16:52:13 -07007static struct rev_info log_tree_opt;
Linus Torvaldsb11645b2005-05-18 13:06:47 -07008
Junio C Hamano45392a62006-02-05 23:00:41 -08009static int diff_tree_commit_sha1(const unsigned char *sha1)
10{
11 struct commit *commit = lookup_commit_reference(sha1);
12 if (!commit)
13 return -1;
Junio C Hamano5f1c3f02006-04-09 01:11:11 -070014 return log_tree_commit(&log_tree_opt, commit);
Junio C Hamano45392a62006-02-05 23:00:41 -080015}
16
Linus Torvaldse0965d82005-05-06 10:03:17 -070017static int diff_tree_stdin(char *line)
18{
19 int len = strlen(line);
Junio C Hamano45392a62006-02-05 23:00:41 -080020 unsigned char sha1[20];
21 struct commit *commit;
Linus Torvaldse0965d82005-05-06 10:03:17 -070022
23 if (!len || line[len-1] != '\n')
24 return -1;
25 line[len-1] = 0;
Junio C Hamano45392a62006-02-05 23:00:41 -080026 if (get_sha1_hex(line, sha1))
Linus Torvaldse0965d82005-05-06 10:03:17 -070027 return -1;
Junio C Hamano45392a62006-02-05 23:00:41 -080028 commit = lookup_commit(sha1);
29 if (!commit || parse_commit(commit))
30 return -1;
31 if (isspace(line[40]) && !get_sha1_hex(line+41, sha1)) {
32 /* Graft the fake parents locally to the commit */
33 int pos = 41;
34 struct commit_list **pptr, *parents;
35
36 /* Free the real parent list */
37 for (parents = commit->parents; parents; ) {
38 struct commit_list *tmp = parents->next;
39 free(parents);
40 parents = tmp;
41 }
42 commit->parents = NULL;
43 pptr = &(commit->parents);
44 while (line[pos] && !get_sha1_hex(line + pos, sha1)) {
45 struct commit *parent = lookup_commit(sha1);
46 if (parent) {
47 pptr = &commit_list_insert(parent, pptr)->next;
48 }
49 pos += 41;
50 }
Linus Torvaldse0965d82005-05-06 10:03:17 -070051 }
Junio C Hamano5f1c3f02006-04-09 01:11:11 -070052 return log_tree_commit(&log_tree_opt, commit);
Linus Torvaldse0965d82005-05-06 10:03:17 -070053}
54
Petr Baudis4d1f1192005-07-29 11:01:26 +020055static const char diff_tree_usage[] =
Junio C Hamanod8f47902006-01-24 01:22:04 -080056"git-diff-tree [--stdin] [-m] [-c] [--cc] [-s] [-v] [--pretty] [-t] [-r] [--root] "
Chris Shoemaker50b8e352005-10-28 13:04:49 -040057"[<common diff options>] <tree-ish> [<tree-ish>] [<path>...]\n"
58" -r diff recursively\n"
59" --root include the initial commit as diff against /dev/null\n"
Junio C Hamanodda2d792005-07-13 12:52:35 -070060COMMON_DIFF_OPTIONS_HELP;
Junio C Hamanoa8db1652005-06-12 17:44:21 -070061
Linus Torvaldsa633fca2006-07-28 22:44:25 -070062int cmd_diff_tree(int argc, const char **argv, const char *prefix)
Linus Torvalds73134b62005-04-10 14:03:58 -070063{
Linus Torvalds0a8365a2005-05-18 13:10:17 -070064 int nr_sha1;
Linus Torvaldse0965d82005-05-06 10:03:17 -070065 char line[1000];
Linus Torvaldscd2bdc52006-04-14 16:52:13 -070066 struct object *tree1, *tree2;
67 static struct rev_info *opt = &log_tree_opt;
Junio C Hamano5f1c3f02006-04-09 01:11:11 -070068 int read_stdin = 0;
Linus Torvalds73134b62005-04-10 14:03:58 -070069
Linus Torvaldsa633fca2006-07-28 22:44:25 -070070 init_revisions(opt, prefix);
Junio C Hamano83ad63c2006-07-08 01:05:16 -070071 git_config(git_default_config); /* no "diff" UI options */
Linus Torvalds0a8365a2005-05-18 13:10:17 -070072 nr_sha1 = 0;
Junio C Hamano8e8f9982006-04-14 22:19:38 -070073 opt->abbrev = 0;
Linus Torvalds91539832006-04-17 11:59:32 -070074 opt->diff = 1;
Linus Torvaldscd2bdc52006-04-14 16:52:13 -070075 argc = setup_revisions(argc, argv, opt, NULL);
Junio C Hamano6b5ee132005-09-21 00:00:47 -070076
Linus Torvaldscd2bdc52006-04-14 16:52:13 -070077 while (--argc > 0) {
78 const char *arg = *++argv;
Linus Torvaldsc5b42382005-04-23 22:08:00 -070079
Linus Torvaldse0965d82005-05-06 10:03:17 -070080 if (!strcmp(arg, "--stdin")) {
81 read_stdin = 1;
82 continue;
83 }
Junio C Hamanoc5bac172005-04-20 19:49:16 -070084 usage(diff_tree_usage);
Linus Torvalds73134b62005-04-10 14:03:58 -070085 }
86
Timo Hirvonenc9b5ef92006-06-24 20:24:14 +030087 if (!opt->diffopt.output_format)
88 opt->diffopt.output_format = DIFF_FORMAT_RAW;
89
Linus Torvaldscd2bdc52006-04-14 16:52:13 -070090 /*
Linus Torvalds1f1e8952006-06-19 17:42:35 -070091 * NOTE! We expect "a ^b" to be equal to "a..b", so we
92 * reverse the order of the objects if the second one
93 * is marked UNINTERESTING.
Linus Torvaldscd2bdc52006-04-14 16:52:13 -070094 */
Linus Torvalds1f1e8952006-06-19 17:42:35 -070095 nr_sha1 = opt->pending.nr;
Linus Torvalds0a8365a2005-05-18 13:10:17 -070096 switch (nr_sha1) {
97 case 0:
98 if (!read_stdin)
99 usage(diff_tree_usage);
100 break;
101 case 1:
Linus Torvalds1f1e8952006-06-19 17:42:35 -0700102 tree1 = opt->pending.objects[0].item;
Linus Torvaldscd2bdc52006-04-14 16:52:13 -0700103 diff_tree_commit_sha1(tree1->sha1);
Linus Torvalds0a8365a2005-05-18 13:10:17 -0700104 break;
105 case 2:
Linus Torvalds1f1e8952006-06-19 17:42:35 -0700106 tree1 = opt->pending.objects[0].item;
107 tree2 = opt->pending.objects[1].item;
108 if (tree2->flags & UNINTERESTING) {
109 struct object *tmp = tree2;
110 tree2 = tree1;
111 tree1 = tmp;
112 }
Linus Torvaldscd2bdc52006-04-14 16:52:13 -0700113 diff_tree_sha1(tree1->sha1,
114 tree2->sha1,
115 "", &opt->diffopt);
Junio C Hamano5f1c3f02006-04-09 01:11:11 -0700116 log_tree_diff_flush(opt);
Linus Torvalds0a8365a2005-05-18 13:10:17 -0700117 break;
118 }
119
Linus Torvaldse0965d82005-05-06 10:03:17 -0700120 if (!read_stdin)
Alex Riesen41bbf9d2007-03-14 01:17:04 +0100121 return opt->diffopt.exit_with_status ?
122 opt->diffopt.has_changes: 0;
Linus Torvaldse0965d82005-05-06 10:03:17 -0700123
Junio C Hamano5f1c3f02006-04-09 01:11:11 -0700124 if (opt->diffopt.detect_rename)
125 opt->diffopt.setup |= (DIFF_SETUP_USE_SIZE_CACHE |
Junio C Hamano6b5ee132005-09-21 00:00:47 -0700126 DIFF_SETUP_USE_CACHE);
Paul Mackerrase0c97ca2006-05-29 19:01:38 -0700127 while (fgets(line, sizeof(line), stdin)) {
128 unsigned char sha1[20];
129
130 if (get_sha1_hex(line, sha1)) {
131 fputs(line, stdout);
Paul Mackerras70f75cc2006-05-18 16:58:51 +1000132 fflush(stdout);
Paul Mackerrase0c97ca2006-05-29 19:01:38 -0700133 }
Paul Mackerras70f75cc2006-05-18 16:58:51 +1000134 else
135 diff_tree_stdin(line);
Paul Mackerrase0c97ca2006-05-29 19:01:38 -0700136 }
Alex Riesen41bbf9d2007-03-14 01:17:04 +0100137 return opt->diffopt.exit_with_status ? opt->diffopt.has_changes: 0;
Linus Torvalds91740262005-04-09 13:00:54 -0700138}