diff options
Diffstat (limited to 'builtin-diff-tree.c')
-rw-r--r-- | builtin-diff-tree.c | 92 |
1 files changed, 62 insertions, 30 deletions
diff --git a/builtin-diff-tree.c b/builtin-diff-tree.c index 0b591c8716..2380c21951 100644 --- a/builtin-diff-tree.c +++ b/builtin-diff-tree.c @@ -14,20 +14,10 @@ static int diff_tree_commit_sha1(const unsigned char *sha1) return log_tree_commit(&log_tree_opt, commit); } -static int diff_tree_stdin(char *line) +/* Diff one or more commits. */ +static int stdin_diff_commit(struct commit *commit, char *line, int len) { - int len = strlen(line); unsigned char sha1[20]; - struct commit *commit; - - if (!len || line[len-1] != '\n') - return -1; - line[len-1] = 0; - if (get_sha1_hex(line, sha1)) - return -1; - commit = lookup_commit(sha1); - if (!commit || parse_commit(commit)) - return -1; if (isspace(line[40]) && !get_sha1_hex(line+41, sha1)) { /* Graft the fake parents locally to the commit */ int pos = 41; @@ -52,8 +42,51 @@ static int diff_tree_stdin(char *line) return log_tree_commit(&log_tree_opt, commit); } +/* Diff two trees. */ +static int stdin_diff_trees(struct tree *tree1, char *line, int len) +{ + unsigned char sha1[20]; + struct tree *tree2; + if (len != 82 || !isspace(line[40]) || get_sha1_hex(line + 41, sha1)) + return error("Need exactly two trees, separated by a space"); + tree2 = lookup_tree(sha1); + if (!tree2 || parse_tree(tree2)) + return -1; + printf("%s %s\n", sha1_to_hex(tree1->object.sha1), + sha1_to_hex(tree2->object.sha1)); + diff_tree_sha1(tree1->object.sha1, tree2->object.sha1, + "", &log_tree_opt.diffopt); + log_tree_diff_flush(&log_tree_opt); + return 0; +} + +static int diff_tree_stdin(char *line) +{ + int len = strlen(line); + unsigned char sha1[20]; + struct object *obj; + + if (!len || line[len-1] != '\n') + return -1; + line[len-1] = 0; + if (get_sha1_hex(line, sha1)) + return -1; + obj = lookup_unknown_object(sha1); + if (!obj || !obj->parsed) + obj = parse_object(sha1); + if (!obj) + return -1; + if (obj->type == OBJ_COMMIT) + return stdin_diff_commit((struct commit *)obj, line, len); + if (obj->type == OBJ_TREE) + return stdin_diff_trees((struct tree *)obj, line, len); + error("Object %s is a %s, not a commit or tree", + sha1_to_hex(sha1), typename(obj->type)); + return -1; +} + static const char diff_tree_usage[] = -"git-diff-tree [--stdin] [-m] [-c] [--cc] [-s] [-v] [--pretty] [-t] [-r] [--root] " +"git diff-tree [--stdin] [-m] [-c] [--cc] [-s] [-v] [--pretty] [-t] [-r] [--root] " "[<common diff options>] <tree-ish> [<tree-ish>] [<path>...]\n" " -r diff recursively\n" " --root include the initial commit as diff against /dev/null\n" @@ -68,10 +101,10 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) int read_stdin = 0; init_revisions(opt, prefix); - git_config(git_default_config); /* no "diff" UI options */ - nr_sha1 = 0; + git_config(git_diff_basic_config, NULL); /* no "diff" UI options */ opt->abbrev = 0; opt->diff = 1; + opt->disable_stdin = 1; argc = setup_revisions(argc, argv, opt, NULL); while (--argc > 0) { @@ -117,22 +150,21 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) break; } - if (!read_stdin) - return opt->diffopt.exit_with_status ? - opt->diffopt.has_changes: 0; + if (read_stdin) { + if (opt->diffopt.detect_rename) + opt->diffopt.setup |= (DIFF_SETUP_USE_SIZE_CACHE | + DIFF_SETUP_USE_CACHE); + while (fgets(line, sizeof(line), stdin)) { + unsigned char sha1[20]; - if (opt->diffopt.detect_rename) - opt->diffopt.setup |= (DIFF_SETUP_USE_SIZE_CACHE | - DIFF_SETUP_USE_CACHE); - while (fgets(line, sizeof(line), stdin)) { - unsigned char sha1[20]; - - if (get_sha1_hex(line, sha1)) { - fputs(line, stdout); - fflush(stdout); + if (get_sha1_hex(line, sha1)) { + fputs(line, stdout); + fflush(stdout); + } + else + diff_tree_stdin(line); } - else - diff_tree_stdin(line); } - return opt->diffopt.exit_with_status ? opt->diffopt.has_changes: 0; + + return diff_result_code(&opt->diffopt, 0); } |