Git development
 help / color / mirror / Atom feed
* Re: gitk-1.0 released
From: walt @ 2005-05-20  1:10 UTC (permalink / raw)
  To: git
In-Reply-To: <17036.36624.911071.810357@cargo.ozlabs.ibm.com>

Paul Mackerras wrote:
> I have released a new version of gitk.  I got brave and called it 1.0
> and it is at:
> 
> 	http://ozlabs.org/~paulus/gitk-1.0
.
.
.

Today, gitk works beautifully for me.  Yesterday, though, I had a weird
first experience when it opened a very attractive tcl/tk interface which
displayed no text of any kind.  I tried fiddling with the two menus you
provide, bit still no success.

I finally just gave up.  When I tried gitk again today -- it was magic!
All the kernel tree appeared just as (I suppose) you intended.

As far as I know, I did nothing to change anything since yesterday.
Can you venture a guess why I had sucess today and failure yesterday?

Does gitk perhaps depend on a generated database of some kind before
it will work properly?


^ permalink raw reply

* [PATCH] diff overhaul
From: Junio C Hamano @ 2005-05-20  2:00 UTC (permalink / raw)
  To: torvalds; +Cc: git

Diff overhaul.

This patch cleans up the way calls are made into the diff core
from diff-tree family and diff-helper.  Earlier, these programs
had "if (generating_patch)" sprinkled all over the place, but
those ugliness are gone and handled uniformly from the diff
core, even when not generating patch format.

This also allowed diff-cache and diff-files to acquire -R
(reverse) option to generate diff in reverse.  Users of
diff-tree can swap two trees easily so I did not add -R there.

Also -M<digits-as-mantissa> suggestion made by Linus has been
implemented.

It also fixes minor permission problems with some of the test
scripts (although it should not matter since they are explicitly
run by being the first argument to "sh"), but this being a patch
that may not convey well.

Documentation updates are also included.

Signed-off-by: Junio C Hamano <junkio@cox.net>
---

Documentation/git-diff-cache.txt |    5 +
Documentation/git-diff-files.txt |    5 +
diff-cache.c                     |   42 ++++-------
diff-files.c                     |   44 ++++--------
diff-helper.c                    |   19 +++--
diff-tree.c                      |   46 ++++--------
diff.c                           |  142 +++++++++++++++++++++++++++++++--------
diff.h                           |    4 -
t/t0000-basic.sh                 |    2 
t/t2002-checkout-cache-u.sh      |    2 
t/t4001-diff-rename.sh           |    6 +
11 files changed, 192 insertions(+), 125 deletions(-)
mode changed (100644 --> 100755): t/t0110-environment-names-old.sh
mode changed (100644 --> 100755): t/t1000-read-tree-m-3way.sh
mode changed (100644 --> 100755): t/t2002-checkout-cache-u.sh
mode changed (100644 --> 100755): t/t4000-diff-format.sh
mode changed (100644 --> 100755): t/t4001-diff-rename.sh

diff --git a/Documentation/git-diff-cache.txt b/Documentation/git-diff-cache.txt
--- a/Documentation/git-diff-cache.txt
+++ b/Documentation/git-diff-cache.txt
@@ -9,7 +9,7 @@ git-diff-cache - Compares content and mo
 
 SYNOPSIS
 --------
-'git-diff-cache' [-p] [-r] [-z] [-m] [-M] [--cached] <tree-ish>
+'git-diff-cache' [-p] [-r] [-z] [-m] [-M] [-R] [--cached] <tree-ish>
 
 DESCRIPTION
 -----------
@@ -36,6 +36,9 @@ OPTIONS
 -M::
 	Detect renames; implies -p.
 
+-R::
+	Output diff in reverse.
+
 --cached::
 	do not consider the on-disk file at all
 
diff --git a/Documentation/git-diff-files.txt b/Documentation/git-diff-files.txt
--- a/Documentation/git-diff-files.txt
+++ b/Documentation/git-diff-files.txt
@@ -9,7 +9,7 @@ git-diff-files - Compares files in the w
 
 SYNOPSIS
 --------
-'git-diff-files' [-p] [-q] [-r] [-z] [-M] [<pattern>...]
+'git-diff-files' [-p] [-q] [-r] [-z] [-M] [-R] [<pattern>...]
 
 DESCRIPTION
 -----------
@@ -26,6 +26,9 @@ OPTIONS
 -q::
 	Remain silent even on nonexisting files
 
+-R::
+	Output diff in reverse.
+
 -M::
 	Detect renames; implies -p.
 
diff --git a/diff-cache.c b/diff-cache.c
--- a/diff-cache.c
+++ b/diff-cache.c
@@ -6,15 +6,13 @@ static int generate_patch = 0;
 static int match_nonexisting = 0;
 static int line_termination = '\n';
 static int detect_rename = 0;
+static int reverse_diff = 0;
+static int diff_score_opt = 0;
 
 /* A file entry went away or appeared */
 static void show_file(const char *prefix, struct cache_entry *ce, unsigned char *sha1, unsigned int mode)
 {
-	if (generate_patch)
-		diff_addremove(prefix[0], ntohl(mode), sha1, ce->name, NULL);
-	else
-		printf("%s%06o\tblob\t%s\t%s%c", prefix, ntohl(mode),
-		       sha1_to_hex(sha1), ce->name, line_termination);
+	diff_addremove(prefix[0], ntohl(mode), sha1, ce->name, NULL);
 }
 
 static int get_stat_data(struct cache_entry *ce, unsigned char **sha1p, unsigned int *modep)
@@ -64,7 +62,6 @@ static int show_modified(struct cache_en
 {
 	unsigned int mode, oldmode;
 	unsigned char *sha1;
-	char old_sha1_hex[60];
 
 	if (get_stat_data(new, &sha1, &mode) < 0) {
 		if (report_missing)
@@ -79,15 +76,8 @@ static int show_modified(struct cache_en
 	mode = ntohl(mode);
 	oldmode = ntohl(oldmode);
 
-	if (generate_patch)
-		diff_change(oldmode, mode,
-			    old->sha1, sha1, old->name, NULL);
-	else {
-		strcpy(old_sha1_hex, sha1_to_hex(old->sha1));
-		printf("*%06o->%06o\tblob\t%s->%s\t%s%c", oldmode, mode,
-		       old_sha1_hex, sha1_to_hex(sha1),
-		       old->name, line_termination);
-	}
+	diff_change(oldmode, mode,
+		    old->sha1, sha1, old->name, NULL);
 	return 0;
 }
 
@@ -127,10 +117,7 @@ static int diff_cache(struct cache_entry
 				break;
 			/* fallthru */
 		case 3:
-			if (generate_patch)
-				diff_unmerge(ce->name);
-			else
-				printf("U %s%c", ce->name, line_termination);
+			diff_unmerge(ce->name);
 			break;
 
 		default:
@@ -166,7 +153,7 @@ static void mark_merge_entries(void)
 }
 
 static char *diff_cache_usage =
-"git-diff-cache [-p] [-r] [-z] [-m] [-M] [--cached] <tree-ish>";
+"git-diff-cache [-p] [-r] [-z] [-m] [-M] [-R] [--cached] <tree-ish>";
 
 int main(int argc, char **argv)
 {
@@ -188,14 +175,19 @@ int main(int argc, char **argv)
 			generate_patch = 1;
 			continue;
 		}
-		if (!strcmp(arg, "-M")) {
+		if (!strncmp(arg, "-M", 2)) {
 			generate_patch = detect_rename = 1;
+			diff_score_opt = diff_scoreopt_parse(arg);
 			continue;
 		}
 		if (!strcmp(arg, "-z")) {
 			line_termination = '\0';
 			continue;
 		}
+		if (!strcmp(arg, "-R")) {
+			reverse_diff = 1;
+			continue;
+		}
 		if (!strcmp(arg, "-m")) {
 			match_nonexisting = 1;
 			continue;
@@ -210,8 +202,9 @@ int main(int argc, char **argv)
 	if (argc != 2 || get_sha1(argv[1], tree_sha1))
 		usage(diff_cache_usage);
 
-	if (generate_patch)
-		diff_setup(detect_rename, 0, 0, 0, 0);
+	diff_setup(detect_rename, diff_score_opt, reverse_diff,
+		   (generate_patch ? -1 : line_termination),
+		   0, 0);
 
 	mark_merge_entries();
 
@@ -222,7 +215,6 @@ int main(int argc, char **argv)
 		die("unable to read tree object %s", argv[1]);
 
 	ret = diff_cache(active_cache, active_nr);
-	if (generate_patch)
-		diff_flush();
+	diff_flush();
 	return ret;
 }
diff --git a/diff-files.c b/diff-files.c
--- a/diff-files.c
+++ b/diff-files.c
@@ -7,11 +7,13 @@
 #include "diff.h"
 
 static const char *diff_files_usage =
-"git-diff-files [-p] [-q] [-r] [-z] [-M] [paths...]";
+"git-diff-files [-p] [-q] [-r] [-z] [-M] [-R] [paths...]";
 
 static int generate_patch = 0;
 static int line_termination = '\n';
 static int detect_rename = 0;
+static int reverse_diff = 0;
+static int diff_score_opt = 0;
 static int silent = 0;
 
 static int matches_pathspec(struct cache_entry *ce, char **spec, int cnt)
@@ -31,36 +33,19 @@ static int matches_pathspec(struct cache
 
 static void show_unmerge(const char *path)
 {
-	if (generate_patch)
-		diff_unmerge(path);
-	else
-		printf("U %s%c", path, line_termination);
+	diff_unmerge(path);
 }
 
 static void show_file(int pfx, struct cache_entry *ce)
 {
-	if (generate_patch)
-		diff_addremove(pfx, ntohl(ce->ce_mode), ce->sha1,
-			       ce->name, NULL);
-	else
-		printf("%c%06o\t%s\t%s\t%s%c",
-		       pfx, ntohl(ce->ce_mode), "blob",
-		       sha1_to_hex(ce->sha1), ce->name, line_termination);
+	diff_addremove(pfx, ntohl(ce->ce_mode), ce->sha1, ce->name, NULL);
 }
 
 static void show_modified(int oldmode, int mode,
 			  const unsigned char *old_sha1, const unsigned char *sha1,
 			  char *path)
 {
-	char old_sha1_hex[41];
-	strcpy(old_sha1_hex, sha1_to_hex(old_sha1));
-
-	if (generate_patch)
-		diff_change(oldmode, mode, old_sha1, sha1, path, NULL);
-	else
-		printf("*%06o->%06o\tblob\t%s->%s\t%s%c",
-		       oldmode, mode, old_sha1_hex, sha1_to_hex(sha1), path,
-		       line_termination);
+	diff_change(oldmode, mode, old_sha1, sha1, path, NULL);
 }
 
 int main(int argc, char **argv)
@@ -80,7 +65,10 @@ int main(int argc, char **argv)
 			; /* no-op */
 		else if (!strcmp(argv[1], "-z"))
 			line_termination = 0;
-		else if (!strcmp(argv[1], "-M")) {
+		else if (!strcmp(argv[1], "-R"))
+			reverse_diff = 1;
+		else if (!strncmp(argv[1], "-M", 2)) {
+			diff_score_opt = diff_scoreopt_parse(argv[1]);
 			detect_rename = generate_patch = 1;
 		}
 		else
@@ -96,8 +84,9 @@ int main(int argc, char **argv)
 		exit(1);
 	}
 
-	if (generate_patch)
-		diff_setup(detect_rename, 0, 0, 0, 0);		
+	diff_setup(detect_rename, diff_score_opt, reverse_diff,
+		   (generate_patch ? -1 : line_termination),
+		   0, 0);
 
 	for (i = 0; i < entries; i++) {
 		struct stat st;
@@ -117,12 +106,12 @@ int main(int argc, char **argv)
 			i--; /* compensate for loop control increments */
 			continue;
 		}
- 
+
 		if (lstat(ce->name, &st) < 0) {
 			if (errno != ENOENT) {
 				perror(ce->name);
 				continue;
-			}	
+			}
 			if (silent)
 				continue;
 			show_file('-', ce);
@@ -139,7 +128,6 @@ int main(int argc, char **argv)
 		show_modified(oldmode, mode, ce->sha1, null_sha1,
 			      ce->name);
 	}
-	if (generate_patch)
-		diff_flush();
+	diff_flush();
 	return 0;
 }
diff --git a/diff-helper.c b/diff-helper.c
--- a/diff-helper.c
+++ b/diff-helper.c
@@ -7,6 +7,7 @@
 #include "diff.h"
 
 static int detect_rename = 0;
+static int diff_score_opt = 0;
 
 static int parse_oneside_change(const char *cp, int *mode,
 				unsigned char *sha1, char *path)
@@ -19,15 +20,15 @@ static int parse_oneside_change(const ch
 		cp++;
 	}
 	*mode = m;
-	if (strncmp(cp, "\tblob\t", 6))
+	if (strncmp(cp, "\tblob\t", 6) && strncmp(cp, " blob ", 6))
 		return -1;
 	cp += 6;
 	if (get_sha1_hex(cp, sha1))
 		return -1;
 	cp += 40;
-	if (*cp++ != '\t')
+	if ((*cp != '\t') && *cp != ' ')
 		return -1;
-	strcpy(path, cp);
+	strcpy(path, ++cp);
 	return 0;
 }
 
@@ -63,7 +64,7 @@ static int parse_diff_raw_output(const c
 			new_mode = (new_mode << 3) | (ch - '0');
 			cp++;
 		}
-		if (strncmp(cp, "\tblob\t", 6))
+		if (strncmp(cp, "\tblob\t", 6) && strncmp(cp, " blob ", 6))
 			return -1;
 		cp += 6;
 		if (get_sha1_hex(cp, old_sha1))
@@ -75,9 +76,9 @@ static int parse_diff_raw_output(const c
 		if (get_sha1_hex(cp, new_sha1))
 			return -1;
 		cp += 40;
-		if (*cp++ != '\t')
+		if ((*cp != '\t') && *cp != ' ')
 			return -1;
-		strcpy(path, cp);
+		strcpy(path, ++cp);
 		diff_change(old_mode, new_mode, old_sha1, new_sha1, path, 0);
 		break;
 	default:
@@ -101,15 +102,17 @@ int main(int ac, const char **av) {
 			reverse = 1;
 		else if (av[1][1] == 'z')
 			line_termination = 0;
-		else if (av[1][1] == 'M')
+		else if (av[1][1] == 'M') {
 			detect_rename = 1;
+			diff_score_opt = diff_scoreopt_parse(av[1]);
+		}
 		else
 			usage(diff_helper_usage);
 		ac--; av++;
 	}
 	/* the remaining parameters are paths patterns */
 
-	diff_setup(detect_rename, 0, reverse, av+1, ac-1);
+	diff_setup(detect_rename, diff_score_opt, reverse, -1, av+1, ac-1);
 
 	while (1) {
 		int status;
diff --git a/diff-tree.c b/diff-tree.c
--- a/diff-tree.c
+++ b/diff-tree.c
@@ -11,6 +11,7 @@ static int read_stdin = 0;
 static int line_termination = '\n';
 static int generate_patch = 0;
 static int detect_rename = 0;
+static int diff_score_opt = 0;
 static const char *header = NULL;
 static const char *header_prefix = "";
 
@@ -84,21 +85,13 @@ static void show_file(const char *prefix
 			die("corrupt tree sha %s", sha1_to_hex(sha1));
 
 		show_tree(prefix, tree, size, newbase);
-		
+
 		free(tree);
 		free(newbase);
 		return;
 	}
 
-	if (generate_patch) {
-		if (!S_ISDIR(mode))
-			diff_addremove(prefix[0], mode, sha1, base, path);
-	}
-	else
-		printf("%s%06o\t%s\t%s\t%s%s%c", prefix, mode,
-		       S_ISDIR(mode) ? "tree" : "blob",
-		       sha1_to_hex(sha1), base, path,
-		       line_termination);
+	diff_addremove(prefix[0], mode, sha1, base, path);
 }
 
 static int compare_tree_entry(void *tree1, unsigned long size1, void *tree2, unsigned long size2, const char *base)
@@ -107,7 +100,6 @@ static int compare_tree_entry(void *tree
 	const char *path1, *path2;
 	const unsigned char *sha1, *sha2;
 	int cmp, pathlen1, pathlen2;
-	char old_sha1_hex[50];
 
 	sha1 = extract(tree1, size1, &path1, &mode1);
 	sha2 = extract(tree2, size2, &path2, &mode2);
@@ -151,17 +143,7 @@ static int compare_tree_entry(void *tree
 	if (silent)
 		return 0;
 
-	if (generate_patch) {
-		if (!S_ISDIR(mode1))
-			diff_change(mode1, mode2, sha1, sha2, base, path1);
-	}
-	else {
-		strcpy(old_sha1_hex, sha1_to_hex(sha1));
-		printf("*%06o->%06o\t%s\t%s->%s\t%s%s%c", mode1, mode2,
-		       S_ISDIR(mode1) ? "tree" : "blob",
-		       old_sha1_hex, sha1_to_hex(sha2), base, path1,
-		       line_termination);
-	}
+	diff_change(mode1, mode2, sha1, sha2, base, path1);
 	return 0;
 }
 
@@ -287,11 +269,12 @@ static int diff_tree_sha1_top(const unsi
 			      const unsigned char *new, const char *base)
 {
 	int ret;
-	if (generate_patch)
-		diff_setup(detect_rename, 0, 0, 0, 0);
+
+	diff_setup(detect_rename, diff_score_opt, 0,
+		   (generate_patch ? -1 : line_termination),
+		   0, 0);
 	ret = diff_tree_sha1(old, new, base);
-	if (generate_patch)
-		diff_flush();
+	diff_flush();
 	return ret;
 }
 
@@ -301,15 +284,15 @@ static int diff_root_tree(const unsigned
 	void *tree;
 	unsigned long size;
 
-	if (generate_patch)
-		diff_setup(detect_rename, 0, 0, 0, 0);
+	diff_setup(detect_rename, diff_score_opt, 0,
+		   (generate_patch ? -1 : line_termination),
+		   0, 0);
 	tree = read_object_with_reference(new, "tree", &size, 0);
 	if (!tree)
 		die("unable to read root tree (%s)", sha1_to_hex(new));
 	retval = diff_tree("", 0, tree, size, base);
 	free(tree);
-	if (generate_patch)
-		diff_flush();
+	diff_flush();
 	return retval;
 }
 
@@ -485,8 +468,9 @@ int main(int argc, char **argv)
 			recursive = generate_patch = 1;
 			continue;
 		}
-		if (!strcmp(arg, "-M")) {
+		if (!strncmp(arg, "-M", 2)) {
 			detect_rename = recursive = generate_patch = 1;
+			diff_score_opt = diff_scoreopt_parse(arg);
 			continue;
 		}
 		if (!strcmp(arg, "-z")) {
diff --git a/diff.c b/diff.c
--- a/diff.c
+++ b/diff.c
@@ -11,6 +11,8 @@
 
 static const char *diff_opts = "-pu";
 static unsigned char null_sha1[20] = { 0, };
+#define MAX_SCORE 10000
+#define DEFAULT_MINIMUM_SCORE 5000
 
 static const char *external_diff(void)
 {
@@ -55,7 +57,7 @@ static char *sq_expand(const char *src)
 	const char *cp;
 	char *bp;
 
-	/* count bytes needed to store the quoted string. */ 
+	/* count bytes needed to store the quoted string. */
 	for (cnt = 1, cp = src; *cp; cnt++, cp++)
 		if (*cp == '\'')
 			cnt += 3;
@@ -93,7 +95,8 @@ struct diff_spec {
 
 static void builtin_diff(const char *name_a,
 			 const char *name_b,
-			 struct diff_tempfile *temp)
+			 struct diff_tempfile *temp,
+			 int rename_score)
 {
 	int i, next_at, cmd_size;
 	const char *diff_cmd = "diff -L'%s%s' -L'%s%s'";
@@ -149,6 +152,10 @@ static void builtin_diff(const char *nam
 			printf("new mode %s\n", temp[1].mode);
 		}
 		if (strcmp(name_a, name_b)) {
+			if (0 < rename_score)
+				printf("rename similarity index %d%%\n",
+				       (int)(0.5+
+					     rename_score*100.0/MAX_SCORE));
 			printf("rename old %s\n", name_a);
 			printf("rename new %s\n", name_b);
 		}
@@ -184,7 +191,7 @@ static int work_tree_matches(const char 
 	 * file.  Practically, this code only helps when we are used
 	 * by diff-cache --cached, which does read the cache before
 	 * calling us.
-	 */ 
+	 */
 	if (!active_cache)
 		return 0;
 
@@ -302,9 +309,10 @@ static void remove_tempfile_on_signal(in
 
 static int detect_rename;
 static int reverse_diff;
+static int diff_raw_output = -1;
 static const char **pathspec;
 static int speccnt;
-static int diff_rename_minimum_score;
+static int minimum_score;
 
 static int matches_pathspec(const char *name)
 {
@@ -334,7 +342,8 @@ static int matches_pathspec(const char *
 static void run_external_diff(const char *name,
 			      const char *other,
 			      struct diff_spec *one,
-			      struct diff_spec *two)
+			      struct diff_spec *two,
+			      int rename_score)
 {
 	struct diff_tempfile *temp = diff_temp;
 	pid_t pid;
@@ -395,7 +404,7 @@ static void run_external_diff(const char
 		 * otherwise we use the built-in one.
 		 */
 		if (one && two)
-			builtin_diff(name, other ? : name, temp);
+			builtin_diff(name, other ? : name, temp, rename_score);
 		else
 			printf("* Unmerged path %s\n", name);
 		exit(0);
@@ -446,7 +455,7 @@ static void hold_diff(const char *name,
 		die("internal error");
 
 	if (!detect_rename) {
-		run_external_diff(name, NULL, one, two);
+		run_external_diff(name, NULL, one, two, -1);
 		return;
 	}
 	elem = xmalloc(sizeof(*elem) + strlen(name));
@@ -519,10 +528,10 @@ static void flush_remaining_diff(struct 
 			continue;
 		if (on_created_list)
 			run_external_diff(elem->path, NULL,
-					  &null_file_spec, &elem->it);
+					  &null_file_spec, &elem->it, -1);
 		else
 			run_external_diff(elem->path, NULL,
-					  &elem->it, &null_file_spec);
+					  &elem->it, &null_file_spec, -1);
 	}
 }
 
@@ -541,7 +550,6 @@ static int is_exact_match(struct diff_sp
 	return 0;
 }
 
-#define MINIMUM_SCORE 5000
 int estimate_similarity(struct diff_spec_hold *src, struct diff_spec_hold *dst)
 {
 	/* src points at a deleted file and dst points at a created
@@ -549,20 +557,24 @@ int estimate_similarity(struct diff_spec
 	 * say src is renamed to dst.
 	 *
 	 * Compare them and return how similar they are, representing
-	 * the score as an integer between 0 and 10000.  10000 is
-	 * reserved for the case where they match exactly.
+	 * the score as an integer between 0 and 10000, except
+	 * where they match exactly it is considered better than anything
+	 * else.
 	 */
 	void *delta;
 	unsigned long delta_size;
+	int score;
 
 	delta_size = ((src->size < dst->size) ?
 		      (dst->size - src->size) : (src->size - dst->size));
 
 	/* We would not consider rename followed by more than
-	 * 20% edits; that is, delta_size must be smaller than
-	 * (src->size + dst->size)/2 * 0.2, which means...
+	 * minimum_score/MAX_SCORE edits; that is, delta_size must be smaller
+	 * than (src->size + dst->size)/2 * minimum_score/MAX_SCORE,
+	 * which means...
 	 */
-	if ((src->size + dst->size) < delta_size * 10)
+
+	if ((src->size+dst->size)*minimum_score < delta_size*MAX_SCORE*2)
 		return 0;
 
 	delta = diff_delta(src->data, src->size,
@@ -573,14 +585,17 @@ int estimate_similarity(struct diff_spec
 	/* This "delta" is really xdiff with adler32 and all the
 	 * overheads but it is a quick and dirty approximation.
 	 *
-	 * Now we will give some score to it.  Let's say 20% edit gets
-	 * 5000 points and 0% edit gets 9000 points.  That is, every
-	 * 1/20000 edit gets 1 point penalty.  The amount of penalty is:
+	 * Now we will give some score to it.  100% edit gets
+	 * 0 points and 0% edit gets MAX_SCORE points.  That is, every
+	 * 1/MAX_SCORE edit gets 1 point penalty.  The amount of penalty is:
 	 *
-	 * (delta_size * 2 / (src->size + dst->size)) * 20000
+	 * (delta_size * 2 / (src->size + dst->size)) * MAX_SCORE
 	 *
 	 */
-	return 9000 - (40000 * delta_size / (src->size+dst->size));
+	score = MAX_SCORE-(MAX_SCORE*2*delta_size/(src->size+dst->size));
+	if (score < 0) return 0;
+	if (MAX_SCORE < score) return MAX_SCORE;
+	return score;
 }
 
 struct diff_score {
@@ -596,14 +611,15 @@ static int score_compare(const void *a_,
 }
 
 static void flush_rename_pair(struct diff_spec_hold *src,
-			      struct diff_spec_hold *dst)
+			      struct diff_spec_hold *dst,
+			      int rename_score)
 {
 	src->flags |= MATCHED;
 	dst->flags |= MATCHED;
 	free_data(src);
 	free_data(dst);
 	run_external_diff(src->path, dst->path,
-			  &src->it, &dst->it);
+			  &src->it, &dst->it, rename_score);
 }
 
 static void free_held_diff(struct diff_spec_hold *list)
@@ -637,7 +653,7 @@ void diff_flush(void)
 				continue;
 			if (! is_exact_match(src, dst))
 				continue;
-			flush_rename_pair(src, dst);
+			flush_rename_pair(src, dst, MAX_SCORE);
 			break;
 		}
 	}
@@ -670,7 +686,7 @@ void diff_flush(void)
 		}
 		c++;
 	}
-	qsort(mx, num_create*num_delete, sizeof(*mx), score_compare); 
+	qsort(mx, num_create*num_delete, sizeof(*mx), score_compare);
 
 #if 0
  	for (c = 0; c < num_create * num_delete; c++) {
@@ -689,9 +705,9 @@ void diff_flush(void)
 		dst = mx[c].dst;
 		if ((src->flags & MATCHED) || (dst->flags & MATCHED))
 			continue;
-		if (mx[c].score < diff_rename_minimum_score)
+		if (mx[c].score < minimum_score)
 			break;
-		flush_rename_pair(src, dst);
+		flush_rename_pair(src, dst, mx[c].score);
 	}
 	free(mx);
 
@@ -703,7 +719,26 @@ void diff_flush(void)
 	createdfile = deletedfile = NULL;
 }
 
+int diff_scoreopt_parse(const char *opt)
+{
+	int diglen, num, scale, i;
+	if (opt[0] != '-' || opt[1] != 'M')
+		return -1; /* that is not -M option */
+	diglen = strspn(opt+2, "0123456789");
+	if (diglen == 0 || strlen(opt+2) != diglen)
+		return 0; /* use default */
+	sscanf(opt+2, "%d", &num);
+	for (i = 0, scale = 1; i < diglen; i++)
+		scale *= 10;
+
+	/* user says num divided by scale and we say internally that
+	 * is MAX_SCORE * num / scale.
+	 */
+	return MAX_SCORE * num / scale;
+}
+
 void diff_setup(int detect_rename_, int minimum_score_, int reverse_diff_,
+		int diff_raw_output_,
 		const char **pathspec_, int speccnt_)
 {
 	free_held_diff(createdfile);
@@ -713,8 +748,14 @@ void diff_setup(int detect_rename_, int 
 	detect_rename = detect_rename_;
 	reverse_diff = reverse_diff_;
 	pathspec = pathspec_;
+	diff_raw_output = diff_raw_output_;
 	speccnt = speccnt_;
-	diff_rename_minimum_score = minimum_score_ ? : MINIMUM_SCORE;
+	minimum_score = minimum_score_ ? : DEFAULT_MINIMUM_SCORE;
+}
+
+static const char *git_object_type(unsigned mode)
+{
+	return S_ISDIR(mode) ? "tree" : "blob";
 }
 
 void diff_addremove(int addremove, unsigned mode,
@@ -724,6 +765,21 @@ void diff_addremove(int addremove, unsig
 	char concatpath[PATH_MAX];
 	struct diff_spec spec[2], *one, *two;
 
+	if (0 <= diff_raw_output) {
+		if (!path)
+			path = "";
+		if (reverse_diff)
+			addremove = (addremove == '+' ? '-' : '+');
+		printf("%c%06o %s %s %s%s%c",
+		       addremove,
+		       mode,
+		       git_object_type(mode), sha1_to_hex(sha1),
+		       base, path, diff_raw_output);
+		return;
+	}
+	if (S_ISDIR(mode))
+		return;
+
 	memcpy(spec[0].blob_sha1, sha1, 20);
 	spec[0].mode = mode;
 	spec[0].sha1_valid = !!memcmp(sha1, null_sha1, 20);
@@ -750,6 +806,29 @@ void diff_change(unsigned old_mode, unsi
 	char concatpath[PATH_MAX];
 	struct diff_spec spec[2];
 
+	if (0 <= diff_raw_output) {
+		char old_hex[41];
+		strcpy(old_hex, sha1_to_hex(old_sha1));
+
+		if (!path)
+			path = "";
+		if (reverse_diff)
+			printf("*%06o->%06o %s %s->%s %s%s%c",
+			       new_mode, old_mode,
+			       git_object_type(new_mode),
+			       sha1_to_hex(new_sha1), old_hex,
+			       base, path, diff_raw_output);
+		else
+			printf("*%06o->%06o %s %s->%s %s%s%c",
+			       old_mode, new_mode,
+			       git_object_type(new_mode),
+			       old_hex, sha1_to_hex(new_sha1),
+			       base, path, diff_raw_output);
+		return;
+	}
+	if (S_ISDIR(new_mode))
+		return;
+
 	if (path) {
 		strcpy(concatpath, base);
 		strcat(concatpath, path);
@@ -766,10 +845,15 @@ void diff_change(unsigned old_mode, unsi
 	/* We do not look at changed files as candidate for
 	 * rename detection ever.
 	 */
-	run_external_diff(path ? concatpath : base, NULL, &spec[0], &spec[1]);
+	run_external_diff(path ? concatpath : base, NULL,
+			  &spec[0], &spec[1], -1);
 }
 
 void diff_unmerge(const char *path)
 {
-	run_external_diff(path, NULL, NULL, NULL);
+	if (0 <= diff_raw_output) {
+		printf("U %s%c", path, diff_raw_output);
+		return;
+	}
+	run_external_diff(path, NULL, NULL, NULL, -1);
 }
diff --git a/diff.h b/diff.h
--- a/diff.h
+++ b/diff.h
@@ -17,8 +17,10 @@ extern void diff_change(unsigned mode1, 
 
 extern void diff_unmerge(const char *path);
 
+extern int diff_scoreopt_parse(const char *opt);
+
 extern void diff_setup(int detect_rename, int minimum_score,
-		       int reverse,
+		       int reverse, int raw_output,
 		       const char **spec, int cnt);
 
 extern void diff_flush(void);
diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh
--- a/t/t0000-basic.sh
+++ b/t/t0000-basic.sh
@@ -166,7 +166,7 @@ cat >expected <<\EOF
 EOF
 test_expect_success \
     'validate git-diff-files output for a know cache/work tree state.' \
-    'git-diff-files >current && cmp -s current expected'
+    'git-diff-files >current && diff >/dev/null -b current expected'
 
 test_expect_success \
     'git-update-cache --refresh should succeed.' \
diff --git a/t/t0110-environment-names-old.sh b/t/t0110-environment-names-old.sh
diff --git a/t/t1000-read-tree-m-3way.sh b/t/t1000-read-tree-m-3way.sh
diff --git a/t/t2002-checkout-cache-u.sh b/t/t2002-checkout-cache-u.sh
--- a/t/t2002-checkout-cache-u.sh
+++ b/t/t2002-checkout-cache-u.sh
@@ -29,3 +29,5 @@ rm -f path0 &&
 git-read-tree $t &&
 git-checkout-cache -u -f -a &&
 git-diff-files | diff - /dev/null'
+
+test_done
diff --git a/t/t4000-diff-format.sh b/t/t4000-diff-format.sh
diff --git a/t/t4001-diff-rename.sh b/t/t4001-diff-rename.sh
--- a/t/t4001-diff-rename.sh
+++ b/t/t4001-diff-rename.sh
@@ -58,3 +58,9 @@ rename new path1
  Line 13
  Line 14
 EOF
+
+test_expect_success \
+    'validate the output.' \
+    'diff -I "rename similarity.*" >/dev/null current expected'
+
+test_done
------------------------------------------------


^ permalink raw reply

* Re: gitk-1.0 released
From: Frank Sorenson @ 2005-05-20  4:55 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: Paul Mackerras, git
In-Reply-To: <1116544421.5153.46.camel@gaston>

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Benjamin Herrenschmidt wrote:
> Cool !
> 
> Here's a feature request though: beeing able to type/paste a SHA1 in the
> SHA1 ID field to "jump" to that commit :)

Very nice.  I really like gitk as well.  In addition to pasting an sha1
in, how about pasting a tag?

Also, what about identifying tagged commits with a different color, a
star instead of just the round bullet, or some other identifier?

Frank
- --
Frank Sorenson - KD7TZK
Systems Manager, Computer Science Department
Brigham Young University
frank@tuxrocks.com
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.6 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFCjW2yaI0dwg4A47wRArsEAKCdkTBQEPD7yyb8ABiBg20nhdmKgACg2D2Y
W0ZxoOGTOspvrRczeEYN9mg=
=y2Z0
-----END PGP SIGNATURE-----

^ permalink raw reply

* Re: [PATCH] diff overhaul
From: Linus Torvalds @ 2005-05-20  5:30 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vll6awta3.fsf@assigned-by-dhcp.cox.net>



On Thu, 19 May 2005, Junio C Hamano wrote:
> 
> This also allowed diff-cache and diff-files to acquire -R
> (reverse) option to generate diff in reverse.  Users of
> diff-tree can swap two trees easily so I did not add -R there.

Actually, diff-tree would want it too.

You can only swap the trees easily if you give two trees, not if you give 
a commit.

		Linus

^ permalink raw reply

* [PATCH] Fix git-fsck-cache segfault on invalid tag
From: Frank Sorenson @ 2005-05-20  7:00 UTC (permalink / raw)
  To: Git Mailing List, Linus Torvalds

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

git-fsck-cache will segfault if a tag contains a non-existent sha1.  This
patch fixes fsck-cache to report the invalid tag and not die.

- ---
commit a6a237ee3f3d2f5d76499b8f32f58057c9b4cd2d
tree ac5d65a040c22194ddcd0706dc5f0b8bb52aef65
parent 5cd4c7b7686d334e341b21d92449349feda3ef65
author Frank Sorenson <frank@tuxrocks.com> Fri, 20 May 2005 00:52:59 -0600
committer Frank Sorenson <frank@tuxrocks.com> Fri, 20 May 2005 00:52:59 -0600

 fsck-cache.c |    4 ++++
 1 files changed, 4 insertions(+)

Index: fsck-cache.c
===================================================================
- --- ca5fef50fb68a3afbb35e1a48ac622f7a964f021/fsck-cache.c  (mode:100644)
+++ ac5d65a040c22194ddcd0706dc5f0b8bb52aef65/fsck-cache.c  (mode:100644)
@@ -315,6 +315,10 @@
 		return;
 
 	obj = lookup_object(sha1);
+	if (!obj) {
+		fprintf(stderr, "invalid tag %s - %s\n", path, hexname);
+		return;
+	}
 	obj->used = 1;
 	mark_reachable(obj, REACHABLE);
 }

Frank
- -- 
Frank Sorenson - KD7TZK
Systems Manager, Computer Science Department
Brigham Young University
frank@tuxrocks.com
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.6 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFCjYsZaI0dwg4A47wRAn2PAJ9hyoev3stnaN0Qn2wWlBJEKiucQACgvT9Z
rVazYmUFj3nXvJDYaBoSRsM=
=KbSv
-----END PGP SIGNATURE-----

^ permalink raw reply

* Re: [PATCH] Fix git-fsck-cache segfault on invalid tag
From: Petr Baudis @ 2005-05-20  8:50 UTC (permalink / raw)
  To: Frank Sorenson; +Cc: Git Mailing List, Linus Torvalds
In-Reply-To: <428D8B19.4070605@tuxrocks.com>

Dear diary, on Fri, May 20, 2005 at 09:00:41AM CEST, I got a letter
where Frank Sorenson <frank@tuxrocks.com> told me that...
> git-fsck-cache will segfault if a tag contains a non-existent sha1.  This
> patch fixes fsck-cache to report the invalid tag and not die.

Oh. I've fixed this too but didn't even get to commit it yet. :-)

> Index: fsck-cache.c
> ===================================================================
> --- ca5fef50fb68a3afbb35e1a48ac622f7a964f021/fsck-cache.c  (mode:100644)
> +++ ac5d65a040c22194ddcd0706dc5f0b8bb52aef65/fsck-cache.c  (mode:100644)
> @@ -315,6 +315,10 @@
>  		return;
>  
>  	obj = lookup_object(sha1);
> +	if (!obj) {
> +		fprintf(stderr, "invalid tag %s - %s\n", path, hexname);
> +		return;
> +	}
>  	obj->used = 1;
>  	mark_reachable(obj, REACHABLE);
>  }

My error message is

	error("%s: invalid sha1 pointer %.40s", path, hexname);

I'd prefer that (at least use the error() call). The .40 is there since
it has a newline on its own.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor

^ permalink raw reply

* [cogito] paged output for cg-diff
From: Michal Rokos @ 2005-05-20  9:05 UTC (permalink / raw)
  To: git

Hello,

I'm a bit curious what is going on in development so I'm using cg-diff
often. Usually I pipe it to the less. So for me it would be very nice
when cg-diff behaves as cg-log that pipes output to pager.

So I changed cg-diff to do so.

New function PAGER() determines whether output is terminal and uses
PAGER in that case.

Do you like it?

 Michal

Signed-off-by: Michal Rokos <michal@rokos.info>

Index: cg-Xlib
===================================================================
--- ca5fef50fb68a3afbb35e1a48ac622f7a964f021/cg-Xlib  (mode:100755)
+++ uncommitted/cg-Xlib  (mode:100755)
@@ -91,3 +91,12 @@
 
 export BROKEN_MKTEMP=1
 del=$($(which mktemp) -t 2>/dev/null) && { rm $del; export BROKEN_MKTEMP=; }
+
+PAGER () {
+ if [ -t 1 ]; then
+  ${PAGER:-less} ${PAGER_FLAGS:--R}
+ else
+  cat
+ fi
+}
+
Index: cg-diff
===================================================================
--- ca5fef50fb68a3afbb35e1a48ac622f7a964f021/cg-diff  (mode:100755)
+++ uncommitted/cg-diff  (mode:100755)
@@ -71,7 +71,7 @@
  # FIXME: Update ret based on what did we match. And take "$@"
  # to account after all.
  ret=
- git-diff-cache -r -z $tree | xargs -0 ${COGITO_LIB}cg-Xdiffdo "$tree" uncommitted "$filter"
+ git-diff-cache -r -z $tree | xargs -0 ${COGITO_LIB}cg-Xdiffdo "$tree" uncommitted "$filter" | PAGER
 
  [ "$filter" ] && rm $filter
 
@@ -85,7 +85,7 @@
 
 [ "$id1" = "$id2" ] && die "trying to diff $id1 against itself"
 
-git-diff-tree -r -z $id1 $id2 | xargs -0 ${COGITO_LIB}cg-Xdiffdo $id1 $id2 "$filter"
+git-diff-tree -r -z $id1 $id2 | xargs -0 ${COGITO_LIB}cg-Xdiffdo $id1 $id2 "$filter" | PAGER
 
 [ "$filter" ] && rm $filter
 exit 0
Index: cg-log
===================================================================
--- ca5fef50fb68a3afbb35e1a48ac622f7a964f021/cg-log  (mode:100755)
+++ uncommitted/cg-log  (mode:100755)
@@ -181,4 +181,4 @@
 
   done
  echo
-done | ${PAGER:-less} ${PAGER_FLAGS:--R}
+done | PAGER

-- 
Michal Rokos

NextSoft s.r.o.
Vyskočilova 1/1410
140 21 Praha 4
tel: +420 267 224 311
fax: +420 267 224 307
mobil: +420 736 646 591
e-mail: michal.rokos@nextsoft.cz

^ permalink raw reply

* Re: gitk-1.0 released
From: Ingo Molnar @ 2005-05-20 11:22 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: git
In-Reply-To: <17037.5109.556362.904185@cargo.ozlabs.ibm.com>


* Paul Mackerras <paulus@samba.org> wrote:

> > (and the biggest missing feature of GIT right now is author + 
> > last-commit annotated file viewing which could be integrated into gitk 
> > a'ka BK's revtool: selecting a given line of the file would bring one to 
> > that commit, etc.)
> 
> Yes, indeed.  I'll have to think about how to do it in a responsive 
> fashion, since getting the necessary information involves reading all 
> the commits and all the tree objects back to the beginning of time, 
> AFAICS. [...]

i guess so. A possible solution seems to be to read every object 
starting at the oldest one (assuming it's possible to get a list of 
object IDs that are predecessors), and to split the oldest object up 
into 'line' objects, attaching the (same) object ID to every line. Then 
the algorithm would go forward in time and would process every diff from 
that point on, and would add/remove line objects, attaching the new 
object IDs as new lines get added. The resulting set of lines then 
contain all the metadata needed (== object ID they originate from).

i dont think other SCMs can do this much faster: you need to go back to 
the last (still relevant) version and have to process the deltas from 
that point on. Delta-based formats would be somewhat faster and easier 
to process, but probably not that much faster in terms of IO overhead.

	Ingo

^ permalink raw reply

* Re: gitk-1.0 released
From: Ingo Molnar @ 2005-05-20 11:33 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: git
In-Reply-To: <17037.5109.556362.904185@cargo.ozlabs.ibm.com>


* Paul Mackerras <paulus@samba.org> wrote:

> > - first window appearance on an uncached repository can be pretty slow 
> >   due to disk seeks - so it might make sense to display something (an 
> >   hourglass?) sooner - when i first started it i thought it hung. On 
> >   already cached repositories the window comes up immediately, and the 
> >   list of commits is updated dynamically.
> 
> The problem is that git-rev-tree HEAD doesn't output anything until it 
> has read all the relevant commits, which can involve a lot of disk 
> seeks.  I put the "Reading commits..." message in to indicate that 
> something was happening, but your hourglass cursor suggestion is a 
> good one.  It looks like git-rev-list might be better suited to what I 
> want, actually.

it was quite a couple of seconds to get the empty windows with the 
'Reading commits...' message. It was this first period of time (5-10 
seconds?) which i mistook for a hang. Perhaps this is some Tk startup 
slowness, not a genuine gitk issue?

> +	if {$nparents($id) > 2} {
> +	    set xt [expr {$xt + ($nparents($id) - 2) * $linespc}]
> +	}

thanks, this fix did the trick.

	Ingo

^ permalink raw reply

* Re: [cogito] paged output for cg-diff
From: Junio C Hamano @ 2005-05-20 12:53 UTC (permalink / raw)
  To: Michal Rokos; +Cc: git
In-Reply-To: <200505201105.08711.michal.rokos@nextsoft.cz>

>>>>> "MR" == Michal Rokos <michal.rokos@nextsoft.cz> writes:

MR> I'm a bit curious what is going on in development so I'm using cg-diff
MR> often. Usually I pipe it to the less. So for me it would be very nice
MR> when cg-diff behaves as cg-log that pipes output to pager.

I think that is a sensible thing to do.  But doesn't "less"
already do this part without being told?

MR> +PAGER () {
MR> + if [ -t 1 ]; then
MR> +  ${PAGER:-less} ${PAGER_FLAGS:--R}
MR> + else
MR> +  cat
MR> + fi
MR> +}



^ permalink raw reply

* Re: [cogito] paged output for cg-diff
From: Michal Rokos @ 2005-05-20 13:17 UTC (permalink / raw)
  To: git

Hello,

Junio is right, following is sufficent. Tested with 'more' too.

 Michal

PS: I'm off the list, so please CC me.

Signed-off-by: Michal Rokos <michal@rokos.info>
Idea-from: Junio C Hamano <junkio@cox.net>

Index: cg-Xlib
===================================================================
--- ca5fef50fb68a3afbb35e1a48ac622f7a964f021/cg-Xlib  (mode:100755)
+++ uncommitted/cg-Xlib  (mode:100755)
@@ -91,3 +91,8 @@

 export BROKEN_MKTEMP=1
 del=$($(which mktemp) -t 2>/dev/null) && { rm $del; export BROKEN_MKTEMP=; }
+
+PAGER () {
+       ${PAGER:-less} ${PAGER_FLAGS:--R}
+}
+
Index: cg-diff
===================================================================
--- ca5fef50fb68a3afbb35e1a48ac622f7a964f021/cg-diff  (mode:100755)
+++ uncommitted/cg-diff  (mode:100755)
@@ -71,7 +71,7 @@
        # FIXME: Update ret based on what did we match. And take "$@"
        # to account after all.
        ret=
-       git-diff-cache -r -z $tree | xargs -0 ${COGITO_LIB}cg-Xdiffdo "$tree" uncommitted "$filter"
+       git-diff-cache -r -z $tree | xargs -0 ${COGITO_LIB}cg-Xdiffdo "$tree" uncommitted "$filter" | PAGER

        [ "$filter" ] && rm $filter

@@ -85,7 +85,7 @@

 [ "$id1" = "$id2" ] && die "trying to diff $id1 against itself"

-git-diff-tree -r -z $id1 $id2 | xargs -0 ${COGITO_LIB}cg-Xdiffdo $id1 $id2 "$filter"
+git-diff-tree -r -z $id1 $id2 | xargs -0 ${COGITO_LIB}cg-Xdiffdo $id1 $id2 "$filter" | PAGER

 [ "$filter" ] && rm $filter
 exit 0
Index: cg-log
===================================================================
--- ca5fef50fb68a3afbb35e1a48ac622f7a964f021/cg-log  (mode:100755)
+++ uncommitted/cg-log  (mode:100755)
@@ -181,4 +181,4 @@

                done
        echo
-done | ${PAGER:-less} ${PAGER_FLAGS:--R}
+done | PAGER

^ permalink raw reply

* [PATCH] Fix and clean up man page building
From: Jonas Fonseca @ 2005-05-20 13:35 UTC (permalink / raw)
  To: Sebastian Kuzminsky; +Cc: git
In-Reply-To: <E1DYpbT-0003jv-JY@highlab.com>

Sebastian Kuzminsky <seb@highlab.com> wrote Thu, May 19, 2005:
> -%.1 : %.xml
> +%.1 %.7 : %.xml
>  	xmlto man $<
> +	# FIXME: this next line works around an output filename bug in asciidoc 6.0.3
> +	[ "$@" = "git.7" ] || mv git.1 $@
>  
>  %.xml : %.txt
>  	asciidoc -b docbook -d manpage $<

This doesn't work for me since make stops when the test fails. Besides
it is a bit verbose. Following is a patch which will only check for
moving when building .7 files. It also cleans up the Makefile so it will
be easier to add the manpages for cogito.

Signed-off-by: Jonas Fonseca <fonseca@diku.dk>

--- f435f47dab3465a47fbd2114cf006e0e869f31a9/Documentation/Makefile  (mode:100644)
+++ uncommitted/Documentation/Makefile  (mode:100644)
@@ -1,6 +1,7 @@
-DOC_SRC=$(wildcard git*.txt)
-DOC_HTML=$(patsubst %.txt,%.html,$(DOC_SRC))
-DOC_MAN=$(patsubst %.txt,%.1,$(wildcard git-*.txt)) git.7
+MAN1_TXT=$(wildcard git-*.txt)
+MAN7_TXT=git.txt
+DOC_HTML=$(patsubst %.txt,%.html,$(MAN1_TXT) $(MAN7_TXT))
+DOC_MAN=$(patsubst %.txt,%.1,$(MAN1_TXT)) $(patsubst %.txt,%.7,$(MAN7_TXT))
 
 all: $(DOC_HTML) $(DOC_MAN)
 
@@ -18,10 +19,12 @@
 %.html : %.txt
 	asciidoc -b css-embedded -d manpage $<
 
+%.7 : %.1
+	# FIXME: this next line works around an output filename bug in asciidoc 6.0.3
+	if [ -f "$<" ]; then mv $< $@; fi
+
 %.1 %.7 : %.xml
 	xmlto man $<
-	# FIXME: this next line works around an output filename bug in asciidoc 6.0.3
-	[ "$@" = "git.7" ] || mv git.1 $@
 
 %.xml : %.txt
 	asciidoc -b docbook -d manpage $<
-- 
Jonas Fonseca

^ permalink raw reply

* Re: [cogito] paged output for cg-diff
From: Junio C Hamano @ 2005-05-20 13:50 UTC (permalink / raw)
  To: Michal Rokos; +Cc: git
In-Reply-To: <200505201517.05995.michal@rokos.info>

>>>>> "MR" == Michal Rokos <michal@rokos.info> writes:

MR> Junio is right, following is sufficent. Tested with 'more' too.
MR> Idea-from: Junio C Hamano <junkio@cox.net>

I appreciate the credit, but that is probably not needed in this
case, since this is quite commonly used pattern.  I've seen many
people do just this:

          command | ${PAGER:-less}

And if you think about it, you would realize that the above is
good enough, and probably is a lot better than what you are
doing.

Your PAGER shell function gives "-R" indiscriminately when
$PAGER_FLAGS is not set (or set to empty, which is even worse
because you are not giving the user to override this _bad_
choice) without even checking if the $PAGER is something that
understands "-R" (namely, "less").  I do not think users with
their PAGER set to "more" or "cat" (I do the latter when I am
working in Emacs) would appreciate that behaviour.

On the other hand, if your user is a "less" user, and if the
user wants it to honor ANSI "color" escape sequences, it would
be more helpful to the user if you educate/encourage the user to
have "LESS=R" in the environment and make that in effect
everywhere less is used not just in Cogito.  Giving that support
silently just in Cogito at the first thought may seem to be more
helpful but in reality it is not.

So I would suggest to use the above form without defining your
own PAGER shell function, and add a tip for "less" users to have
"LESS=R" in their environment somewhere in the documentation.


^ permalink raw reply

* Re: [PATCH] Fix git-fsck-cache segfault on invalid tag
From: Junio C Hamano @ 2005-05-20 13:58 UTC (permalink / raw)
  To: Petr Baudis; +Cc: Frank Sorenson, Git Mailing List, Linus Torvalds
In-Reply-To: <20050520085047.GA27787@pasky.ji.cz>

>>>>> "PB" == Petr Baudis <pasky@ucw.cz> writes:

>> obj = lookup_object(sha1);
>> +	if (!obj) {
>> +		fprintf(stderr, "invalid tag %s - %s\n", path, hexname);
>> +		return;
>> +	}
>> ...

PB> My error message is
PB> 	error("%s: invalid sha1 pointer %.40s", path, hexname);
PB> I'd prefer that (at least use the error() call).

Ack.

I was about to say "doesn't lookup_object() give its own error
message before you say that, though?" because I remembered a
comment to that effect around ll 410 that gets the heads from
the command line argument, and then looked at lookup_object()
implementation to find that it does _not_ give error message.

So if you are going to do this, would you mind giving similar
error message to that command line heads stuff while you are at
it, please?


^ permalink raw reply

* Re: [PATCH] Fix and clean up man page building
From: Raja R Harinath @ 2005-05-20 14:08 UTC (permalink / raw)
  To: git
In-Reply-To: <20050520133533.GA27395@diku.dk>

Hi,

Jonas Fonseca <fonseca@diku.dk> writes:

> +%.7 : %.1
> +	# FIXME: this next line works around an output filename bug in asciidoc 6.0.3
> +	if [ -f "$<" ]; then mv $< $@; fi
> +
>  %.1 %.7 : %.xml
>  	xmlto man $<
> -	# FIXME: this next line works around an output filename bug in asciidoc 6.0.3
> -	[ "$@" = "git.7" ] || mv git.1 $@
>  
>  %.xml : %.txt
>  	asciidoc -b docbook -d manpage $<

That doesn't look right.  I think you want

  %.7: %.xml
      xmlto man %<

  %.1: %.xml
       xmlto man $<
       [ test -f $@ ] || mv git.1 $@

- Hari


^ permalink raw reply

* Re: [PATCH] Fix git-fsck-cache segfault on invalid tag
From: Frank Sorenson @ 2005-05-20 14:36 UTC (permalink / raw)
  To: Petr Baudis; +Cc: Git Mailing List, Linus Torvalds
In-Reply-To: <20050520085047.GA27787@pasky.ji.cz>

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Petr Baudis wrote:
> Dear diary, on Fri, May 20, 2005 at 09:00:41AM CEST, I got a letter
> where Frank Sorenson <frank@tuxrocks.com> told me that...
> 
>>git-fsck-cache will segfault if a tag contains a non-existent sha1.  This
>>patch fixes fsck-cache to report the invalid tag and not die.
> 
> 
> Oh. I've fixed this too but didn't even get to commit it yet. :-)

Okay.  At least we fixed the same bug.  It was a good exercise for me to
track it down anyway :)

> My error message is
> 
> 	error("%s: invalid sha1 pointer %.40s", path, hexname);
> 
> I'd prefer that (at least use the error() call). The .40 is there since
> it has a newline on its own.

Great.  Your message looks fine.  It looks like error() should work fine
as well.

Frank
- --
Frank Sorenson - KD7TZK
Systems Manager, Computer Science Department
Brigham Young University
frank@tuxrocks.com
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.6 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org

iD8DBQFCjfXgaI0dwg4A47wRAikrAKCvPmZBQK34sdnnY61/meuewu2jzQCfT7Qf
TDSNgfp3WBJOTvWG5uhwX4s=
=CUF2
-----END PGP SIGNATURE-----

^ permalink raw reply

* Re: [PATCH] Fix and clean up man page building
From: Jonas Fonseca @ 2005-05-20 14:52 UTC (permalink / raw)
  To: Raja R Harinath; +Cc: git
In-Reply-To: <m37jhu56ta.fsf@harinath.blr.novell.com>

Raja R Harinath <rharinath@novell.com> wrote Fri, May 20, 2005:
> Hi,
> 
> Jonas Fonseca <fonseca@diku.dk> writes:
> 
> > +%.7 : %.1
> > +	# FIXME: this next line works around an output filename bug in asciidoc 6.0.3
> > +	if [ -f "$<" ]; then mv $< $@; fi
> > +
> >  %.1 %.7 : %.xml
> >  	xmlto man $<
> > -	# FIXME: this next line works around an output filename bug in asciidoc 6.0.3
> > -	[ "$@" = "git.7" ] || mv git.1 $@
> >  
> >  %.xml : %.txt
> >  	asciidoc -b docbook -d manpage $<
> 
> That doesn't look right.  I think you want
> 
>   %.7: %.xml
>       xmlto man %<
>
>   %.1: %.xml
>        xmlto man $<
>        [ test -f $@ ] || mv git.1 $@

[ Looks like you mixed up %.1 and %.7 ]

Yes, separating the rule for %.1 and %.7 might be clearer. But it would
be great if it would work for any man page in section 7 not just git.7.
Since I hope to add cogito.7 soon.

-- 
Jonas Fonseca

^ permalink raw reply

* Re: [cogito] paged output for cg-diff
From: Thomas Glanzmann @ 2005-05-20 14:55 UTC (permalink / raw)
  To: git
In-Reply-To: <7v64xevz15.fsf@assigned-by-dhcp.cox.net>

Hello,

> I think that is a sensible thing to do.  But doesn't "less"
> already do this part without being told?

yes, every pager does.

	Thomas

^ permalink raw reply

* "git-diff-tree -R A B == git-diff-tree B A"?
From: Junio C Hamano @ 2005-05-20 14:56 UTC (permalink / raw)
  To: torvalds; +Cc: git

I was preparing a set of tests for diff family because I wanted
to have something that catches screwups I am going to inflict
upon them during the coming couple of days.  One of the tests
accidentally found out that the above is not true in the current
implementation.  Just an excerpt of relevant lines [*1*]:

$ git-diff-tree -r $tree_B $tree_A

+100644 blob 7e426fb079479fd67f6d81f984e4ec649a44bc25 AN
+100644 blob 68a6d8b91da11045cf4aa3a5ab9f2a781c701249 DF/DF
-100644 blob 71420ab81e254145d26d6fc0cddee64c1acd4787 DF
-100644 blob 3c4d8de5fbad08572bab8e10eef8dbb264cf0231 DM

$ git-diff-tree -R $tree_A $tree_B

+100644 blob 7e426fb079479fd67f6d81f984e4ec649a44bc25 AN
-100644 blob 71420ab81e254145d26d6fc0cddee64c1acd4787 DF
+100644 blob 68a6d8b91da11045cf4aa3a5ab9f2a781c701249 DF/DF
-100644 blob 3c4d8de5fbad08572bab8e10eef8dbb264cf0231 DM

I personally don't care about the difference of the order these
are output, but it affects the stability of the test, and also
is inconsistent --- everybody else sorts the entries in the
cache order.

Although I do not see practical problems in this inconsistency,
I am asking you just in case if you care about it.  If there is
a downstream consumer that relies on the ordering of the entries
this may cause problems (diff-helper is OK).

[Footnote]
*1* The trees are taken from t1000-read-tree-m-3way.sh test.


^ permalink raw reply

* [cogito PATCH] Add "-c" (colorize) option to cg-diff
From: Catalin Marinas @ 2005-05-20 14:58 UTC (permalink / raw)
  To: git

[-- Attachment #1: Type: text/plain, Size: 134 bytes --]

An option I found quite useful in quilt. I just copied the
corresponding code from quilt (released under GPLv2) to cg-diff.

Catalin


[-- Attachment #2: patch-color-diff --]
[-- Type: text/plain, Size: 3131 bytes --]

Add "-c" (colorize) option to cg-diff

Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>

Index: cg-diff
===================================================================
--- ca5fef50fb68a3afbb35e1a48ac622f7a964f021/cg-diff  (mode:100755)
+++ uncommitted/cg-diff  (mode:100755)
@@ -14,6 +14,8 @@
 # -p instead of one ID denotes a parent commit to the specified ID
 # (which must not be a tree, obviously).
 #
+# -c colorizes the diff output
+#
 # Outputs a diff converting the first tree to the second one.
 
 . ${COGITO_LIB}cg-Xlib
@@ -22,7 +24,17 @@
 id1=" "
 id2=" "
 parent=
+opt_color=
 
+setup_colors()
+{
+	local C=diff_hdr=32:diff_add=36:diff_mod=35:diff_rem=35:diff_hunk=33:diff_ctx=35:diff_cctx=33:patch_offs=33:patch_fuzz=35:patch_fail=31:clear=00
+	[ -n "$COGITO_COLORS" ] && C="$C:$COGITO_COLORS"
+
+	C=${C//=/=\'$'\e'[}
+	C=color_${C//:/m\'; color_}m\'
+	eval $C
+}
 
 # FIXME: The commandline parsing is awful.
 
@@ -31,6 +43,12 @@
 	parent=1
 fi
 
+if [ "$1" = "-c" ]; then
+	shift
+	opt_color=1
+	setup_colors
+fi
+
 if [ "$1" = "-r" ]; then
 	shift
 	id1=$(echo "$1": | cut -d : -f 1)
@@ -44,6 +62,32 @@
 	shift
 fi
 
+colorize() {
+	if [ "$opt_color" ]; then
+		/usr/bin/gawk '
+		{ if (/^(Index:|\-\-\-|\+\+\+|\*\*\*) /)
+		    print "'$color_diff_hdr'" $0 "'$color_clear'"
+		  else if (/^\+/)
+		    print "'$color_diff_add'" $0 "'$color_clear'"
+		  else if (/^-/)
+		    print "'$color_diff_rem'" $0 "'$color_clear'"
+		  else if (/^!/)
+		    print "'$color_diff_mod'" $0 "'$color_clear'"
+		  else if (/^@@ \-[0-9]+(,[0-9]+)? \+[0-9]+(,[0-9]+)? @@/)
+		    print gensub(/^(@@[^@]*@@)([ \t]*)(.*)/,
+		         "'$color_diff_hunk'" "\\1" "'$color_clear'" \
+			 "\\2" \
+			 "'$color_diff_ctx'" "\\3" "'$color_clear'", "")
+		  else if (/^\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/)
+		    print "'$color_diff_cctx'" $0 "'$color_clear'"
+		  else
+		    print
+		}'
+	else
+		cat
+	fi
+}
+
 if [ "$parent" ]; then
 	id2="$id1"
 	id1=$(parent-id "$id2" | head -n 1)
@@ -71,7 +115,7 @@
 	# FIXME: Update ret based on what did we match. And take "$@"
 	# to account after all.
 	ret=
-	git-diff-cache -r -z $tree | xargs -0 ${COGITO_LIB}cg-Xdiffdo "$tree" uncommitted "$filter"
+	git-diff-cache -r -z $tree | xargs -0 ${COGITO_LIB}cg-Xdiffdo "$tree" uncommitted "$filter" | colorize
 
 	[ "$filter" ] && rm $filter
 
@@ -85,7 +129,7 @@
 
 [ "$id1" = "$id2" ] && die "trying to diff $id1 against itself"
 
-git-diff-tree -r -z $id1 $id2 | xargs -0 ${COGITO_LIB}cg-Xdiffdo $id1 $id2 "$filter"
+git-diff-tree -r -z $id1 $id2 | xargs -0 ${COGITO_LIB}cg-Xdiffdo $id1 $id2 "$filter" | colorize
 
 [ "$filter" ] && rm $filter
 exit 0
Index: cg-help
===================================================================
--- ca5fef50fb68a3afbb35e1a48ac622f7a964f021/cg-help  (mode:100755)
+++ uncommitted/cg-help  (mode:100755)
@@ -26,7 +26,7 @@
 	cg-cancel
 	cg-clone	[-s] SOURCE_LOC [DESTDIR]
 	cg-commit	[-m"Commit message"]... [-e | -E] [FILE]... < log message
-	cg-diff		[-p] [-r FROM_ID[:TO_ID]] [FILE]...
+	cg-diff		[-p] [-c] [-r FROM_ID[:TO_ID]] [FILE]...
 	cg-export	DEST [TREE_ID]
 	cg-help		[COMMAND]
 	cg-init

^ permalink raw reply

* [PATCH] cg-log: make -r id:id show the given id instead of nothing
From: Jonas Fonseca @ 2005-05-20 15:04 UTC (permalink / raw)
  To: Petr Baudis; +Cc: git

If cg-log is passed -r cogito-0.10 -r cogito-0.10 no log entries are
shown. This patch make it show the log for the given ID.

Signed-off-by: Jonas Fonseca <fonseca@diku.dk>

Index: cg-log
===================================================================
--- ca5fef50fb68a3afbb35e1a48ac622f7a964f021/cg-log  (mode:100755)
+++ uncommitted/cg-log  (mode:100755)
@@ -113,6 +113,9 @@
 if [ "$log_end" ]; then
 	id1="$(commit-id $log_start)" || exit 1
 	id2="$(commit-id $log_end)" || exit 1
+	if [ "$id1" = "$id2" ]; then
+		id1=$(git-cat-file commit $id1 | sed -n '/^parent /,0s/parent //p')
+	fi
 	revls="git-rev-tree $id2 ^$id1"
 	revsort="sort -rn"
 	revfmt="git-rev-tree"
-- 
Jonas Fonseca

^ permalink raw reply

* Re: "git-diff-tree -R A B == git-diff-tree B A"?
From: Linus Torvalds @ 2005-05-20 15:20 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vacmquet3.fsf@assigned-by-dhcp.cox.net>



On Fri, 20 May 2005, Junio C Hamano wrote:
>
> I was preparing a set of tests for diff family because I wanted
> to have something that catches screwups I am going to inflict
> upon them during the coming couple of days.  One of the tests
> accidentally found out that the above is not true in the current
> implementation.  Just an excerpt of relevant lines [*1*]:
> 
> $ git-diff-tree -r $tree_B $tree_A
> 
> +100644 blob 7e426fb079479fd67f6d81f984e4ec649a44bc25 AN
> +100644 blob 68a6d8b91da11045cf4aa3a5ab9f2a781c701249 DF/DF
> -100644 blob 71420ab81e254145d26d6fc0cddee64c1acd4787 DF
> -100644 blob 3c4d8de5fbad08572bab8e10eef8dbb264cf0231 DM
> 
> $ git-diff-tree -R $tree_A $tree_B
> 
> +100644 blob 7e426fb079479fd67f6d81f984e4ec649a44bc25 AN
> -100644 blob 71420ab81e254145d26d6fc0cddee64c1acd4787 DF
> +100644 blob 68a6d8b91da11045cf4aa3a5ab9f2a781c701249 DF/DF
> -100644 blob 3c4d8de5fbad08572bab8e10eef8dbb264cf0231 DM


Ahh.. "diff-tree" uses the wrong algorithm for selecting name ordering.

It thinks that "DF" and "DF/" sort equally because it just looks at the
name, not the type. So then, becuse the names sort the same, it will sort
them according to where they come from, and you get the behaviour you see.

It doesn't really matter, but you're right, I should fix it to be
consistent.

git-diff-cache and git-diff-files should automaticallu get it right thanks
to reading the whole tree, so it's likely just git-diff-tree that can get 
confused.

		Linus

^ permalink raw reply

* Re: "git-diff-tree -R A B == git-diff-tree B A"?
From: Junio C Hamano @ 2005-05-20 15:29 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.58.0505200806150.2206@ppc970.osdl.org>

>>>>> "LT" == Linus Torvalds <torvalds@osdl.org> writes:

LT> On Fri, 20 May 2005, Junio C Hamano wrote:
>> 
>> I was preparing a set of tests for diff family because I wanted
>> to have something that catches screwups I am going to inflict
>> upon them during the coming couple of days.  One of the tests
>> accidentally found out that the above is not true in the current
>> implementation.  Just an excerpt of relevant lines [*1*]:
>> 
>> $ git-diff-tree -r $tree_B $tree_A
>> 
>> +100644 blob 7e426fb079479fd67f6d81f984e4ec649a44bc25 AN
>> +100644 blob 68a6d8b91da11045cf4aa3a5ab9f2a781c701249 DF/DF
>> -100644 blob 71420ab81e254145d26d6fc0cddee64c1acd4787 DF
>> -100644 blob 3c4d8de5fbad08572bab8e10eef8dbb264cf0231 DM
>> 
>> $ git-diff-tree -R $tree_A $tree_B
>> 
>> +100644 blob 7e426fb079479fd67f6d81f984e4ec649a44bc25 AN
>> -100644 blob 71420ab81e254145d26d6fc0cddee64c1acd4787 DF
>> +100644 blob 68a6d8b91da11045cf4aa3a5ab9f2a781c701249 DF/DF
>> -100644 blob 3c4d8de5fbad08572bab8e10eef8dbb264cf0231 DM


LT> Ahh.. "diff-tree" uses the wrong algorithm for selecting name ordering.

LT> It thinks that "DF" and "DF/" sort equally because it just looks at the
LT> name, not the type. So then, becuse the names sort the same, it will sort
LT> them according to where they come from, and you get the behaviour you see.

LT> It doesn't really matter, but you're right, I should fix it to be
LT> consistent.

Don't bother.  I already have a fix with the test case.


^ permalink raw reply

* Re: "git-diff-tree -R A B == git-diff-tree B A"?
From: Junio C Hamano @ 2005-05-20 15:32 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.58.0505200806150.2206@ppc970.osdl.org>

Keep git-diff-tree output sorted in cache order on dir/file swap.

When one tree has a tree where the other has a blob, diff-tree
always outputs delete/create pair for that entry; deletion of
the entry in the first tree is output first and then creation in
the second tree.  This order results in entries in the
subdirectories from the first tree reported before the plain
blob is shown from the second tree, i.e. not in the cache order.

This inconsistency may break downstream tools that expect the
entries are sorted, since the git-* tools that output paths in
all other cases do so in the cache order.  Also this is needed
to make "diff-tree A B" === "diff-tree -R B A".

Signed-off-by: Junio C Hamano <junkio@cox.net>
---

diff-tree.c                 |   16 +++
t/lib-read-tree-m-3way.sh   |  144 +++++++++++++++++++++++++++++++++
t/t1000-read-tree-m-3way.sh |  171 ----------------------------------------
t/t4002-diff-basic.sh       |  187 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 347 insertions(+), 171 deletions(-)
new file (100755): t/lib-read-tree-m-3way.sh
new file (100755): t/t4002-diff-basic.sh

diff --git a/diff-tree.c b/diff-tree.c
--- a/diff-tree.c
+++ b/diff-tree.c
@@ -124,8 +124,22 @@ static int compare_tree_entry(void *tree
 	 * file, we need to consider it a remove and an add.
 	 */
 	if (S_ISDIR(mode1) != S_ISDIR(mode2)) {
-		show_file("-", tree1, size1, base);
+		/*
+		 * This "one_first" is needed for keeping the output in
+		 * the cache entry order.  Otherwise, "diff A B" becomes
+		 * different from "diff -R B A".
+		 *
+		 * It may look counterintuitive that one_first is not
+		 * defined as (!recursive || S_ISDIR(mode2)), but this
+		 * is deliberate; again otherwise, "diff A B" becomes
+		 * different from "diff -R B A".
+		 */
+		int one_first = S_ISDIR(mode2);
+		if (one_first)
+			show_file("-", tree1, size1, base);
 		show_file("+", tree2, size2, base);
+		if (!one_first)
+			show_file("-", tree1, size1, base);
 		return 0;
 	}
 
diff --git a/t/lib-read-tree-m-3way.sh b/t/lib-read-tree-m-3way.sh
new file mode 100755
--- /dev/null
+++ b/t/lib-read-tree-m-3way.sh
@@ -0,0 +1,144 @@
+: Included from t1000-read-tree-m-3way.sh and others
+# Original tree.
+mkdir Z
+for a in N D M
+do
+    for b in N D M
+    do
+        p=$a$b
+	echo This is $p from the original tree. >$p
+	echo This is Z/$p from the original tree. >Z/$p
+	test_expect_success \
+	    "adding test file $p and Z/$p" \
+	    'git-update-cache --add $p &&
+	    git-update-cache --add Z/$p'
+    done
+done
+echo This is SS from the original tree. >SS
+test_expect_success \
+    'adding test file SS' \
+    'git-update-cache --add SS'
+cat >TT <<\EOF
+This is a trivial merge sample text.
+Branch A is expected to upcase this word, here.
+There are some filler lines to avoid diff context
+conflicts here,
+like this one,
+and this one,
+and this one is yet another one of them.
+At the very end, here comes another line, that is
+the word, expected to be upcased by Branch B.
+This concludes the trivial merge sample file.
+EOF
+test_expect_success \
+    'adding test file TT' \
+    'git-update-cache --add TT'
+test_expect_success \
+    'prepare initial tree' \
+    'tree_O=$(git-write-tree)'
+
+################################################################
+# Branch A and B makes the changes according to the above matrix.
+
+################################################################
+# Branch A
+
+to_remove=$(echo D? Z/D?)
+rm -f $to_remove
+test_expect_success \
+    'change in branch A (removal)' \
+    'git-update-cache --remove $to_remove'
+
+for p in M? Z/M?
+do
+    echo This is modified $p in the branch A. >$p
+    test_expect_success \
+	'change in branch A (modification)' \
+        "git-update-cache $p"
+done
+
+for p in AN AA Z/AN Z/AA
+do
+    echo This is added $p in the branch A. >$p
+    test_expect_success \
+	'change in branch A (addition)' \
+	"git-update-cache --add $p"
+done
+
+echo This is SS from the modified tree. >SS
+echo This is LL from the modified tree. >LL
+test_expect_success \
+    'change in branch A (addition)' \
+    'git-update-cache --add LL &&
+     git-update-cache SS'
+mv TT TT-
+sed -e '/Branch A/s/word/WORD/g' <TT- >TT
+rm -f TT-
+test_expect_success \
+    'change in branch A (edit)' \
+    'git-update-cache TT'
+
+mkdir DF
+echo Branch A makes a file at DF/DF, creating a directory DF. >DF/DF
+test_expect_success \
+    'change in branch A (change file to directory)' \
+    'git-update-cache --add DF/DF'
+
+test_expect_success \
+    'recording branch A tree' \
+    'tree_A=$(git-write-tree)'
+	   
+################################################################
+# Branch B
+# Start from O
+
+rm -rf [NDMASLT][NDMASLT] Z DF
+mkdir Z
+test_expect_success \
+    'reading original tree and checking out' \
+    'git-read-tree $tree_O &&
+     git-checkout-cache -a'
+
+to_remove=$(echo ?D Z/?D)
+rm -f $to_remove
+test_expect_success \
+    'change in branch B (removal)' \
+    "git-update-cache --remove $to_remove"
+
+for p in ?M Z/?M
+do
+    echo This is modified $p in the branch B. >$p
+    test_expect_success \
+	'change in branch B (modification)' \
+	"git-update-cache $p"
+done
+
+for p in NA AA Z/NA Z/AA
+do
+    echo This is added $p in the branch B. >$p
+    test_expect_success \
+	'change in branch B (addition)' \
+	"git-update-cache --add $p"
+done
+echo This is SS from the modified tree. >SS
+echo This is LL from the modified tree. >LL
+test_expect_success \
+    'change in branch B (addition and modification)' \
+    'git-update-cache --add LL &&
+     git-update-cache SS'
+mv TT TT-
+sed -e '/Branch B/s/word/WORD/g' <TT- >TT
+rm -f TT-
+test_expect_success \
+    'change in branch B (modification)' \
+    'git-update-cache TT'
+
+echo Branch B makes a file at DF. >DF
+test_expect_success \
+    'change in branch B (addition of a file to conflict with directory)' \
+    'git-update-cache --add DF'
+
+test_expect_success \
+    'recording branch B tree' \
+    'tree_B=$(git-write-tree)'
+
diff --git a/t/t1000-read-tree-m-3way.sh b/t/t1000-read-tree-m-3way.sh
--- a/t/t1000-read-tree-m-3way.sh
+++ b/t/t1000-read-tree-m-3way.sh
@@ -71,177 +71,8 @@ In addition:
  DF: a special case, where A makes a directory and B makes a file.
 
 '
-
 . ./test-lib.sh
-
-# Original tree.
-mkdir Z
-for a in N D M
-do
-    for b in N D M
-    do
-        p=$a$b
-	echo This is $p from the original tree. >$p
-	echo This is Z/$p from the original tree. >Z/$p
-	test_expect_success \
-	    "adding test file $p and Z/$p" \
-	    'git-update-cache --add $p &&
-	    git-update-cache --add Z/$p'
-    done
-done
-echo This is SS from the original tree. >SS
-test_expect_success \
-    'adding test file SS' \
-    'git-update-cache --add SS'
-cat >TT <<\EOF
-This is a trivial merge sample text.
-Branch A is expected to upcase this word, here.
-There are some filler lines to avoid diff context
-conflicts here,
-like this one,
-and this one,
-and this one is yet another one of them.
-At the very end, here comes another line, that is
-the word, expected to be upcased by Branch B.
-This concludes the trivial merge sample file.
-EOF
-test_expect_success \
-    'adding test file TT' \
-    'git-update-cache --add TT'
-test_expect_success \
-    'prepare initial tree' \
-    'tree_O=$(git-write-tree)'
-
-test_expect_success \
-    'commit initial tree' \
-    'commit_O=$(echo "Original tree for the merge test." |
-     git-commit-tree $tree_O)'
-echo $commit_O >.git/HEAD-O
-
-################################################################
-# Branch A and B makes the changes according to the above matrix.
-
-################################################################
-# Branch A
-
-to_remove=$(echo D? Z/D?)
-rm -f $to_remove
-test_expect_success \
-    'change in branch A (removal)' \
-    'git-update-cache --remove $to_remove'
-
-for p in M? Z/M?
-do
-    echo This is modified $p in the branch A. >$p
-    test_expect_success \
-	'change in branch A (modification)' \
-        "git-update-cache $p"
-done
-
-for p in AN AA Z/AN Z/AA
-do
-    echo This is added $p in the branch A. >$p
-    test_expect_success \
-	'change in branch A (addition)' \
-	"git-update-cache --add $p"
-done
-
-echo This is SS from the modified tree. >SS
-echo This is LL from the modified tree. >LL
-test_expect_success \
-    'change in branch A (addition)' \
-    'git-update-cache --add LL &&
-     git-update-cache SS'
-mv TT TT-
-sed -e '/Branch A/s/word/WORD/g' <TT- >TT
-rm -f TT-
-test_expect_success \
-    'change in branch A (edit)' \
-    'git-update-cache TT'
-
-mkdir DF
-echo Branch A makes a file at DF/DF, creating a directory DF. >DF/DF
-test_expect_success \
-    'change in branch A (change file to directory)' \
-    'git-update-cache --add DF/DF'
-
-test_expect_success \
-    'recording branch A tree' \
-    'tree_A=$(git-write-tree)'
-test_expect_success \
-    'committing branch A changes' \
-    'commit_A=$(echo "Branch A for the merge test." |
-           git-commit-tree $tree_A -p $commit_O)'
-echo $commit_A >.git/HEAD-A
-	   
-################################################################
-# Branch B
-# Start from O
-
-rm -rf [NDMASLT][NDMASLT] Z DF
-mkdir Z
-test_expect_success \
-    'reading original tree and checking out' \
-    'git-read-tree $tree_O &&
-     git-checkout-cache -a'
-
-to_remove=$(echo ?D Z/?D)
-rm -f $to_remove
-test_expect_success \
-    'change in branch B (removal)' \
-    "git-update-cache --remove $to_remove"
-
-for p in ?M Z/?M
-do
-    echo This is modified $p in the branch B. >$p
-    test_expect_success \
-	'change in branch B (modification)' \
-	"git-update-cache $p"
-done
-
-for p in NA AA Z/NA Z/AA
-do
-    echo This is added $p in the branch B. >$p
-    test_expect_success \
-	'change in branch B (addition)' \
-	"git-update-cache --add $p"
-done
-echo This is SS from the modified tree. >SS
-echo This is LL from the modified tree. >LL
-test_expect_success \
-    'change in branch B (addition and modification)' \
-    'git-update-cache --add LL &&
-     git-update-cache SS'
-mv TT TT-
-sed -e '/Branch B/s/word/WORD/g' <TT- >TT
-rm -f TT-
-test_expect_success \
-    'change in branch B (modification)' \
-    'git-update-cache TT'
-
-echo Branch B makes a file at DF. >DF
-test_expect_success \
-    'change in branch B (addition of a file to conflict with directory)' \
-    'git-update-cache --add DF'
-
-test_expect_success \
-    'recording branch B tree' \
-    'tree_B=$(git-write-tree)'
-test_expect_success \
-    'committing branch B changes' \
-    'commit_B=$(echo "Branch B for the merge test." |
-           git-commit-tree $tree_B -p $commit_O)'
-echo $commit_B >.git/HEAD-B
-
-################################################################
-# Done preparation.
-
-test_debug '
-    for T in O A B
-    do
-	echo "# $T $(eval git-cat-file commit \$commit_$T | sed -e 1q)"
-    done
-'
+. ../lib-read-tree-m-3way.sh
 
 ################################################################
 # Try merging and showing the various diffs
diff --git a/t/t4002-diff-basic.sh b/t/t4002-diff-basic.sh
new file mode 100755
--- /dev/null
+++ b/t/t4002-diff-basic.sh
@@ -0,0 +1,187 @@
+#!/bin/sh
+#
+# Copyright (c) 2005 Junio C Hamano
+#
+
+test_description='Test diff raw-output.
+
+'
+. ./test-lib.sh
+. ../lib-read-tree-m-3way.sh
+
+cat >.test-plain-OA <<\EOF
++100644 blob ccba72ad3888a3520b39efcf780b9ee64167535d AA
++100644 blob 7e426fb079479fd67f6d81f984e4ec649a44bc25 AN
+-100644 blob bcc68ef997017466d5c9094bcf7692295f588c9a DD
++040000 tree 6d50f65d3bdab91c63444294d38f08aeff328e42 DF
+-100644 blob 141c1f1642328e4bc46a7d801a71da392e66791e DM
+-100644 blob 35abde1506ddf806572ff4d407bd06885d0f8ee9 DN
++100644 blob 1d41122ebdd7a640f29d3c9cc4f9d70094374762 LL
+*100644->100644 blob 03f24c8c4700babccfd28b654e7e8eac402ad6cd->103d9f89b50b9aad03054b579be5e7aa665f2d57 MD
+*100644->100644 blob b258508afb7ceb449981bd9d63d2d3e971bf8d34->b431b272d829ff3aa4d1a5085f4394ab4d3305b6 MM
+*100644->100644 blob bd084b0c27c7b6cc34f11d6d0509a29be3caf970->a716d58de4a570e0038f5c307bd8db34daea021f MN
+*100644->100644 blob 40c959f984c8b89a2b02520d17f00d717f024397->2ac547ae9614a00d1b28275de608131f7a0e259f SS
+*100644->100644 blob 4ac13458899ab908ef3b1128fa378daefc88d356->4c86f9a85fbc5e6804ee2e17a797538fbe785bca TT
+*040000->040000 tree 7d670fdcdb9929f6c7dac196ff78689cd1c566a1->5e5f22072bb39f6e12cf663a57cb634c76eefb49 Z
+EOF
+
+cat >.test-recursive-OA <<\EOF
++100644 blob ccba72ad3888a3520b39efcf780b9ee64167535d AA
++100644 blob 7e426fb079479fd67f6d81f984e4ec649a44bc25 AN
+-100644 blob bcc68ef997017466d5c9094bcf7692295f588c9a DD
++100644 blob 68a6d8b91da11045cf4aa3a5ab9f2a781c701249 DF/DF
+-100644 blob 141c1f1642328e4bc46a7d801a71da392e66791e DM
+-100644 blob 35abde1506ddf806572ff4d407bd06885d0f8ee9 DN
++100644 blob 1d41122ebdd7a640f29d3c9cc4f9d70094374762 LL
+*100644->100644 blob 03f24c8c4700babccfd28b654e7e8eac402ad6cd->103d9f89b50b9aad03054b579be5e7aa665f2d57 MD
+*100644->100644 blob b258508afb7ceb449981bd9d63d2d3e971bf8d34->b431b272d829ff3aa4d1a5085f4394ab4d3305b6 MM
+*100644->100644 blob bd084b0c27c7b6cc34f11d6d0509a29be3caf970->a716d58de4a570e0038f5c307bd8db34daea021f MN
+*100644->100644 blob 40c959f984c8b89a2b02520d17f00d717f024397->2ac547ae9614a00d1b28275de608131f7a0e259f SS
+*100644->100644 blob 4ac13458899ab908ef3b1128fa378daefc88d356->4c86f9a85fbc5e6804ee2e17a797538fbe785bca TT
++100644 blob 8acb8e9750e3f644bf323fcf3d338849db106c77 Z/AA
++100644 blob 087494262084cefee7ed484d20c8dc0580791272 Z/AN
+-100644 blob 879007efae624d2b1307214b24a956f0a8d686a8 Z/DD
+-100644 blob 9b541b2275c06e3a7b13f28badf5294e2ae63df4 Z/DM
+-100644 blob beb5d38c55283d280685ea21a0e50cfcc0ca064a Z/DN
+*100644->100644 blob d41fda41b7ec4de46b43cb7ea42a45001ae393d5->a79ac3be9377639e1c7d1edf1ae1b3a5f0ccd8a9 Z/MD
+*100644->100644 blob 4ca22bae2527d3d9e1676498a0fba3b355bd1278->61422ba9c2c873416061a88cd40a59a35b576474 Z/MM
+*100644->100644 blob b16d7b25b869f2beb124efa53467d8a1550ad694->a5c544c21cfcb07eb80a4d89a5b7d1570002edfd Z/MN
+EOF
+cat >.test-plain-OB <<\EOF
++100644 blob 6aa2b5335b16431a0ef71e5c0a28be69183cf6a2 AA
+-100644 blob bcc68ef997017466d5c9094bcf7692295f588c9a DD
++100644 blob 71420ab81e254145d26d6fc0cddee64c1acd4787 DF
+*100644->100644 blob 141c1f1642328e4bc46a7d801a71da392e66791e->3c4d8de5fbad08572bab8e10eef8dbb264cf0231 DM
++100644 blob 1d41122ebdd7a640f29d3c9cc4f9d70094374762 LL
+-100644 blob 03f24c8c4700babccfd28b654e7e8eac402ad6cd MD
+*100644->100644 blob b258508afb7ceb449981bd9d63d2d3e971bf8d34->19989d4559aae417fedee240ccf2ba315ea4dc2b MM
++100644 blob 15885881ea69115351c09b38371f0348a3fb8c67 NA
+-100644 blob a4e179e4291e5536a5e1c82e091052772d2c5a93 ND
+*100644->100644 blob c8f25781e8f1792e3e40b74225e20553041b5226->cdb9a8c3da571502ac30225e9c17beccb8387983 NM
+*100644->100644 blob 40c959f984c8b89a2b02520d17f00d717f024397->2ac547ae9614a00d1b28275de608131f7a0e259f SS
+*100644->100644 blob 4ac13458899ab908ef3b1128fa378daefc88d356->c4e4a12231b9fa79a0053cb6077fcb21bb5b135a TT
+*040000->040000 tree 7d670fdcdb9929f6c7dac196ff78689cd1c566a1->1ba523955d5160681af65cb776411f574c1e8155 Z
+EOF
+cat >.test-recursive-OB <<\EOF
++100644 blob 6aa2b5335b16431a0ef71e5c0a28be69183cf6a2 AA
+-100644 blob bcc68ef997017466d5c9094bcf7692295f588c9a DD
++100644 blob 71420ab81e254145d26d6fc0cddee64c1acd4787 DF
+*100644->100644 blob 141c1f1642328e4bc46a7d801a71da392e66791e->3c4d8de5fbad08572bab8e10eef8dbb264cf0231 DM
++100644 blob 1d41122ebdd7a640f29d3c9cc4f9d70094374762 LL
+-100644 blob 03f24c8c4700babccfd28b654e7e8eac402ad6cd MD
+*100644->100644 blob b258508afb7ceb449981bd9d63d2d3e971bf8d34->19989d4559aae417fedee240ccf2ba315ea4dc2b MM
++100644 blob 15885881ea69115351c09b38371f0348a3fb8c67 NA
+-100644 blob a4e179e4291e5536a5e1c82e091052772d2c5a93 ND
+*100644->100644 blob c8f25781e8f1792e3e40b74225e20553041b5226->cdb9a8c3da571502ac30225e9c17beccb8387983 NM
+*100644->100644 blob 40c959f984c8b89a2b02520d17f00d717f024397->2ac547ae9614a00d1b28275de608131f7a0e259f SS
+*100644->100644 blob 4ac13458899ab908ef3b1128fa378daefc88d356->c4e4a12231b9fa79a0053cb6077fcb21bb5b135a TT
++100644 blob 6c0b99286d0bce551ac4a7b3dff8b706edff3715 Z/AA
+-100644 blob 879007efae624d2b1307214b24a956f0a8d686a8 Z/DD
+*100644->100644 blob 9b541b2275c06e3a7b13f28badf5294e2ae63df4->d77371d15817fcaa57eeec27f770c505ba974ec1 Z/DM
+-100644 blob d41fda41b7ec4de46b43cb7ea42a45001ae393d5 Z/MD
+*100644->100644 blob 4ca22bae2527d3d9e1676498a0fba3b355bd1278->697aad7715a1e7306ca76290a3dd4208fbaeddfa Z/MM
++100644 blob d12979c22fff69c59ca9409e7a8fe3ee25eaee80 Z/NA
+-100644 blob a18393c636b98e9bd7296b8b437ea4992b72440c Z/ND
+*100644->100644 blob 3fdbe17fd013303a2e981e1ca1c6cd6e72789087->7e09d6a3a14bd630913e8c75693cea32157b606d Z/NM
+EOF
+cat >.test-plain-AB <<\EOF
+*100644->100644 blob ccba72ad3888a3520b39efcf780b9ee64167535d->6aa2b5335b16431a0ef71e5c0a28be69183cf6a2 AA
+-100644 blob 7e426fb079479fd67f6d81f984e4ec649a44bc25 AN
++100644 blob 71420ab81e254145d26d6fc0cddee64c1acd4787 DF
+-040000 tree 6d50f65d3bdab91c63444294d38f08aeff328e42 DF
++100644 blob 3c4d8de5fbad08572bab8e10eef8dbb264cf0231 DM
++100644 blob 35abde1506ddf806572ff4d407bd06885d0f8ee9 DN
+-100644 blob 103d9f89b50b9aad03054b579be5e7aa665f2d57 MD
+*100644->100644 blob b431b272d829ff3aa4d1a5085f4394ab4d3305b6->19989d4559aae417fedee240ccf2ba315ea4dc2b MM
+*100644->100644 blob a716d58de4a570e0038f5c307bd8db34daea021f->bd084b0c27c7b6cc34f11d6d0509a29be3caf970 MN
++100644 blob 15885881ea69115351c09b38371f0348a3fb8c67 NA
+-100644 blob a4e179e4291e5536a5e1c82e091052772d2c5a93 ND
+*100644->100644 blob c8f25781e8f1792e3e40b74225e20553041b5226->cdb9a8c3da571502ac30225e9c17beccb8387983 NM
+*100644->100644 blob 4c86f9a85fbc5e6804ee2e17a797538fbe785bca->c4e4a12231b9fa79a0053cb6077fcb21bb5b135a TT
+*040000->040000 tree 5e5f22072bb39f6e12cf663a57cb634c76eefb49->1ba523955d5160681af65cb776411f574c1e8155 Z
+EOF
+cat >.test-recursive-AB <<\EOF
+*100644->100644 blob ccba72ad3888a3520b39efcf780b9ee64167535d->6aa2b5335b16431a0ef71e5c0a28be69183cf6a2 AA
+-100644 blob 7e426fb079479fd67f6d81f984e4ec649a44bc25 AN
++100644 blob 71420ab81e254145d26d6fc0cddee64c1acd4787 DF
+-100644 blob 68a6d8b91da11045cf4aa3a5ab9f2a781c701249 DF/DF
++100644 blob 3c4d8de5fbad08572bab8e10eef8dbb264cf0231 DM
++100644 blob 35abde1506ddf806572ff4d407bd06885d0f8ee9 DN
+-100644 blob 103d9f89b50b9aad03054b579be5e7aa665f2d57 MD
+*100644->100644 blob b431b272d829ff3aa4d1a5085f4394ab4d3305b6->19989d4559aae417fedee240ccf2ba315ea4dc2b MM
+*100644->100644 blob a716d58de4a570e0038f5c307bd8db34daea021f->bd084b0c27c7b6cc34f11d6d0509a29be3caf970 MN
++100644 blob 15885881ea69115351c09b38371f0348a3fb8c67 NA
+-100644 blob a4e179e4291e5536a5e1c82e091052772d2c5a93 ND
+*100644->100644 blob c8f25781e8f1792e3e40b74225e20553041b5226->cdb9a8c3da571502ac30225e9c17beccb8387983 NM
+*100644->100644 blob 4c86f9a85fbc5e6804ee2e17a797538fbe785bca->c4e4a12231b9fa79a0053cb6077fcb21bb5b135a TT
+*100644->100644 blob 8acb8e9750e3f644bf323fcf3d338849db106c77->6c0b99286d0bce551ac4a7b3dff8b706edff3715 Z/AA
+-100644 blob 087494262084cefee7ed484d20c8dc0580791272 Z/AN
++100644 blob d77371d15817fcaa57eeec27f770c505ba974ec1 Z/DM
++100644 blob beb5d38c55283d280685ea21a0e50cfcc0ca064a Z/DN
+-100644 blob a79ac3be9377639e1c7d1edf1ae1b3a5f0ccd8a9 Z/MD
+*100644->100644 blob 61422ba9c2c873416061a88cd40a59a35b576474->697aad7715a1e7306ca76290a3dd4208fbaeddfa Z/MM
+*100644->100644 blob a5c544c21cfcb07eb80a4d89a5b7d1570002edfd->b16d7b25b869f2beb124efa53467d8a1550ad694 Z/MN
++100644 blob d12979c22fff69c59ca9409e7a8fe3ee25eaee80 Z/NA
+-100644 blob a18393c636b98e9bd7296b8b437ea4992b72440c Z/ND
+*100644->100644 blob 3fdbe17fd013303a2e981e1ca1c6cd6e72789087->7e09d6a3a14bd630913e8c75693cea32157b606d Z/NM
+EOF
+
+test_expect_success \
+    'diff-tree of known trees.' \
+    'git-diff-tree $tree_O $tree_A >.test-a &&
+     cmp -s .test-a .test-plain-OA'
+
+test_expect_success \
+    'diff-tree of known trees.' \
+    'git-diff-tree -r $tree_O $tree_A >.test-a &&
+     cmp -s .test-a .test-recursive-OA'
+
+test_expect_success \
+    'diff-tree of known trees.' \
+    'git-diff-tree $tree_O $tree_B >.test-a &&
+     cmp -s .test-a .test-plain-OB'
+
+test_expect_success \
+    'diff-tree of known trees.' \
+    'git-diff-tree -r $tree_O $tree_B >.test-a &&
+     cmp -s .test-a .test-recursive-OB'
+
+test_expect_success \
+    'diff-tree of known trees.' \
+    'git-diff-tree $tree_A $tree_B >.test-a &&
+     cmp -s .test-a .test-plain-AB'
+
+test_expect_success \
+    'diff-tree of known trees.' \
+    'git-diff-tree -r $tree_A $tree_B >.test-a &&
+     cmp -s .test-a .test-recursive-AB'
+
+################################################################
+# Now we have established the baseline, we do not have to
+# rely on individual object ID values that much.
+
+test_expect_success \
+    'diff-tree O A == diff-tree -R A O' \
+    'git-diff-tree $tree_O $tree_A >.test-a &&
+    git-diff-tree -R $tree_A $tree_O >.test-b &&
+    cmp -s .test-a .test-b'
+
+test_expect_success \
+    'diff-tree -r O A == diff-tree -r -R A O' \
+    'git-diff-tree -r $tree_O $tree_A >.test-a &&
+    git-diff-tree -r -R $tree_A $tree_O >.test-b &&
+    cmp -s .test-a .test-b'
+
+test_expect_success \
+    'diff-tree B A == diff-tree -R A B' \
+    'git-diff-tree $tree_B $tree_A >.test-a &&
+    git-diff-tree -R $tree_A $tree_B >.test-b &&
+    cmp -s .test-a .test-b'
+
+test_expect_success \
+    'diff-tree -r B A == diff-tree -r -R A B' \
+    'git-diff-tree -r $tree_B $tree_A >.test-a &&
+    git-diff-tree -r -R $tree_A $tree_B >.test-b &&
+    cmp -s .test-a .test-b'
+
+test_done
------------------------------------------------


^ permalink raw reply

* Re: "git-diff-tree -R A B == git-diff-tree B A"?
From: Linus Torvalds @ 2005-05-20 15:53 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vzmupud54.fsf@assigned-by-dhcp.cox.net>



On Fri, 20 May 2005, Junio C Hamano wrote:
>
> Keep git-diff-tree output sorted in cache order on dir/file swap.

No, this is wrong.

Or rather, it is incomplete - it gets only a small subset of the 
interesting cases right.

You need to really teach diff-tree about directory sorting, because it is 
more complicated than you think.

The sorting does _not_ just affect files/directories with the same names.  
It affects files and directories that have the same _beginning_.

The only correct way to do name sorting is the one that fsck does in
"verify_order()". To realize why, you need to realize that "A" (the
directory) sorts _after_ a filename "A file", because '/' sorts after ' '.  

In contrast, "A" (the directory) sorts _before_ "ABBA" (the band), because
'/' sorts before 'B'.

-- 
Side note:

Btw, right now I depend on "memcmp()" doing comparisons as "unsigned
char", which is supposed to be true, but I don't know whether it's 
entirely portable. So it might be that I should implement my own 
"namecmp()" entirely from scratch.

Does anybody know if some broken system does "memcmp" ordering on signed 
chars?

		Linus

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox