Git development
 help / color / mirror / Atom feed
* [RFH/PATCH] imap-send: support SNI (RFC4366)
From: Junio C Hamano @ 2013-02-21  0:18 UTC (permalink / raw)
  To: git

To talk to a site that serves multiple names on a single IP address,
the client needs to ask for the specific hostname it wants to talk
to. Otherwise, the default certificate returned from the IP address
may not match that of the host we wanted to talk to.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---

 * I need help from people on this patch in two areas:

 (1) I only tested this patch by connecting to https://googlemail.com/ 
     with

     $ git -c imap.host=imaps://googlemail.com -c imap.port=443 imap-send <this-patch.txt

     as it is the only site I knew clients needs to talk SNI to get
     the right certificate to verify; of course the port does not
     talk imap, and the only thing that is tested by that approach is
     we successfully establish an SSL/TLS connection.  Without the
     patch, we fail to verify the certificate (we get a cert that is
     for another hostname that is hosted at the same IP address), and
     with the patch, we successfully get the right one.

     I would appreciate it if somebody knows an imap server that
     needs SNI and runs an end-to-end test against that server.

 (2) I do not know if everybody has SSL_set_tslext_host_name() macro
     defined, so this patch may be breaking build for people with
     different versions of OpenSSL.

 imap-send.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/imap-send.c b/imap-send.c
index 171c887..d9abd8b 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -370,6 +370,15 @@ static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int ve
 		return -1;
 	}
 
+	/*
+	 * SNI (RFC4366)
+	 * OpenSSL does not document this function, but the implementation
+	 * returns 1 on success, 0 on failure after calling SSLerr().
+	 */
+	ret = SSL_set_tlsext_host_name(sock->ssl, server.host);
+	if (ret != 1)
+		warning("SSL_set_tslext_host_name(%s) failed.\n", server.host);
+
 	ret = SSL_connect(sock->ssl);
 	if (ret <= 0) {
 		socket_perror("SSL_connect", sock, ret);
-- 
1.8.2.rc0.106.ga6e4a61

^ permalink raw reply related

* [PATCH v3 1/4] difftool: silence uninitialized variable warning
From: David Aguilar @ 2013-02-21  4:03 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Jonathan Nieder

Git::config() returns `undef` when given keys that do not exist.
Check that the $guitool value is defined to prevent a noisy
"Use of uninitialized variable $guitool in length" warning.

Signed-off-by: David Aguilar <davvid@gmail.com>
---
Unchanged since v1.

 git-difftool.perl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/git-difftool.perl b/git-difftool.perl
index 0a90de4..12231fb 100755
--- a/git-difftool.perl
+++ b/git-difftool.perl
@@ -336,7 +336,7 @@ sub main
 	}
 	if ($opts{gui}) {
 		my $guitool = Git::config('diff.guitool');
-		if (length($guitool) > 0) {
+		if (defined($guitool) && length($guitool) > 0) {
 			$ENV{GIT_DIFF_TOOL} = $guitool;
 		}
 	}
-- 
1.8.2.rc0.20.gf548dd7

^ permalink raw reply related

* [PATCH 2/4] t7800: update copyright notice
From: David Aguilar @ 2013-02-21  4:03 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Jonathan Nieder
In-Reply-To: <1361419428-22410-1-git-send-email-davvid@gmail.com>

Signed-off-by: David Aguilar <davvid@gmail.com>
---
Unchanged since v2.

 t/t7800-difftool.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh
index eb1d3f8..5b5939b 100755
--- a/t/t7800-difftool.sh
+++ b/t/t7800-difftool.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# Copyright (c) 2009, 2010 David Aguilar
+# Copyright (c) 2009, 2010, 2012, 2013 David Aguilar
 #
 
 test_description='git-difftool
-- 
1.8.2.rc0.20.gf548dd7

^ permalink raw reply related

* [PATCH v3 3/4] t7800: modernize tests
From: David Aguilar @ 2013-02-21  4:03 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Jonathan Nieder
In-Reply-To: <1361419428-22410-2-git-send-email-davvid@gmail.com>

Eliminate a lot of redundant work by using test_config().
Catch more return codes by more use of temporary files
and test_cmp.

The original tests relied upon restore_test_defaults()
from the previous test to provide the next test with a sane
environment.  Make the tests do their own setup so that they
are not dependent on the success of the previous test.
The end result is shorter tests and better test isolation.

Signed-off-by: David Aguilar <davvid@gmail.com>
---
v3 includes Junio's review notes to avoid cat with stdin_contains
and to use DQ around $LOCAL.

Another difference from v2 is that it tweaks the function
declarations to keep a SP between the name and parens to better
follow the standard git style.

 t/t7800-difftool.sh | 366 ++++++++++++++++++++++++----------------------------
 1 file changed, 168 insertions(+), 198 deletions(-)

diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh
index 5b5939b..fb00273 100755
--- a/t/t7800-difftool.sh
+++ b/t/t7800-difftool.sh
@@ -10,43 +10,25 @@ Testing basic diff tool invocation
 
 . ./test-lib.sh
 
-remove_config_vars()
+difftool_test_setup ()
 {
-	# Unset all config variables used by git-difftool
-	git config --unset diff.tool
-	git config --unset diff.guitool
-	git config --unset difftool.test-tool.cmd
-	git config --unset difftool.prompt
-	git config --unset merge.tool
-	git config --unset mergetool.test-tool.cmd
-	git config --unset mergetool.prompt
-	return 0
+	test_config diff.tool test-tool &&
+	test_config difftool.test-tool.cmd 'cat "$LOCAL"' &&
+	test_config difftool.bogus-tool.cmd false
 }
 
-restore_test_defaults()
-{
-	# Restores the test defaults used by several tests
-	remove_config_vars
-	unset GIT_DIFF_TOOL
-	unset GIT_DIFFTOOL_PROMPT
-	unset GIT_DIFFTOOL_NO_PROMPT
-	git config diff.tool test-tool &&
-	git config difftool.test-tool.cmd 'cat $LOCAL'
-	git config difftool.bogus-tool.cmd false
-}
-
-prompt_given()
+prompt_given ()
 {
 	prompt="$1"
 	test "$prompt" = "Launch 'test-tool' [Y/n]: branch"
 }
 
-stdin_contains()
+stdin_contains ()
 {
 	grep >/dev/null "$1"
 }
 
-stdin_doesnot_contain()
+stdin_doesnot_contain ()
 {
 	! stdin_contains "$1"
 }
@@ -65,249 +47,237 @@ test_expect_success PERL 'setup' '
 
 # Configure a custom difftool.<tool>.cmd and use it
 test_expect_success PERL 'custom commands' '
-	restore_test_defaults &&
-	git config difftool.test-tool.cmd "cat \$REMOTE" &&
+	difftool_test_setup &&
+	test_config difftool.test-tool.cmd "cat \"\$REMOTE\"" &&
+	echo master >expect &&
+	git difftool --no-prompt branch >actual &&
+	test_cmp expect actual &&
 
-	diff=$(git difftool --no-prompt branch) &&
-	test "$diff" = "master" &&
-
-	restore_test_defaults &&
-	diff=$(git difftool --no-prompt branch) &&
-	test "$diff" = "branch"
+	test_config difftool.test-tool.cmd "cat \"\$LOCAL\"" &&
+	echo branch >expect &&
+	git difftool --no-prompt branch >actual &&
+	test_cmp expect actual
 '
 
-# Ensures that a custom difftool.<tool>.cmd overrides built-ins
-test_expect_success PERL 'custom commands override built-ins' '
-	restore_test_defaults &&
-	git config difftool.defaults.cmd "cat \$REMOTE" &&
-
-	diff=$(git difftool --tool defaults --no-prompt branch) &&
-	test "$diff" = "master" &&
-
-	git config --unset difftool.defaults.cmd
+test_expect_success PERL 'custom tool commands override built-ins' '
+	test_config difftool.defaults.cmd "cat \"\$REMOTE\"" &&
+	echo master >expect &&
+	git difftool --tool defaults --no-prompt branch >actual &&
+	test_cmp expect actual
 '
 
-# Ensures that git-difftool ignores bogus --tool values
 test_expect_success PERL 'difftool ignores bad --tool values' '
-	diff=$(git difftool --no-prompt --tool=bad-tool branch)
-	test "$?" = 1 &&
-	test "$diff" = ""
+	: >expect &&
+	test_expect_code 1 \
+		git difftool --no-prompt --tool=bad-tool branch >actual &&
+	test_cmp expect actual
 '
 
 test_expect_success PERL 'difftool forwards arguments to diff' '
+	difftool_test_setup &&
 	>for-diff &&
 	git add for-diff &&
 	echo changes>for-diff &&
 	git add for-diff &&
-	diff=$(git difftool --cached --no-prompt -- for-diff) &&
-	test "$diff" = "" &&
+	: >expect &&
+	git difftool --cached --no-prompt -- for-diff >actual &&
+	test_cmp expect actual &&
 	git reset -- for-diff &&
 	rm for-diff
 '
 
 test_expect_success PERL 'difftool honors --gui' '
-	git config merge.tool bogus-tool &&
-	git config diff.tool bogus-tool &&
-	git config diff.guitool test-tool &&
-
-	diff=$(git difftool --no-prompt --gui branch) &&
-	test "$diff" = "branch" &&
+	difftool_test_setup &&
+	test_config merge.tool bogus-tool &&
+	test_config diff.tool bogus-tool &&
+	test_config diff.guitool test-tool &&
 
-	restore_test_defaults
+	echo branch >expect &&
+	git difftool --no-prompt --gui branch >actual &&
+	test_cmp expect actual
 '
 
 test_expect_success PERL 'difftool --gui last setting wins' '
-	git config diff.guitool bogus-tool &&
-	git difftool --no-prompt --gui --no-gui &&
+	difftool_test_setup &&
+	: >expect &&
+	git difftool --no-prompt --gui --no-gui >actual &&
+	test_cmp expect actual &&
 
-	git config merge.tool bogus-tool &&
-	git config diff.tool bogus-tool &&
-	git config diff.guitool test-tool &&
-	diff=$(git difftool --no-prompt --no-gui --gui branch) &&
-	test "$diff" = "branch" &&
-
-	restore_test_defaults
+	test_config merge.tool bogus-tool &&
+	test_config diff.tool bogus-tool &&
+	test_config diff.guitool test-tool &&
+	echo branch >expect &&
+	git difftool --no-prompt --no-gui --gui branch >actual &&
+	test_cmp expect actual
 '
 
 test_expect_success PERL 'difftool --gui works without configured diff.guitool' '
-	git config diff.tool test-tool &&
-
-	diff=$(git difftool --no-prompt --gui branch) &&
-	test "$diff" = "branch" &&
-
-	restore_test_defaults
+	difftool_test_setup &&
+	echo branch >expect &&
+	git difftool --no-prompt --gui branch >actual &&
+	test_cmp expect actual
 '
 
 # Specify the diff tool using $GIT_DIFF_TOOL
 test_expect_success PERL 'GIT_DIFF_TOOL variable' '
-	test_might_fail git config --unset diff.tool &&
-	GIT_DIFF_TOOL=test-tool &&
-	export GIT_DIFF_TOOL &&
-
-	diff=$(git difftool --no-prompt branch) &&
-	test "$diff" = "branch" &&
-
-	restore_test_defaults
+	difftool_test_setup &&
+	git config --unset diff.tool &&
+	echo branch >expect &&
+	GIT_DIFF_TOOL=test-tool git difftool --no-prompt branch >actual &&
+	test_cmp expect actual
 '
 
 # Test the $GIT_*_TOOL variables and ensure
 # that $GIT_DIFF_TOOL always wins unless --tool is specified
 test_expect_success PERL 'GIT_DIFF_TOOL overrides' '
-	git config diff.tool bogus-tool &&
-	git config merge.tool bogus-tool &&
-
-	GIT_DIFF_TOOL=test-tool &&
-	export GIT_DIFF_TOOL &&
-
-	diff=$(git difftool --no-prompt branch) &&
-	test "$diff" = "branch" &&
+	difftool_test_setup &&
+	test_config diff.tool bogus-tool &&
+	test_config merge.tool bogus-tool &&
 
-	GIT_DIFF_TOOL=bogus-tool &&
-	export GIT_DIFF_TOOL &&
+	echo branch >expect &&
+	GIT_DIFF_TOOL=test-tool git difftool --no-prompt branch >actual &&
+	test_cmp expect actual &&
 
-	diff=$(git difftool --no-prompt --tool=test-tool branch) &&
-	test "$diff" = "branch" &&
-
-	restore_test_defaults
+	test_config diff.tool bogus-tool &&
+	test_config merge.tool bogus-tool &&
+	GIT_DIFF_TOOL=bogus-tool \
+		git difftool --no-prompt --tool=test-tool branch >actual &&
+	test_cmp expect actual
 '
 
 # Test that we don't have to pass --no-prompt to difftool
 # when $GIT_DIFFTOOL_NO_PROMPT is true
 test_expect_success PERL 'GIT_DIFFTOOL_NO_PROMPT variable' '
-	GIT_DIFFTOOL_NO_PROMPT=true &&
-	export GIT_DIFFTOOL_NO_PROMPT &&
-
-	diff=$(git difftool branch) &&
-	test "$diff" = "branch" &&
-
-	restore_test_defaults
+	difftool_test_setup &&
+	echo branch >expect &&
+	GIT_DIFFTOOL_NO_PROMPT=true git difftool branch >actual &&
+	test_cmp expect actual
 '
 
 # git-difftool supports the difftool.prompt variable.
 # Test that GIT_DIFFTOOL_PROMPT can override difftool.prompt = false
 test_expect_success PERL 'GIT_DIFFTOOL_PROMPT variable' '
-	git config difftool.prompt false &&
-	GIT_DIFFTOOL_PROMPT=true &&
-	export GIT_DIFFTOOL_PROMPT &&
-
-	prompt=$(echo | git difftool branch | tail -1) &&
-	prompt_given "$prompt" &&
-
-	restore_test_defaults
+	difftool_test_setup &&
+	test_config difftool.prompt false &&
+	echo >input &&
+	GIT_DIFFTOOL_PROMPT=true git difftool branch <input >output &&
+	prompt=$(tail -1 <output) &&
+	prompt_given "$prompt"
 '
 
 # Test that we don't have to pass --no-prompt when difftool.prompt is false
 test_expect_success PERL 'difftool.prompt config variable is false' '
-	git config difftool.prompt false &&
-
-	diff=$(git difftool branch) &&
-	test "$diff" = "branch" &&
-
-	restore_test_defaults
+	difftool_test_setup &&
+	test_config difftool.prompt false &&
+	echo branch >expect &&
+	git difftool branch >actual &&
+	test_cmp expect actual
 '
 
 # Test that we don't have to pass --no-prompt when mergetool.prompt is false
 test_expect_success PERL 'difftool merge.prompt = false' '
+	difftool_test_setup &&
 	test_might_fail git config --unset difftool.prompt &&
-	git config mergetool.prompt false &&
-
-	diff=$(git difftool branch) &&
-	test "$diff" = "branch" &&
-
-	restore_test_defaults
+	test_config mergetool.prompt false &&
+	echo branch >expect &&
+	git difftool branch >actual &&
+	test_cmp expect actual
 '
 
 # Test that the -y flag can override difftool.prompt = true
 test_expect_success PERL 'difftool.prompt can overridden with -y' '
-	git config difftool.prompt true &&
-
-	diff=$(git difftool -y branch) &&
-	test "$diff" = "branch" &&
-
-	restore_test_defaults
+	difftool_test_setup &&
+	test_config difftool.prompt true &&
+	echo branch >expect &&
+	git difftool -y branch >actual &&
+	test_cmp expect actual
 '
 
 # Test that the --prompt flag can override difftool.prompt = false
 test_expect_success PERL 'difftool.prompt can overridden with --prompt' '
-	git config difftool.prompt false &&
-
-	prompt=$(echo | git difftool --prompt branch | tail -1) &&
-	prompt_given "$prompt" &&
-
-	restore_test_defaults
+	difftool_test_setup &&
+	test_config difftool.prompt false &&
+	echo >input &&
+	git difftool --prompt branch <input >output &&
+	prompt=$(tail -1 <output) &&
+	prompt_given "$prompt"
 '
 
 # Test that the last flag passed on the command-line wins
 test_expect_success PERL 'difftool last flag wins' '
-	diff=$(git difftool --prompt --no-prompt branch) &&
-	test "$diff" = "branch" &&
-
-	restore_test_defaults &&
-
-	prompt=$(echo | git difftool --no-prompt --prompt branch | tail -1) &&
-	prompt_given "$prompt" &&
-
-	restore_test_defaults
+	difftool_test_setup &&
+	echo branch >expect &&
+	git difftool --prompt --no-prompt branch >actual &&
+	test_cmp expect actual &&
+	echo >input &&
+	git difftool --no-prompt --prompt branch <input >output &&
+	prompt=$(tail -1 <output) &&
+	prompt_given "$prompt"
 '
 
 # git-difftool falls back to git-mergetool config variables
 # so test that behavior here
 test_expect_success PERL 'difftool + mergetool config variables' '
-	remove_config_vars &&
-	git config merge.tool test-tool &&
-	git config mergetool.test-tool.cmd "cat \$LOCAL" &&
-
-	diff=$(git difftool --no-prompt branch) &&
-	test "$diff" = "branch" &&
+	test_config merge.tool test-tool &&
+	test_config mergetool.test-tool.cmd "cat \$LOCAL" &&
+	echo branch >expect &&
+	git difftool --no-prompt branch >actual &&
+	test_cmp expect actual &&
 
 	# set merge.tool to something bogus, diff.tool to test-tool
-	git config merge.tool bogus-tool &&
-	git config diff.tool test-tool &&
-
-	diff=$(git difftool --no-prompt branch) &&
-	test "$diff" = "branch" &&
-
-	restore_test_defaults
+	test_config merge.tool bogus-tool &&
+	test_config diff.tool test-tool &&
+	git difftool --no-prompt branch >actual &&
+	test_cmp expect actual
 '
 
 test_expect_success PERL 'difftool.<tool>.path' '
-	git config difftool.tkdiff.path echo &&
-	diff=$(git difftool --tool=tkdiff --no-prompt branch) &&
-	git config --unset difftool.tkdiff.path &&
-	lines=$(echo "$diff" | grep file | wc -l) &&
-	test "$lines" -eq 1 &&
-
-	restore_test_defaults
+	test_config difftool.tkdiff.path echo &&
+	git difftool --tool=tkdiff --no-prompt branch >output &&
+	lines=$(grep file output | wc -l) &&
+	test "$lines" -eq 1
 '
 
 test_expect_success PERL 'difftool --extcmd=cat' '
-	diff=$(git difftool --no-prompt --extcmd=cat branch) &&
-	test "$diff" = branch"$LF"master
+	echo branch >expect &&
+	echo master >>expect &&
+	git difftool --no-prompt --extcmd=cat branch >actual &&
+	test_cmp expect actual
 '
 
 test_expect_success PERL 'difftool --extcmd cat' '
-	diff=$(git difftool --no-prompt --extcmd cat branch) &&
-	test "$diff" = branch"$LF"master
+	echo branch >expect &&
+	echo master >>expect &&
+	git difftool --no-prompt --extcmd=cat branch >actual &&
+	test_cmp expect actual
 '
 
 test_expect_success PERL 'difftool -x cat' '
-	diff=$(git difftool --no-prompt -x cat branch) &&
-	test "$diff" = branch"$LF"master
+	echo branch >expect &&
+	echo master >>expect &&
+	git difftool --no-prompt -x cat branch >actual &&
+	test_cmp expect actual
 '
 
 test_expect_success PERL 'difftool --extcmd echo arg1' '
-	diff=$(git difftool --no-prompt --extcmd sh\ -c\ \"echo\ \$1\" branch) &&
-	test "$diff" = file
+	echo file >expect &&
+	git difftool --no-prompt \
+		--extcmd sh\ -c\ \"echo\ \$1\" branch >actual &&
+	test_cmp expect actual
 '
 
 test_expect_success PERL 'difftool --extcmd cat arg1' '
-	diff=$(git difftool --no-prompt --extcmd sh\ -c\ \"cat\ \$1\" branch) &&
-	test "$diff" = master
+	echo master >expect &&
+	git difftool --no-prompt \
+		--extcmd sh\ -c\ \"cat\ \$1\" branch >actual &&
+	test_cmp expect actual
 '
 
 test_expect_success PERL 'difftool --extcmd cat arg2' '
-	diff=$(git difftool --no-prompt --extcmd sh\ -c\ \"cat\ \$2\" branch) &&
-	test "$diff" = branch
+	echo branch >expect &&
+	git difftool --no-prompt \
+		--extcmd sh\ -c\ \"cat\ \$2\" branch >actual &&
+	test_cmp expect actual
 '
 
 # Create a second file on master and a different version on branch
@@ -324,26 +294,26 @@ test_expect_success PERL 'setup with 2 files different' '
 '
 
 test_expect_success PERL 'say no to the first file' '
-	diff=$( (echo n; echo) | git difftool -x cat branch ) &&
-
-	echo "$diff" | stdin_contains m2 &&
-	echo "$diff" | stdin_contains br2 &&
-	echo "$diff" | stdin_doesnot_contain master &&
-	echo "$diff" | stdin_doesnot_contain branch
+	(echo n && echo) >input &&
+	git difftool -x cat branch <input >output &&
+	stdin_contains m2 <output &&
+	stdin_contains br2 <output &&
+	stdin_doesnot_contain master <output &&
+	stdin_doesnot_contain branch <output
 '
 
 test_expect_success PERL 'say no to the second file' '
-	diff=$( (echo; echo n) | git difftool -x cat branch ) &&
-
-	echo "$diff" | stdin_contains master &&
-	echo "$diff" | stdin_contains branch &&
-	echo "$diff" | stdin_doesnot_contain m2 &&
-	echo "$diff" | stdin_doesnot_contain br2
+	(echo && echo n) >input &&
+	git difftool -x cat branch <input >output &&
+	stdin_contains master <output &&
+	stdin_contains branch  <output &&
+	stdin_doesnot_contain m2 <output &&
+	stdin_doesnot_contain br2 <output
 '
 
 test_expect_success PERL 'difftool --tool-help' '
-	tool_help=$(git difftool --tool-help) &&
-	echo "$tool_help" | stdin_contains tool
+	git difftool --tool-help >output &&
+	stdin_contains tool <output
 '
 
 test_expect_success PERL 'setup change in subdirectory' '
@@ -359,29 +329,29 @@ test_expect_success PERL 'setup change in subdirectory' '
 '
 
 test_expect_success PERL 'difftool -d' '
-	diff=$(git difftool -d --extcmd ls branch) &&
-	echo "$diff" | stdin_contains sub &&
-	echo "$diff" | stdin_contains file
+	git difftool -d --extcmd ls branch >output &&
+	stdin_contains sub <output &&
+	stdin_contains file <output
 '
 
 test_expect_success PERL 'difftool --dir-diff' '
-	diff=$(git difftool --dir-diff --extcmd ls branch) &&
-	echo "$diff" | stdin_contains sub &&
-	echo "$diff" | stdin_contains file
+	git difftool --dir-diff --extcmd ls branch >output &&
+	stdin_contains sub <output &&
+	stdin_contains file <output
 '
 
 test_expect_success PERL 'difftool --dir-diff ignores --prompt' '
-	diff=$(git difftool --dir-diff --prompt --extcmd ls branch) &&
-	echo "$diff" | stdin_contains sub &&
-	echo "$diff" | stdin_contains file
+	git difftool --dir-diff --prompt --extcmd ls branch >output &&
+	stdin_contains sub <output &&
+	stdin_contains file <output
 '
 
 test_expect_success PERL 'difftool --dir-diff from subdirectory' '
 	(
 		cd sub &&
-		diff=$(git difftool --dir-diff --extcmd ls branch) &&
-		echo "$diff" | stdin_contains sub &&
-		echo "$diff" | stdin_contains file
+		git difftool --dir-diff --extcmd ls branch >output &&
+		stdin_contains sub <output &&
+		stdin_contains file <output
 	)
 '
 
-- 
1.8.2.rc0.20.gf548dd7

^ permalink raw reply related

* [PATCH v3 4/4] t7800: "defaults" is no longer a builtin tool name
From: David Aguilar @ 2013-02-21  4:03 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Jonathan Nieder
In-Reply-To: <1361419428-22410-3-git-send-email-davvid@gmail.com>

073678b8e6324a155fa99f40eee0637941a70a34 reworked the
mergetools/ directory so that every file corresponds to a
difftool-supported tool.  When this happened the "defaults"
file went away as it was no longer needed by mergetool--lib.

t7800 tests that configured commands can override builtins,
but this test was not adjusted when the "defaults" file was
removed because the test continued to pass.

Adjust the test to use the everlasting "vimdiff" tool name
instead of "defaults" so that it correctly tests against a tool
that is known by mergetool--lib.

Signed-off-by: David Aguilar <davvid@gmail.com>
---
Rebased against PATCH v3 3/4.

 t/t7800-difftool.sh | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh
index fb00273..21fbba9 100755
--- a/t/t7800-difftool.sh
+++ b/t/t7800-difftool.sh
@@ -60,9 +60,9 @@ test_expect_success PERL 'custom commands' '
 '
 
 test_expect_success PERL 'custom tool commands override built-ins' '
-	test_config difftool.defaults.cmd "cat \"\$REMOTE\"" &&
+	test_config difftool.vimdiff "cat \"\$REMOTE\"" &&
 	echo master >expect &&
-	git difftool --tool defaults --no-prompt branch >actual &&
+	git difftool --tool vimdiff --no-prompt branch >actual &&
 	test_cmp expect actual
 '
 
-- 
1.8.2.rc0.20.gf548dd7

^ permalink raw reply related

* Re: [PATCH v3 4/4] t7800: "defaults" is no longer a builtin tool name
From: Junio C Hamano @ 2013-02-21  4:55 UTC (permalink / raw)
  To: David Aguilar; +Cc: git, Jonathan Nieder
In-Reply-To: <1361419428-22410-4-git-send-email-davvid@gmail.com>

Thanks; will replace and queue.

^ permalink raw reply

* Re: [PATCH v3 4/4] t7800: "defaults" is no longer a builtin tool name
From: Junio C Hamano @ 2013-02-21  5:00 UTC (permalink / raw)
  To: David Aguilar; +Cc: git, Jonathan Nieder
In-Reply-To: <1361419428-22410-4-git-send-email-davvid@gmail.com>

David Aguilar <davvid@gmail.com> writes:

> diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh
> index fb00273..21fbba9 100755
> --- a/t/t7800-difftool.sh
> +++ b/t/t7800-difftool.sh
> @@ -60,9 +60,9 @@ test_expect_success PERL 'custom commands' '
>  '
>  
>  test_expect_success PERL 'custom tool commands override built-ins' '
> -	test_config difftool.defaults.cmd "cat \"\$REMOTE\"" &&
> +	test_config difftool.vimdiff "cat \"\$REMOTE\"" &&
>  	echo master >expect &&
> -	git difftool --tool defaults --no-prompt branch >actual &&
> +	git difftool --tool vimdiff --no-prompt branch >actual &&
>  	test_cmp expect actual
>  '

Eek.

$ sh t7800-difftool.sh -i
ok 1 - setup
ok 2 - custom commands
not ok 3 - custom tool commands override built-ins
#
#               test_config difftool.vimdiff "cat \"\$REMOTE\"" &&
#               echo master >expect &&
#               git difftool --tool vimdiff --no-prompt branch >actual &&
#               test_cmp expect actual
#

Running the same test with "-v" seems to get stuck with this
forever:

expecting success:
        test_config difftool.vimdiff "cat \"\$REMOTE\"" &&
        echo master >expect &&
        git difftool --tool vimdiff --no-prompt branch >actual &&
        test_cmp expect actual

Vim: Warning: Output is not to a terminal
Vim: Warning: Input is not from a terminal

^ permalink raw reply

* Re: [RFH/PATCH] imap-send: support SNI (RFC4366)
From: Junio C Hamano @ 2013-02-21  5:35 UTC (permalink / raw)
  To: git
In-Reply-To: <7vbobey0xv.fsf@alter.siamese.dyndns.org>

Junio C Hamano <gitster@pobox.com> writes:

> To talk to a site that serves multiple names on a single IP address,
> the client needs to ask for the specific hostname it wants to talk
> to. Otherwise, the default certificate returned from the IP address
> may not match that of the host we wanted to talk to.
>
> Signed-off-by: Junio C Hamano <gitster@pobox.com>
> ---
>
>  * I need help from people on this patch in two areas:
>
>  (1) I only tested this patch by connecting to https://googlemail.com/ 
>      with
> ...
>      I would appreciate it if somebody knows an imap server that
>      needs SNI and runs an end-to-end test against that server.
> 
>  (2) I do not know if everybody has SSL_set_tslext_host_name() macro
>      defined, so this patch may be breaking build for people with
>      different versions of OpenSSL.

What I queued for tonight replaces the posted patch with this
version in order to address (2) above.

-- >8 --
Subject: [PATCH] imap-send: support SNI (RFC4366)

To talk with some sites that serve multiple names on a single IP
address, the client needs to ask for the specific host it wants to
talk to.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 imap-send.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/imap-send.c b/imap-send.c
index 171c887..ab2098a 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -370,6 +370,17 @@ static int ssl_socket_connect(struct imap_socket *sock, int use_tls_only, int ve
 		return -1;
 	}
 
+#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
+	/*
+	 * SNI (RFC4366)
+	 * OpenSSL does not document this function, but the implementation
+	 * returns 1 on success, 0 on failure after calling SSLerr().
+	 */
+	ret = SSL_set_tlsext_host_name(sock->ssl, server.host);
+	if (ret != 1)
+		warning("SSL_set_tslext_host_name(%s) failed.\n", server.host);
+#endif
+
 	ret = SSL_connect(sock->ssl);
 	if (ret <= 0) {
 		socket_perror("SSL_connect", sock, ret);
-- 
1.8.2.rc0.127.g4d5d7da

^ permalink raw reply related

* Re: [RFH/PATCH] imap-send: support SNI (RFC4366)
From: Jeff King @ 2013-02-21  5:48 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vr4kaw7or.fsf@alter.siamese.dyndns.org>

On Wed, Feb 20, 2013 at 09:35:16PM -0800, Junio C Hamano wrote:

>>  (2) I do not know if everybody has SSL_set_tslext_host_name() macro
>>      defined, so this patch may be breaking build for people with
>>      different versions of OpenSSL.
> [...]
>
> +#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
> +	/*
> +	 * SNI (RFC4366)
> +	 * OpenSSL does not document this function, but the implementation
> +	 * returns 1 on success, 0 on failure after calling SSLerr().
> +	 */
> +	ret = SSL_set_tlsext_host_name(sock->ssl, server.host);
> +	if (ret != 1)
> +		warning("SSL_set_tslext_host_name(%s) failed.\n", server.host);
> +#endif

Yes, I think this is the right macro to check. According to OpenSSL's
CHANGES file, it was introduced between 0.9.8n and 1.0.0 (Mar 2010). But
I note that the use of the same macro in libcurl dates to 2008. Curious.

Note that you have a typo in your warning text (tslext) and an
extra newline.

As far as testing goes, I don't have an SNI IMAP server handy, but I
think you can simulate one with "openssl s_server". It may be a good
long-term goal to test any ssl-specific code against that in our test
suite (on the other hand, most of the interesting stuff is https, where
the details are all handled by curl).

-Peff

^ permalink raw reply

* Re: [BUG] Infinite make recursion when configure.ac changes
From: Jeff King @ 2013-02-21  6:04 UTC (permalink / raw)
  To: Stefano Lattarini; +Cc: Git List, Martin von Zweigbergk, Jonathan Nieder
In-Reply-To: <51248D0A.50603@gmail.com>

On Wed, Feb 20, 2013 at 09:44:58AM +0100, Stefano Lattarini wrote:

> From a pristine master checkout:
> 
>   $ make configure && ./configure make
>   ... # All successfull
>   $ touch configure.ac
>   $ make
>     GEN config.status
>   make[1]: Entering directory `/storage/home/stefano/git/src'
>     GEN config.status
>   make[2]: Entering directory `/storage/home/stefano/git/src'
>     GEN config.status
>   make[3]: Entering directory `/storage/home/stefano/git/src'
>     GEN config.status
>   make[4]: Entering directory `/storage/home/stefano/git/src'
>     GEN config.status
>   make[5]: Entering directory `/storage/home/stefano/git/src'
>     GEN config.status
>   ...
> 
> and I have to hit ^C to interrupt that recursion.

I can easily replicate it here.

> This seems due to the change in commit v1.7.12.4-1-g1226504: the
> issue is still present there, but no longer is in the preceding
> commit 7e201053 (a.k.a. v1.7.12.4).
> 
> I haven't investigated this any further for the moment.

Hmm. It looks like config.status depends on configure.ac. So make
rebuilds config.status, which runs "make configure", which includes
"config.mak.autogen", leading "make" to think that it should rebuild the
include file to make sure it is up to date. The include file depends on
"config.status", which needs to be rebuilt due to configure.ac, which
entails running "make configure", and so on.

So the real problem is that make things that "make configure" depends on
"config.mak.autogen" being up to date, which isn't true at all; the
whole point is to make a new configure script so we can write a new
config.mak.autogen. The simplest thing is to just avoid re-running
"make" to get the configure script; the only thing we are gaining is
that we don't have to repeat the build recipe, but we can sneak around
that by sticking it in a variable. Something like this seems to work:

diff --git a/Makefile b/Makefile
index 3b2c92c..ee1c0b0 100644
--- a/Makefile
+++ b/Makefile
@@ -1871,12 +1871,14 @@ configure: configure.ac GIT-VERSION-FILE
 	mv $@+ $@
 endif # NO_PYTHON
 
+CONFIGURE_RECIPE = $(RM) configure configure.ac+ && \
+		   sed -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
+			configure.ac >configure.ac+ && \
+		   autoconf -o configure configure.ac+ && \
+		   $(RM) configure.ac+
+
 configure: configure.ac GIT-VERSION-FILE
-	$(QUIET_GEN)$(RM) $@ $<+ && \
-	sed -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
-	    $< > $<+ && \
-	autoconf -o $@ $<+ && \
-	$(RM) $<+
+	$(QUIET_GEN)$(CONFIGURE_RECIPE)
 
 ifdef AUTOCONFIGURED
 # We avoid depending on 'configure' here, because it gets rebuilt
@@ -1885,7 +1887,7 @@ config.status: configure.ac
 # do want to recheck when the platform/environment detection logic
 # changes, hence this depends on configure.ac.
 config.status: configure.ac
-	$(QUIET_GEN)$(MAKE) configure && \
+	$(QUIET_GEN)$(CONFIGURE_RECIPE) && \
 	if test -f config.status; then \
 	  ./config.status --recheck; \
 	else \

-Peff

^ permalink raw reply related

* Re: [BUG] Infinite make recursion when configure.ac changes
From: Junio C Hamano @ 2013-02-21  6:10 UTC (permalink / raw)
  To: Jeff King
  Cc: Stefano Lattarini, Git List, Martin von Zweigbergk,
	Jonathan Nieder
In-Reply-To: <20130221060401.GC25943@sigill.intra.peff.net>

Jeff King <peff@peff.net> writes:

> I can easily replicate it here.
>
>> This seems due to the change in commit v1.7.12.4-1-g1226504: the
>> issue is still present there, but no longer is in the preceding
>> commit 7e201053 (a.k.a. v1.7.12.4).
>> 
>> I haven't investigated this any further for the moment.
>
> Hmm. It looks like config.status depends on configure.ac. So make
> rebuilds config.status, which runs "make configure", which includes
> "config.mak.autogen", leading "make" to think that it should rebuild the
> include file to make sure it is up to date. The include file depends on
> "config.status", which needs to be rebuilt due to configure.ac, which
> entails running "make configure", and so on.

I noticed this while looking at the other autoconf patch yesterday,
but I was otherwise occupied in the evening and did not pursue it
further.  Thanks for looking into it.

This may be an unrelated issue, but I've always thought that it was
strange and extremely unintuitive that running "make configure" once
only creates config.mak.autogen, while running it once again after
that (i.e. while having config.mak.autogen in the tree) seems to run
the resulting "./configure" as well. Maybe it is just me.

^ permalink raw reply

* Re: [BUG] Infinite make recursion when configure.ac changes
From: Jeff King @ 2013-02-21  6:26 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Stefano Lattarini, Git List, Martin von Zweigbergk,
	Jonathan Nieder
In-Reply-To: <7vk3q2w61p.fsf@alter.siamese.dyndns.org>

On Wed, Feb 20, 2013 at 10:10:42PM -0800, Junio C Hamano wrote:

> I noticed this while looking at the other autoconf patch yesterday,
> but I was otherwise occupied in the evening and did not pursue it
> further.  Thanks for looking into it.

Here's the patch with a commit message. I'm pretty sure this is the
right thing to do. I was tempted to find a way of telling make "no,
don't include config.mak.autogen, but that actually _isn't_ right. It
might be defining $(RM) or some other variable that we use in the
recipe. By including it inline, we will use whatever is in the current
config.mak.autogen (that we read when we started this make invocation),
which is better than nothing.

> This may be an unrelated issue, but I've always thought that it was
> strange and extremely unintuitive that running "make configure" once
> only creates config.mak.autogen, while running it once again after
> that (i.e. while having config.mak.autogen in the tree) seems to run
> the resulting "./configure" as well. Maybe it is just me.

It's not the "configure" target that causes it to run. It's the fact
that we include config.mak.autogen, which we then tell make can be
rebuilt by running ./configure. _But_ we only tell it so if one already
exists (since otherwise everybody would get automake cruft). This is the
"ifdef AUTOCONFIGURED" you see.

So I think the rule makes sense. Once you have told the Makefile that
you are interested in autoconf (by running configure once), then it
rebuilds it as necessary, and it should be consistent. You can opt back
out of it be removing config.mak.autogen.

Anyway, here is the patch to fix the loop.

-- >8 --
Subject: [PATCH] Makefile: avoid infinite loop on configure.ac change

If you are using autoconf and change the configure.ac, the
Makefile will notice that config.status is older than
configure.ac, and will attempt to rebuild and re-run the
configure script to pick up your changes. The first step in
doing so is to run "make configure". Unfortunately, this
tries to include config.mak.autogen, which depends on
config.status, which depends on configure.ac; so we must
rebuild config.status. Which leads to us running "make
configure", and so on.

It's easy to demonstrate with:

  make configure
  ./configure
  touch configure.ac
  make

We can break this cycle by not re-invoking make to build
"configure", and instead just putting its rules inline into
our config.status rebuild procedure.  We can avoid a copy by
factoring the rules into a make variable.

Signed-off-by: Jeff King <peff@peff.net>
---
 Makefile | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/Makefile b/Makefile
index 3b2c92c..ee1c0b0 100644
--- a/Makefile
+++ b/Makefile
@@ -1871,12 +1871,14 @@ configure: configure.ac GIT-VERSION-FILE
 	mv $@+ $@
 endif # NO_PYTHON
 
+CONFIGURE_RECIPE = $(RM) configure configure.ac+ && \
+		   sed -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
+			configure.ac >configure.ac+ && \
+		   autoconf -o configure configure.ac+ && \
+		   $(RM) configure.ac+
+
 configure: configure.ac GIT-VERSION-FILE
-	$(QUIET_GEN)$(RM) $@ $<+ && \
-	sed -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
-	    $< > $<+ && \
-	autoconf -o $@ $<+ && \
-	$(RM) $<+
+	$(QUIET_GEN)$(CONFIGURE_RECIPE)
 
 ifdef AUTOCONFIGURED
 # We avoid depending on 'configure' here, because it gets rebuilt
@@ -1885,7 +1887,7 @@ config.status: configure.ac
 # do want to recheck when the platform/environment detection logic
 # changes, hence this depends on configure.ac.
 config.status: configure.ac
-	$(QUIET_GEN)$(MAKE) configure && \
+	$(QUIET_GEN)$(CONFIGURE_RECIPE) && \
 	if test -f config.status; then \
 	  ./config.status --recheck; \
 	else \
-- 
1.8.1.4.4.g265d2fa

^ permalink raw reply related

* Re: [BUG] Infinite make recursion when configure.ac changes
From: Junio C Hamano @ 2013-02-21  7:59 UTC (permalink / raw)
  To: Jeff King
  Cc: Stefano Lattarini, Git List, Martin von Zweigbergk,
	Jonathan Nieder
In-Reply-To: <20130221062614.GA8827@sigill.intra.peff.net>

Jeff King <peff@peff.net> writes:

> Anyway, here is the patch to fix the loop.
>
> -- >8 --
> Subject: [PATCH] Makefile: avoid infinite loop on configure.ac change
>
> If you are using autoconf and change the configure.ac, the
> Makefile will notice that config.status is older than
> configure.ac, and will attempt to rebuild and re-run the
> configure script to pick up your changes. The first step in
> doing so is to run "make configure". Unfortunately, this
> tries to include config.mak.autogen, which depends on
> config.status, which depends on configure.ac; so we must
> rebuild config.status. Which leads to us running "make
> configure", and so on.
>
> It's easy to demonstrate with:
>
>   make configure
>   ./configure
>   touch configure.ac
>   make
>
> We can break this cycle by not re-invoking make to build
> "configure", and instead just putting its rules inline into
> our config.status rebuild procedure.  We can avoid a copy by
> factoring the rules into a make variable.
>
> Signed-off-by: Jeff King <peff@peff.net>
> ---

Thanks.  This needs to go to both v1.8.1.x and v1.8.2.

Will apply.

>  Makefile | 14 ++++++++------
>  1 file changed, 8 insertions(+), 6 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index 3b2c92c..ee1c0b0 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -1871,12 +1871,14 @@ configure: configure.ac GIT-VERSION-FILE
>  	mv $@+ $@
>  endif # NO_PYTHON
>  
> +CONFIGURE_RECIPE = $(RM) configure configure.ac+ && \
> +		   sed -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
> +			configure.ac >configure.ac+ && \
> +		   autoconf -o configure configure.ac+ && \
> +		   $(RM) configure.ac+
> +
>  configure: configure.ac GIT-VERSION-FILE
> -	$(QUIET_GEN)$(RM) $@ $<+ && \
> -	sed -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
> -	    $< > $<+ && \
> -	autoconf -o $@ $<+ && \
> -	$(RM) $<+
> +	$(QUIET_GEN)$(CONFIGURE_RECIPE)
>  
>  ifdef AUTOCONFIGURED
>  # We avoid depending on 'configure' here, because it gets rebuilt
> @@ -1885,7 +1887,7 @@ config.status: configure.ac
>  # do want to recheck when the platform/environment detection logic
>  # changes, hence this depends on configure.ac.
>  config.status: configure.ac
> -	$(QUIET_GEN)$(MAKE) configure && \
> +	$(QUIET_GEN)$(CONFIGURE_RECIPE) && \
>  	if test -f config.status; then \
>  	  ./config.status --recheck; \
>  	else \

^ permalink raw reply

* Another slash at index size
From: Nguyễn Thái Ngọc Duy @ 2013-02-21  9:45 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

I noticed that even with v4, we still duplicate a lot of info in the
remaining fields. ce_uid and ce_guid for instance are unlikely to
change ever between entries. So I attempt to store offsets between the
previous entry instead. The result looks good. This is webkit index:

 25M index-v2
 14M index-v4
7.7M index-v5
4.5M index-v5.gz

gzip beats me naturally, we still have a lot of spare bits and we
don't use dictionaries. But the code is simpler and should run faster
than gzip.

Performance is improved too:

$ time GIT_INDEX_FILE=index-v2 ./git ls-files |head -n1 >/dev/null

real    0m0.437s
user    0m0.385s
sys     0m0.048s
$ time GIT_INDEX_FILE=index-v4 ./git ls-files |head -n1 >/dev/null

real    0m0.319s
user    0m0.277s
sys     0m0.040s
$ time GIT_INDEX_FILE=index-v5 ./git ls-files |head -n1 >/dev/null

real    0m0.250s
user    0m0.213s
sys     0m0.036s

Some details on the new format:

 - in general varint is used to store numbers, unless we know the
   numbers are really big.
 - flags is the first field on disk, it has extra bits to let git know
   what to do with the rest of the fields
 - Many fields like ctime, mtime, uid, gid, dev, ino are stored as
   offsets
 - ce_mode's special values 100644 and 100755 are stored in flags. So
   unless you use gitlinks or something else, ce_mode will not be
   stored.
 - ce_namelen is no longer stored on disk
 - pathname is compressed just like in v4

---
 cache.h      |   2 +-
 read-cache.c | 273 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 2 files changed, 269 insertions(+), 6 deletions(-)

diff --git a/cache.h b/cache.h
index e493563..6ab53e7 100644
--- a/cache.h
+++ b/cache.h
@@ -106,7 +106,7 @@ struct cache_header {
 };
 
 #define INDEX_FORMAT_LB 2
-#define INDEX_FORMAT_UB 4
+#define INDEX_FORMAT_UB 5
 
 /*
  * The "cache_time" is just the low 32 bits of the
diff --git a/read-cache.c b/read-cache.c
index 827ae55..147ace1 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -1260,7 +1260,7 @@ static int verify_hdr(struct cache_header *hdr, unsigned long size)
 	if (hdr->hdr_signature != htonl(CACHE_SIGNATURE))
 		return error("bad signature");
 	hdr_version = ntohl(hdr->hdr_version);
-	if (hdr_version < 2 || 4 < hdr_version)
+	if (hdr_version < 2 || 5 < hdr_version)
 		return error("bad index version %d", hdr_version);
 	git_SHA1_Init(&c);
 	git_SHA1_Update(&c, hdr, size - 20);
@@ -1407,6 +1407,137 @@ static struct cache_entry *create_from_disk(struct ondisk_cache_entry *ondisk,
 	return ce;
 }
 
+/*
+ * Often used flags come first to keep flags in common case small so
+ * that encode_varint() produces fewer bytes
+ */
+#define CE5_OFS_MTIME		(1 << 0)
+#define CE5_MODEMASK		(3 << 1)
+#define CE5_MODE_644		 0
+#define CE5_MODE_755		(1 << 1)
+#define CE5_MODE_FULL		(2 << 1)
+#define CE5_FULL_INO		(1 << 3)
+#define CE5_STAGESHIFT		 4
+#define CE5_STAGEMASK		(3 << CE5_STAGESHIFT)
+#define CE5_ITA			(1 << 6)
+#define CE5_VALID		(1 << 7)
+#define CE5_SWT			(1 << 8)
+#define CE5_FULL_UID		(1 << 9)
+#define CE5_FULL_GID		(1 << 10)
+#define CE5_FULL_TIME		(1 << 11)
+#define CE5_FULL_DEV		(1 << 12)
+
+static uintmax_t decode_offset(const unsigned char **bufp, uintmax_t base)
+{
+	uintmax_t offset = decode_varint(bufp);
+	if (offset & 1)	/* negative */
+		return base - (offset >> 1);
+	else
+		return base + (offset >> 1);
+
+}
+
+static struct cache_entry *create_from_disk_v5(const unsigned char *data,
+					       unsigned long *consumed,
+					       struct strbuf *previous_name,
+					       const struct cache_entry *previous_ce)
+{
+	const unsigned char *orig = data;
+	struct cache_entry ce_tmp;
+	struct cache_entry *ce;
+	unsigned int flags;
+
+	flags = decode_varint(&data);
+	ce_tmp.ce_flags = ((flags & CE5_STAGEMASK) >> CE5_STAGESHIFT) << CE_STAGESHIFT;
+	if (flags & CE5_ITA)
+		ce_tmp.ce_flags |= CE_INTENT_TO_ADD;
+	if (flags & CE5_VALID)
+		ce_tmp.ce_flags |= CE_VALID;
+	if (flags & CE5_SWT)
+		ce_tmp.ce_flags |= CE_SKIP_WORKTREE;
+
+	if (flags & CE5_FULL_TIME) { /* full format, 16 bytes */
+		ce_tmp.ce_ctime.sec = ntoh_l(*(uint32_t*)data);
+		data += sizeof(uint32_t);
+		ce_tmp.ce_ctime.nsec = ntoh_l(*(uint32_t*)data);
+		data += sizeof(uint32_t);
+
+		ce_tmp.ce_mtime.sec = ntoh_l(*(uint32_t*)data);
+		data += sizeof(uint32_t);
+		ce_tmp.ce_mtime.nsec = ntoh_l(*(uint32_t*)data);
+		data += sizeof(uint32_t);
+	} else {
+		/* offset from previous ce */
+		ce_tmp.ce_ctime.sec = decode_offset(&data, previous_ce->ce_ctime.sec);
+		ce_tmp.ce_ctime.nsec = decode_offset(&data, previous_ce->ce_ctime.nsec);
+
+		if (flags & CE5_OFS_MTIME) {
+			/* offset from previous ce */
+			ce_tmp.ce_mtime.sec = decode_offset(&data, previous_ce->ce_mtime.sec);
+			ce_tmp.ce_mtime.nsec = decode_offset(&data, previous_ce->ce_mtime.nsec);
+		} else
+			ce_tmp.ce_mtime = ce_tmp.ce_ctime;
+	}
+
+
+	if (flags & CE5_FULL_DEV)
+		ce_tmp.ce_dev = decode_varint(&data);
+	else
+		ce_tmp.ce_dev = previous_ce->ce_dev;
+	if (flags & CE5_FULL_INO) {
+		ce_tmp.ce_ino = ntoh_l(*(uint32_t*)data);
+		data += sizeof(uint32_t);
+	} else {
+		uintmax_t offset = decode_varint(&data);
+		if (offset & 1)	/* negative */
+			ce_tmp.ce_ino = previous_ce->ce_ino - (offset >> 1);
+		else
+			ce_tmp.ce_ino = previous_ce->ce_ino + (offset >> 1);
+	}
+	switch (flags & CE5_MODEMASK) {
+	case CE5_MODE_644:
+		ce_tmp.ce_mode = 0100644;
+		break;
+	case CE5_MODE_755:
+		ce_tmp.ce_mode = 0100755;
+		break;
+	case CE5_MODE_FULL:
+		ce_tmp.ce_mode = decode_varint(&data);
+		break;
+	default:
+		die("Huh?");
+	}
+	if (flags & CE5_FULL_UID)
+		ce_tmp.ce_uid = decode_varint(&data);
+	else
+		ce_tmp.ce_uid = previous_ce->ce_uid;
+	if (flags & CE5_FULL_GID)
+		ce_tmp.ce_gid = decode_varint(&data);
+	else
+		ce_tmp.ce_gid = previous_ce->ce_gid;
+	ce_tmp.ce_size = decode_varint(&data);
+	hashcpy(ce_tmp.sha1, data);
+	data += 20;
+
+	*consumed = data - orig;
+	*consumed += expand_name_field(previous_name, (const char *)data);
+
+	ce = xmalloc(cache_entry_size(previous_name->len));
+	ce->ce_ctime = ce_tmp.ce_ctime;
+	ce->ce_mtime = ce_tmp.ce_mtime;
+	ce->ce_dev   = ce_tmp.ce_dev;
+	ce->ce_ino   = ce_tmp.ce_ino;
+	ce->ce_mode  = ce_tmp.ce_mode;
+	ce->ce_uid   = ce_tmp.ce_uid;
+	ce->ce_gid   = ce_tmp.ce_gid;
+	ce->ce_size  = ce_tmp.ce_size;
+	ce->ce_flags = ce_tmp.ce_flags;
+	ce->ce_namelen = previous_name->len;
+	hashcpy(ce->sha1, ce_tmp.sha1);
+	memcpy(ce->name, previous_name->buf, previous_name->len + 1);
+	return ce;
+}
+
 /* remember to discard_cache() before reading a different cache! */
 int read_index_from(struct index_state *istate, const char *path)
 {
@@ -1452,7 +1583,7 @@ int read_index_from(struct index_state *istate, const char *path)
 	istate->cache = xcalloc(istate->cache_alloc, sizeof(struct cache_entry *));
 	istate->initialized = 1;
 
-	if (istate->version == 4)
+	if (istate->version >= 4)
 		previous_name = &previous_name_buf;
 	else
 		previous_name = NULL;
@@ -1464,7 +1595,13 @@ int read_index_from(struct index_state *istate, const char *path)
 		unsigned long consumed;
 
 		disk_ce = (struct ondisk_cache_entry *)((char *)mmap + src_offset);
-		ce = create_from_disk(disk_ce, &consumed, previous_name);
+		if (istate->version == 5)
+			ce = create_from_disk_v5((const unsigned char*)disk_ce,
+						 &consumed,
+						 previous_name,
+						 i > 0 ? istate->cache[i - 1] : NULL);
+		else
+			ce = create_from_disk(disk_ce, &consumed, previous_name);
 		set_index_entry(istate, i, ce);
 
 		src_offset += consumed;
@@ -1652,6 +1789,125 @@ static void ce_smudge_racily_clean_entry(struct cache_entry *ce)
 	}
 }
 
+static void strbuf_encode_varint(struct strbuf *sb, uintmax_t value)
+{
+	static unsigned char varint[16];
+	int varint_len = encode_varint(value, varint);
+	strbuf_add(sb, varint, varint_len);
+}
+
+static void strbuf_encode_offset(struct strbuf *sb, unsigned int v1, unsigned int v2)
+{
+	if (v1 < v2)
+		strbuf_encode_varint(sb, (v2 - v1) << 1);
+	else
+		strbuf_encode_varint(sb, 1 | ((v1 - v2) << 1));
+}
+
+static int ce_write_entry_v5(git_SHA_CTX *c, int fd,
+			     struct cache_entry *ce,
+			     struct strbuf *previous_name,
+			     struct cache_entry *previous_ce)
+{
+	uint32_t data[4];
+	unsigned int flags = 0;
+	struct strbuf sb = STRBUF_INIT;
+	int result;
+
+	if (ce->ce_flags & CE_INTENT_TO_ADD)
+		flags |= CE5_ITA;
+	if (ce->ce_flags & CE_VALID)
+		flags |= CE5_VALID;
+	if (ce->ce_flags & CE_SKIP_WORKTREE)
+		flags |= CE5_SWT;
+	flags |= ce_stage(ce) << CE5_STAGESHIFT;
+
+	if (previous_ce) {
+		if (ce->ce_ctime.sec != ce->ce_mtime.sec ||
+		    ce->ce_ctime.nsec != ce->ce_mtime.nsec)
+			flags |= CE5_OFS_MTIME;
+		if (ce->ce_uid != previous_ce->ce_uid)
+			flags |= CE5_FULL_UID;
+		if (ce->ce_gid != previous_ce->ce_gid)
+			flags |= CE5_FULL_GID;
+		if (ce->ce_dev != previous_ce->ce_dev)
+			flags |= CE5_FULL_DEV;
+	} else
+		flags |= CE5_FULL_TIME | CE5_FULL_UID | CE5_FULL_GID | CE5_FULL_DEV;
+	if (ce->ce_mode == 0100644)
+		flags |= CE5_MODE_644; /* no bit sets actually */
+	else if (ce->ce_mode == 0100755)
+		flags |= CE5_MODE_755;
+	else
+		flags |= CE5_MODE_FULL;
+	if (previous_ce &&
+	    (ce->ce_ino - previous_ce->ce_ino < 16000 ||
+	     previous_ce->ce_ino - ce->ce_ino < 16000))
+		;		/* inode offset */
+	else
+		flags |= CE5_FULL_INO;
+
+	strbuf_encode_varint(&sb, flags);
+
+	if (flags & CE5_FULL_TIME) { /* full format, 16 bytes */
+		data[0] = htonl(ce->ce_ctime.sec);
+		data[1] = htonl(ce->ce_ctime.nsec);
+		data[2] = htonl(ce->ce_mtime.sec);
+		data[3] = htonl(ce->ce_mtime.nsec);
+		strbuf_add(&sb, data, sizeof(data));
+	} else {
+		/* offset from previous ce */
+		strbuf_encode_offset(&sb, previous_ce->ce_ctime.sec, ce->ce_ctime.sec);
+		strbuf_encode_offset(&sb, previous_ce->ce_ctime.nsec, ce->ce_ctime.nsec);
+
+		if (flags & CE5_OFS_MTIME) {
+			/* offset from previous ce */
+			strbuf_encode_offset(&sb, previous_ce->ce_mtime.sec, ce->ce_mtime.sec);
+			strbuf_encode_offset(&sb, previous_ce->ce_mtime.nsec, ce->ce_mtime.nsec);
+		}
+	}
+
+	if (flags & CE5_FULL_DEV)
+		strbuf_encode_varint(&sb, ce->ce_dev);
+	if (flags & CE5_FULL_INO) {
+		data[0] =  htonl(ce->ce_ino);
+		strbuf_add(&sb, data, sizeof(*data));
+	} else
+		strbuf_encode_offset(&sb, previous_ce->ce_ino, ce->ce_ino);
+	if (flags & CE5_MODE_FULL)
+		strbuf_encode_varint(&sb, ce->ce_mode);
+	if (flags & CE5_FULL_UID)
+		strbuf_encode_varint(&sb, ce->ce_uid);
+	if (flags & CE5_FULL_GID)
+		strbuf_encode_varint(&sb, ce->ce_gid);
+	strbuf_encode_varint(&sb, ce->ce_size);
+	strbuf_add(&sb, ce->sha1, 20);
+
+	if (previous_name) {
+		int common, to_remove, prefix_size;
+		unsigned char to_remove_vi[16];
+		for (common = 0;
+		     (ce->name[common] &&
+		      common < previous_name->len &&
+		      ce->name[common] == previous_name->buf[common]);
+		     common++)
+			; /* still matching */
+		to_remove = previous_name->len - common;
+		prefix_size = encode_varint(to_remove, to_remove_vi);
+
+		strbuf_add(&sb, to_remove_vi, prefix_size);
+		strbuf_add(&sb, ce->name + common, ce_namelen(ce) - common);
+
+		strbuf_splice(previous_name, common, to_remove,
+			      ce->name + common, ce_namelen(ce) - common);
+	} else
+		strbuf_add(&sb, ce->name, ce_namelen(ce));
+
+	result = ce_write(c, fd, sb.buf, sb.len + 1);
+	strbuf_release(&sb);
+	return result;
+}
+
 /* Copy miscellaneous fields but not the name */
 static char *copy_cache_entry_to_ondisk(struct ondisk_cache_entry *ondisk,
 				       struct cache_entry *ce)
@@ -1793,16 +2049,23 @@ int write_index(struct index_state *istate, int newfd)
 	if (ce_write(&c, newfd, &hdr, sizeof(hdr)) < 0)
 		return -1;
 
-	previous_name = (hdr_version == 4) ? &previous_name_buf : NULL;
+	previous_name = (hdr_version >= 4) ? &previous_name_buf : NULL;
 	for (i = 0; i < entries; i++) {
 		struct cache_entry *ce = cache[i];
+		int ret;
 		if (ce->ce_flags & CE_REMOVE)
 			continue;
 		if (!ce_uptodate(ce) && is_racy_timestamp(istate, ce))
 			ce_smudge_racily_clean_entry(ce);
 		if (is_null_sha1(ce->sha1))
 			return error("cache entry has null sha1: %s", ce->name);
-		if (ce_write_entry(&c, newfd, ce, previous_name) < 0)
+		if (hdr_version == 5)
+			ret = ce_write_entry_v5(&c, newfd, ce,
+						previous_name,
+						i > 0 ? cache[i-1] : NULL);
+		else
+			ret = ce_write_entry(&c, newfd, ce, previous_name);
+		if (ret < 0)
 			return -1;
 	}
 	strbuf_release(&previous_name_buf);
-- 
1.8.1.2.495.g3fdf5d5.dirty

^ permalink raw reply related

* running git from non-standard location on Mac
From: James French @ 2013-02-21  9:48 UTC (permalink / raw)
  To: git@vger.kernel.org

Hi,

I wonder if someone could help me. I installed git on a Mac and then I copied the install somewhere else (which I do want to do, trust me).  I'm now having trouble with git svn. I'm getting "Can't locate Git/SVN.pm in @INC..."

I've added the bin folder to PATH. What else do I need to do? Do I need to use -exec-path=/MyPathToGit/libexec/git-core? How do I change the content of @INC?

Apologies if this is a dumb question, I'm not much of a unix man.

Cheers,
James

^ permalink raw reply

* RFD: concatening textconv filters
From: Michael J Gruber @ 2013-02-21 10:28 UTC (permalink / raw)
  To: Git Mailing List

During my day-to-day UGFWIINIT I noticed that we don't do textconv
iteratively. E.g.: I have a file

SuperSecretButDumbFormat.pdf.gpg

and textconv filters with attributes set for *.gpg and *.pdf (using
"gpg" resp. "pdftotext"). For Git, the file has only the "gpg"
attribute, of course. In this case, I would have wanted to pass the gpg
output through pdftotext.

Now, I can set up an extra filter "gpgtopdftotext" for *.pdf.gpg (hoping
I get the ordering in .gitattributes right), of course, but wondering
whether we could and should support concatenating filters by either

- making it easy to request it (say by setting
"filter.gpgtopdftotext.textconvpipe" to a list of textconv filter names
which are to be applied in sequence)

or

- doing it automatically (remove the pattern which triggered the filter,
and apply attributes again to the resulting pathspec)

Maybe it's just not worth the effort. Or a nice GSoC project ;)

Michael

^ permalink raw reply

* Re: running git from non-standard location on Mac
From: Konstantin Khomoutov @ 2013-02-21 10:35 UTC (permalink / raw)
  To: James French; +Cc: git@vger.kernel.org
In-Reply-To: <1CE1BECC0915A6448EAE5D7080EDA905052078C95E@oxexc1>

On Thu, 21 Feb 2013 09:48:36 +0000
James French <James.French@naturalmotion.com> wrote:

> I wonder if someone could help me. I installed git on a Mac and then
> I copied the install somewhere else (which I do want to do, trust
> me).  I'm now having trouble with git svn. I'm getting "Can't locate
> Git/SVN.pm in @INC..."
> 
> I've added the bin folder to PATH. What else do I need to do? Do I
> need to use -exec-path=/MyPathToGit/libexec/git-core? How do I change
> the content of @INC?
> 
> Apologies if this is a dumb question, I'm not much of a unix man.

`git svn` is implemented in Perl (which is supposedly bundled with your
Git package, but I'm not sure), and "SVN.pm" is a Perl module (a
library written in Perl, ".pm" stands for "Perl Module").

@INC is an internal variable used by Perl to locate its modules.
Its contents is partially inferred from the Perl's installation
location and partially from the environment.

This [1] should help you get started with affecting @INC.

1. http://stackoverflow.com/a/2526809/720999

^ permalink raw reply

* Re: running git from non-standard location on Mac
From: Matthieu Moy @ 2013-02-21 10:53 UTC (permalink / raw)
  To: Konstantin Khomoutov; +Cc: James French, git@vger.kernel.org
In-Reply-To: <20130221143525.726f06827351376b59a02f4b@domain007.com>

Konstantin Khomoutov <flatworm@users.sourceforge.net> writes:

> This [1] should help you get started with affecting @INC.

In the particular case of Git, the Makefile hardcodes the path to the
Git library. The script git-svn in Git's exec-path should start with:

use lib (split(/:/, $ENV{GITPERLLIB} || "/some/hardcoded/path/to/perl/5.10.1"));

Setting the $GITPERLLIB environment variable or editing the script to
let the hardcoded path point to the place where the Git.pm file is
should do it.


But I still have to wonder why you didn't build Git with the right paths
in the first place.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/

^ permalink raw reply

* RE: running git from non-standard location on Mac
From: James French @ 2013-02-21 11:48 UTC (permalink / raw)
  To: Konstantin Khomoutov; +Cc: git@vger.kernel.org
In-Reply-To: <20130221143525.726f06827351376b59a02f4b@domain007.com>



-----Original Message-----
From: Konstantin Khomoutov [mailto:flatworm@users.sourceforge.net] 
Sent: 21 February 2013 10:35
To: James French
Cc: git@vger.kernel.org
Subject: Re: running git from non-standard location on Mac

On Thu, 21 Feb 2013 09:48:36 +0000
James French <James.French@naturalmotion.com> wrote:

> I wonder if someone could help me. I installed git on a Mac and then I 
> copied the install somewhere else (which I do want to do, trust me).  
> I'm now having trouble with git svn. I'm getting "Can't locate 
> Git/SVN.pm in @INC..."
> 
> I've added the bin folder to PATH. What else do I need to do? Do I 
> need to use -exec-path=/MyPathToGit/libexec/git-core? How do I change 
> the content of @INC?
> 
> Apologies if this is a dumb question, I'm not much of a unix man.

`git svn` is implemented in Perl (which is supposedly bundled with your Git package, but I'm not sure), and "SVN.pm" is a Perl module (a library written in Perl, ".pm" stands for "Perl Module").

@INC is an internal variable used by Perl to locate its modules.
Its contents is partially inferred from the Perl's installation location and partially from the environment.

This [1] should help you get started with affecting @INC.

1. http://stackoverflow.com/a/2526809/720999



Thanks for the help guys. I got it working using --exec-path and PERL5LIB environment variable. But Matthieu is right, I should build it from source to do it properly.

^ permalink raw reply

* "git branch HEAD" dumps core when on detached head (NULL pointer dereference)
From: Per Cederqvist @ 2013-02-21 12:27 UTC (permalink / raw)
  To: git

Running "git branch HEAD" may be a stupid thing to do. It actually
was a mistake on my part. Still, I don't think git should dereference
a NULL pointer.

Tested using git 1.8.1.4 adn 1.8.1.1.

Repeat by:

     mkdir branchcrash || exit 1
     cd branchcrash
     git init
     touch a; git add a; git commit -m"Added a".
     touch b; git add b; git commit -m"Added b".
     git checkout HEAD^
     git branch HEAD

The last command dumps core.  gdb session:

gdb /usr/local/bin/git core
GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later 
<http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /usr/local/bin/git...done.
[New LWP 7174]

warning: Can't read pathname for load map: Input/output error.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `git branch HEAD'.
Program terminated with signal 11, Segmentation fault.
#0  cmd_branch (argc=1, argv=0x7fffe6e2a0f0, prefix=<optimized out>)
     at builtin/branch.c:919
919			strbuf_addf(&buf, "refs/remotes/%s", branch->name);
(gdb) bt
#0  cmd_branch (argc=1, argv=0x7fffe6e2a0f0, prefix=<optimized out>)
     at builtin/branch.c:919
#1  0x00000000004046ac in run_builtin (argv=0x7fffe6e2a0f0, argc=2,
     p=<optimized out>) at git.c:273
#2  handle_internal_command (argc=2, argv=0x7fffe6e2a0f0) at git.c:434
#3  0x0000000000404df3 in run_argv (argv=0x7fffe6e29f90, 
argcp=0x7fffe6e29f9c)
     at git.c:480
#4  main (argc=2, argv=0x7fffe6e2a0f0) at git.c:555
(gdb) p branch
$1 = (struct branch *) 0x0
(gdb) quit

     /ceder

^ permalink raw reply

* Re: "git branch HEAD" dumps core when on detached head (NULL pointer dereference)
From: Duy Nguyen @ 2013-02-21 12:50 UTC (permalink / raw)
  To: Per Cederqvist; +Cc: git
In-Reply-To: <512612AD.4000609@opera.com>

On Thu, Feb 21, 2013 at 7:27 PM, Per Cederqvist <cederp@opera.com> wrote:
> Running "git branch HEAD" may be a stupid thing to do. It actually
> was a mistake on my part. Still, I don't think git should dereference
> a NULL pointer.

We should not. Can you make a patch to fix it (with test cases)? You
may want to fix the two preceding blocks, "if (new_upstream)" and "if
(unset_upstream)", as well. They don't check for NULL branch either. I
think we can say something like "detached HEAD is not valid for this
operation" before exit.

>
> Tested using git 1.8.1.4 adn 1.8.1.1.
>
> Repeat by:
>
>     mkdir branchcrash || exit 1
>     cd branchcrash
>     git init
>     touch a; git add a; git commit -m"Added a".
>     touch b; git add b; git commit -m"Added b".
>     git checkout HEAD^
>     git branch HEAD
>
> The last command dumps core.  gdb session:
>
> gdb /usr/local/bin/git core
> GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04
> Copyright (C) 2012 Free Software Foundation, Inc.
> License GPLv3+: GNU GPL version 3 or later
> <http://gnu.org/licenses/gpl.html>
> This is free software: you are free to change and redistribute it.
> There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
> and "show warranty" for details.
> This GDB was configured as "x86_64-linux-gnu".
> For bug reporting instructions, please see:
> <http://bugs.launchpad.net/gdb-linaro/>...
> Reading symbols from /usr/local/bin/git...done.
> [New LWP 7174]
>
> warning: Can't read pathname for load map: Input/output error.
> [Thread debugging using libthread_db enabled]
> Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
> Core was generated by `git branch HEAD'.
> Program terminated with signal 11, Segmentation fault.
> #0  cmd_branch (argc=1, argv=0x7fffe6e2a0f0, prefix=<optimized out>)
>     at builtin/branch.c:919
> 919                     strbuf_addf(&buf, "refs/remotes/%s", branch->name);
> (gdb) bt
> #0  cmd_branch (argc=1, argv=0x7fffe6e2a0f0, prefix=<optimized out>)
>     at builtin/branch.c:919
> #1  0x00000000004046ac in run_builtin (argv=0x7fffe6e2a0f0, argc=2,
>     p=<optimized out>) at git.c:273
> #2  handle_internal_command (argc=2, argv=0x7fffe6e2a0f0) at git.c:434
> #3  0x0000000000404df3 in run_argv (argv=0x7fffe6e29f90,
> argcp=0x7fffe6e29f9c)
>     at git.c:480
> #4  main (argc=2, argv=0x7fffe6e2a0f0) at git.c:555
> (gdb) p branch
> $1 = (struct branch *) 0x0
> (gdb) quit
>
>     /ceder
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Duy

^ permalink raw reply

* "git branch --contains x y" creates a branch instead of checking containment
From: Per Cederqvist @ 2013-02-21 13:00 UTC (permalink / raw)
  To: git

The "git branch --list --contains x y" command lists
all branches that contains commit x and matches the
pattern y. Reading the git-branch(1) manual page gives
the impression that "--list" is redundant, and that
you can instead write

    git branch --contains x y

That command does something completely different,
though. The "--contains x" part is silently ignored,
so it creates a branch named "y" pointing at HEAD.

Tested in git 1.8.1.1 and 1.8.1.4.

In my opinion, there are two ways to fix this:

  - change the "git branch" implementation so
    that --contains implies --list.

  - change the manual page synopsis so that
    it is clear that --contains can only be
    used if --list is also used.  Also add an
    error check to the "git branch" implementation
    so that using --contains without specifying
    --list produces a fatal error message.

Personally I would prefer the first solution.

Repeat by running these commands:

# Set up a repo with two commits.
# Branch a points to the oldest one, and
# b and master to the newest one.
mkdir contains || exit 1
cd contains
git init
touch a; git add a; git commit -m"Added a".
git branch a
touch b; git add b; git commit -m"Added b".
git branch b

git branch --list --contains a
# Prints "a", "b" and "master, as expected.

git branch --contains a
# Prints "a", "b" and "master, as expected.
# In this case, the --list option can be removed.

git branch --list --contains a b
# Prints "b", as expected.  "b" is a <pattern>.

git branch --list --contains a c
# Prints nothing, as expected, as the "c" pattern doesn't match any of
# the existing branches.

git for-each-ref
# Prints three lines: refs/heads/a, refs/heads/b and
# refs/heads/master, as expected.

git branch --contains a c
# Prints nothing, as expected, but...

git for-each-ref
# Prints four lines!  Apparently, the command above created
# refs/heads/c.

     /ceder

P.S. What I really wanted to do was "git merge-base
--is-ancestor a b", but I keep forgetting its name.

^ permalink raw reply

* QNX support
From: David Ondřich @ 2013-02-21 13:05 UTC (permalink / raw)
  To: git

Hi,

I've read [1] recently, there's been some QNX port being initiated. Does that involve also old versions of QNX 4?

Since we are using QNX both internally and for our customers we started porting Git on QNX ourselves some time ago and we do have some experiences. Basically, it's possible to get Git up and running but there are some limitations, and some hacks have to be applied.

If some additional info wanted, please contact me.

dond

[1] http://lkml.indiana.edu/hypermail/linux/kernel/1302.2/00406.html

^ permalink raw reply

* Re: "git branch HEAD" dumps core when on detached head (NULL pointer dereference)
From: Per Cederqvist @ 2013-02-21 13:24 UTC (permalink / raw)
  To: Duy Nguyen; +Cc: git
In-Reply-To: <CACsJy8CuRvwsbXbcKr7dHneEDF7UmoG4ioCxfDi_7qWDD-4wgQ@mail.gmail.com>

On 02/21/13 13:50, Duy Nguyen wrote:
> On Thu, Feb 21, 2013 at 7:27 PM, Per Cederqvist <cederp@opera.com> wrote:
>> Running "git branch HEAD" may be a stupid thing to do. It actually
>> was a mistake on my part. Still, I don't think git should dereference
>> a NULL pointer.
>
> We should not. Can you make a patch to fix it (with test cases)? You
> may want to fix the two preceding blocks, "if (new_upstream)" and "if
> (unset_upstream)", as well. They don't check for NULL branch either. I
> think we can say something like "detached HEAD is not valid for this
> operation" before exit.

Sorry, but isolating the issue reporting it here is about as much time
as I can spend on this issue. Learning the coding standard of Git and
how to write test cases is not something I'm prepared to do, at least
not at the moment. I hope there is a place for users and reporters of
bugs in the Git community.

     /ceder

>>
>> Tested using git 1.8.1.4 adn 1.8.1.1.
>>
>> Repeat by:
>>
>>      mkdir branchcrash || exit 1
>>      cd branchcrash
>>      git init
>>      touch a; git add a; git commit -m"Added a".
>>      touch b; git add b; git commit -m"Added b".
>>      git checkout HEAD^
>>      git branch HEAD
>>
>> The last command dumps core.  gdb session:
>>
>> gdb /usr/local/bin/git core
>> GNU gdb (Ubuntu/Linaro 7.4-2012.04-0ubuntu2.1) 7.4-2012.04
>> Copyright (C) 2012 Free Software Foundation, Inc.
>> License GPLv3+: GNU GPL version 3 or later
>> <http://gnu.org/licenses/gpl.html>
>> This is free software: you are free to change and redistribute it.
>> There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
>> and "show warranty" for details.
>> This GDB was configured as "x86_64-linux-gnu".
>> For bug reporting instructions, please see:
>> <http://bugs.launchpad.net/gdb-linaro/>...
>> Reading symbols from /usr/local/bin/git...done.
>> [New LWP 7174]
>>
>> warning: Can't read pathname for load map: Input/output error.
>> [Thread debugging using libthread_db enabled]
>> Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
>> Core was generated by `git branch HEAD'.
>> Program terminated with signal 11, Segmentation fault.
>> #0  cmd_branch (argc=1, argv=0x7fffe6e2a0f0, prefix=<optimized out>)
>>      at builtin/branch.c:919
>> 919                     strbuf_addf(&buf, "refs/remotes/%s", branch->name);
>> (gdb) bt
>> #0  cmd_branch (argc=1, argv=0x7fffe6e2a0f0, prefix=<optimized out>)
>>      at builtin/branch.c:919
>> #1  0x00000000004046ac in run_builtin (argv=0x7fffe6e2a0f0, argc=2,
>>      p=<optimized out>) at git.c:273
>> #2  handle_internal_command (argc=2, argv=0x7fffe6e2a0f0) at git.c:434
>> #3  0x0000000000404df3 in run_argv (argv=0x7fffe6e29f90,
>> argcp=0x7fffe6e29f9c)
>>      at git.c:480
>> #4  main (argc=2, argv=0x7fffe6e2a0f0) at git.c:555
>> (gdb) p branch
>> $1 = (struct branch *) 0x0
>> (gdb) quit
>>
>>      /ceder
>> --
>> To unsubscribe from this list: send the line "unsubscribe git" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>
>

^ permalink raw reply

* Re: "git branch HEAD" dumps core when on detached head (NULL pointer dereference)
From: Duy Nguyen @ 2013-02-21 13:32 UTC (permalink / raw)
  To: Per Cederqvist; +Cc: git
In-Reply-To: <51261FF9.2090304@opera.com>

On Thu, Feb 21, 2013 at 8:24 PM, Per Cederqvist <cederp@opera.com> wrote:
> Sorry, but isolating the issue reporting it here is about as much time
> as I can spend on this issue. Learning the coding standard of Git and
> how to write test cases is not something I'm prepared to do, at least
> not at the moment. I hope there is a place for users and reporters of
> bugs in the Git community.

Sure. No problem. I just thought you might want to finish it off. I'll
look into it.
-- 
Duy

^ 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