Git development
 help / color / mirror / Atom feed
* Re: ALSA official git repository
From: Chris Wedgwood @ 2005-05-28  3:33 UTC (permalink / raw)
  To: Andrew Morton; +Cc: Linus Torvalds, perex, linux-kernel, git
In-Reply-To: <20050527154625.5490f405.akpm@osdl.org>

On Fri, May 27, 2005 at 03:46:25PM -0700, Andrew Morton wrote:

> That all assumes that the tools are smart enough to separate the email
> headers from the body :(

the first blank line separates these, sed can do that --- so is it
really a problem?


^ permalink raw reply

* [PATCH] Adjust diff-helper to diff-tree -v -z changes.
From: Junio C Hamano @ 2005-05-28  4:05 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git
In-Reply-To: <7vfyw8zg1w.fsf@assigned-by-dhcp.cox.net>

The latest change to diff-tree -z output adds an extra line
termination after non diff-raw material (the header and the
commit message).  To compensate for this change, stop adding the
output termination of our own.  "diff-tree -v -z" piped to
"diff-helper -z" would give different result from "diff-tree -v"
piped to "diff-helper" without this change.

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

diff-helper.c |    5 ++++-
1 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/diff-helper.c b/diff-helper.c
--- a/diff-helper.c
+++ b/diff-helper.c
@@ -15,6 +15,7 @@ static const char *diff_helper_usage =
 
 int main(int ac, const char **av) {
 	struct strbuf sb;
+	const char *garbage_flush_format;
 
 	strbuf_init(&sb);
 
@@ -30,6 +31,8 @@ int main(int ac, const char **av) {
 			usage(diff_helper_usage);
 		ac--; av++;
 	}
+	garbage_flush_format = (line_termination == 0) ? "%s" : "%s\n";
+
 	/* the remaining parameters are paths patterns */
 
 	diff_setup(0);
@@ -134,7 +137,7 @@ int main(int ac, const char **av) {
 		if (pickaxe)
 			diffcore_pickaxe(pickaxe, pickaxe_opts);
 		diff_flush(DIFF_FORMAT_PATCH, 0);
-		printf("%s\n", sb.buf);
+		printf(garbage_flush_format, sb.buf);
 	}
 	if (1 < ac)
 		diffcore_pathspec(av + 1);
------------------------------------------------


^ permalink raw reply

* [PATCH-RFC] Rewrite ls-tree to behave more like "/bin/ls -a"
From: Junio C Hamano @ 2005-05-28  7:05 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Jason McMullan, git
In-Reply-To: <7v1x7syqkm.fsf@assigned-by-dhcp.cox.net>

This is a complete rewrite of ls-tree to make it behave more
like what "/bin/ls -a" does in the current working directory.

Namely, the changes are:

 - Unlike the old ls-tree behaviour that used paths arguments to
   restrict output (not that it worked as intended---as pointed
   out in the mailing list discussion, it was quite incoherent),
   this rewrite uses paths arguments to specify what to show.

 - Without arguments, it implicitly uses the root level as its
   sole argument ("/bin/ls -a" behaves as if "." is given
   without argument).

 - Without -r (recursive) flag, it shows the named blob (either
   file or symlink), or the named tree and its immediate
   children.

 - With -r flag, it shows the named path, and recursively
   descends into it if it is a tree.

 - With -d flag, it shows the named path and does not show its
   children even if the path is a tree, nor descends into it
   recursively.

This is still request-for-comments patch.  There is no mailing
list consensus that this proposed new behaviour is a good one.

The patch to t/t3100-ls-tree-restrict.sh illustrates
user-visible behaviour changes.  Namely:

 * "git-ls-tree $tree path1 path0" lists path1 first and then
   path0.  It used to use paths as an output restrictor and
   showed output in cache entry order (i.e. path0 first and then
   path1) regardless of the order of paths arguments.

 * "git-ls-tree $tree path2" lists path2 and its immediate
   children but having explicit paths argument does not imply
   recursive behaviour anymore, hence paths/baz is shown but not
   paths/baz/b.

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

Documentation/git-ls-tree.txt |   20 +-
ls-tree.c                     |  333 +++++++++++++++++++++++-------------------
t/t3100-ls-tree-restrict.sh   |    3 
tree.c                        |    2 
tree.h                        |    1 
5 files changed, 199 insertions(+), 160 deletions(-)

diff --git a/Documentation/git-ls-tree.txt b/Documentation/git-ls-tree.txt
--- a/Documentation/git-ls-tree.txt
+++ b/Documentation/git-ls-tree.txt
@@ -4,23 +4,26 @@ v0.1, May 2005
 
 NAME
 ----
-git-ls-tree - Displays a tree object in human readable form
+git-ls-tree - Lists the contents of a tree object.
 
 
 SYNOPSIS
 --------
-'git-ls-tree' [-r] [-z] <tree-ish> [paths...]
+'git-ls-tree' [-d] [-r] [-z] <tree-ish> [paths...]
 
 DESCRIPTION
 -----------
-Converts the tree object to a human readable (and script processable)
-form.
+Lists the contents of a tree object, like what "/bin/ls -a" does
+in the current working directory.
 
 OPTIONS
 -------
 <tree-ish>::
 	Id of a tree.
 
+-d::
+	show only the named tree entry itself, not its children
+
 -r::
 	recurse into sub-trees
 
@@ -28,18 +31,19 @@ OPTIONS
 	\0 line termination on output
 
 paths::
-	Optionally, restrict the output of git-ls-tree to specific
-	paths. Directories will only list their tree blob ids.
-	Implies -r.
+	When paths are given, shows them.  Otherwise implicitly
+	uses the root level of the tree as the sole path argument.
+
 
 Output Format
 -------------
-        <mode>\t	<type>\t	<object>\t	<file>
+        <mode> SP <type> SP <object> TAB <file>
 
 
 Author
 ------
 Written by Linus Torvalds <torvalds@osdl.org>
+Completely rewritten from scratch by Junio C Hamano <junkio@cox.net>
 
 Documentation
 --------------
diff --git a/ls-tree.c b/ls-tree.c
--- a/ls-tree.c
+++ b/ls-tree.c
@@ -4,188 +4,217 @@
  * Copyright (C) Linus Torvalds, 2005
  */
 #include "cache.h"
+#include "blob.h"
+#include "tree.h"
 
 static int line_termination = '\n';
-static int recursive = 0;
+#define LS_RECURSIVE 1
+#define LS_TREE_ONLY 2
+static int ls_options = 0;
 
-struct path_prefix {
-	struct path_prefix *prev;
-	const char *name;
-};
-
-#define DEBUG(fmt, ...)	
-
-static int string_path_prefix(char *buff, size_t blen, struct path_prefix *prefix)
-{
-	int len = 0;
-	if (prefix) {
-		if (prefix->prev) {
-			len = string_path_prefix(buff,blen,prefix->prev);
-			buff += len;
-			blen -= len;
-			if (blen > 0) {
-				*buff = '/';
-				len++;
-				buff++;
-				blen--;
-			}
-		}
-		strncpy(buff,prefix->name,blen);
-		return len + strlen(prefix->name);
-	}
+static struct tree_entry_list root_entry;
 
-	return 0;
+static void prepare_root(unsigned char *sha1)
+{
+	unsigned char rsha[20];
+	unsigned long size;
+	void *buf;
+	struct tree *root_tree;
+
+	buf = read_object_with_reference(sha1, "tree", &size, rsha);
+	free(buf);
+	if (!buf)
+		die("Could not read %s", sha1_to_hex(sha1));
+
+	root_tree = lookup_tree(rsha);
+	if (!root_tree)
+		die("Could not read %s", sha1_to_hex(sha1));
+
+	/* Prepare a fake entry */
+	root_entry.directory = 1;
+	root_entry.executable = root_entry.symlink = 0;
+	root_entry.mode = S_IFDIR;
+	root_entry.name = "";
+	root_entry.item.tree = root_tree;
+	root_entry.parent = NULL;
 }
 
-static void print_path_prefix(struct path_prefix *prefix)
+static int prepare_children(struct tree_entry_list *elem)
 {
-	if (prefix) {
-		if (prefix->prev) {
-			print_path_prefix(prefix->prev);
-			putchar('/');
-		}
-		fputs(prefix->name, stdout);
+	if (!elem->directory)
+		return -1;
+	if (!elem->item.tree->object.parsed) {
+		struct tree_entry_list *e;
+		if (parse_tree(elem->item.tree))
+			return -1;
+		/* Set up the parent link */
+		for (e = elem->item.tree->entries; e; e = e->next)
+			e->parent = elem;
 	}
+	return 0;
 }
 
-/*
- * return:
- * 	-1 if prefix is *not* a subset of path
- * 	 0 if prefix == path
- * 	 1 if prefix is a subset of path
- */
-static int pathcmp(const char *path, struct path_prefix *prefix)
-{
-	char buff[PATH_MAX];
-	int len,slen;
+static struct tree_entry_list *find_entry_0(struct tree_entry_list *elem,
+					    const char *path,
+					    const char *path_end)
+{
+	const char *ep;
+	int len;
+
+	while (path < path_end) {
+		if (prepare_children(elem))
+			return NULL;
 
-	if (prefix == NULL)
-		return 1;
+		/* In elem->tree->entries, find the one that has name
+		 * that matches what is between path and ep.
+		 */
+		elem = elem->item.tree->entries;
 
-	len = string_path_prefix(buff, sizeof buff, prefix);
-	slen = strlen(path);
+		ep = strchr(path, '/');
+		if (!ep || path_end <= ep)
+			ep = path_end;
+		len = ep - path;
+
+		while (elem) {
+			if ((strlen(elem->name) == len) &&
+			    !strncmp(elem->name, path, len))
+				break;
+			elem = elem->next;
+		}
+		if (path_end <= ep || !elem)
+			return elem;
+		while (*ep == '/' && ep < path_end)
+			ep++;
+		path = ep;
+	}
+	return NULL;
+}
 
-	if (slen < len)
-		return -1;
+static struct tree_entry_list *find_entry(const char *path,
+					  const char *path_end)
+{
+	/* Find tree element, descending from root, that
+	 * corresponds to the named path, lazily expanding
+	 * the tree if possible.
+	 */
+	if (path == path_end) {
+		/* Special.  This is the root level */
+		return &root_entry;
+	}
+	return find_entry_0(&root_entry, path, path_end);
+}
 
-	if (strncmp(path,buff,len) == 0) {
-		if (slen == len)
-			return 0;
-		else
-			return 1;
+static void show_entry_name(struct tree_entry_list *e)
+{
+	/* This is yucky.  The root level is there for
+	 * our convenience but we really want to do a
+	 * forest.
+	 */
+	if (e->parent && e->parent != &root_entry) {
+		show_entry_name(e->parent);
+		putchar('/');
 	}
+	printf("%s", e->name);
+}
 
-	return -1;
-}	
+static const char *entry_type(struct tree_entry_list *e)
+{
+	return (e->directory ? "tree" : "blob");
+}
 
-/*
- * match may be NULL, or a *sorted* list of paths
- */
-static void list_recursive(void *buffer,
-			   const char *type,
-			   unsigned long size,
-			   struct path_prefix *prefix,
-			   char **match, int matches)
-{
-	struct path_prefix this_prefix;
-	this_prefix.prev = prefix;
-
-	if (strcmp(type, "tree"))
-		die("expected a 'tree' node");
-
-	if (matches)
-		recursive = 1;
-
-	while (size) {
-		int namelen = strlen(buffer)+1;
-		void *eltbuf = NULL;
-		char elttype[20];
-		unsigned long eltsize;
-		unsigned char *sha1 = buffer + namelen;
-		char *path = strchr(buffer, ' ') + 1;
-		unsigned int mode;
-		const char *matched = NULL;
-		int mtype = -1;
-		int mindex;
-
-		if (size < namelen + 20 || sscanf(buffer, "%o", &mode) != 1)
-			die("corrupt 'tree' file");
-		buffer = sha1 + 20;
-		size -= namelen + 20;
-
-		this_prefix.name = path;
-		for ( mindex = 0; mindex < matches; mindex++) {
-			mtype = pathcmp(match[mindex],&this_prefix);
-			if (mtype >= 0) {
-				matched = match[mindex];
-				break;
-			}
-		}
+static const char *entry_hex(struct tree_entry_list *e)
+{
+	return sha1_to_hex(e->directory
+			   ? e->item.tree->object.sha1
+			   : e->item.blob->object.sha1);
+}
 
-		/*
-		 * If we're not matching, or if this is an exact match,
-		 * print out the info
-		 */
-		if (!matches || (matched != NULL && mtype == 0)) {
-			printf("%06o %s %s\t", mode,
-			       S_ISDIR(mode) ? "tree" : "blob",
-			       sha1_to_hex(sha1));
-			print_path_prefix(&this_prefix);
-			putchar(line_termination);
-		}
+/* forward declaration for mutually recursive routines */
+static int show_entry(struct tree_entry_list *, int);
 
-		if (! recursive || ! S_ISDIR(mode))
-			continue;
+static int show_children(struct tree_entry_list *e, int level)
+{
+	if (prepare_children(e))
+		die("internal error: ls-tree show_children called with non tree");
+	e = e->item.tree->entries;
+	while (e) {
+		show_entry(e, level);
+		e = e->next;
+	}
+	return 0;
+}
 
-		if (matches && ! matched)
-			continue;
+static int show_entry(struct tree_entry_list *e, int level)
+{
+	int err = 0; 
 
-		if (! (eltbuf = read_sha1_file(sha1, elttype, &eltsize)) ) {
-			error("cannot read %s", sha1_to_hex(sha1));
-			continue;
-		}
+	if (e != &root_entry) {
+		printf("%06o %s %s	", e->mode, entry_type(e),
+		       entry_hex(e));
+		show_entry_name(e);
+		putchar(line_termination);
+	}
 
-		/* If this is an exact directory match, we may have
-		 * directory files following this path. Match on them.
-		 * Otherwise, we're at a pach subcomponent, and we need
-		 * to try to match again.
+	if (e->directory) {
+		/* If this is a directory, we have the following cases:
+		 * (1) This is the top-level request (explicit path from the
+		 *     command line, or "root" if there is no command line).
+		 *  a. Without any flag.  We show direct children.  We do not 
+		 *     recurse into them.
+		 *  b. With -r.  We do recurse into children.
+		 *  c. With -d.  We do not recurse into children.
+		 * (2) We came here because our caller is either (1-a) or
+		 *     (1-b).
+		 *  a. Without any flag.  We do not show our children (which
+		 *     are grandchildren for the original request).
+		 *  b. With -r.  We continue to recurse into our children.
+		 *  c. With -d.  We should not have come here to begin with.
 		 */
-		if (mtype == 0)
-			mindex++;
-
-		list_recursive(eltbuf, elttype, eltsize, &this_prefix, &match[mindex], matches-mindex);
-		free(eltbuf);
+		if (level == 0 && !(ls_options & LS_TREE_ONLY))
+			/* case (1)-a and (1)-b */
+			err = err | show_children(e, level+1);
+		else if (level && ls_options & LS_RECURSIVE)
+			/* case (2)-b */
+			err = err | show_children(e, level+1);
 	}
+	return err;
 }
 
-static int qcmp(const void *a, const void *b)
+static int list_one(const char *path, const char *path_end)
 {
-	return strcmp(*(char **)a, *(char **)b);
+	int err = 0;
+	struct tree_entry_list *e = find_entry(path, path_end);
+	if (!e) {
+		/* traditionally ls-tree does not complain about
+		 * missing path.  We may change this later to match
+		 * what "/bin/ls -a" does, which is to complain.
+		 */
+		return err;
+	}
+	err = err | show_entry(e, 0);
+	return err;
 }
 
-static int list(unsigned char *sha1,char **path)
+static int list(char **path)
 {
-	void *buffer;
-	unsigned long size;
-	int npaths;
-
-	for (npaths = 0; path[npaths] != NULL; npaths++)
-		;
-
-	qsort(path,npaths,sizeof(char *),qcmp);
-
-	buffer = read_object_with_reference(sha1, "tree", &size, NULL);
-	if (!buffer)
-		die("unable to read sha1 file");
-	list_recursive(buffer, "tree", size, NULL, path, npaths);
-	free(buffer);
-	return 0;
+	int i;
+	int err = 0;
+	for (i = 0; path[i]; i++) {
+		int len = strlen(path[i]);
+		while (0 <= len && path[i][len] == '/')
+			len--;
+		err = err | list_one(path[i], path[i] + len);
+	}
+	return err;
 }
 
-static const char *ls_tree_usage = "git-ls-tree [-r] [-z] <key> [paths...]";
+static const char *ls_tree_usage =
+	"git-ls-tree [-d] [-r] [-z] <tree-ish> [path...]";
 
 int main(int argc, char **argv)
 {
+	static char *path0[] = { "", NULL };
+	char **path;
 	unsigned char sha1[20];
 
 	while (1 < argc && argv[1][0] == '-') {
@@ -194,7 +223,10 @@ int main(int argc, char **argv)
 			line_termination = 0;
 			break;
 		case 'r':
-			recursive = 1;
+			ls_options |= LS_RECURSIVE;
+			break;
+		case 'd':
+			ls_options |= LS_TREE_ONLY;
 			break;
 		default:
 			usage(ls_tree_usage);
@@ -206,7 +238,10 @@ int main(int argc, char **argv)
 		usage(ls_tree_usage);
 	if (get_sha1(argv[1], sha1) < 0)
 		usage(ls_tree_usage);
-	if (list(sha1, &argv[2]) < 0)
+
+	path = (argc == 2) ? path0 : (argv + 2);
+	prepare_root(sha1);
+	if (list(path) < 0)
 		die("list failed");
 	return 0;
 }
diff --git a/t/t3100-ls-tree-restrict.sh b/t/t3100-ls-tree-restrict.sh
--- a/t/t3100-ls-tree-restrict.sh
+++ b/t/t3100-ls-tree-restrict.sh
@@ -74,8 +74,8 @@ test_expect_success \
     'ls-tree filtered' \
     'git-ls-tree $tree path1 path0 >current &&
      cat >expected <<\EOF &&
-100644 blob X	path0
 120000 blob X	path1
+100644 blob X	path0
 EOF
      test_output'
 
@@ -85,7 +85,6 @@ test_expect_success \
      cat >expected <<\EOF &&
 040000 tree X	path2
 040000 tree X	path2/baz
-100644 blob X	path2/baz/b
 120000 blob X	path2/bazbo
 100644 blob X	path2/foo
 EOF
diff --git a/tree.c b/tree.c
--- a/tree.c
+++ b/tree.c
@@ -133,7 +133,7 @@ int parse_tree_buffer(struct tree *item,
 		}
 		if (obj)
 			add_ref(&item->object, obj);
-
+		entry->parent = NULL; /* needs to be filled by the user */
 		*list_p = entry;
 		list_p = &entry->next;
 	}
diff --git a/tree.h b/tree.h
--- a/tree.h
+++ b/tree.h
@@ -16,6 +16,7 @@ struct tree_entry_list {
 		struct tree *tree;
 		struct blob *blob;
 	} item;
+	struct tree_entry_list *parent;
 };
 
 struct tree {
------------------------------------------------


^ permalink raw reply

* [OT] if (4 < number_of_children) you're in trouble
From: Junio C Hamano @ 2005-05-28  7:55 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git
In-Reply-To: <7v3bscqdlr.fsf@assigned-by-dhcp.cox.net>

I received this from my mentor tonight.  Although I said I am
not going to discuss this issue anymore, with his permission, I
would like to share where the "visual order" came from with the
list.

From: Paul Eggert <eggert@CS.UCLA.EDU>
Subject: Re: FYI: comparison order in boolean expressions
To: Junio C Hamano <junkio@cox.net>
Date: Sat, 28 May 2005 00:28:31 -0700

> http://marc.theaimsgroup.com/?l=git&m=111698274620068&w=2

Thanks!  That made my day.

You can forward the following to that mailing list if you like:


I learned the "textual order should reflect actual order" convention
from D. Val Schorre, one of the best programmers I've ever worked
with.  Val was credited by Donald E. Knuth as the first person to
seriously advocate goto-less programming.  In 1974 Knuth wrote:

  When I met Schorre in 1963, he told me of his radical ideas, and I
  didn't believe they would work....  In 1964 I challenged him to
  write a program for the eight-queens problem without using go to
  statements, and he responded with a program using recursive
  procedures and Boolean variables, very much like the program later
  published independently by Wirth.

  I was still not convinced....

Knuth's reaction to Schorre's ideas on avoiding gotos sounds a bit
like Linus's reaction to Schorre's ideas on comparison order, no?

Anyway, here's the reference, if you'd like to find out how Knuth's
story ends:

  Donald E. Knuth
  Structured Programming with go to Statements
  ACM Computing Surveys 6, 4 (December 1974), 261-301.
  http://portal.acm.org/citation.cfm?id=356640


PS.  The idea that textual form should reflect the underlying reality
goes all the way back to Gottfried Leibniz's alphabet of human thought
<http://en.wikipedia.org/wiki/Alphabet_of_human_thought>.  Leibniz was
a brilliant designer of notations -- one of the best the world has
ever seen -- and it is amusing to speculate what he would have done
with programming had he been born some time in the past few decades.
(Personally I suspect that Leibniz would have liked "1 < x".)






^ permalink raw reply

* Re: More gitweb queries..
From: Kay Sievers @ 2005-05-28  8:42 UTC (permalink / raw)
  To: Daniel Serpell; +Cc: Git Mailing List
In-Reply-To: <f0796bb705052718035cd5dbe2@mail.gmail.com>

On Fri, May 27, 2005 at 09:03:24PM -0400, Daniel Serpell wrote:
> Hi!
> 
> On 5/27/05, Kay Sievers <kay.sievers@vrfy.org> wrote:
> > On Fri, May 27, 2005 at 12:24:20PM -0700, Linus Torvalds wrote:
> > >   Combining some of the features of the two (that über-cool revision
> > >   history graph from gitk rules, for example) might be cool. I get the
> > >   urge to do octopus-merges in the kernel just because of how good they
> > >   look in gitk ;) ]
> > 
> > I would like to show something like the graph too, but I don't really know
> > how to do this in html. Seems slippery if not impossible.
> > If anybody has a nice idea how to represent that, I will give it a try.
> 
> Well, you could draw them in javascript, using
> http://www.walterzorn.com/jsgraphics/jsgraphics_e.htm :-)

You know how that stuff works? :) It is a very nice idea for
small stuff, but it uses a <div> for every pixel/line you draw and
places this in the background and I expect it to kill your browser if
you try to draw things like gitk does.

> Alternatively, you could use a fixed set of little images, a bar "|", a
> dot "o" and branches like "Y", "7" and "\". Obviously, octopus-merges
> are very difficult to draw using only those.

Did you look at gitk? With a all the crossing and long lines, you definitely
need to draw the lines with colors. Otherwise you will see _nothing_, but
random characters. :)

> BTW, I tried searching on gitweb, and I think that found a problem, see:
> http://ehlo.org/~kay/gitweb.cgi?p=git/git.git;a=search;s=check
> At the bottom of the page, highlighting of the search term stops and the
> commits are all the same color.

Well, you see a list of files which contain the text, not the text
itself. I can print the filename in red. :)

Thanks,
Kay

^ permalink raw reply

* [PATCH] Pickaxe fixes.
From: Junio C Hamano @ 2005-05-28  9:53 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git

A bug in the command line argument parsing code was making
pickaxe not to work at all in diff-cache and diff-files commands.
Embarrassingly enough, the working pickaxe in diff-tree tells me
that it was not working in these two commands from day one.
This patch fixes it.

Also updates the documentation to describe the --pickaxe-all option.

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

Documentation/git-diff-cache.txt |    6 +++++-
Documentation/git-diff-files.txt |    6 +++++-
Documentation/git-diff-tree.txt  |    7 ++++++-
diff-cache.c                     |    2 +-
diff-files.c                     |    2 +-
5 files changed, 18 insertions(+), 5 deletions(-)

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] [-R] [-C] [-S<string>] [--cached] <tree-ish> [<path>...]
+'git-diff-cache' [-p] [-r] [-z] [-m] [-M] [-R] [-C] [-S<string>] [--pickaxe-all] [--cached] <tree-ish> [<path>...]
 
 DESCRIPTION
 -----------
@@ -44,6 +44,10 @@ OPTIONS
 -S<string>::
 	Look for differences that contains the change in <string>.
 
+--pickaxe-all::
+	When -S finds a change, show all the changes in that
+	changeset, not just the files that contains the change
+	in <string>.
 
 -R::
 	Output diff in reverse.
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] [-C] [-R] [-S<string>] [<pattern>...]
+'git-diff-files' [-p] [-q] [-r] [-z] [-M] [-C] [-R] [-S<string>] [--pickaxe-all] [<pattern>...]
 
 DESCRIPTION
 -----------
@@ -38,6 +38,10 @@ OPTIONS
 -S<string>::
 	Look for differences that contains the change in <string>.
 
+--pickaxe-all::
+	When -S finds a change, show all the changes in that
+	changeset, not just the files that contains the change
+	in <string>.
 
 -r::
 	This flag does not mean anything.  It is there only to match
diff --git a/Documentation/git-diff-tree.txt b/Documentation/git-diff-tree.txt
--- a/Documentation/git-diff-tree.txt
+++ b/Documentation/git-diff-tree.txt
@@ -9,7 +9,7 @@ git-diff-tree - Compares the content and
 
 SYNOPSIS
 --------
-'git-diff-tree' [-p] [-r] [-z] [--stdin] [-M] [-R] [-C] [-S<string>] [-m] [-s] [-v] [-t] <tree-ish> <tree-ish> [<pattern>]\*
+'git-diff-tree' [-p] [-r] [-z] [--stdin] [-M] [-R] [-C] [-S<string>] [--pickaxe-all] [-m] [-s] [-v] [-t] <tree-ish> <tree-ish> [<pattern>]\*
 
 DESCRIPTION
 -----------
@@ -45,6 +45,11 @@ OPTIONS
 -S<string>::
 	Look for differences that contains the change in <string>.
 
+--pickaxe-all::
+	When -S finds a change, show all the changes in that
+	changeset, not just the files that contains the change
+	in <string>.
+
 -r::
 	recurse
 
diff --git a/diff-cache.c b/diff-cache.c
--- a/diff-cache.c
+++ b/diff-cache.c
@@ -206,7 +206,7 @@ int main(int argc, const char **argv)
 			diff_setup_opt |= DIFF_SETUP_REVERSE;
 			continue;
 		}
-		if (!strcmp(arg, "-S")) {
+		if (!strncmp(arg, "-S", 2)) {
 			pickaxe = arg + 2;
 			continue;
 		}
diff --git a/diff-files.c b/diff-files.c
--- a/diff-files.c
+++ b/diff-files.c
@@ -53,7 +53,7 @@ int main(int argc, const char **argv)
 			diff_output_format = DIFF_FORMAT_MACHINE;
 		else if (!strcmp(argv[1], "-R"))
 			diff_setup_opt |= DIFF_SETUP_REVERSE;
-		else if (!strcmp(argv[1], "-S"))
+		else if (!strncmp(argv[1], "-S", 2))
 			pickaxe = argv[1] + 2;
 		else if (!strcmp(argv[1], "--pickaxe-all"))
 			pickaxe_opts = DIFF_PICKAXE_ALL;
------------------------------------------------


^ permalink raw reply

* [PATCH] Add -O<orderfile> option to diff-* brothers.
From: Junio C Hamano @ 2005-05-28  9:54 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git

A new diffcore filter diffcore-order is introduced.  This takes
a text file each of whose line is a shell glob pattern.  Patches
matching the glob pattern on an earlier line in the file are
output before patches matching the glob pattern on a later line,
and patches not matching any glob pattern is output last.

A typical orderfile for git project would probably look like
this:

    README
    Documentation
    Makefile
    *.h
    *.c

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

Documentation/git-diff-cache.txt |    6 +
Documentation/git-diff-files.txt |    6 +
Documentation/git-diff-tree.txt  |    6 +
Makefile                         |    3 
diff-cache.c                     |    7 ++
diff-files.c                     |    5 +
diff-tree.c                      |    7 ++
diff.h                           |    2 
diffcore-order.c                 |  121 +++++++++++++++++++++++++++++++++++++++
9 files changed, 159 insertions(+), 4 deletions(-)
new file (100644): diffcore-order.c

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] [-R] [-C] [-S<string>] [--pickaxe-all] [--cached] <tree-ish> [<path>...]
+'git-diff-cache' [-p] [-r] [-z] [-m] [-M] [-R] [-C] [-O<orderfile>] [-S<string>] [--pickaxe-all] [--cached] <tree-ish> [<path>...]
 
 DESCRIPTION
 -----------
@@ -49,6 +49,10 @@ OPTIONS
 	changeset, not just the files that contains the change
 	in <string>.
 
+-O<orderfile>::
+	Output the patch in the order specified in the
+	<orderfile>, which has one shell glob pattern per line.
+
 -R::
 	Output diff in reverse.
 
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] [-C] [-R] [-S<string>] [--pickaxe-all] [<pattern>...]
+'git-diff-files' [-p] [-q] [-r] [-z] [-M] [-C] [-R] [-O<orderfile>] [-S<string>] [--pickaxe-all] [<pattern>...]
 
 DESCRIPTION
 -----------
@@ -43,6 +43,10 @@ OPTIONS
 	changeset, not just the files that contains the change
 	in <string>.
 
+-O<orderfile>::
+	Output the patch in the order specified in the
+	<orderfile>, which has one shell glob pattern per line.
+
 -r::
 	This flag does not mean anything.  It is there only to match
 	git-diff-tree.  Unlike git-diff-tree, git-diff-files always looks
diff --git a/Documentation/git-diff-tree.txt b/Documentation/git-diff-tree.txt
--- a/Documentation/git-diff-tree.txt
+++ b/Documentation/git-diff-tree.txt
@@ -9,7 +9,7 @@ git-diff-tree - Compares the content and
 
 SYNOPSIS
 --------
-'git-diff-tree' [-p] [-r] [-z] [--stdin] [-M] [-R] [-C] [-S<string>] [--pickaxe-all] [-m] [-s] [-v] [-t] <tree-ish> <tree-ish> [<pattern>]\*
+'git-diff-tree' [-p] [-r] [-z] [--stdin] [-M] [-R] [-C] [-O<orderfile>] [-S<string>] [--pickaxe-all] [-m] [-s] [-v] [-t] <tree-ish> <tree-ish> [<pattern>]\*
 
 DESCRIPTION
 -----------
@@ -50,6 +50,10 @@ OPTIONS
 	changeset, not just the files that contains the change
 	in <string>.
 
+-O<orderfile>::
+	Output the patch in the order specified in the
+	<orderfile>, which has one shell glob pattern per line.
+
 -r::
 	recurse
 
diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -48,7 +48,7 @@ LIB_OBJS += strbuf.o
 
 LIB_H += diff.h count-delta.h
 LIB_OBJS += diff.o diffcore-rename.o diffcore-pickaxe.o diffcore-pathspec.o \
-	count-delta.o
+	count-delta.o diffcore-order.o
 
 LIB_OBJS += gitenv.o
 
@@ -130,6 +130,7 @@ diff.o: $(LIB_H) diffcore.h
 diffcore-rename.o : $(LIB_H) diffcore.h
 diffcore-pathspec.o : $(LIB_H) diffcore.h
 diffcore-pickaxe.o : $(LIB_H) diffcore.h
+diffcore-order.o : $(LIB_H) diffcore.h
 
 test: all
 	$(MAKE) -C t/ all
diff --git a/diff-cache.c b/diff-cache.c
--- a/diff-cache.c
+++ b/diff-cache.c
@@ -9,6 +9,7 @@ static int diff_setup_opt = 0;
 static int diff_score_opt = 0;
 static const char *pickaxe = NULL;
 static int pickaxe_opts = 0;
+static const char *orderfile = NULL;
 
 /* A file entry went away or appeared */
 static void show_file(const char *prefix, struct cache_entry *ce, unsigned char *sha1, unsigned int mode)
@@ -210,6 +211,10 @@ int main(int argc, const char **argv)
 			pickaxe = arg + 2;
 			continue;
 		}
+		if (!strncmp(arg, "-O", 2)) {
+			orderfile = arg + 2;
+			continue;
+		}
 		if (!strcmp(arg, "--pickaxe-all")) {
 			pickaxe_opts = DIFF_PICKAXE_ALL;
 			continue;
@@ -246,6 +251,8 @@ int main(int argc, const char **argv)
 		diffcore_rename(detect_rename, diff_score_opt);
 	if (pickaxe)
 		diffcore_pickaxe(pickaxe, pickaxe_opts);
+	if (orderfile)
+		diffcore_order(orderfile);
 	diff_flush(diff_output_format, 1);
 	return ret;
 }
diff --git a/diff-files.c b/diff-files.c
--- a/diff-files.c
+++ b/diff-files.c
@@ -15,6 +15,7 @@ static int diff_setup_opt = 0;
 static int diff_score_opt = 0;
 static const char *pickaxe = NULL;
 static int pickaxe_opts = 0;
+static const char *orderfile = NULL;
 static int silent = 0;
 
 static void show_unmerge(const char *path)
@@ -55,6 +56,8 @@ int main(int argc, const char **argv)
 			diff_setup_opt |= DIFF_SETUP_REVERSE;
 		else if (!strncmp(argv[1], "-S", 2))
 			pickaxe = argv[1] + 2;
+		else if (!strncmp(argv[1], "-O", 2))
+			orderfile = argv[1] + 2;
 		else if (!strcmp(argv[1], "--pickaxe-all"))
 			pickaxe_opts = DIFF_PICKAXE_ALL;
 		else if (!strncmp(argv[1], "-M", 2)) {
@@ -122,6 +125,8 @@ int main(int argc, const char **argv)
 		diffcore_rename(detect_rename, diff_score_opt);
 	if (pickaxe)
 		diffcore_pickaxe(pickaxe, pickaxe_opts);
+	if (orderfile)
+		diffcore_order(orderfile);
 	diff_flush(diff_output_format, 1);
 	return 0;
 }
diff --git a/diff-tree.c b/diff-tree.c
--- a/diff-tree.c
+++ b/diff-tree.c
@@ -14,6 +14,7 @@ static int diff_setup_opt = 0;
 static int diff_score_opt = 0;
 static const char *pickaxe = NULL;
 static int pickaxe_opts = 0;
+static const char *orderfile = NULL;
 static const char *header = NULL;
 static const char *header_prefix = "";
 
@@ -269,6 +270,8 @@ static int call_diff_flush(void)
 		diff_flush(DIFF_FORMAT_NO_OUTPUT, 0);
 		return 0;
 	}
+	if (orderfile)
+		diffcore_order(orderfile);
 	if (header) {
 		const char *fmt = "%s";
 		if (diff_output_format == DIFF_FORMAT_MACHINE)
@@ -510,6 +513,10 @@ int main(int argc, const char **argv)
 			pickaxe = arg + 2;
 			continue;
 		}
+		if (!strncmp(arg, "-O", 2)) {
+			orderfile = arg + 2;
+			continue;
+		}
 		if (!strcmp(arg, "--pickaxe-all")) {
 			pickaxe_opts = DIFF_PICKAXE_ALL;
 			continue;
diff --git a/diff.h b/diff.h
--- a/diff.h
+++ b/diff.h
@@ -43,6 +43,8 @@ extern void diffcore_pickaxe(const char 
 
 extern void diffcore_pathspec(const char **pathspec);
 
+extern void diffcore_order(const char *orderfile);
+
 extern int diff_queue_is_empty(void);
 
 #define DIFF_FORMAT_HUMAN	0
diff --git a/diffcore-order.c b/diffcore-order.c
new file mode 100644
--- /dev/null
+++ b/diffcore-order.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2005 Junio C Hamano
+ */
+#include "cache.h"
+#include "diff.h"
+#include "diffcore.h"
+#include <fnmatch.h>
+
+static char **order;
+static int order_cnt;
+
+static void prepare_order(const char *orderfile)
+{
+	int fd, cnt, pass;
+	void *map;
+	char *cp, *endp;
+	struct stat st;
+
+	if (order)
+		return;
+
+	fd = open(orderfile, O_RDONLY);
+	if (fd < 0)
+		return;
+	if (fstat(fd, &st)) {
+		close(fd);
+		return;
+	}
+	map = mmap(NULL, st.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
+	close(fd);
+	if (-1 == (int)(long)map)
+		return;
+	endp = map + st.st_size;
+	for (pass = 0; pass < 2; pass++) {
+		cnt = 0;
+		cp = map;
+		while (cp < endp) {
+			char *ep;
+			for (ep = cp; ep < endp && *ep != '\n'; ep++)
+				;
+			/* cp to ep has one line */
+			if (*cp == '\n' || *cp == '#')
+				; /* comment */
+			else if (pass == 0)
+				cnt++;
+			else {
+				if (*ep == '\n') {
+					*ep = 0;
+					order[cnt] = cp;
+				}
+				else {
+					order[cnt] = xmalloc(ep-cp+1);
+					memcpy(order[cnt], cp, ep-cp);
+					order[cnt][ep-cp] = 0;
+				}
+				cnt++;
+			}
+			if (ep < endp)
+				ep++;
+			cp = ep;
+		}
+		if (pass == 0) {
+			order_cnt = cnt;
+			order = xmalloc(sizeof(*order) * cnt);
+		}
+	}
+}
+
+struct pair_order {
+	struct diff_filepair *pair;
+	int orig_order;
+	int order;
+};
+
+static int match_order(const char *path)
+{
+	int i;
+	char p[PATH_MAX];
+
+	for (i = 0; i < order_cnt; i++) {
+		strcpy(p, path);
+		while (p[0]) {
+			char *cp;
+			if (!fnmatch(order[i], p, 0))
+				return i;
+			cp = strrchr(p, '/');
+			if (!cp)
+				break;
+			*cp = 0;
+		}
+	}
+	return order_cnt;
+}
+
+static int compare_pair_order(const void *a_, const void *b_)
+{
+	struct pair_order const *a, *b;
+	a = (struct pair_order const *)a_;
+	b = (struct pair_order const *)b_;
+	if (a->order != b->order)
+		return a->order - b->order;
+	return a->orig_order - b->orig_order;
+}
+
+void diffcore_order(const char *orderfile)
+{
+	struct diff_queue_struct *q = &diff_queued_diff;
+	struct pair_order *o = xmalloc(sizeof(*o) * q->nr);
+	int i;
+
+	prepare_order(orderfile);
+	for (i = 0; i < q->nr; i++) {
+		o[i].pair = q->queue[i];
+		o[i].orig_order = i;
+		o[i].order = match_order(o[i].pair->two->path);
+	}
+	qsort(o, q->nr, sizeof(*o), compare_pair_order);
+	for (i = 0; i < q->nr; i++)
+		q->queue[i] = o[i].pair;
+	return;
+}
------------------------------------------------


^ permalink raw reply

* [PATCH] Do not include unused header files.
From: Junio C Hamano @ 2005-05-28  9:55 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git

Some source files were including "delta.h" without actually
needing it.  Remove them.

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

count-delta.c       |    1 -
diffcore-pathspec.c |    1 -
diffcore-pickaxe.c  |    1 -
3 files changed, 3 deletions(-)

diff --git a/count-delta.c b/count-delta.c
--- a/count-delta.c
+++ b/count-delta.c
@@ -6,7 +6,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <limits.h>
-#include "delta.h"
 #include "count-delta.h"
 
 static unsigned long get_hdr_size(const unsigned char **datap)
diff --git a/diffcore-pathspec.c b/diffcore-pathspec.c
--- a/diffcore-pathspec.c
+++ b/diffcore-pathspec.c
@@ -4,7 +4,6 @@
 #include "cache.h"
 #include "diff.h"
 #include "diffcore.h"
-#include "delta.h"
 
 struct path_spec {
 	const char *spec;
diff --git a/diffcore-pickaxe.c b/diffcore-pickaxe.c
--- a/diffcore-pickaxe.c
+++ b/diffcore-pickaxe.c
@@ -4,7 +4,6 @@
 #include "cache.h"
 #include "diff.h"
 #include "diffcore.h"
-#include "delta.h"
 
 static int contains(struct diff_filespec *one,
 		    const char *needle, unsigned long len)
------------------------------------------------


^ permalink raw reply

* [PATCH] Do not show empty diff in diff-cache uncached.
From: Junio C Hamano @ 2005-05-28 10:11 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Git Mailing List
In-Reply-To: <7v3bs82rwh.fsf@assigned-by-dhcp.cox.net>

Pre- "diff --git" built-in diff did not add any extended header
on its own, so it did not show anything for unmodified but
stat-dirty file from diff-cache command without --cached flag.

Recent diff-cache produces "diff --git" header internally before
calling the "diff" command, which results in an empty diff for
such a file, cluttering the output.  This patch fixes this.

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

diff.c            |   26 ++++++++++++++++++++++++++
diffcore-rename.c |   17 -----------------
diffcore.h        |    2 ++
3 files changed, 28 insertions(+), 17 deletions(-)

diff --git a/diff.c b/diff.c
--- a/diff.c
+++ b/diff.c
@@ -684,6 +684,23 @@ int diff_unmodified_pair(struct diff_fil
 	return 0;
 }
 
+int is_exact_match(struct diff_filespec *src, struct diff_filespec *dst)
+{
+	if (src->sha1_valid && dst->sha1_valid &&
+	    !memcmp(src->sha1, dst->sha1, 20))
+		return 1;
+	if (diff_populate_filespec(src, 1) || diff_populate_filespec(dst, 1))
+		return 0;
+	if (src->size != dst->size)
+		return 0;
+	if (diff_populate_filespec(src, 0) || diff_populate_filespec(dst, 0))
+		return 0;
+	if (src->size == dst->size &&
+	    !memcmp(src->data, dst->data, src->size))
+		return 1;
+	return 0;
+}
+
 static void diff_flush_patch(struct diff_filepair *p)
 {
 	const char *name, *other;
@@ -692,6 +709,15 @@ static void diff_flush_patch(struct diff
 	if (diff_unmodified_pair(p))
 		return;
 
+	/* When diff-raw would have said "look at the filesystem", we
+	 * need to see if the two are the same and if so not to emit
+	 * anything at all.  Avoid is_exact_match() comparison when it
+	 * does not matter.
+	 */
+	if ((DIFF_FILE_VALID(p->two) && !p->two->sha1_valid) &&
+	    is_exact_match(p->one, p->two))
+		return;
+
 	name = p->one->path;
 	other = (strcmp(name, p->two->path) ? p->two->path : NULL);
 	if ((DIFF_FILE_VALID(p->one) && S_ISDIR(p->one->mode)) ||
diff --git a/diffcore-rename.c b/diffcore-rename.c
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -94,23 +94,6 @@ static struct diff_rename_src *register_
 	return &(rename_src[first]);
 }
 
-static int is_exact_match(struct diff_filespec *src, struct diff_filespec *dst)
-{
-	if (src->sha1_valid && dst->sha1_valid &&
-	    !memcmp(src->sha1, dst->sha1, 20))
-		return 1;
-	if (diff_populate_filespec(src, 1) || diff_populate_filespec(dst, 1))
-		return 0;
-	if (src->size != dst->size)
-		return 0;
-	if (diff_populate_filespec(src, 0) || diff_populate_filespec(dst, 0))
-		return 0;
-	if (src->size == dst->size &&
-	    !memcmp(src->data, dst->data, src->size))
-		return 1;
-	return 0;
-}
-
 struct diff_score {
 	int src; /* index in rename_src */
 	int dst; /* index in rename_dst */
diff --git a/diffcore.h b/diffcore.h
--- a/diffcore.h
+++ b/diffcore.h
@@ -29,6 +29,8 @@ struct diff_filespec {
 	unsigned should_munmap : 1; /* data should be munmap()'ed */
 };
 
+extern int is_exact_match(struct diff_filespec *, struct diff_filespec *);
+
 extern struct diff_filespec *alloc_filespec(const char *);
 extern void fill_filespec(struct diff_filespec *, const unsigned char *,
 			  unsigned short);
------------------------------------------------


^ permalink raw reply

* Re: More gitweb queries..
From: Kay Sievers @ 2005-05-28 10:56 UTC (permalink / raw)
  To: David Lang; +Cc: Daniel Serpell, Git Mailing List
In-Reply-To: <Pine.LNX.4.62.0505271949480.15585@qynat.qvtvafvgr.pbz>

On Fri, May 27, 2005 at 07:51:39PM -0700, David Lang wrote:
> >Hi!
> >
> >On 5/27/05, Kay Sievers <kay.sievers@vrfy.org> wrote:
> >>On Fri, May 27, 2005 at 12:24:20PM -0700, Linus Torvalds wrote:
> >>>  Combining some of the features of the two (that über-cool revision
> >>>  history graph from gitk rules, for example) might be cool. I get the
> >>>  urge to do octopus-merges in the kernel just because of how good they
> >>>  look in gitk ;) ]
> >>
> >>I would like to show something like the graph too, but I don't really know
> >>how to do this in html. Seems slippery if not impossible.
> >>If anybody has a nice idea how to represent that, I will give it a try.
> >
> >Well, you could draw them in javascript, using
> >http://www.walterzorn.com/jsgraphics/jsgraphics_e.htm :-)
> >
> >Alternatively, you could use a fixed set of little images, a bar "|", a
> >dot "o" and branches like "Y", "7" and "\". Obviously, octopus-merges
> >are very difficult to draw using only those.
> 
> you could look into SVG (scaleable vector graphics or some such thing) 
> that are supposed to be in the newest browsers (or soon to be added, I'm 
> not sure). this should let you do all the drawing nessasary reasonably 
> easily (if you are willing to limit users to that, which is probably not 
> that big of a problem for git)

Well, technology that is "soon to be added" since years is probably not
my favorite thing to base my work on. SVG could be nice, sure, but nearly
noone is able to see it today and I expect, I will need to wait wait for
another few years. :)

Kay

^ permalink raw reply

* Re: [PATCH] Pickaxe fixes.
From: Thomas Glanzmann @ 2005-05-28 10:59 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7v7jhjy8uw.fsf@assigned-by-dhcp.cox.net>

Hello,

> Also updates the documentation to describe the --pickaxe-all option.
> A typical orderfile for git project would probably look like this ...

I can't believe it. I began to support pickaxe this morning in my little
git frontend and thought about exactly these two questions (patch
ordering and show me all deltas in the matched changeset). Thanks for
the patches! Btw. When doing the.  'git-whatchanged drivers/ide' thing
... does that show only deltas which happened actually in this tree or
if a changeset contains deltas inside and outside?

	Thomas

^ permalink raw reply

* Re: [PATCH] Add -O<orderfile> option to diff-* brothers.
From: Petr Baudis @ 2005-05-28 11:12 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Linus Torvalds, git
In-Reply-To: <7vzmufwu8w.fsf@assigned-by-dhcp.cox.net>

Dear diary, on Sat, May 28, 2005 at 11:54:39AM CEST, I got a letter
where Junio C Hamano <junkio@cox.net> told me that...
> A new diffcore filter diffcore-order is introduced.  This takes
> a text file each of whose line is a shell glob pattern.  Patches
> matching the glob pattern on an earlier line in the file are
> output before patches matching the glob pattern on a later line,
> and patches not matching any glob pattern is output last.
> 
> A typical orderfile for git project would probably look like
> this:
> 
>     README
>     Documentation
>     Makefile
>     *.h
>     *.c
> 
> Signed-off-by: Junio C Hamano <junkio@cox.net>

Hmm, is this really useful in practice? diff itself doesn't appear to
have it either, and I haven't seen something like this before. So is it
worth the code?

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

^ permalink raw reply

* Re: [PATCH] Add -O<orderfile> option to diff-* brothers.
From: Thomas Glanzmann @ 2005-05-28 11:19 UTC (permalink / raw)
  To: Petr Baudis; +Cc: Junio C Hamano, git
In-Reply-To: <20050528111238.GA1036@pasky.ji.cz>

Hello,

> Hmm, is this really useful in practice? diff itself doesn't appear to
> have it either, and I haven't seen something like this before. So is it
> worth the code?

I think it is. For example on git development it is nice to see the
Documentation first. So you know what it is supposed to do and later you
see the actual implementation. I think Junio requested this exactly
before.

	Thoms

^ permalink raw reply

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


another small bug: if you click into the main window _before_ the commit 
list has been fully generated (i.e. into the empty window) then all 
sorts of error messages pop up. ("Cant use empty string ...")

	Ingo

^ permalink raw reply

* (unknown)
From: Thomas Glanzmann @ 2005-05-28 14:15 UTC (permalink / raw)
  To: Linus Torvalds, GIT

diff-tree fb94d3e7fbe8e22201d8d015ed444d46485a3f76 (from 8310c2c0b585d3ac35a275f795e15fd9887e8b7d)
Author: Thomas Glanzmann <sithglan@stud.uni-erlangen.de>
Date:   Sat May 28 16:13:22 2005 +0200
    
    [PATCH] Document the --root switch of git-diff-tree
    
    Signed-off-by: Thomas Glanzmann <sithglan@stud.uni-erlangen.de>


fb94d3e7fbe8e22201d8d015ed444d46485a3f76 (from 8310c2c0b585d3ac35a275f795e15fd9887e8b7d)

diff --git a/Documentation/git-diff-tree.txt b/Documentation/git-diff-tree.txt
--- a/Documentation/git-diff-tree.txt
+++ b/Documentation/git-diff-tree.txt
@@ -54,6 +54,11 @@ OPTIONS
 -z::
 	\0 line termination on output
 
+--root::
+	When '--root' is specified the initial commit of a new file
+	will be showed as a big creation event. This is equivalent to
+	a diff against NULL.
+
 --stdin::
 	When '--stdin' is specified, the command does not take
 	<tree-ish> arguments from the command line.  Instead, it

^ permalink raw reply

* [PATCH] Document the --root switch of git-diff-tree (try 2)
From: Thomas Glanzmann @ 2005-05-28 14:38 UTC (permalink / raw)
  To: Linus Torvalds, GIT

diff-tree a63bd10cbec0978c4d1d0076db4f06c52c670449 (from 8310c2c0b585d3ac35a275f795e15fd9887e8b7d)
Author: Thomas Glanzmann <sithglan@stud.uni-erlangen.de>
Date:   Sat May 28 16:37:28 2005 +0200
    
    [PATCH] Document the --root switch of git-diff-tree
    
    Signed-off-by: Thomas Glanzmann <sithglan@stud.uni-erlangen.de>

diff --git a/Documentation/git-diff-tree.txt b/Documentation/git-diff-tree.txt
--- a/Documentation/git-diff-tree.txt
+++ b/Documentation/git-diff-tree.txt
@@ -54,6 +54,10 @@ OPTIONS
 -z::
 	\0 line termination on output
 
+--root::
+	When '--root' is specified the initial commit will be showed as a big
+	creation event. This is equivalent to a diff against a NULL tree.
+
 --stdin::
 	When '--stdin' is specified, the command does not take
 	<tree-ish> arguments from the command line.  Instead, it

^ permalink raw reply

* [PATCH] Document the --root switch of git-diff-tree (try 3)
From: Thomas Glanzmann @ 2005-05-28 14:42 UTC (permalink / raw)
  To: Linus Torvalds, GIT

diff-tree a63bd10cbec0978c4d1d0076db4f06c52c670449 (from 8310c2c0b585d3ac35a275f795e15fd9887e8b7d)
Author: Thomas Glanzmann <sithglan@stud.uni-erlangen.de>
Date:   Sat May 28 16:37:28 2005 +0200
    
    [PATCH] Document the --root switch of git-diff-tree
    
    Signed-off-by: Thomas Glanzmann <sithglan@stud.uni-erlangen.de>

diff --git a/Documentation/git-diff-tree.txt b/Documentation/git-diff-tree.txt
--- a/Documentation/git-diff-tree.txt
+++ b/Documentation/git-diff-tree.txt
@@ -54,6 +54,10 @@ OPTIONS
 -z::
 	\0 line termination on output
 
+--root::
+	When '--root' is specified the initial commit will be showed as a big
+	creation event. This is equivalent to a diff against the NULL tree.
+
 --stdin::
 	When '--stdin' is specified, the command does not take
 	<tree-ish> arguments from the command line.  Instead, it

^ permalink raw reply

* [PATCH] Document the --root switch of git-diff-tree (try 4)
From: Thomas Glanzmann @ 2005-05-28 14:55 UTC (permalink / raw)
  To: Linus Torvalds, GIT

diff-tree a63bd10cbec0978c4d1d0076db4f06c52c670449 (from 8310c2c0b585d3ac35a275f795e15fd9887e8b7d)
Author: Thomas Glanzmann <sithglan@stud.uni-erlangen.de>
Date:   Sat May 28 16:37:28 2005 +0200
    
    [PATCH] Document the --root switch of git-diff-tree
    
    Signed-off-by: Thomas Glanzmann <sithglan@stud.uni-erlangen.de>

diff --git a/Documentation/git-diff-tree.txt b/Documentation/git-diff-tree.txt
--- a/Documentation/git-diff-tree.txt
+++ b/Documentation/git-diff-tree.txt
@@ -54,6 +54,10 @@ OPTIONS
 -z::
 	\0 line termination on output
 
+--root::
+	When '--root' is specified the initial commit will be shown as a big
+	creation event. This is equivalent to a diff against the NULL tree.
+
 --stdin::
 	When '--stdin' is specified, the command does not take
 	<tree-ish> arguments from the command line.  Instead, it

^ permalink raw reply

* Re: [PATCH] Add -O<orderfile> option to diff-* brothers.
From: Junio C Hamano @ 2005-05-28 16:14 UTC (permalink / raw)
  To: Petr Baudis; +Cc: Linus Torvalds, git
In-Reply-To: <20050528111238.GA1036@pasky.ji.cz>

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

PB> Hmm, is this really useful in practice? diff itself doesn't appear to
PB> have it either, and I haven't seen something like this before. So is it
PB> worth the code?

CVS nor SVN does not do pickaxe as far as I know either, but I
think some people in GIT community are already having fun with
pickaxe.

The amount of the code is small, and it does not impact if you
do not use the option.  I am more concerned by (1) the fact that
each new diffcore filters would carve out its own niche from the
scarse command option namespace; (2) you have to duplicate the
option parsing in all three diff-* brothers; and (3) diff-tree
is sometimes an odd-man-out among those three and it is not so
simple to unify the option parsing.  A help in that area is very
much appreciated.


^ permalink raw reply

* Re: [PATCH] Pickaxe fixes.
From: Junio C Hamano @ 2005-05-28 16:16 UTC (permalink / raw)
  To: Thomas Glanzmann; +Cc: git
In-Reply-To: <20050528105914.GA8467@cip.informatik.uni-erlangen.de>

>>>>> "TG" == Thomas Glanzmann <sithglan@stud.uni-erlangen.de> writes:

TG> Btw. When doing the.  'git-whatchanged drivers/ide' thing
TG> ... does that show only deltas which happened actually in
TG> this tree or if a changeset contains deltas inside and
TG> outside?

That's up to Linus right now.  The behaviour is different
before and after the 12-part patch I sent out yesterday [*1*].

My earlier thinking was to use the pathspec (e.g. drivers/ide)
as the output filter, but Linus corrected me yesterday morning
that he wants the pathspec as the input filter.  What this means
to your question is:

 - Under my earlier thinking, if drivers/ide/foo is a rename
   from drivers/usb/bar, diffcore gets both creation of foo and
   deletion of bar, diffcore-rename matches them up, and
   diffcore-pathspec filters the output to drivers/ide tree.
   Earlier pathspec picked up filepair that had the specified
   path on either src or dst side, so this would have been shown
   as a rename from usb/bar to ide/foo.

 - After the 12-part patch, the pathspec comes first and
   establishes a narrowed down world we operate in.  So in the
   same situation, diffcore is fed only creation of foo but does
   not see deletion of bar (which happened in drivers/usb, which
   is outside our world).  Hence diffcore-rename does not have
   anything to match up and this would be shown as a creation of
   ide/foo.

I agree with Linus that the latter is the semantics we usually
want.  If we make diffcore filters stackable (I mean, the order
of applications controllable by the program and the user), we
could also have the older semantics when the user wants it, but
I would do that after this series stabilizes.


[Footnote]

*1* When I talk about time of the day, it is in US Pacific
timezone.




^ permalink raw reply

* Re: [PATCH] Pickaxe fixes.
From: Thomas Glanzmann @ 2005-05-28 16:22 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vpsvbuxzb.fsf@assigned-by-dhcp.cox.net>

Hello,

> I agree with Linus that the latter is the semantics we usually
> want.  If we make diffcore filters stackable (I mean, the order
> of applications controllable by the program and the user), we
> could also have the older semantics when the user wants it, but
> I would do that after this series stabilizes.

thanks for the elaboration on this topic. However at the moment I don't
have an opinion on this, I have to use it a bit longer. But it is a good
thing that I know by now that it limits its view to the subdirectory
after your patch-train is applied.

	Thomas

^ permalink raw reply

* Re: [PATCH] Add -O<orderfile> option to diff-* brothers.
From: Junio C Hamano @ 2005-05-28 16:25 UTC (permalink / raw)
  To: Thomas Glanzmann; +Cc: Petr Baudis, git
In-Reply-To: <20050528111959.GA28780@cip.informatik.uni-erlangen.de>

>>>>> "TG" == Thomas Glanzmann <sithglan@stud.uni-erlangen.de> writes:

TG> I think it is. For example on git development it is nice to see the
TG> Documentation first. So you know what it is supposed to do and later you
TG> see the actual implementation. I think Junio requested this exactly
TG> before.

Well, yes and no.  I do want to see the patches in the suggested
order because that would make things easier to understand if
they are related.

The request you are referring to was not about the order of
patches in one e-mail message.  It was more like "please show us
documentation first so that we can pick nits in the design (goal
of implementation) before you start to code".  That way, if
there were a change (like -A flag in checkout-cache) that people
would find objectionable, the effort to code the change and
the effort to review the code can both be saved.


^ permalink raw reply

* [PATCH] Fix leak in diffcore-order.c
From: Junio C Hamano @ 2005-05-28 16:44 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git
In-Reply-To: <7vzmufwu8w.fsf@assigned-by-dhcp.cox.net>

A temporary array used for sorting the filepairs were not freed
after use.

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

diffcore-order.c |    1 +
1 files changed, 1 insertion(+)

diff --git a/diffcore-order.c b/diffcore-order.c
--- a/diffcore-order.c
+++ b/diffcore-order.c
@@ -117,5 +117,6 @@ void diffcore_order(const char *orderfil
 	qsort(o, q->nr, sizeof(*o), compare_pair_order);
 	for (i = 0; i < q->nr; i++)
 		q->queue[i] = o[i].pair;
+	free(o);
 	return;
 }
------------------------------------------------


^ permalink raw reply

* [PATCH] Diff: two fixes.
From: Junio C Hamano @ 2005-05-28 19:22 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Git Mailing List
In-Reply-To: <7vis13wth4.fsf_-_@assigned-by-dhcp.cox.net>

The count-delta routine sometimes overcounted the copied source
material which resulted in unsigned int wraparound.

The latest diff-cache (uncached) fix to eliminate empty diffs
from the output revealed that is_exact_match() was not careful
enough, which resulted in a sanity check routine triggering when
a file is added to an index.

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

count-delta.c |    3 +++
diff.c        |    3 +++
2 files changed, 6 insertions(+)

diff --git a/count-delta.c b/count-delta.c
--- a/count-delta.c
+++ b/count-delta.c
@@ -88,5 +88,8 @@ unsigned long count_delta(void *delta_bu
 	/* delete size is what was _not_ copied from source.
 	 * edit size is that and literal additions.
 	 */
+	if (src_size + added_literal < copied_from_source)
+		/* we ended up overcounting and underflowed */
+		return 0;
 	return (src_size - copied_from_source) + added_literal;
 }
diff --git a/diff.c b/diff.c
--- a/diff.c
+++ b/diff.c
@@ -689,6 +689,9 @@ int is_exact_match(struct diff_filespec 
 	if (src->sha1_valid && dst->sha1_valid &&
 	    !memcmp(src->sha1, dst->sha1, 20))
 		return 1;
+	/* if either is invalid they cannot match */
+	if (!DIFF_FILE_VALID(src) || !DIFF_FILE_VALID(dst))
+		return 0;
 	if (diff_populate_filespec(src, 1) || diff_populate_filespec(dst, 1))
 		return 0;
 	if (src->size != dst->size)
------------------------------------------------


^ permalink raw reply

* [PATCH] Add -B flag to diff-* brothers.
From: Junio C Hamano @ 2005-05-28 19:33 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Git Mailing List

This introduces diffcore-break.c, a new diffcore
transformation.

When the -B flag is given, a patch that represents a complete
rewrite is broken into a deletion followed by a creation.  This
makes it easier to review such a complete rewrite patch.

The -B flag takes the same syntax as the -M and -C flags to
specify the maximum amount of source material the resulting file
can still have to be considered a complete rewrite, and defaults
to 15% if not specified.  For example, this detects the complete
rewrite of ls-tree.c I sent earlier.

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

Makefile          |    3 -
diff-cache.c      |    7 +++
diff-files.c      |    5 ++
diff-tree.c       |    7 +++
diff.h            |    2 
diffcore-break.c  |  110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
diffcore-rename.c |    4 -
diffcore.h        |    3 -
8 files changed, 137 insertions(+), 4 deletions(-)
new file (100644): diffcore-break.c

diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -48,7 +48,7 @@ LIB_OBJS += strbuf.o
 
 LIB_H += diff.h count-delta.h
 LIB_OBJS += diff.o diffcore-rename.o diffcore-pickaxe.o diffcore-pathspec.o \
-	count-delta.o diffcore-order.o
+	count-delta.o diffcore-order.o diffcore-break.o
 
 LIB_OBJS += gitenv.o
 
@@ -131,6 +131,7 @@ diffcore-rename.o : $(LIB_H) diffcore.h
 diffcore-pathspec.o : $(LIB_H) diffcore.h
 diffcore-pickaxe.o : $(LIB_H) diffcore.h
 diffcore-order.o : $(LIB_H) diffcore.h
+diffcore-break.o : $(LIB_H) diffcore.h
 
 test: all
 	$(MAKE) -C t/ all
diff --git a/diff-cache.c b/diff-cache.c
--- a/diff-cache.c
+++ b/diff-cache.c
@@ -9,6 +9,7 @@ static int diff_setup_opt = 0;
 static int diff_score_opt = 0;
 static const char *pickaxe = NULL;
 static int pickaxe_opts = 0;
+static int diff_break_opt = -1;
 static const char *orderfile = NULL;
 
 /* A file entry went away or appeared */
@@ -189,6 +190,10 @@ int main(int argc, const char **argv)
 			diff_output_format = DIFF_FORMAT_PATCH;
 			continue;
 		}
+		if (!strncmp(arg, "-B", 2)) {
+			diff_break_opt = diff_scoreopt_parse(arg);
+			continue;
+		}
 		if (!strncmp(arg, "-M", 2)) {
 			detect_rename = DIFF_DETECT_RENAME;
 			diff_score_opt = diff_scoreopt_parse(arg);
@@ -251,6 +256,8 @@ int main(int argc, const char **argv)
 		diffcore_rename(detect_rename, diff_score_opt);
 	if (pickaxe)
 		diffcore_pickaxe(pickaxe, pickaxe_opts);
+	if (0 <= diff_break_opt)
+		diffcore_break(diff_break_opt);
 	if (orderfile)
 		diffcore_order(orderfile);
 	diff_flush(diff_output_format, 1);
diff --git a/diff-files.c b/diff-files.c
--- a/diff-files.c
+++ b/diff-files.c
@@ -15,6 +15,7 @@ static int diff_setup_opt = 0;
 static int diff_score_opt = 0;
 static const char *pickaxe = NULL;
 static int pickaxe_opts = 0;
+static int diff_break_opt = -1;
 static const char *orderfile = NULL;
 static int silent = 0;
 
@@ -60,6 +61,8 @@ int main(int argc, const char **argv)
 			orderfile = argv[1] + 2;
 		else if (!strcmp(argv[1], "--pickaxe-all"))
 			pickaxe_opts = DIFF_PICKAXE_ALL;
+		else if (!strncmp(argv[1], "-B", 2))
+			diff_break_opt = diff_scoreopt_parse(argv[1]);
 		else if (!strncmp(argv[1], "-M", 2)) {
 			diff_score_opt = diff_scoreopt_parse(argv[1]);
 			detect_rename = DIFF_DETECT_RENAME;
@@ -125,6 +128,8 @@ int main(int argc, const char **argv)
 		diffcore_rename(detect_rename, diff_score_opt);
 	if (pickaxe)
 		diffcore_pickaxe(pickaxe, pickaxe_opts);
+	if (0 <= diff_break_opt)
+		diffcore_break(diff_break_opt);
 	if (orderfile)
 		diffcore_order(orderfile);
 	diff_flush(diff_output_format, 1);
diff --git a/diff-tree.c b/diff-tree.c
--- a/diff-tree.c
+++ b/diff-tree.c
@@ -14,6 +14,7 @@ static int diff_setup_opt = 0;
 static int diff_score_opt = 0;
 static const char *pickaxe = NULL;
 static int pickaxe_opts = 0;
+static int diff_break_opt = -1;
 static const char *orderfile = NULL;
 static const char *header = NULL;
 static const char *header_prefix = "";
@@ -266,6 +267,8 @@ static int call_diff_flush(void)
 		diffcore_rename(detect_rename, diff_score_opt);
 	if (pickaxe)
 		diffcore_pickaxe(pickaxe, pickaxe_opts);
+	if (0 <= diff_break_opt)
+		diffcore_break(diff_break_opt);
 	if (diff_queue_is_empty()) {
 		diff_flush(DIFF_FORMAT_NO_OUTPUT, 0);
 		return 0;
@@ -531,6 +534,10 @@ int main(int argc, const char **argv)
 			diff_score_opt = diff_scoreopt_parse(arg);
 			continue;
 		}
+		if (!strncmp(arg, "-B", 2)) {
+			diff_break_opt = diff_scoreopt_parse(arg);
+			continue;
+		}
 		if (!strcmp(arg, "-z")) {
 			diff_output_format = DIFF_FORMAT_MACHINE;
 			continue;
diff --git a/diff.h b/diff.h
--- a/diff.h
+++ b/diff.h
@@ -45,6 +45,8 @@ extern void diffcore_pathspec(const char
 
 extern void diffcore_order(const char *orderfile);
 
+extern void diffcore_break(int max_score);
+
 extern int diff_queue_is_empty(void);
 
 #define DIFF_FORMAT_HUMAN	0
diff --git a/diffcore-break.c b/diffcore-break.c
new file mode 100644
--- /dev/null
+++ b/diffcore-break.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2005 Junio C Hamano
+ */
+#include "cache.h"
+#include "diff.h"
+#include "diffcore.h"
+#include "delta.h"
+#include "count-delta.h"
+
+static int very_different(struct diff_filespec *src,
+			  struct diff_filespec *dst,
+			  int max_score)
+{
+	/* dst is recorded as a modification of src.  Are they so
+	 * different that we are better off recording this as a pair
+	 * of delete and create?  max_score is maximum size that is
+	 * common between src and dst for the pair to be still considered
+	 * a change (not delete and create), and typically set to 5-10%.
+	 */
+	void *delta;
+	unsigned long delta_size, base_size;
+
+	if (!S_ISREG(src->mode) || !S_ISREG(dst->mode))
+		return 0; /* leave symlink rename alone */
+
+	if (diff_populate_filespec(src, 1) || diff_populate_filespec(dst, 1))
+		return 0; /* error but caught downstream */
+
+	delta_size = ((src->size < dst->size) ?
+		      (dst->size - src->size) : (src->size - dst->size));
+	base_size = ((src->size < dst->size) ? src->size : dst->size);
+
+	/*
+	 * If delta size is larger than
+	 * (MAX_SCORE-max_score)/MAX_SCORE * min(src->size, dst->size)
+	 * then we declare this is too big a change to be a patch.
+	 */
+	if (base_size * (MAX_SCORE-max_score) < delta_size * MAX_SCORE)
+		return 1;
+
+	if (diff_populate_filespec(src, 0) || diff_populate_filespec(dst, 0))
+		return 0; /* error but caught downstream */
+
+	delta = diff_delta(src->data, src->size,
+			   dst->data, dst->size,
+			   &delta_size);
+
+	/* A delta that has a lot of literal additions would have
+	 * big delta_size no matter what else it does.
+	 */
+	if (base_size * (MAX_SCORE-max_score) < delta_size * MAX_SCORE)
+		return 1;
+
+	/* Estimate the edit size by interpreting delta. */
+	delta_size = count_delta(delta, delta_size);
+	free(delta);
+	if (delta_size == UINT_MAX)
+		return 0; /* error in delta computation */
+	/*
+	 * So how big is the edit?
+	 */
+	if (base_size * (MAX_SCORE-max_score) < delta_size * MAX_SCORE)
+		return 1;
+	return 0;
+}
+
+void diffcore_break(int max_score)
+{
+	struct diff_queue_struct *q = &diff_queued_diff;
+	struct diff_queue_struct outq;
+	int i;
+
+	if (!max_score)
+		max_score = DEFAULT_MAXIMUM_SCORE;
+
+	outq.nr = outq.alloc = 0;
+	outq.queue = NULL;
+
+	for (i = 0; i < q->nr; i++) {
+		struct diff_filepair *p = q->queue[i];
+		/* We deal only with in-place edit of non directory */
+		if (DIFF_FILE_VALID(p->one) && DIFF_FILE_VALID(p->two) &&
+		    !S_ISDIR(p->one->mode) && !S_ISDIR(p->two->mode) &&
+		    !strcmp(p->one->path, p->two->path) &&
+		    very_different(p->one, p->two, max_score)) {
+			/* Split this into delete and create */
+			struct diff_filespec *one_pre, *one_post,
+				*two_pre, *two_post;
+
+			/* deletion of one */
+			one_pre = alloc_filespec(p->one->path);
+			fill_filespec(one_pre, p->one->sha1, p->one->mode);
+			one_post = alloc_filespec(p->one->path);
+			diff_queue(&outq, one_pre, one_post);
+
+			/* creation of two */
+			two_pre = alloc_filespec(p->two->path);
+			two_post = alloc_filespec(p->two->path);
+			fill_filespec(two_post, p->two->sha1, p->two->mode);
+			diff_queue(&outq, two_pre, two_post);
+			diff_free_filepair(p);
+		}
+		else
+			diff_q(&outq, p);
+	}
+	free(q->queue);
+	*q = outq;
+
+	return;
+}
diff --git a/diffcore-rename.c b/diffcore-rename.c
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -208,8 +208,8 @@ static int score_compare(const void *a_,
 int diff_scoreopt_parse(const char *opt)
 {
 	int diglen, num, scale, i;
-	if (opt[0] != '-' || (opt[1] != 'M' && opt[1] != 'C'))
-		return -1; /* that is not a -M nor -C option */
+	if (opt[0] != '-' || (opt[1] != 'M' && opt[1] != 'C' && opt[1] != 'B'))
+		return -1; /* that is not a -M, -C nor -B option */
 	diglen = strspn(opt+2, "0123456789");
 	if (diglen == 0 || strlen(opt+2) != diglen)
 		return 0; /* use default */
diff --git a/diffcore.h b/diffcore.h
--- a/diffcore.h
+++ b/diffcore.h
@@ -9,7 +9,8 @@
  * in anything else.
  */
 #define MAX_SCORE 10000
-#define DEFAULT_MINIMUM_SCORE 5000
+#define DEFAULT_MINIMUM_SCORE 5000 /* rename/copy similarity minimum */
+#define DEFAULT_MAXIMUM_SCORE 1500 /* similarity maximum for break to happen */
 
 #define RENAME_DST_MATCHED 01
 
------------------------------------------------


^ 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