This introduces a new command-line option: --exit-code. The diff programs will return 1 for differences, return 0 for equality, and something else for errors. Signed-off-by: Alex Riesen <raa.lkml@xxxxxxxxx> --- Still working on my e-mail problems. Sorry for duplications. As promised on irc. I'm somewhat confused about diff_tree: it used to unconditionally return 0, yet every caller of it saves and passes the value! Documentation/diff-options.txt | 5 ++++ builtin-diff-tree.c | 12 +++++---- builtin-diff.c | 5 ++- diff-lib.c | 12 +++++++-- diff.c | 2 + diff.h | 3 +- t/t4017-diff-retval.sh | 51 ++++++++++++++++++++++++++++++++++++++++ tree-diff.c | 11 +++++++- 8 files changed, 88 insertions(+), 13 deletions(-) create mode 100755 t/t4017-diff-retval.sh
From 2309f82f88274a0ddac0d5b06c5df580f5cb7d81 Mon Sep 17 00:00:00 2001 From: Alex Riesen <raa.lkml@xxxxxxxxx> Date: Tue, 13 Mar 2007 18:06:08 +0100 Subject: [PATCH] Allow git-diff exit with codes similar to diff(1) This introduces a new command-line option: --exit-code. The diff programs will return 1 for differences, return 0 for equality, and something else for errors. Signed-off-by: Alex Riesen <raa.lkml@xxxxxxxxx> --- Documentation/diff-options.txt | 5 ++++ builtin-diff-tree.c | 12 +++++---- builtin-diff.c | 5 ++- diff-lib.c | 12 +++++++-- diff.c | 2 + diff.h | 3 +- t/t4017-diff-retval.sh | 51 ++++++++++++++++++++++++++++++++++++++++ tree-diff.c | 11 +++++++- 8 files changed, 88 insertions(+), 13 deletions(-) create mode 100755 t/t4017-diff-retval.sh diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index d8696b7..77a3f78 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -159,5 +159,10 @@ -w:: Shorthand for "--ignore-all-space". +--exit-code:: + Make the program exit with codes similar to diff(1). + That is, it exits with 1 if there were differences and + 0 means no differences. + For more detailed explanation on these common options, see also link:diffcore.html[diffcore documentation]. diff --git a/builtin-diff-tree.c b/builtin-diff-tree.c index 24cb2d7..d293a5e 100644 --- a/builtin-diff-tree.c +++ b/builtin-diff-tree.c @@ -61,6 +61,7 @@ COMMON_DIFF_OPTIONS_HELP; int cmd_diff_tree(int argc, const char **argv, const char *prefix) { + int result = 0; int nr_sha1; char line[1000]; struct object *tree1, *tree2; @@ -110,7 +111,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) tree2 = tree1; tree1 = tmp; } - diff_tree_sha1(tree1->sha1, + result = diff_tree_sha1(tree1->sha1, tree2->sha1, "", &opt->diffopt); log_tree_diff_flush(opt); @@ -118,7 +119,7 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) } if (!read_stdin) - return 0; + return opt->diffopt.diff_exit_code ? result: 0; if (opt->diffopt.detect_rename) opt->diffopt.setup |= (DIFF_SETUP_USE_SIZE_CACHE | @@ -130,8 +131,9 @@ int cmd_diff_tree(int argc, const char **argv, const char *prefix) fputs(line, stdout); fflush(stdout); } - else - diff_tree_stdin(line); + else if (diff_tree_stdin(line)) { + result = 1; + } } - return 0; + return opt->diffopt.diff_exit_code ? result: 0; } diff --git a/builtin-diff.c b/builtin-diff.c index 4efbb82..5e6265f 100644 --- a/builtin-diff.c +++ b/builtin-diff.c @@ -130,6 +130,7 @@ static int builtin_diff_tree(struct rev_info *revs, { const unsigned char *(sha1[2]); int swap = 0; + int result = 0; if (argc > 1) usage(builtin_diff_usage); @@ -141,9 +142,9 @@ static int builtin_diff_tree(struct rev_info *revs, swap = 1; sha1[swap] = ent[0].item->sha1; sha1[1-swap] = ent[1].item->sha1; - diff_tree_sha1(sha1[0], sha1[1], "", &revs->diffopt); + result = diff_tree_sha1(sha1[0], sha1[1], "", &revs->diffopt); log_tree_diff_flush(revs); - return 0; + return result; } static int builtin_diff_combined(struct rev_info *revs, diff --git a/diff-lib.c b/diff-lib.c index 6abb981..f943b6f 100644 --- a/diff-lib.c +++ b/diff-lib.c @@ -170,8 +170,10 @@ static int handle_diff_files_args(struct rev_info *revs, else if (!strcmp(argv[1], "--theirs")) revs->max_count = 3; else if (!strcmp(argv[1], "-n") || - !strcmp(argv[1], "--no-index")) + !strcmp(argv[1], "--no-index")) { revs->max_count = -2; + revs->diffopt.diff_exit_code = 1; + } else if (!strcmp(argv[1], "-q")) *silent = 1; else @@ -237,6 +239,7 @@ int setup_diff_no_index(struct rev_info *revs, break; } else if (i < argc - 3 && !strcmp(argv[i], "--no-index")) { i = argc - 3; + revs->diffopt.diff_exit_code = 1; break; } if (argc != i + 2 || (!is_outside_repo(argv[i + 1], nongit, prefix) && @@ -309,6 +312,7 @@ int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv) int run_diff_files(struct rev_info *revs, int silent_on_removed) { + int result = 0; int entries, i; int diff_unmerged_stage = revs->max_count; @@ -433,8 +437,9 @@ int run_diff_files(struct rev_info *revs, int silent_on_removed) } diffcore_std(&revs->diffopt); + result = revs->diffopt.diff_exit_code && diff_queued_diff.nr ? 1: 0; diff_flush(&revs->diffopt); - return 0; + return result; } /* @@ -664,9 +669,10 @@ int run_diff_index(struct rev_info *revs, int cached) return error("bad tree object %s", tree_name); if (read_tree(tree, 1, revs->prune_data)) return error("unable to read tree object %s", tree_name); - ret = diff_cache(revs, active_cache, active_nr, revs->prune_data, + diff_cache(revs, active_cache, active_nr, revs->prune_data, cached, match_missing); diffcore_std(&revs->diffopt); + ret = revs->diffopt.diff_exit_code && diff_queued_diff.nr ? 1: 0; diff_flush(&revs->diffopt); return ret; } diff --git a/diff.c b/diff.c index 954ca83..e2f91ed 100644 --- a/diff.c +++ b/diff.c @@ -2134,6 +2134,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac) options->color_diff = options->color_diff_words = 1; else if (!strcmp(arg, "--no-renames")) options->detect_rename = 0; + else if (!strcmp(arg, "--exit-code")) + options->diff_exit_code = 1; else return 0; return 1; diff --git a/diff.h b/diff.h index 4b435e8..cea61b5 100644 --- a/diff.h +++ b/diff.h @@ -56,7 +56,8 @@ struct diff_options { silent_on_remove:1, find_copies_harder:1, color_diff:1, - color_diff_words:1; + color_diff_words:1, + diff_exit_code:1; int context; int break_opt; int detect_rename; diff --git a/t/t4017-diff-retval.sh b/t/t4017-diff-retval.sh new file mode 100755 index 0000000..81a9393 --- /dev/null +++ b/t/t4017-diff-retval.sh @@ -0,0 +1,51 @@ +#!/bin/sh + +test_description='Return value of diffs' + +. ./test-lib.sh + +test_expect_success 'setup' ' + echo 1 >a && + git add . && + git commit -m first && + echo 2 >b && + git add . && + git commit -a -m second +' + +test_expect_failure 'git diff-tree HEAD^ HEAD' ' + git diff-tree --exit-code HEAD^ HEAD +' +test_expect_failure 'echo HEAD | git diff-tree --stdin' ' + echo $(git rev-parse HEAD) | git diff-tree --exit-code --stdin +' +test_expect_success 'git diff-tree HEAD HEAD' ' + git diff-tree --exit-code HEAD HEAD +' + +test_expect_success 'git diff-files' ' + git diff-files --exit-code +' + +test_expect_success 'git diff-index --cached HEAD' ' + git diff-index --exit-code --cached HEAD +' +test_expect_failure 'git diff-index --cached HEAD^' ' + git diff-index --exit-code --cached HEAD^ +' +test_expect_failure 'git diff-index --cached HEAD^' ' + echo 3 >c && + git add . && + git diff-index --exit-code --cached HEAD^ +' +git commit -m 'third' >/dev/null +test_expect_failure 'git diff-files' ' + echo 3 >>c && + git diff-files --exit-code +' +test_expect_failure 'git diff-index --cached HEAD' ' + git update-index c && + git diff-index --exit-code --cached HEAD +' + +test_done diff --git a/tree-diff.c b/tree-diff.c index c827582..47c516f 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -160,6 +160,8 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree int diff_tree(struct tree_desc *t1, struct tree_desc *t2, const char *base, struct diff_options *opt) { + int result = 0; + while (t1->size | t2->size) { if (opt->nr_paths && t1->size && !interesting(t1, base, opt)) { update_tree_entry(t1); @@ -170,29 +172,34 @@ int diff_tree(struct tree_desc *t1, struct tree_desc *t2, const char *base, stru continue; } if (!t1->size) { + result = 1; show_entry(opt, "+", t2, base); update_tree_entry(t2); continue; } if (!t2->size) { + result = 1; show_entry(opt, "-", t1, base); update_tree_entry(t1); continue; } switch (compare_tree_entry(t1, t2, base, opt)) { case -1: + result = 1; update_tree_entry(t1); continue; case 0: update_tree_entry(t1); - /* Fallthrough */ + update_tree_entry(t2); + continue; case 1: + result = 1; update_tree_entry(t2); continue; } die("git-diff-tree: internal error"); } - return 0; + return opt->diff_exit_code ? result: 0; } int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const char *base, struct diff_options *opt) -- 1.5.0.3.545.g5d3ba