[PATCH] Allow git-diff exit with codes similar to diff(1)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]