Git development
 help / color / mirror / Atom feed
* An alternative: call setup_git_directory() early
From: Junio C Hamano @ 2006-07-29  4:41 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0607282118230.4168@g5.osdl.org>

We classify built-in commands into three classes: ones that
require to know where the .git directory is, ones that could use
the knowledge of where the .git directory is but can operate
without, and ones that should not attempt any .git discovery.

Most of the commands fall within the first category.
apply, mailsplit and mailinfo falls within the second category
(e.g. patches can be applied to non-git files without --index),
and the last category includes init-db (which should never do
a discovery).

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

> On Fri, 28 Jul 2006, Junio C Hamano wrote:
>> 
>> No clever ideas, but I agree it would be _very_ nice if we could
>> do the setup unconditionally and early.  Some commands that call
>> setup want to know prefix, so we would need to introduce a
>> global to hold the prefix for them.
>
> Ho humm. In the meantime, how about this? It fixes the places I noticed, 
> but is mostly just a totally mindless conversion to move the call to 
> "setup_git_directory()" into the caller.

I guess our mails crossed.  This seems to pass all the tests but
our test do not cover subdirectory operation that much.


diff --git a/builtin-add.c b/builtin-add.c
index 3a73a17..07a29bc 100644
--- a/builtin-add.c
+++ b/builtin-add.c
@@ -127,7 +127,7 @@ int cmd_add(int argc, const char **argv,
 {
 	int i, newfd;
 	int verbose = 0, show_only = 0;
-	const char *prefix = setup_git_directory();
+	const char *prefix = git_prefix;
 	const char **pathspec;
 	struct dir_struct dir;
 
diff --git a/builtin-apply.c b/builtin-apply.c
index d4381d9..fb06cc3 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -2370,7 +2370,7 @@ int cmd_apply(int argc, const char **arg
 		}
 
 		if (check_index && prefix_length < 0) {
-			prefix = setup_git_directory();
+			prefix = git_prefix;
 			prefix_length = prefix ? strlen(prefix) : 0;
 			git_config(git_apply_config);
 			if (!whitespace_option && apply_default_whitespace)
diff --git a/builtin-cat-file.c b/builtin-cat-file.c
index 4d36817..53b15ef 100644
--- a/builtin-cat-file.c
+++ b/builtin-cat-file.c
@@ -102,7 +102,6 @@ int cmd_cat_file(int argc, const char **
 	unsigned long size;
 	int opt;
 
-	setup_git_directory();
 	git_config(git_default_config);
 	if (argc != 3)
 		usage("git-cat-file [-t|-s|-e|-p|<type>] <sha1>");
diff --git a/builtin-commit-tree.c b/builtin-commit-tree.c
index ec082bf..cae544b 100644
--- a/builtin-commit-tree.c
+++ b/builtin-commit-tree.c
@@ -88,8 +88,6 @@ int cmd_commit_tree(int argc, const char
 	unsigned int size;
 
 	setup_ident();
-	setup_git_directory();
-
 	git_config(git_default_config);
 
 	if (argc < 2)
diff --git a/builtin-diff-stages.c b/builtin-diff-stages.c
index 9c62702..9630a37 100644
--- a/builtin-diff-stages.c
+++ b/builtin-diff-stages.c
@@ -58,7 +58,7 @@ static void diff_stages(int stage1, int 
 int cmd_diff_stages(int ac, const char **av, char **envp)
 {
 	int stage1, stage2;
-	const char *prefix = setup_git_directory();
+	const char *prefix = git_prefix;
 	const char **pathspec = NULL;
 
 	git_config(git_default_config); /* no "diff" UI options */
diff --git a/builtin-grep.c b/builtin-grep.c
index a79bac3..713cca1 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -926,7 +926,7 @@ int cmd_grep(int argc, const char **argv
 	int seen_dashdash = 0;
 	struct grep_opt opt;
 	struct object_array list = { 0, 0, NULL };
-	const char *prefix = setup_git_directory();
+	const char *prefix = git_prefix;
 	const char **paths = NULL;
 	int i;
 
diff --git a/builtin-ls-files.c b/builtin-ls-files.c
index 8dae9f7..49e848e 100644
--- a/builtin-ls-files.c
+++ b/builtin-ls-files.c
@@ -329,7 +329,7 @@ int cmd_ls_files(int argc, const char **
 	struct dir_struct dir;
 
 	memset(&dir, 0, sizeof(dir));
-	prefix = setup_git_directory();
+	prefix = git_prefix;
 	if (prefix)
 		prefix_offset = strlen(prefix);
 	git_config(git_default_config);
diff --git a/builtin-ls-tree.c b/builtin-ls-tree.c
index b8d0d88..5cd4964 100644
--- a/builtin-ls-tree.c
+++ b/builtin-ls-tree.c
@@ -90,7 +90,7 @@ int cmd_ls_tree(int argc, const char **a
 	unsigned char sha1[20];
 	struct tree *tree;
 
-	prefix = setup_git_directory();
+	prefix = git_prefix;
 	git_config(git_default_config);
 	if (prefix && *prefix)
 		chomp_prefix = strlen(prefix);
diff --git a/builtin-read-tree.c b/builtin-read-tree.c
index 122b6f1..375347d 100644
--- a/builtin-read-tree.c
+++ b/builtin-read-tree.c
@@ -882,7 +882,6 @@ int cmd_read_tree(int argc, const char *
 	state.quiet = 1;
 	state.refresh_cache = 1;
 
-	setup_git_directory();
 	git_config(git_default_config);
 
 	newfd = hold_lock_file_for_update(&lock_file, get_index_file());
diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c
index b3e4386..cca9b05 100644
--- a/builtin-rev-parse.c
+++ b/builtin-rev-parse.c
@@ -213,7 +213,7 @@ int cmd_rev_parse(int argc, const char *
 {
 	int i, as_is = 0, verify = 0;
 	unsigned char sha1[20];
-	const char *prefix = setup_git_directory();
+	const char *prefix = git_prefix;
 
 	git_config(git_default_config);
 
diff --git a/builtin-rm.c b/builtin-rm.c
index bb810ba..25d0da3 100644
--- a/builtin-rm.c
+++ b/builtin-rm.c
@@ -47,7 +47,7 @@ int cmd_rm(int argc, const char **argv, 
 {
 	int i, newfd;
 	int verbose = 0, show_only = 0, force = 0;
-	const char *prefix = setup_git_directory();
+	const char *prefix = git_prefix;
 	const char **pathspec;
 	char *seen;
 
diff --git a/builtin-show-branch.c b/builtin-show-branch.c
index 82f75b7..43ab1f8 100644
--- a/builtin-show-branch.c
+++ b/builtin-show-branch.c
@@ -573,7 +573,6 @@ int cmd_show_branch(int ac, const char *
 	int topics = 0;
 	int dense = 1;
 
-	setup_git_directory();
 	git_config(git_show_branch_config);
 
 	/* If nothing is specified, try the default first */
diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c
index e5aaded..3e6b736 100644
--- a/builtin-tar-tree.c
+++ b/builtin-tar-tree.c
@@ -319,7 +319,6 @@ static int generate_tar(int argc, const 
 	current_path.alloc = PATH_MAX;
 	current_path.len = current_path.eof = 0;
 
-	setup_git_directory();
 	git_config(git_tar_config);
 
 	switch (argc) {
diff --git a/builtin-update-index.c b/builtin-update-index.c
index 1a4200d..c64506b 100644
--- a/builtin-update-index.c
+++ b/builtin-update-index.c
@@ -481,7 +481,7 @@ int cmd_update_index(int argc, const cha
 	int i, newfd, entries, has_errors = 0, line_termination = '\n';
 	int allow_options = 1;
 	int read_from_stdin = 0;
-	const char *prefix = setup_git_directory();
+	const char *prefix = git_prefix;
 	int prefix_length = prefix ? strlen(prefix) : 0;
 	char set_executable_bit = 0;
 	unsigned int refresh_flags = 0;
diff --git a/builtin-update-ref.c b/builtin-update-ref.c
index 83094ab..8138eba 100644
--- a/builtin-update-ref.c
+++ b/builtin-update-ref.c
@@ -13,7 +13,6 @@ int cmd_update_ref(int argc, const char 
 	int i;
 
 	setup_ident();
-	setup_git_directory();
 	git_config(git_default_config);
 
 	for (i = 1; i < argc; i++) {
diff --git a/builtin-write-tree.c b/builtin-write-tree.c
index 449a4d1..d987d0b 100644
--- a/builtin-write-tree.c
+++ b/builtin-write-tree.c
@@ -66,8 +66,6 @@ int cmd_write_tree(int argc, const char 
 	const char *prefix = NULL;
 	unsigned char sha1[20];
 
-	setup_git_directory();
-
 	while (1 < argc) {
 		const char *arg = argv[1];
 		if (!strcmp(arg, "--missing-ok"))
diff --git a/cache.h b/cache.h
index eee5fc9..6c008f9 100644
--- a/cache.h
+++ b/cache.h
@@ -130,6 +130,8 @@ extern char *get_graft_file(void);
 
 #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
 
+extern int gitdir_not_found;
+extern const char *git_prefix;
 extern const char **get_pathspec(const char *prefix, const char **pathspec);
 extern const char *setup_git_directory_gently(int *);
 extern const char *setup_git_directory(void);
diff --git a/environment.c b/environment.c
index 42f39d6..2fb978d 100644
--- a/environment.c
+++ b/environment.c
@@ -23,6 +23,8 @@ int shared_repository = PERM_UMASK;
 const char *apply_default_whitespace = NULL;
 int zlib_compression_level = Z_DEFAULT_COMPRESSION;
 int pager_in_use;
+int gitdir_not_found;
+const char *git_prefix;
 
 static char *git_dir, *git_object_dir, *git_index_file, *git_refs_dir,
 	*git_graft_file;
diff --git a/git.c b/git.c
index 885e1ce..a9d6340 100644
--- a/git.c
+++ b/git.c
@@ -220,45 +220,50 @@ static void handle_internal_command(int 
 	static struct cmd_struct {
 		const char *cmd;
 		int (*fn)(int, const char **, char **);
+		enum use_gitdir {
+			GITDIR_OPTIONAL,
+			GITDIR_REQUIRED,
+			GITDIR_DONTCARE,
+		} use_gitdir;
 	} commands[] = {
-		{ "version", cmd_version },
-		{ "help", cmd_help },
-		{ "log", cmd_log },
-		{ "whatchanged", cmd_whatchanged },
-		{ "show", cmd_show },
-		{ "push", cmd_push },
-		{ "format-patch", cmd_format_patch },
-		{ "count-objects", cmd_count_objects },
-		{ "diff", cmd_diff },
-		{ "grep", cmd_grep },
-		{ "rm", cmd_rm },
-		{ "add", cmd_add },
-		{ "rev-list", cmd_rev_list },
-		{ "init-db", cmd_init_db },
-		{ "get-tar-commit-id", cmd_get_tar_commit_id },
-		{ "upload-tar", cmd_upload_tar },
-		{ "check-ref-format", cmd_check_ref_format },
-		{ "ls-files", cmd_ls_files },
-		{ "ls-tree", cmd_ls_tree },
-		{ "tar-tree", cmd_tar_tree },
-		{ "read-tree", cmd_read_tree },
-		{ "commit-tree", cmd_commit_tree },
-		{ "apply", cmd_apply },
-		{ "show-branch", cmd_show_branch },
-		{ "diff-files", cmd_diff_files },
-		{ "diff-index", cmd_diff_index },
-		{ "diff-stages", cmd_diff_stages },
-		{ "diff-tree", cmd_diff_tree },
-		{ "cat-file", cmd_cat_file },
-		{ "rev-parse", cmd_rev_parse },
-		{ "write-tree", cmd_write_tree },
-		{ "mailsplit", cmd_mailsplit },
-		{ "mailinfo", cmd_mailinfo },
-		{ "stripspace", cmd_stripspace },
-		{ "update-index", cmd_update_index },
-		{ "update-ref", cmd_update_ref },
-		{ "fmt-merge-msg", cmd_fmt_merge_msg },
-		{ "prune", cmd_prune },
+		{ "version", cmd_version, GITDIR_DONTCARE },
+		{ "help", cmd_help, GITDIR_DONTCARE },
+		{ "log", cmd_log, GITDIR_REQUIRED },
+		{ "whatchanged", cmd_whatchanged, GITDIR_REQUIRED },
+		{ "show", cmd_show, GITDIR_REQUIRED },
+		{ "push", cmd_push, GITDIR_REQUIRED },
+		{ "format-patch", cmd_format_patch, GITDIR_REQUIRED },
+		{ "count-objects", cmd_count_objects, GITDIR_REQUIRED },
+		{ "diff", cmd_diff, GITDIR_REQUIRED },
+		{ "grep", cmd_grep, GITDIR_REQUIRED },
+		{ "rm", cmd_rm, GITDIR_REQUIRED },
+		{ "add", cmd_add, GITDIR_REQUIRED },
+		{ "rev-list", cmd_rev_list, GITDIR_REQUIRED },
+		{ "init-db", cmd_init_db, GITDIR_DONTCARE },
+		{ "get-tar-commit-id", cmd_get_tar_commit_id, GITDIR_REQUIRED },
+		{ "upload-tar", cmd_upload_tar, GITDIR_REQUIRED },
+		{ "check-ref-format", cmd_check_ref_format, GITDIR_DONTCARE },
+		{ "ls-files", cmd_ls_files, GITDIR_REQUIRED },
+		{ "ls-tree", cmd_ls_tree, GITDIR_REQUIRED },
+		{ "tar-tree", cmd_tar_tree, GITDIR_REQUIRED },
+		{ "read-tree", cmd_read_tree, GITDIR_REQUIRED },
+		{ "commit-tree", cmd_commit_tree, GITDIR_REQUIRED },
+		{ "apply", cmd_apply, GITDIR_OPTIONAL },
+		{ "show-branch", cmd_show_branch, GITDIR_REQUIRED },
+		{ "diff-files", cmd_diff_files, GITDIR_REQUIRED },
+		{ "diff-index", cmd_diff_index, GITDIR_REQUIRED },
+		{ "diff-stages", cmd_diff_stages, GITDIR_REQUIRED },
+		{ "diff-tree", cmd_diff_tree, GITDIR_REQUIRED },
+		{ "cat-file", cmd_cat_file, GITDIR_REQUIRED },
+		{ "rev-parse", cmd_rev_parse, GITDIR_REQUIRED },
+		{ "write-tree", cmd_write_tree, GITDIR_REQUIRED },
+		{ "mailsplit", cmd_mailsplit, GITDIR_OPTIONAL },
+		{ "mailinfo", cmd_mailinfo, GITDIR_OPTIONAL },
+		{ "stripspace", cmd_stripspace, GITDIR_OPTIONAL },
+		{ "update-index", cmd_update_index, GITDIR_REQUIRED },
+		{ "update-ref", cmd_update_ref, GITDIR_REQUIRED },
+		{ "fmt-merge-msg", cmd_fmt_merge_msg, GITDIR_DONTCARE },
+		{ "prune", cmd_prune, GITDIR_REQUIRED },
 	};
 	int i;
 
@@ -284,6 +289,18 @@ static void handle_internal_command(int 
 			fflush(stderr);
 		}
 
+		gitdir_not_found = 0;
+		switch (p->use_gitdir) {
+		case GITDIR_REQUIRED:
+			git_prefix = setup_git_directory();
+			break;
+		case GITDIR_OPTIONAL:
+			git_prefix =
+				setup_git_directory_gently(&gitdir_not_found);
+			break;
+		case GITDIR_DONTCARE:
+			break;
+		}
 		exit(p->fn(argc, argv, envp));
 	}
 }
diff --git a/t/trash/path0 b/t/trash/path0
deleted file mode 100644
index f87290f..0000000
--- a/t/trash/path0
+++ /dev/null
@@ -1 +0,0 @@
-hello path0
diff --git a/t/trash/path0sym b/t/trash/path0sym
deleted file mode 120000
index 15a9843..0000000
--- a/t/trash/path0sym
+++ /dev/null
@@ -1 +0,0 @@
-hello path0
\ No newline at end of file
diff --git a/t/trash/path2/file2 b/t/trash/path2/file2
deleted file mode 100644
index 3feff94..0000000
--- a/t/trash/path2/file2
+++ /dev/null
@@ -1 +0,0 @@
-hello path2/file2
diff --git a/t/trash/path2/file2sym b/t/trash/path2/file2sym
deleted file mode 120000
index d8ce161..0000000
--- a/t/trash/path2/file2sym
+++ /dev/null
@@ -1 +0,0 @@
-hello path2/file2
\ No newline at end of file
diff --git a/t/trash/path3/file3 b/t/trash/path3/file3
deleted file mode 100644
index 0aa34ca..0000000
--- a/t/trash/path3/file3
+++ /dev/null
@@ -1 +0,0 @@
-hello path3/file3
diff --git a/t/trash/path3/file3sym b/t/trash/path3/file3sym
deleted file mode 120000
index 8599103..0000000
--- a/t/trash/path3/file3sym
+++ /dev/null
@@ -1 +0,0 @@
-hello path3/file3
\ No newline at end of file
diff --git a/t/trash/path3/subp3/file3 b/t/trash/path3/subp3/file3
deleted file mode 100644
index 00fb590..0000000
--- a/t/trash/path3/subp3/file3
+++ /dev/null
@@ -1 +0,0 @@
-hello path3/subp3/file3
diff --git a/t/trash/path3/subp3/file3sym b/t/trash/path3/subp3/file3sym
deleted file mode 120000
index 6649a1e..0000000
--- a/t/trash/path3/subp3/file3sym
+++ /dev/null
@@ -1 +0,0 @@
-hello path3/subp3/file3
\ No newline at end of file

^ permalink raw reply related

* Re: Licensing and the library version of git
From: Jon Smirl @ 2006-07-29  4:31 UTC (permalink / raw)
  To: Shawn Pearce; +Cc: Johannes Schindelin, Wolfgang Denk, git
In-Reply-To: <20060729035632.GC28128@spearce.org>

On 7/28/06, Shawn Pearce <spearce@spearce.org> wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> > Hi,
> >
> > On Fri, 28 Jul 2006, Shawn Pearce wrote:
> >
> > > [...] as the GPL is incompatible with the Sun JRE runtime lirbary.
> >
> > This is not true. You can legally write and run GPLed software on the JRE
> > runtime library.
> >
> > BTW I found an Eclipse plugin which is GPLed:
> >
> > http://www.eclipseplugincentral.com/Web_Links-index-req-viewlink-cid-651.html
>
> Thanks.  I did a little research on it myself after reading your
> email. I turned up the following two pages from the FSF:
>
>   http://www.gnu.org/licenses/gpl-faq.html#InterpreterIncompat
>   http://www.gnu.org/licenses/lgpl-java.html
>
> Both suggest that I can license everything under the GPL but provide
> exclusions to allow users to run the code against its dependencies
> which aren't GPL'd:
>
>   - the end-user may 'link' the code against any Java runtime library
>     of their choice;
>
>   - the end-user may 'link' the code against any Eclipse platform
>     or derivative of their choice;
>
> So given that I'm seriously considering changing the license to
> GPLv2 for the next version.

Using the GPL plus your own exceptions creates another new license
which is a pain for everyone involved. Why not just use the standard
version with exceptions, the LGPL. The LGPL already allows the two
exceptions listed.

I don't believe there is any legal way to link GPL code into a Java
app since there are no free Java runtimes. This includes both C
libraries and Java code.

GPL is great for a kernel, but it runs into difficulties in user space
where there are hundreds of historical licenses that it can't mix
with. The viral concept only works if the target app has the ability
to relicense which is usually impossible for existing code.

-- 
Jon Smirl
jonsmirl@gmail.com

^ permalink raw reply

* Call setup_git_directory() early
From: Linus Torvalds @ 2006-07-29  4:21 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Mailing List
In-Reply-To: <7v3bclkwfj.fsf@assigned-by-dhcp.cox.net>


Any git command that expects to work in a subdirectory of a project, and 
that reads the git config files (which is just about all of them) needs to 
make sure that it does the "setup_git_directory()" call before it tries to 
read the config file.

This means, among other things, that we need to move the call out of 
"init_revisions()", and into the caller.

This does the mostly trivial conversion to do that.

Signed-off-by: Linus Torvalds <torvalds@osdl.org>
----


On Fri, 28 Jul 2006, Junio C Hamano wrote:
> 
> No clever ideas, but I agree it would be _very_ nice if we could
> do the setup unconditionally and early.  Some commands that call
> setup want to know prefix, so we would need to introduce a
> global to hold the prefix for them.

Ho humm. In the meantime, how about this? It fixes the places I noticed, 
but is mostly just a totally mindless conversion to move the call to 
"setup_git_directory()" into the caller.

diff --git a/blame.c b/blame.c
index b04b8f5..76712b5 100644
--- a/blame.c
+++ b/blame.c
@@ -834,7 +834,7 @@ int main(int argc, const char **argv)
 	}
 
 
-	init_revisions(&rev);
+	init_revisions(&rev, setup_git_directory());
 	rev.remove_empty_trees = 1;
 	rev.topo_order = 1;
 	rev.prune_fn = simplify_commit;
diff --git a/builtin-diff-files.c b/builtin-diff-files.c
index 2e10118..ea2936a 100644
--- a/builtin-diff-files.c
+++ b/builtin-diff-files.c
@@ -18,7 +18,7 @@ int cmd_diff_files(int argc, const char 
 	struct rev_info rev;
 	int silent = 0;
 
-	init_revisions(&rev);
+	init_revisions(&rev, setup_git_directory());
 	git_config(git_default_config); /* no "diff" UI options */
 	rev.abbrev = 0;
 
diff --git a/builtin-diff-index.c b/builtin-diff-index.c
index dc52c05..eeeee93 100644
--- a/builtin-diff-index.c
+++ b/builtin-diff-index.c
@@ -15,7 +15,7 @@ int cmd_diff_index(int argc, const char 
 	int cached = 0;
 	int i;
 
-	init_revisions(&rev);
+	init_revisions(&rev, setup_git_directory());
 	git_config(git_default_config); /* no "diff" UI options */
 	rev.abbrev = 0;
 
diff --git a/builtin-diff-tree.c b/builtin-diff-tree.c
index 8957b45..f8215ea 100644
--- a/builtin-diff-tree.c
+++ b/builtin-diff-tree.c
@@ -67,7 +67,7 @@ int cmd_diff_tree(int argc, const char *
 	static struct rev_info *opt = &log_tree_opt;
 	int read_stdin = 0;
 
-	init_revisions(opt);
+	init_revisions(opt, setup_git_directory());
 	git_config(git_default_config); /* no "diff" UI options */
 	nr_sha1 = 0;
 	opt->abbrev = 0;
diff --git a/builtin-diff.c b/builtin-diff.c
index 7d5ad62..7965c2c 100644
--- a/builtin-diff.c
+++ b/builtin-diff.c
@@ -227,7 +227,7 @@ int cmd_diff(int argc, const char **argv
 	struct rev_info rev;
 	struct object_array_entry ent[100];
 	int ents = 0, blobs = 0, paths = 0;
-	const char *path = NULL;
+	const char *path = NULL, *prefix;
 	struct blobinfo blob[2];
 
 	/*
@@ -250,9 +250,9 @@ int cmd_diff(int argc, const char **argv
 	 * Other cases are errors.
 	 */
 
-	init_revisions(&rev);
+	prefix = setup_git_directory();
 	git_config(git_diff_ui_config);
-	diff_setup(&rev.diffopt);
+	init_revisions(&rev, prefix);
 
 	argc = setup_revisions(argc, argv, &rev, NULL);
 	if (!rev.diffopt.output_format) {
diff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c
index f20b27b..338f209 100644
--- a/builtin-fmt-merge-msg.c
+++ b/builtin-fmt-merge-msg.c
@@ -250,6 +250,7 @@ int cmd_fmt_merge_msg(int argc, char **a
 	const char *sep = "";
 	unsigned char head_sha1[20];
 	const char *head, *current_branch;
+	const char *prefix = setup_git_directory();
 
 	git_config(fmt_merge_msg_config);
 
@@ -342,7 +343,7 @@ int cmd_fmt_merge_msg(int argc, char **a
 		struct rev_info rev;
 
 		head = lookup_commit(head_sha1);
-		init_revisions(&rev);
+		init_revisions(&rev, prefix);
 		rev.commit_format = CMIT_FMT_ONELINE;
 		rev.ignore_merges = 1;
 		rev.limited = 1;
diff --git a/builtin-log.c b/builtin-log.c
index 88c835a..52064cd 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -48,10 +48,10 @@ static int cmd_log_walk(struct rev_info 
 int cmd_whatchanged(int argc, const char **argv, char **envp)
 {
 	struct rev_info rev;
+	const char *prefix = setup_git_directory();
 
-	init_revisions(&rev);
 	git_config(git_diff_ui_config);
-	diff_setup(&rev.diffopt);
+	init_revisions(&rev, prefix);
 	rev.diff = 1;
 	rev.diffopt.recursive = 1;
 	rev.simplify_history = 0;
@@ -64,10 +64,10 @@ int cmd_whatchanged(int argc, const char
 int cmd_show(int argc, const char **argv, char **envp)
 {
 	struct rev_info rev;
+	const char *prefix = setup_git_directory();
 
-	init_revisions(&rev);
 	git_config(git_diff_ui_config);
-	diff_setup(&rev.diffopt);
+	init_revisions(&rev, prefix);
 	rev.diff = 1;
 	rev.diffopt.recursive = 1;
 	rev.combine_merges = 1;
@@ -82,10 +82,10 @@ int cmd_show(int argc, const char **argv
 int cmd_log(int argc, const char **argv, char **envp)
 {
 	struct rev_info rev;
+	const char *prefix = setup_git_directory();
 
-	init_revisions(&rev);
 	git_config(git_diff_ui_config);
-	diff_setup(&rev.diffopt);
+	init_revisions(&rev, prefix);
 	rev.always_show_header = 1;
 	cmd_log_init(argc, argv, envp, &rev);
 	return cmd_log_walk(&rev);
@@ -188,6 +188,7 @@ static void get_patch_ids(struct rev_inf
 	struct object *o1, *o2;
 	unsigned flags1, flags2;
 	unsigned char sha1[20];
+	const char *prefix = setup_git_directory();
 
 	if (rev->pending.nr != 2)
 		die("Need exactly one range.");
@@ -206,7 +207,7 @@ static void get_patch_ids(struct rev_inf
 		die("diff_setup_done failed");
 
 	/* given a range a..b get all patch ids for b..a */
-	init_revisions(&check_rev);
+	init_revisions(&check_rev, prefix);
 	o1->flags ^= UNINTERESTING;
 	o2->flags ^= UNINTERESTING;
 	add_pending_object(&check_rev, o1, "o1");
@@ -260,9 +261,10 @@ int cmd_format_patch(int argc, const cha
 	char *add_signoff = NULL;
 	char message_id[1024];
 	char ref_message_id[1024];
+	const char *prefix = setup_git_directory();
 
 	git_config(git_format_config);
-	init_revisions(&rev);
+	init_revisions(&rev, prefix);
 	rev.commit_format = CMIT_FMT_EMAIL;
 	rev.verbose_header = 1;
 	rev.diff = 1;
diff --git a/builtin-prune.c b/builtin-prune.c
index d196c41..4ed1e1b 100644
--- a/builtin-prune.c
+++ b/builtin-prune.c
@@ -234,7 +234,7 @@ int cmd_prune(int argc, const char **arg
 	 * Set up revision parsing, and mark us as being interested
 	 * in all object types, not just commits.
 	 */
-	init_revisions(&revs);
+	init_revisions(&revs, setup_git_directory());
 	revs.tag_objects = 1;
 	revs.blob_objects = 1;
 	revs.tree_objects = 1;
diff --git a/builtin-rev-list.c b/builtin-rev-list.c
index 8f32871..2b6691c 100644
--- a/builtin-rev-list.c
+++ b/builtin-rev-list.c
@@ -311,7 +311,7 @@ int cmd_rev_list(int argc, const char **
 	struct commit_list *list;
 	int i;
 
-	init_revisions(&revs);
+	init_revisions(&revs, setup_git_directory());
 	revs.abbrev = 0;
 	revs.commit_format = CMIT_FMT_UNSPECIFIED;
 	argc = setup_revisions(argc, argv, &revs, NULL);
diff --git a/http-push.c b/http-push.c
index 4768619..4021e7d 100644
--- a/http-push.c
+++ b/http-push.c
@@ -2521,7 +2521,7 @@ int main(int argc, char **argv)
 			commit_argv[3] = old_sha1_hex;
 			commit_argc++;
 		}
-		init_revisions(&revs);
+		init_revisions(&revs, setup_git_directory());
 		setup_revisions(commit_argc, commit_argv, &revs, NULL);
 		free(new_sha1_hex);
 		if (old_sha1_hex) {
diff --git a/revision.c b/revision.c
index 874e349..a58257a 100644
--- a/revision.c
+++ b/revision.c
@@ -509,7 +509,7 @@ static int add_parents_only(struct rev_i
 	return 1;
 }
 
-void init_revisions(struct rev_info *revs)
+void init_revisions(struct rev_info *revs, const char *prefix)
 {
 	memset(revs, 0, sizeof(*revs));
 
@@ -521,7 +521,7 @@ void init_revisions(struct rev_info *rev
 	revs->pruning.change = file_change;
 	revs->lifo = 1;
 	revs->dense = 1;
-	revs->prefix = setup_git_directory();
+	revs->prefix = prefix;
 	revs->max_age = -1;
 	revs->min_age = -1;
 	revs->max_count = -1;
diff --git a/revision.h b/revision.h
index e23ec8f..0c3b8d9 100644
--- a/revision.h
+++ b/revision.h
@@ -87,7 +87,7 @@ #define REV_TREE_DIFFERENT	2
 extern int rev_same_tree_as_empty(struct rev_info *, struct tree *t1);
 extern int rev_compare_tree(struct rev_info *, struct tree *t1, struct tree *t2);
 
-extern void init_revisions(struct rev_info *revs);
+extern void init_revisions(struct rev_info *revs, const char *prefix);
 extern int setup_revisions(int argc, const char **argv, struct rev_info *revs, const char *def);
 extern void prepare_revision_walk(struct rev_info *revs);
 extern struct commit *get_revision(struct rev_info *revs);

^ permalink raw reply related

* Re: Java GIT/Eclipse GIT version 0.1.1
From: Shawn Pearce @ 2006-07-29  4:08 UTC (permalink / raw)
  To: Pavel Roskin; +Cc: Peter Baumann, git
In-Reply-To: <1154145355.26378.35.camel@dv>

Pavel Roskin <proski@gnu.org> wrote:
> On Fri, 2006-07-28 at 23:32 -0400, Shawn Pearce wrote:
> 
> > Hmm.  My website is known to return 200 OK status codes on missing
> > files with HTML pages rather than proper 404 Not Found.  I guess
> > I need to get that fixed.
> 
> Maybe git-http-fetch could treat MIME type text/html like error 404?
> It's not like any valid file git requests can be in HTML format.

This has been discussed to death on the list, mostly due to my pg
repository causing the same error (its on the same server).

The solution turned out to be rather good in my opinion: if an
object is corrupt we log it, and skip to pack downloading.  At the
end the bad object is logged and the user is encouraged to run
git-fsck-objects to verify there's no corrupt objects or objects
which are missing things they point at (e.g. ancestor commits
or trees).

Of course the real solution here is for me to fix my server.  :-)

> > I just compiled and installed `next` (1.4.2.rc1.g802da) and it can
> > clone this repository just fine over HTTP, despite my broken server.
> > So I'm not really sure what is going on.
> 
> Sorry, I was unclear.  I can clone the repository, I was just concerned
> that something was missing from it.

git-http-fetch recommends running git-fsck-objects to be sure,
but yea, usually its complete even though you get the error.

-- 
Shawn.

^ permalink raw reply

* Re: Licensing and the library version of git
From: Shawn Pearce @ 2006-07-29  3:56 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Wolfgang Denk, Jon Smirl, git
In-Reply-To: <Pine.LNX.4.63.0607281041420.29667@wbgn013.biozentrum.uni-wuerzburg.de>

Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> Hi,
> 
> On Fri, 28 Jul 2006, Shawn Pearce wrote:
> 
> > [...] as the GPL is incompatible with the Sun JRE runtime lirbary.
> 
> This is not true. You can legally write and run GPLed software on the JRE 
> runtime library.
> 
> BTW I found an Eclipse plugin which is GPLed:
> 
> http://www.eclipseplugincentral.com/Web_Links-index-req-viewlink-cid-651.html

Thanks.  I did a little research on it myself after reading your
email. I turned up the following two pages from the FSF:

  http://www.gnu.org/licenses/gpl-faq.html#InterpreterIncompat
  http://www.gnu.org/licenses/lgpl-java.html

Both suggest that I can license everything under the GPL but provide
exclusions to allow users to run the code against its dependencies
which aren't GPL'd:

  - the end-user may 'link' the code against any Java runtime library
    of their choice;

  - the end-user may 'link' the code against any Eclipse platform
    or derivative of their choice;

So given that I'm seriously considering changing the license to
GPLv2 for the next version.

-- 
Shawn.

^ permalink raw reply

* Re: Java GIT/Eclipse GIT version 0.1.1
From: Pavel Roskin @ 2006-07-29  3:55 UTC (permalink / raw)
  To: Shawn Pearce; +Cc: Peter Baumann, git
In-Reply-To: <20060729033214.GA28128@spearce.org>

On Fri, 2006-07-28 at 23:32 -0400, Shawn Pearce wrote:

> Hmm.  My website is known to return 200 OK status codes on missing
> files with HTML pages rather than proper 404 Not Found.  I guess
> I need to get that fixed.

Maybe git-http-fetch could treat MIME type text/html like error 404?
It's not like any valid file git requests can be in HTML format.

> I just compiled and installed `next` (1.4.2.rc1.g802da) and it can
> clone this repository just fine over HTTP, despite my broken server.
> So I'm not really sure what is going on.

Sorry, I was unclear.  I can clone the repository, I was just concerned
that something was missing from it.

-- 
Regards,
Pavel Roskin

^ permalink raw reply

* Re: print errors from git-update-ref
From: Shawn Pearce @ 2006-07-29  3:44 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Johannes Schindelin
In-Reply-To: <7vejw6mbqj.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano <junkio@cox.net> wrote:
> Shawn Pearce <spearce@spearce.org> writes:
> 
> > Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> >> Hi,
> >> 
> >> On Wed, 26 Jul 2006, Shawn Pearce wrote:
> >> 
> >> > This change adds a test for trying to create a ref within a directory
> >> > that is actually currently a file, and adds error printing within
> >> > the ref locking routine should the resolve operation fail.
> >> 
> >> Why not just print an error message when the resolve operation fails, 
> >> instead of special casing this obscure corner case? It is way shorter, 
> >> too. The test should stay, though.
> >
> > Did you read the patch?  If resolve_ref returns NULL then this
> > change prints an error (from errno) no matter what.  If errno is
> > ENOTDIR then it tries to figure out what part of the ref path wasn't
> > a directory (but was attempted to be used as such) and prints an
> > ENOTDIR error about that path instead of the one actually given
> > to the ref lock function
> >
> > So I think I'm doing what you are suggesting...
>
[snip]
> But the last step does not take into account what resolve_ref()
> does, doesn't it?  What if orig_path is "HEAD", which is a
> symref, which contained "ref: refs/heads/myhack/one" and
> "refs/heads/myhack" is a file?  Ideally you may want to say
> something like:
> 
>      '''while resolving %s, which points at %s,
>         we found out %s is not a directory''' %
>         ("HEAD", "refs/heads/myhack/one", "refs/heads/myhack")
> 
> So I tend to agree with Johannes's "why bother?" reaction.

OK, that's a bug.  It would be horribly misleading.  So I'm taking
the shortcut here and just telling the user ENOTDIR and orig_path
rather than resolving it and finding that bad directory component.

-->8--
Display an error from update-ref if target ref name is invalid.

Alex Riesen (raa.lkml@gmail.com) recently observed that git branch
would fail with no error message due to unexpected situations with
regards to refs.  For example, if .git/refs/heads/gu is a file but
`git branch -b refs/heads/gu/fixa HEAD` was invoked by the user
it would fail silently due to refs/heads/gu being a file and not
a directory.

This change adds a test for trying to create a ref within a directory
that is actually currently a file, and adds error printing within
the ref locking routine should the resolve operation fail.

The error printing code probably belongs at this level of the library
as other failures within the ref locking, writing and logging code
are also currently at this level of the code.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 refs.c                |    5 +++++
 t/t1400-update-ref.sh |   12 ++++++++++++
 2 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/refs.c b/refs.c
index 56db394..02850b6 100644
--- a/refs.c
+++ b/refs.c
@@ -294,6 +294,7 @@ static struct ref_lock *lock_ref_sha1_ba
 	int plen,
 	const unsigned char *old_sha1, int mustexist)
 {
+	const char *orig_path = path;
 	struct ref_lock *lock;
 	struct stat st;
 
@@ -303,7 +304,11 @@ static struct ref_lock *lock_ref_sha1_ba
 	plen = strlen(path) - plen;
 	path = resolve_ref(path, lock->old_sha1, mustexist);
 	if (!path) {
+		int last_errno = errno;
+		error("unable to resolve reference %s: %s",
+			orig_path, strerror(errno));
 		unlock_ref(lock);
+		errno = last_errno;
 		return NULL;
 	}
 	lock->lk = xcalloc(1, sizeof(struct lock_file));
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index 04fab26..ddc80bb 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -14,6 +14,8 @@ D=44444444444444444444444444444444444444
 E=5555555555555555555555555555555555555555
 F=6666666666666666666666666666666666666666
 m=refs/heads/master
+n_dir=refs/heads/gu
+n=$n_dir/fixes
 
 test_expect_success \
 	"create $m" \
@@ -26,6 +28,16 @@ test_expect_success \
 rm -f .git/$m
 
 test_expect_success \
+	"fail to create $n" \
+	'touch .git/$n_dir
+	 git-update-ref $n $A >out 2>err
+	 test $? = 1 &&
+	 test "" = "$(cat out)" &&
+	 grep "error: unable to resolve reference" err &&
+	 grep $n err'
+rm -f .git/$n_dir out err
+
+test_expect_success \
 	"create $m (by HEAD)" \
 	'git-update-ref HEAD $A &&
 	 test $A = $(cat .git/$m)'
-- 
1.4.2.rc1.g802da

^ permalink raw reply related

* Re: Java GIT/Eclipse GIT version 0.1.1
From: Shawn Pearce @ 2006-07-29  3:32 UTC (permalink / raw)
  To: Pavel Roskin; +Cc: Peter Baumann, git
In-Reply-To: <20060728030859.n8ks44ck8884ss44@webmail.spamcop.net>

Pavel Roskin <proski@gnu.org> wrote:
> Quoting Peter Baumann <Peter.B.Baumann@stud.informatik.uni-erlangen.de>:
> 
> > On 2006-07-28, Shawn Pearce <spearce@spearce.org> wrote:
> > > My Java GIT library and Eclipse GIT team provider is now at a point
> > > where it may be partially useful to someone else who is also trying
> > > to write something which interacts with GIT.  Or who might also
> > > be interested in seeing a pure-Java Eclipse team provider for GIT.
> > >
> > > So I've posted my repository (currently ~200 KB) on my website:
> > >
> > >   http://www.spearce.org/projects/scm/egit.git
> > >
> >
> > Doesn't work for me.
> 
> Neither does it for me:
> 
> $ git clone http://www.spearce.org/projects/scm/egit.git
> error: File ac32c7cc2f7cf87a1ed80d0cdfca2af2a0385bb2
> (http://www.spearce.org/projects/scm/egit.git/objects/ac/32c7cc2f7cf87a1ed80d0cdfca2af2a0385bb2)
> corrupt
> Getting pack list for http://www.spearce.org/projects/scm/egit.git/
> error: XML error: not well-formed (invalid token)

Hmm.  My website is known to return 200 OK status codes on missing
files with HTML pages rather than proper 404 Not Found.  I guess
I need to get that fixed.

I just compiled and installed `next` (1.4.2.rc1.g802da) and it can
clone this repository just fine over HTTP, despite my broken server.
So I'm not really sure what is going on.

I should look into fixing my server, but its low on my priority list.

-- 
Shawn.

^ permalink raw reply

* Re: Java GIT/Eclipse GIT version 0.1.1
From: Pavel Roskin @ 2006-07-29  2:10 UTC (permalink / raw)
  To: Peter Baumann; +Cc: git
In-Reply-To: <slrnecjeru.bou.Peter.B.Baumann@xp.machine.xx>

On Fri, 2006-07-28 at 09:23 +0200, Peter Baumann wrote:
> >> *** glibc detected *** double free or corruption (!prev): 0x080933b0 ***
> >> /usr/bin/git-clone: line 29: 10712 Aborted                 git-http-fetch -v
> >> -a -w "$tname" "$name" "$1/"
> >
> > I'm not getting that.  I hope you are just using an obsolete version of git.
> 
> Not _that_ old, me thinks. I'm using the debian unstable version.

I tried to reproduce it but couldn't.  I tried valgrind (3.2.0 and
current) on two architectures, I tried _FORTIFY_SOURCE=2 to no avail -
it just won't crash or report anything suspicious.  It's the current
master branch of git.

So, it's up to you to debug it.

-- 
Regards,
Pavel Roskin

^ permalink raw reply

* Re: log and diff family: honor config even from subdirectories
From: Junio C Hamano @ 2006-07-29  1:54 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0607281811580.4168@g5.osdl.org>

Linus Torvalds <torvalds@osdl.org> writes:

> I'd actually _like_ to do the setup unconditionally inside the git wrapper 
> (early - to make sure that we don't have this bug), but some things (at 
> least "init-db", "clone" and "ls-remote") are obviously not supposed to do 
> it, since they work outside of a git directory. So either we need to do it 
> in each builtin command separately, or we'd need to add a flag in the 
> command descriptor array.
>
> Any clever ideas?
>
> 		Linus

No clever ideas, but I agree it would be _very_ nice if we could
do the setup unconditionally and early.  Some commands that call
setup want to know prefix, so we would need to introduce a
global to hold the prefix for them.

I do not do this myself, but it is conceivable that you might
want to be able to set GIT_DIR to point at somewhere outside
your working tree hierarchy, _and_ still work in a subdirectory.
The current setup does not allow you to do that; we could
introduce GIT_PROJECT_ROOT environment variable, and when
GIT_PROJECT_ROOT exists difference between getcwd() and the
project root could become the value of prefix.

^ permalink raw reply

* Re: log and diff family: honor config even from subdirectories
From: Linus Torvalds @ 2006-07-29  1:17 UTC (permalink / raw)
  To: Junio C Hamano, Git Mailing List


Junio,
 I think your patch is fine as a band-aid, but I wonder if we shouldn't 
just move the "setup_git_directory()" call out of init_revisions(), and 
pass it as an argument to init_revision(). Some of the callers have 
already done setup_git_directory() earlier for their own reasons anyway.

And from a quick look it looks like you missed the same bug happening in 
cmd_format_patch(), which calls git_config(git_format_config) before 
having done the setup.

I'd actually _like_ to do the setup unconditionally inside the git wrapper 
(early - to make sure that we don't have this bug), but some things (at 
least "init-db", "clone" and "ls-remote") are obviously not supposed to do 
it, since they work outside of a git directory. So either we need to do it 
in each builtin command separately, or we'd need to add a flag in the 
command descriptor array.

Any clever ideas?

		Linus

^ permalink raw reply

* [PATCH] Fix http-fetch
From: Johannes Schindelin @ 2006-07-29  0:10 UTC (permalink / raw)
  To: git, junkio


With the latest changes in fetch.c, http-fetch crashed accessing 
write_ref[i], where write_ref was NULL.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 fetch.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/fetch.c b/fetch.c
index 2151c7b..aeb6bf2 100644
--- a/fetch.c
+++ b/fetch.c
@@ -245,7 +245,7 @@ void pull_targets_free(int targets, char
 {
 	while (targets--) {
 		free(target[targets]);
-		if (write_ref[targets])
+		if (write_ref && write_ref[targets])
 			free((char *) write_ref[targets]);
 	}
 }
@@ -263,7 +263,7 @@ int pull(int targets, char **target, con
 	track_object_refs = 0;
 
 	for (i = 0; i < targets; i++) {
-		if (!write_ref[i])
+		if (!write_ref || !write_ref[i])
 			continue;
 
 		lock[i] = lock_ref_sha1(write_ref[i], NULL, 0);
@@ -295,7 +295,7 @@ int pull(int targets, char **target, con
 		msg = NULL;
 	}
 	for (i = 0; i < targets; i++) {
-		if (!write_ref[i])
+		if (!write_ref || !write_ref[i])
 			continue;
 		ret = write_ref_sha1(lock[i], &sha1[20 * i], msg ? msg : "fetch (unknown)");
 		lock[i] = NULL;
-- 
1.4.2.rc2.g0d86-dirty

^ permalink raw reply related

* Oh, you do it very fast...
From: Lamb @ 2006-07-28 23:40 UTC (permalink / raw)
  To: glenda

Nice to see you! The good news are that this obstacle can be overcome by you, the real man. Safe, efficient and covering all aspects, Extra-Time will help you forget the premature nightmare. Any man wants to last longer and make his partner happy with that. Come on in: http://juliasterkl.com/gall/get/ You will never see her face frustrated again. No arguments and no complaints!

^ permalink raw reply

* [RFC] Add the --color-words option to the diff options family
From: Johannes Schindelin @ 2006-07-28 21:56 UTC (permalink / raw)
  To: git


With this option, the changed words are shown inline. For example,
if a file containing "This is foo" is changed to "This is bar", the diff
will now show "This is " in plain text, "foo" in red, and "bar" in green.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>

---

	I am probably the only person who finds it useful, but there
	is a high coolness factor attached to it.

	And the libxdiff library actually made it very easy to do. (Yes, 
	there are two nested calls to xdiff...)

 Documentation/diff-options.txt |    3 +
 diff.c                         |  178 +++++++++++++++++++++++++++++++++++++++-
 diff.h                         |    3 -
 3 files changed, 177 insertions(+), 7 deletions(-)

diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index 47ba9a4..b5d9763 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -36,6 +36,9 @@
 	Turn off colored diff, even when the configuration file
 	gives the default to color output.
 
+--color-words::
+	Show colored word diff, i.e. color words which have changed.
+
 --no-renames::
 	Turn off rename detection, even when the configuration
 	file gives the default to do so.
diff --git a/diff.c b/diff.c
index 6198a61..e910971 100644
--- a/diff.c
+++ b/diff.c
@@ -358,12 +358,152 @@ static int fill_mmfile(mmfile_t *mf, str
 	return 0;
 }
 
+struct diff_words_buffer {
+	mmfile_t text;
+	long alloc;
+	long current; /* output pointer */
+	int suppressed_newline;
+};
+
+static void diff_words_append(char *line, unsigned long len,
+		struct diff_words_buffer *buffer)
+{
+	if (buffer->text.size + len > buffer->alloc) {
+		buffer->alloc = (buffer->text.size + len) * 3 / 2;
+		buffer->text.ptr = xrealloc(buffer->text.ptr, buffer->alloc);
+	}
+	line++;
+	len--;
+	memcpy(buffer->text.ptr + buffer->text.size, line, len);
+	buffer->text.size += len;
+}
+
+struct diff_words_data {
+	struct xdiff_emit_state xm;
+	struct diff_words_buffer minus, plus;
+};
+
+static void print_word(struct diff_words_buffer *buffer, int len, int color,
+		int suppress_newline)
+{
+	const char *ptr;
+	int eol = 0;
+
+	if (len == 0)
+		return;
+
+	ptr  = buffer->text.ptr + buffer->current;
+	buffer->current += len;
+
+	if (ptr[len - 1] == '\n') {
+		eol = 1;
+		len--;
+	}
+
+	fputs(diff_get_color(1, color), stdout);
+	fwrite(ptr, len, 1, stdout);
+	fputs(diff_get_color(1, DIFF_RESET), stdout);
+
+	if (eol) {
+		if (suppress_newline)
+			buffer->suppressed_newline = 1;
+		else
+			putchar('\n');
+	}
+}
+
+static void fn_out_diff_words_aux(void *priv, char *line, unsigned long len)
+{
+	struct diff_words_data *diff_words = priv;
+
+	if (diff_words->minus.suppressed_newline) {
+		if (line[0] != '+')
+			putchar('\n');
+		diff_words->minus.suppressed_newline = 0;
+	}
+
+	len--;
+	switch (line[0]) {
+		case '-':
+			print_word(&diff_words->minus, len, DIFF_FILE_OLD, 1);
+			break;
+		case '+':
+			print_word(&diff_words->plus, len, DIFF_FILE_NEW, 0);
+			break;
+		case ' ':
+			print_word(&diff_words->plus, len, DIFF_PLAIN, 0);
+			diff_words->minus.current += len;
+			break;
+	}
+}
+
+/* this executes the word diff on the accumulated buffers */
+static void diff_words_show(struct diff_words_data *diff_words)
+{
+	xpparam_t xpp;
+	xdemitconf_t xecfg;
+	xdemitcb_t ecb;
+	mmfile_t minus, plus;
+	int i;
+
+	minus.size = diff_words->minus.text.size;
+	minus.ptr = xmalloc(minus.size);
+	memcpy(minus.ptr, diff_words->minus.text.ptr, minus.size);
+	for (i = 0; i < minus.size; i++)
+		if (isspace(minus.ptr[i]))
+			minus.ptr[i] = '\n';
+	diff_words->minus.current = 0;
+
+	plus.size = diff_words->plus.text.size;
+	plus.ptr = xmalloc(plus.size);
+	memcpy(plus.ptr, diff_words->plus.text.ptr, plus.size);
+	for (i = 0; i < plus.size; i++)
+		if (isspace(plus.ptr[i]))
+			plus.ptr[i] = '\n';
+	diff_words->plus.current = 0;
+
+	xpp.flags = XDF_NEED_MINIMAL;
+	xecfg.ctxlen = diff_words->minus.alloc + diff_words->plus.alloc;
+	xecfg.flags = 0;
+	ecb.outf = xdiff_outf;
+	ecb.priv = diff_words;
+	diff_words->xm.consume = fn_out_diff_words_aux;
+	xdl_diff(&minus, &plus, &xpp, &xecfg, &ecb);
+
+	free(minus.ptr);
+	free(plus.ptr);
+	diff_words->minus.text.size = diff_words->plus.text.size = 0;
+
+	if (diff_words->minus.suppressed_newline) {
+		putchar('\n');
+		diff_words->minus.suppressed_newline = 0;
+	}
+}
+
 struct emit_callback {
 	struct xdiff_emit_state xm;
 	int nparents, color_diff;
 	const char **label_path;
+	struct diff_words_data *diff_words;
 };
 
+static void free_diff_words_data(struct emit_callback *ecbdata)
+{
+	if (ecbdata->diff_words) {
+		/* flush buffers */
+		if (ecbdata->diff_words->minus.text.size ||
+				ecbdata->diff_words->plus.text.size)
+			diff_words_show(ecbdata->diff_words);
+
+		if (ecbdata->diff_words->minus.text.ptr)
+			free (ecbdata->diff_words->minus.text.ptr);
+		if (ecbdata->diff_words->plus.text.ptr)
+			free (ecbdata->diff_words->plus.text.ptr);
+		free(ecbdata->diff_words);
+		ecbdata->diff_words = NULL;
+	}
+}
+
 const char *diff_get_color(int diff_use_color, enum color_diff ix)
 {
 	if (diff_use_color)
@@ -398,12 +538,31 @@ static void fn_out_consume(void *priv, c
 	else {
 		int nparents = ecbdata->nparents;
 		int color = DIFF_PLAIN;
-		for (i = 0; i < nparents && len; i++) {
-			if (line[i] == '-')
-				color = DIFF_FILE_OLD;
-			else if (line[i] == '+')
-				color = DIFF_FILE_NEW;
-		}
+		if (ecbdata->diff_words && nparents != 1)
+			/* fall back to normal diff */
+			free_diff_words_data(ecbdata);
+		if (ecbdata->diff_words) {
+			if (line[0] == '-') {
+				diff_words_append(line, len,
+						&ecbdata->diff_words->minus);
+				return;
+			} else if (line[0] == '+') {
+				diff_words_append(line, len,
+						&ecbdata->diff_words->plus);
+				return;
+			}
+			if (ecbdata->diff_words->minus.text.size ||
+					ecbdata->diff_words->plus.text.size)
+				diff_words_show(ecbdata->diff_words);
+			line++;
+			len--;
+		} else
+			for (i = 0; i < nparents && len; i++) {
+				if (line[i] == '-')
+					color = DIFF_FILE_OLD;
+				else if (line[i] == '+')
+					color = DIFF_FILE_NEW;
+			}
 		set = diff_get_color(ecbdata->color_diff, color);
 	}
 	if (len > 0 && line[len-1] == '\n')
@@ -836,7 +995,12 @@ static void builtin_diff(const char *nam
 		ecb.outf = xdiff_outf;
 		ecb.priv = &ecbdata;
 		ecbdata.xm.consume = fn_out_consume;
+		if (o->color_diff_words)
+			ecbdata.diff_words =
+				xcalloc(1, sizeof(struct diff_words_data));
 		xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
+		if (o->color_diff_words)
+			free_diff_words_data(&ecbdata);
 	}
 
  free_ab_and_return:
@@ -1712,6 +1876,8 @@ int diff_opt_parse(struct diff_options *
 		options->xdl_opts |= XDF_IGNORE_WHITESPACE;
 	else if (!strcmp(arg, "-b") || !strcmp(arg, "--ignore-space-change"))
 		options->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE;
+	else if (!strcmp(arg, "--color-words"))
+		options->color_diff = options->color_diff_words = 1;
 	else if (!strcmp(arg, "--no-renames"))
 		options->detect_rename = 0;
 	else
diff --git a/diff.h b/diff.h
index 0d32830..51c163b 100644
--- a/diff.h
+++ b/diff.h
@@ -46,7 +46,8 @@ struct diff_options {
 		 full_index:1,
 		 silent_on_remove:1,
 		 find_copies_harder:1,
-		 color_diff:1;
+		 color_diff:1,
+		 color_diff_words:1;
 	int context;
 	int break_opt;
 	int detect_rename;
-- 
1.4.2.rc2.g8b063-dirty

^ permalink raw reply related

* Re: [PATCH] Teach git-apply about '-R'
From: Johannes Schindelin @ 2006-07-28 19:36 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vhd11leny.fsf@assigned-by-dhcp.cox.net>

Hi,

On Fri, 28 Jul 2006, Junio C Hamano wrote:

> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> 
> > On Fri, 28 Jul 2006, Junio C Hamano wrote:
> >> 
> >> A quick comment without looking much at the code.  Do you sanely
> >> bail out when asked to reverse-apply a binary patch?
> >
> > Nope. I swap old_sha1_prefix and new_sha1_prefix in that case, I hoped 
> > that is enough?
> 
> You would need something like this, at least for now, since both
> deflated literal and deflated delta methods are irreversible.

Somehow I had the impression that binary diff meant that you needed both 
objects in the object database. I was wrong.

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH] Teach git-apply about '-R'
From: Junio C Hamano @ 2006-07-28 19:20 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.63.0607281748390.29667@wbgn013.biozentrum.uni-wuerzburg.de>

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> On Fri, 28 Jul 2006, Junio C Hamano wrote:
>> 
>> A quick comment without looking much at the code.  Do you sanely
>> bail out when asked to reverse-apply a binary patch?
>
> Nope. I swap old_sha1_prefix and new_sha1_prefix in that case, I hoped 
> that is enough?

You would need something like this, at least for now, since both
deflated literal and deflated delta methods are irreversible.
I'll cook up another binary diff output that can go
bidirectional.

Note that --allow-binary-replacement uses the blob object name
recorded on index lines of binary patch, and uses it to cheat
(iow, when it knows your version is the old version recorded on
index line and your repository happens to have the resulting
blob, it just uses the blob without looking at the binary
contents recorded in the patch), so you have to work a bit hard
to cause it to fail in t/trash repository after you run t4103
test.  Resetting to "master", apply BF.diff, and immediately
reverse apply BF.diff would _work_, only because "master" and
"binary" branch keep both preimage and postimage.

-- >8 --
diff --git a/builtin-apply.c b/builtin-apply.c
index 6b38a8a..d4381d9 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -1535,6 +1535,12 @@ static int apply_binary_fragment(struct 
 	void *data;
 	void *result;
 
+	/* Binary patch is irreversible */
+	if (patch->is_reverse)
+		return error("cannot reverse-apply a binary patch to '%s'",
+			     patch->new_name
+			     ? patch->new_name : patch->old_name);
+
 	data = inflate_it(fragment->patch, fragment->size,
 			  patch->deflate_origlen);
 	if (!data)

^ permalink raw reply related

* Re: [PATCH] Makefile: ssh-pull.o depends on ssh-fetch.c
From: Johannes Schindelin @ 2006-07-28 18:55 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vslkllhqo.fsf@assigned-by-dhcp.cox.net>

Hi,

On Fri, 28 Jul 2006, Junio C Hamano wrote:

> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> 
> > +ssh-pull.o: ssh-fetch.c
> 
> My personal preference would be to deprecate these commit walkers ;-) 
> but in any case we would also need to make ssh-push.o depend on 
> ssh-upload.c for the same logic.

Probably. But this was a _necessary_ fix: git stopped compiling here (yes, 
I could have done "make clean && make", but that takes all the fun out of 
it...).

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH] Teach the git wrapper about --name-rev and --name-rev-by-tags
From: Johannes Schindelin @ 2006-07-28 18:53 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Junio C Hamano, git
In-Reply-To: <Pine.LNX.4.64.0607280952200.4168@g5.osdl.org>

Hi,

On Fri, 28 Jul 2006, Linus Torvalds wrote:

> On Fri, 28 Jul 2006, Johannes Schindelin wrote:
> > 
> > Now you can say
> > 
> > 	git --name-rev log
> 
> I think this is wrong.

I think it is not wrong. :-)

> It may be a straightforward translation of
> 
> > 	git log | git name-rev --stdin | less
> 
> but that doesn't make it any more "correct".

I use it also for other git commands, so this was very much on purpose.

> Also, I doubt most people want every release named.

You are probably right. But _I_ want to know that e.g. commit 
a025463bc0ec2c894a88f2dfb44cf88ba71bb712 is really tags/v1.4.0^0~27^2. 
Both are immutable, but the latter is nicer to people than to computers.

> I think the common case would be that you want those releases named that 
> match heads (and tags in particular) _exactly_. If you want everything 
> named, maybe you want to do "--name-rev-all" or something.
> 
> Hmm?
> 
> (That would also likely perform a lot better)

True. But then, you probably know which head it is, because you probably 
specified it yourself on the command line.

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH] Makefile: ssh-pull.o depends on ssh-fetch.c
From: Junio C Hamano @ 2006-07-28 18:14 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.63.0607281117240.29667@wbgn013.biozentrum.uni-wuerzburg.de>

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
> ---
>  Makefile |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index 636679f..e8037ad 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -661,6 +661,7 @@ git-%$X: %.o $(GITLIBS)
>  	$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
>  		$(LIB_FILE) $(SIMPLE_LIB)
>  
> +ssh-pull.o: ssh-fetch.c
>  git-local-fetch$X: fetch.o
>  git-ssh-fetch$X: rsh.o fetch.o
>  git-ssh-upload$X: rsh.o

My personal preference would be to deprecate these commit
walkers ;-) but in any case we would also need to make
ssh-push.o depend on ssh-upload.c for the same logic.

^ permalink raw reply

* [PATCH] cg-commit --review may permanently delete changes
From: Dennis Stosberg @ 2006-07-28 17:11 UTC (permalink / raw)
  To: Petr Baudis; +Cc: git

If the patch is changed in the editor in such a way that cg-patch
can not apply it, all changes made since the last commit are
irrecoverably lost, which is _really_ bad.

This patch lets cg-commit reapply the old patch and keep the edited
patch for manual fix-up.

Signed-off-by: Dennis Stosberg <dennis@stosberg.net>
---
 cg-commit |    7 +++++--
 1 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/cg-commit b/cg-commit
index 0cec58f..9604ad7 100755
--- a/cg-commit
+++ b/cg-commit
@@ -524,8 +524,11 @@ if [ "$review" ]; then
 		fi
 		echo "Applying the edited patch..."
 		if ! cg-patch < "$PATCH2"; then
-			rm "$PATCH" "$PATCH2" "$LOGMSG"
-			die "unable to apply the edited patch"
+			echo "The edited patch does not apply. Reapplying old patch."
+			cg-patch <"$PATCH" >/dev/null
+			edited_patch="$(mktemp -t edited-patch.XXXXXX)"
+			mv "$PATCH2" "$edited_patch"
+			die "You can find the edited patch in \"$edited_patch\" for manual review."
 		fi
 	fi
 fi
-- 
1.4.1

^ permalink raw reply related

* Re: [PATCH] Teach the git wrapper about --name-rev and --name-rev-by-tags
From: Linus Torvalds @ 2006-07-28 16:59 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Junio C Hamano, git
In-Reply-To: <Pine.LNX.4.63.0607281308280.29667@wbgn013.biozentrum.uni-wuerzburg.de>



On Fri, 28 Jul 2006, Johannes Schindelin wrote:
> 
> Now you can say
> 
> 	git --name-rev log

I think this is wrong.

It may be a straightforward translation of

> 	git log | git name-rev --stdin | less

but that doesn't make it any more "correct".

>From a logical standpoint, it should be an argument to the _logging_, not 
to the main git binary, so it should be

	git log --name-rev

and you should do the parsing (and the output) inside revision.c.

Also, I doubt most people want every release named. I think the common 
case would be that you want those releases named that match heads (and 
tags in particular) _exactly_. If you want everything named, maybe you 
want to do "--name-rev-all" or something.

Hmm?

(That would also likely perform a lot better)

		Linus

^ permalink raw reply

* Re: [PATCH] Teach git-apply about '-R'
From: Johannes Schindelin @ 2006-07-28 15:50 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Petr Baudis, git
In-Reply-To: <7v3bcln3m5.fsf@assigned-by-dhcp.cox.net>

Hi,

On Fri, 28 Jul 2006, Junio C Hamano wrote:

> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> 
> > Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
> 
> A quick comment without looking much at the code.  Do you sanely
> bail out when asked to reverse-apply a binary patch?

Nope. I swap old_sha1_prefix and new_sha1_prefix in that case, I hoped 
that is enough?

> Also what was the reason to change an existing test vector in
> 4102?  That does not look like related to -R flag.

I changed "copy" to "rename", so that I could reuse that patch to test -R, 
too. Note that in the end, the original test vector is written, and 
tested.

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH 1/2] t7001: add test for git-mv dir1 dir2/
From: Petr Baudis @ 2006-07-28 15:47 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vr706mj0u.fsf@assigned-by-dhcp.cox.net>

Dear diary, on Fri, Jul 28, 2006 at 06:48:49AM CEST, I got a letter
where Junio C Hamano <junkio@cox.net> said that...
> Petr Baudis <pasky@suse.cz> writes:
> > Well, at once? I can do (iv) by adding --index but that contradicts (v).
> > But maybe I'm missing something.
> 
> What should the semantics of such operation be?  Apply to index
> on paths that are clean while leave the index entries untouched
> for paths that are dirty?  What should happen on renamed paths
> that are dirty?

Keep the original sha1 but change the name. If an entry with the new
name already exists, we might just leave the index alone and create a
.rej file. (Alternatively we might create two stages in the index file
but we can't do that in case of regular rejects so I'd rather stay
consistent.)

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
Snow falling on Perl. White noise covering line noise.
Hides all the bugs too. -- J. Putnam

^ permalink raw reply

* [PATCH v2] Teach git-apply about '-R'
From: Johannes Schindelin @ 2006-07-28 15:46 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Petr Baudis, git, junkio
In-Reply-To: <Pine.LNX.4.64.0607280809550.4168@g5.osdl.org>


Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
---

On Fri, 28 Jul 2006, Linus Torvalds wrote:

> On Fri, 28 Jul 2006, Johannes Schindelin wrote:
> >
> > +/* a and b may not overlap! */
> > +static void memswap(void *a, void *b, unsigned int len)
> 
> This is disgusting.

Yes, it is. Sorry, was just meant for prototyping. I had in mind to 
replace it with temporary variables, but your solution seems way 
nicer.

 builtin-apply.c         |   65 ++++++++++++++++++++++++++++++++++++++++-------
 t/t4102-apply-rename.sh |   24 ++++++++++++++++-
 2 files changed, 77 insertions(+), 12 deletions(-)

diff --git a/builtin-apply.c b/builtin-apply.c
index d924ac3..6b38a8a 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -120,7 +120,7 @@ struct fragment {
 struct patch {
 	char *new_name, *old_name, *def_name;
 	unsigned int old_mode, new_mode;
-	int is_rename, is_copy, is_new, is_delete, is_binary;
+	int is_rename, is_copy, is_new, is_delete, is_binary, is_reverse;
 #define BINARY_DELTA_DEFLATED 1
 #define BINARY_LITERAL_DEFLATED 2
 	unsigned long deflate_origlen;
@@ -1119,6 +1119,34 @@ static int parse_chunk(char *buffer, uns
 	return offset + hdrsize + patchsize;
 }
 
+#define swap(a,b) myswap((a),(b),sizeof(a))
+
+#define myswap(a, b, size) do {		\
+	unsigned char mytmp[size];	\
+	memcpy(mytmp, &a, size);		\
+	memcpy(&a, &b, size);		\
+	memcpy(&b, mytmp, size);		\
+} while (0)
+
+static void reverse_patches(struct patch *p)
+{
+	for (; p; p = p->next) {
+		struct fragment *frag = p->fragments;
+
+		swap(p->new_name, p->old_name);
+		swap(p->new_mode, p->old_mode);
+		swap(p->is_new, p->is_delete);
+		swap(p->lines_added, p->lines_deleted);
+		swap(p->old_sha1_prefix, p->new_sha1_prefix);
+
+		for (; frag; frag = frag->next) {
+			swap(frag->newpos, frag->oldpos);
+			swap(frag->newlines, frag->oldlines);
+		}
+		p->is_reverse = !p->is_reverse;
+	}
+}
+
 static const char pluses[] = "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
 static const char minuses[]= "----------------------------------------------------------------------";
 
@@ -1336,7 +1364,7 @@ static int apply_line(char *output, cons
 }
 
 static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag,
-	int inaccurate_eof)
+	int reverse, int inaccurate_eof)
 {
 	int match_beginning, match_end;
 	char *buf = desc->buffer;
@@ -1350,6 +1378,7 @@ static int apply_one_fragment(struct buf
 	int pos, lines;
 
 	while (size > 0) {
+		char first;
 		int len = linelen(patch, size);
 		int plen;
 
@@ -1366,16 +1395,23 @@ static int apply_one_fragment(struct buf
 		plen = len-1;
 		if (len < size && patch[len] == '\\')
 			plen--;
-		switch (*patch) {
+		first = *patch;
+		if (reverse) {
+			if (first == '-')
+				first = '+';
+			else if (first == '+')
+				first = '-';
+		}
+		switch (first) {
 		case ' ':
 		case '-':
 			memcpy(old + oldsize, patch + 1, plen);
 			oldsize += plen;
-			if (*patch == '-')
+			if (first == '-')
 				break;
 		/* Fall-through for ' ' */
 		case '+':
-			if (*patch != '+' || !no_add)
+			if (first != '+' || !no_add)
 				newsize += apply_line(new + newsize, patch,
 						      plen);
 			break;
@@ -1615,7 +1651,8 @@ static int apply_fragments(struct buffer
 		return apply_binary(desc, patch);
 
 	while (frag) {
-		if (apply_one_fragment(desc, frag, patch->inaccurate_eof) < 0)
+		if (apply_one_fragment(desc, frag, patch->is_reverse,
+					patch->inaccurate_eof) < 0)
 			return error("patch failed: %s:%ld",
 				     name, frag->oldpos);
 		frag = frag->next;
@@ -2142,7 +2179,8 @@ static int use_patch(struct patch *p)
 	return 1;
 }
 
-static int apply_patch(int fd, const char *filename, int inaccurate_eof)
+static int apply_patch(int fd, const char *filename,
+		int reverse, int inaccurate_eof)
 {
 	unsigned long offset, size;
 	char *buffer = read_patch_file(fd, &size);
@@ -2162,6 +2200,8 @@ static int apply_patch(int fd, const cha
 		nr = parse_chunk(buffer + offset, size, patch);
 		if (nr < 0)
 			break;
+		if (reverse)
+			reverse_patches(patch);
 		if (use_patch(patch)) {
 			patch_stats(patch);
 			*listp = patch;
@@ -2226,6 +2266,7 @@ int cmd_apply(int argc, const char **arg
 {
 	int i;
 	int read_stdin = 1;
+	int reverse = 0;
 	int inaccurate_eof = 0;
 
 	const char *whitespace_option = NULL;
@@ -2236,7 +2277,7 @@ int cmd_apply(int argc, const char **arg
 		int fd;
 
 		if (!strcmp(arg, "-")) {
-			apply_patch(0, "<stdin>", inaccurate_eof);
+			apply_patch(0, "<stdin>", reverse, inaccurate_eof);
 			read_stdin = 0;
 			continue;
 		}
@@ -2313,6 +2354,10 @@ int cmd_apply(int argc, const char **arg
 			parse_whitespace_option(arg + 13);
 			continue;
 		}
+		if (!strcmp(arg, "-R") || !strcmp(arg, "--reverse")) {
+			reverse = 1;
+			continue;
+		}
 		if (!strcmp(arg, "--inaccurate-eof")) {
 			inaccurate_eof = 1;
 			continue;
@@ -2333,12 +2378,12 @@ int cmd_apply(int argc, const char **arg
 			usage(apply_usage);
 		read_stdin = 0;
 		set_default_whitespace_mode(whitespace_option);
-		apply_patch(fd, arg, inaccurate_eof);
+		apply_patch(fd, arg, reverse, inaccurate_eof);
 		close(fd);
 	}
 	set_default_whitespace_mode(whitespace_option);
 	if (read_stdin)
-		apply_patch(0, "<stdin>", inaccurate_eof);
+		apply_patch(0, "<stdin>", reverse, inaccurate_eof);
 	if (whitespace_error) {
 		if (squelch_whitespace_errors &&
 		    squelch_whitespace_errors < whitespace_error) {
diff --git a/t/t4102-apply-rename.sh b/t/t4102-apply-rename.sh
index fbb508d..22da6a0 100755
--- a/t/t4102-apply-rename.sh
+++ b/t/t4102-apply-rename.sh
@@ -13,8 +13,8 @@ # setup
 cat >test-patch <<\EOF
 diff --git a/foo b/bar
 similarity index 47%
-copy from foo
-copy to bar
+rename from foo
+rename to bar
 --- a/foo
 +++ b/bar
 @@ -1 +1 @@
@@ -39,4 +39,24 @@ else
 	    'test -f bar && ls -l bar | grep "^-..x......"'
 fi
 
+test_expect_success 'apply reverse' \
+    'git-apply -R --index --stat --summary --apply test-patch &&
+     test "$(cat foo)" = "This is foo"'
+
+cat >test-patch <<\EOF
+diff --git a/foo b/bar
+similarity index 47%
+copy from foo
+copy to bar
+--- a/foo
++++ b/bar
+@@ -1 +1 @@
+-This is foo
++This is bar
+EOF
+
+test_expect_success 'apply copy' \
+    'git-apply --index --stat --summary --apply test-patch &&
+     test "$(cat bar)" = "This is bar" -a "$(cat foo)" = "This is foo"'
+
 test_done
-- 
1.4.2.rc2.g8b063-dirty

^ permalink raw reply related

* Re: [PATCH] Teach the git wrapper about --name-rev and --name-rev-by-tags
From: Junio C Hamano @ 2006-07-28 15:43 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.63.0607281308280.29667@wbgn013.biozentrum.uni-wuerzburg.de>

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> 	On Wed, 26 Jul 2006, Junio C Hamano wrote:
>
> 	>  * Passing the standard error from "fetch-pack -v" to "name-rev
> 	>    --stdin" makes it a bit more pleasant to see what is going on.
>
> 	This patch makes it even easier.

Probably wouldn't for that particular one, since what I wanted
to do was "git fetch-pack -v 2>&1 | git name-rev >/var/tmp/1",
so isatty(1) check in setup_name_rev_pager() is defeated by
redirection, and the information I wanted to pass name-rev would
not have passed it anyway.

But this _might_ be useful for other more general cases.  I'm
not sure -- it feels somewhat like a hack, though.

^ 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