Re: [PATCH 4/6] dir.c::match_pathname(): pay attention to the length of string parameters

2013-03-29 Thread Duy Nguyen
On Fri, Mar 29, 2013 at 4:48 AM, Jeff King p...@peff.net wrote:
 -   return fnmatch_icase(pattern, name, FNM_PATHNAME) == 0;
 +   return fnmatch_icase_mem(pattern, patternlen,
 +name, namelen,
 +FNM_PATHNAME) == 0;
  }

I think you (or Junio) should rebase this on maint. Since c41244e
(included in maint), this call is turned to wildmatch(WM_PATHNAME) and
WM_PATHNAME is _not_ the same as FNM_PATHNAME for patterns like
foo/**/bar. A diff between next and pu shows me that WM_PATHNAME is
incorrectly converted to FNM_PATHNAME. I hope that is the cause of all
breakages Junio found out on pu.
-- 
Duy
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 4/6] dir.c::match_pathname(): pay attention to the length of string parameters

2013-03-29 Thread Duy Nguyen
On Fri, Mar 29, 2013 at 3:45 PM, Duy Nguyen pclo...@gmail.com wrote:
 On Fri, Mar 29, 2013 at 4:48 AM, Jeff King p...@peff.net wrote:
 -   return fnmatch_icase(pattern, name, FNM_PATHNAME) == 0;
 +   return fnmatch_icase_mem(pattern, patternlen,
 +name, namelen,
 +FNM_PATHNAME) == 0;
  }

 I think you (or Junio) should rebase this on maint. Since c41244e
 (included in maint), this call is turned to wildmatch(WM_PATHNAME) and
 WM_PATHNAME is _not_ the same as FNM_PATHNAME for patterns like
 foo/**/bar. A diff between next and pu shows me that WM_PATHNAME is
 incorrectly converted to FNM_PATHNAME. I hope that is the cause of all
 breakages Junio found out on pu.

Just tested. t0003 and t3001 on 'pu' work for me because I have
USE_WILDMATCH on (which turns FNM_PATHNAME to WM_PATHNAME). Both break
without USE_WILDMATCH.
-- 
Duy
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/5] difftool improvements

2013-03-29 Thread John Keeping
This is a consolidated series replacing jk/t7800-modernize.  The patches
here have been rebased on master.

Patch 1 is new and moves the test added by commit 02c5631 (difftool
--dir-diff: symlink all files matching the working tree) to the end of
the test file.  This means that once this is applied the second patch
and the final three patches can become independent branches.

Patch 2 is a fix for a long standing deficiency, but the potential for
this to happen has been increased by the commit mentioned above.  It has
already been through a couple of iterations [1].

The final three patches are the same as the current jk/t7800-modernize,
with one tweaked commit message.

[1] http://article.gmane.org/gmane.comp.version-control.git/219100

John Keeping (5):
  t7800: move '--symlinks' specific test to the end
  difftool: don't overwrite modified files
  t7800: don't hide grep output
  t7800: fix tests when difftool uses --no-symlinks
  t7800: run --dir-diff tests with and without symlinks

 git-difftool.perl   |  73 +---
 t/t7800-difftool.sh | 105 ++--
 2 files changed, 127 insertions(+), 51 deletions(-)

-- 
1.8.2.411.g65a544e

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/5] t7800: move '--symlinks' specific test to the end

2013-03-29 Thread John Keeping
This will group the tests more logically when we introduce a helper to
run most --dir-diff tests with both --symlinks and --no-symlinks.

Signed-off-by: John Keeping j...@keeping.me.uk
---
 t/t7800-difftool.sh | 30 +++---
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh
index c6d6b1c..e6a16cd 100755
--- a/t/t7800-difftool.sh
+++ b/t/t7800-difftool.sh
@@ -340,6 +340,21 @@ test_expect_success PERL 'difftool --dir-diff' '
stdin_contains file output
 '
 
+test_expect_success PERL 'difftool --dir-diff ignores --prompt' '
+   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 
+   git difftool --dir-diff --extcmd ls branch output 
+   stdin_contains sub output 
+   stdin_contains file output
+   )
+'
+
 write_script .git/CHECK_SYMLINKS \EOF
 for f in file file2 sub/sub
 do
@@ -362,19 +377,4 @@ test_expect_success PERL,SYMLINKS 'difftool --dir-diff 
--symlink without unstage
test_cmp actual expect
 '
 
-test_expect_success PERL 'difftool --dir-diff ignores --prompt' '
-   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 
-   git difftool --dir-diff --extcmd ls branch output 
-   stdin_contains sub output 
-   stdin_contains file output
-   )
-'
-
 test_done
-- 
1.8.2.411.g65a544e

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/5] difftool: don't overwrite modified files

2013-03-29 Thread John Keeping
After running the user's diff tool, git-difftool will copy any files
that differ between the working tree and the temporary tree.  This is
useful when the user edits the file in their diff tool but is wrong if
they edit the working tree file while examining the diff.

Instead of copying unconditionally when the files differ, create and
index from the working tree files and only copy the temporary file back
if it was modified and the working tree file was not.  If both files
have been modified, print a warning and exit with an error.

Note that we cannot use an existing index in git-difftool since those
contain the modified files that need to be checked out but here we are
looking at those files which are copied from the working tree and not
checked out.  These are precisely the files which are not in the
existing indices.

Signed-off-by: John Keeping j...@keeping.me.uk

---
Changes since v2:
- Set TMPDIR to $TRASH_DIRECTORY in the test where difftool fails

 git-difftool.perl   | 73 +++--
 t/t7800-difftool.sh | 30 ++
 2 files changed, 89 insertions(+), 14 deletions(-)

diff --git a/git-difftool.perl b/git-difftool.perl
index 663640d..844f619 100755
--- a/git-difftool.perl
+++ b/git-difftool.perl
@@ -13,9 +13,9 @@
 use 5.008;
 use strict;
 use warnings;
+use Error qw(:try);
 use File::Basename qw(dirname);
 use File::Copy;
-use File::Compare;
 use File::Find;
 use File::stat;
 use File::Path qw(mkpath rmtree);
@@ -88,14 +88,45 @@ sub use_wt_file
my ($repo, $workdir, $file, $sha1, $symlinks) = @_;
my $null_sha1 = '0' x 40;
 
-   if ($sha1 eq $null_sha1) {
-   return 1;
-   } elsif (not $symlinks) {
+   if ($sha1 ne $null_sha1 and not $symlinks) {
return 0;
}
 
my $wt_sha1 = $repo-command_oneline('hash-object', $workdir/$file);
-   return $sha1 eq $wt_sha1;
+   my $use = ($sha1 eq $null_sha1) || ($sha1 eq $wt_sha1);
+   return ($use, $wt_sha1);
+}
+
+sub changed_files
+{
+   my ($repo_path, $index, $worktree) = @_;
+   $ENV{GIT_INDEX_FILE} = $index;
+   $ENV{GIT_WORK_TREE} = $worktree;
+   my $must_unset_git_dir = 0;
+   if (not defined($ENV{GIT_DIR})) {
+   $must_unset_git_dir = 1;
+   $ENV{GIT_DIR} = $repo_path;
+   }
+
+   my @refreshargs = qw/update-index --really-refresh -q --unmerged/;
+   my @gitargs = qw/diff-files --name-only -z/;
+   try {
+   Git::command_oneline(@refreshargs);
+   } catch Git::Error::Command with {};
+
+   my $line = Git::command_oneline(@gitargs);
+   my @files;
+   if (defined $line) {
+   @files = split('\0', $line);
+   } else {
+   @files = ();
+   }
+
+   delete($ENV{GIT_INDEX_FILE});
+   delete($ENV{GIT_WORK_TREE});
+   delete($ENV{GIT_DIR}) if ($must_unset_git_dir);
+
+   return map { $_ = 1 } @files;
 }
 
 sub setup_dir_diff
@@ -121,6 +152,7 @@ sub setup_dir_diff
my $null_sha1 = '0' x 40;
my $lindex = '';
my $rindex = '';
+   my $wtindex = '';
my %submodule;
my %symlink;
my @working_tree = ();
@@ -174,8 +206,12 @@ EOF
}
 
if ($rmode ne $null_mode) {
-   if (use_wt_file($repo, $workdir, $dst_path, $rsha1, 
$symlinks)) {
-   push(@working_tree, $dst_path);
+   my ($use, $wt_sha1) = use_wt_file($repo, $workdir,
+ $dst_path, $rsha1,
+ $symlinks);
+   if ($use) {
+   push @working_tree, $dst_path;
+   $wtindex .= $rmode $wt_sha1\t$dst_path\0;
} else {
$rindex .= $rmode $rsha1\t$dst_path\0;
}
@@ -218,6 +254,12 @@ EOF
$rc = system('git', 'checkout-index', '--all', --prefix=$rdir/);
exit_cleanup($tmpdir, $rc) if $rc != 0;
 
+   $ENV{GIT_INDEX_FILE} = $tmpdir/wtindex;
+   ($inpipe, $ctx) =
+   $repo-command_input_pipe(qw(update-index --info-only -z 
--index-info));
+   print($inpipe $wtindex);
+   $repo-command_close_pipe($inpipe, $ctx);
+
# If $GIT_DIR was explicitly set just for the update/checkout
# commands, then it should be unset before continuing.
delete($ENV{GIT_DIR}) if ($must_unset_git_dir);
@@ -390,19 +432,22 @@ sub dir_diff
# should be copied back to the working tree.
# Do not copy back files when symlinks are used and the
# external tool did not replace the original link with a file.
+   my %wt_modified = changed_files($repo-repo_path(),
+   $tmpdir/wtindex, $workdir);
+   my %tmp_modified = changed_files($repo-repo_path(),
+   $tmpdir/wtindex, $b);
  

[PATCH 3/5] t7800: don't hide grep output

2013-03-29 Thread John Keeping
Remove the stdin_contains and stdin_doesnt_contain helper functions
which add nothing but hide the output of grep, hurting debugging.

Suggested-by: Johannes Sixt j.s...@viscovery.net
Signed-off-by: John Keeping j...@keeping.me.uk
---
 t/t7800-difftool.sh | 44 +---
 1 file changed, 17 insertions(+), 27 deletions(-)

diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh
index 017f55a..9fd09db 100755
--- a/t/t7800-difftool.sh
+++ b/t/t7800-difftool.sh
@@ -23,16 +23,6 @@ prompt_given ()
test $prompt = Launch 'test-tool' [Y/n]: branch
 }
 
-stdin_contains ()
-{
-   grep /dev/null $1
-}
-
-stdin_doesnot_contain ()
-{
-   ! stdin_contains $1
-}
-
 # Create a file on master and change it on branch
 test_expect_success PERL 'setup' '
echo master file 
@@ -296,24 +286,24 @@ test_expect_success PERL 'setup with 2 files different' '
 test_expect_success PERL 'say no to the first file' '
(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
+   grep m2 output 
+   grep br2 output 
+   ! grep master output 
+   ! grep branch output
 '
 
 test_expect_success PERL 'say no to the second file' '
(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
+   grep master output 
+   grep branch output 
+   ! grep m2 output 
+   ! grep br2 output
 '
 
 test_expect_success PERL 'difftool --tool-help' '
git difftool --tool-help output 
-   stdin_contains tool output
+   grep tool output
 '
 
 test_expect_success PERL 'setup change in subdirectory' '
@@ -330,28 +320,28 @@ test_expect_success PERL 'setup change in subdirectory' '
 
 test_expect_success PERL 'difftool -d' '
git difftool -d --extcmd ls branch output 
-   stdin_contains sub output 
-   stdin_contains file output
+   grep sub output 
+   grep file output
 '
 
 test_expect_success PERL 'difftool --dir-diff' '
git difftool --dir-diff --extcmd ls branch output 
-   stdin_contains sub output 
-   stdin_contains file output
+   grep sub output 
+   grep file output
 '
 
 test_expect_success PERL 'difftool --dir-diff ignores --prompt' '
git difftool --dir-diff --prompt --extcmd ls branch output 
-   stdin_contains sub output 
-   stdin_contains file output
+   grep sub output 
+   grep file output
 '
 
 test_expect_success PERL 'difftool --dir-diff from subdirectory' '
(
cd sub 
git difftool --dir-diff --extcmd ls branch output 
-   stdin_contains sub output 
-   stdin_contains file output
+   grep sub output 
+   grep file output
)
 '
 
-- 
1.8.2.411.g65a544e

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/5] t7800: fix tests when difftool uses --no-symlinks

2013-03-29 Thread John Keeping
When 'git difftool --dir-diff' is using --no-symlinks (either explicitly
or implicitly because it's running on Windows), any working tree files
that have been copied to the temporary directory are copied back after
the difftool completes.

Because an earlier test uses git add ., the output file used by
tests is tracked by Git and the following sequence occurs during some
tests:

1) the shell opens output to redirect the difftool output
2) difftool copies the empty output to the temporary directory
3) difftool runs ls which writes to output
4) difftool copies the empty output file back over the output of the
   command
5) the output file doesn't contain the expected output, causing the
   test to fail

Instead of adding all changes, explicitly add only the files that the
test is using, allowing later tests to write their result files into the
working tree.

Signed-off-by: John Keeping j...@keeping.me.uk

---
Changes since v2:
- Fix grammar issues in commit message
- Remove the final paragraph of the commit message since this is now
  addressed by patch 2/5 in this series

 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 9fd09db..df443a9 100755
--- a/t/t7800-difftool.sh
+++ b/t/t7800-difftool.sh
@@ -314,7 +314,7 @@ test_expect_success PERL 'setup change in subdirectory' '
git commit -m added sub/sub 
echo test file 
echo test sub/sub 
-   git add . 
+   git add file sub/sub 
git commit -m modified both
 '
 
-- 
1.8.2.411.g65a544e

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 5/5] t7800: run --dir-diff tests with and without symlinks

2013-03-29 Thread John Keeping
Currently the difftool --dir-diff tests may or may not use symlinks
depending on the operating system on which they are run.  In one case
this has caused a test failure to be noticed only on Windows when the
test also fails on Linux when difftool is invoked with --no-symlinks.

Rewrite these tests so that they do not depend on the environment but
run explicitly with both --symlinks and --no-symlinks, protecting the
--symlinks version with a SYMLINKS prerequisite.

Signed-off-by: John Keeping j...@keeping.me.uk
---
 t/t7800-difftool.sh | 27 +++
 1 file changed, 19 insertions(+), 8 deletions(-)

diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh
index df443a9..a6bd99e 100755
--- a/t/t7800-difftool.sh
+++ b/t/t7800-difftool.sh
@@ -318,28 +318,39 @@ test_expect_success PERL 'setup change in subdirectory' '
git commit -m modified both
 '
 
-test_expect_success PERL 'difftool -d' '
-   git difftool -d --extcmd ls branch output 
+run_dir_diff_test () {
+   test_expect_success PERL $1 --no-symlinks 
+   symlinks=--no-symlinks 
+   $2
+   
+   test_expect_success PERL,SYMLINKS $1 --symlinks 
+   symlinks=--symlinks 
+   $2
+   
+}
+
+run_dir_diff_test 'difftool -d' '
+   git difftool -d $symlinks --extcmd ls branch output 
grep sub output 
grep file output
 '
 
-test_expect_success PERL 'difftool --dir-diff' '
-   git difftool --dir-diff --extcmd ls branch output 
+run_dir_diff_test 'difftool --dir-diff' '
+   git difftool --dir-diff $symlinks --extcmd ls branch output 
grep sub output 
grep file output
 '
 
-test_expect_success PERL 'difftool --dir-diff ignores --prompt' '
-   git difftool --dir-diff --prompt --extcmd ls branch output 
+run_dir_diff_test 'difftool --dir-diff ignores --prompt' '
+   git difftool --dir-diff $symlinks --prompt --extcmd ls branch output 
grep sub output 
grep file output
 '
 
-test_expect_success PERL 'difftool --dir-diff from subdirectory' '
+run_dir_diff_test 'difftool --dir-diff from subdirectory' '
(
cd sub 
-   git difftool --dir-diff --extcmd ls branch output 
+   git difftool --dir-diff $symlinks --extcmd ls branch output 
grep sub output 
grep file output
)
-- 
1.8.2.411.g65a544e

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 4/6] dir.c::match_pathname(): pay attention to the length of string parameters

2013-03-29 Thread Torsten Bögershausen
On 29.03.13 11:03, Duy Nguyen wrote:
 On Fri, Mar 29, 2013 at 3:45 PM, Duy Nguyen pclo...@gmail.com wrote:
 On Fri, Mar 29, 2013 at 4:48 AM, Jeff King p...@peff.net wrote:
 -   return fnmatch_icase(pattern, name, FNM_PATHNAME) == 0;
 +   return fnmatch_icase_mem(pattern, patternlen,
 +name, namelen,
 +FNM_PATHNAME) == 0;
  }

 I think you (or Junio) should rebase this on maint. Since c41244e
 (included in maint), this call is turned to wildmatch(WM_PATHNAME) and
 WM_PATHNAME is _not_ the same as FNM_PATHNAME for patterns like
 foo/**/bar. A diff between next and pu shows me that WM_PATHNAME is
 incorrectly converted to FNM_PATHNAME. I hope that is the cause of all
 breakages Junio found out on pu.
 
 Just tested. t0003 and t3001 on 'pu' work for me because I have
 USE_WILDMATCH on (which turns FNM_PATHNAME to WM_PATHNAME). Both break
 without USE_WILDMATCH.
 
Hm, tested what?

diff --git a/dir.c b/dir.c
index 73a08af..0b63167 100644
--- a/dir.c
+++ b/dir.c
@@ -564,7 +564,7 @@ int match_pathname(const char *pathname, int pathlen,
 
return fnmatch_icase_mem(pattern, patternlen,
 name, namelen,
-FNM_PATHNAME) == 0;
+WM_PATHNAME) == 0;
 }
 
Gives only one breakage, so we are coming closer.


*** t3001-ls-files-others-exclude.sh ***
[snip]
not ok 17 - ls-files with ** patterns



--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 4/6] dir.c::match_pathname(): pay attention to the length of string parameters

2013-03-29 Thread Duy Nguyen
On Fri, Mar 29, 2013 at 6:32 PM, Torsten Bögershausen tbo...@web.de wrote:
 Just tested. t0003 and t3001 on 'pu' work for me because I have
 USE_WILDMATCH on (which turns FNM_PATHNAME to WM_PATHNAME). Both break
 without USE_WILDMATCH.

 Hm, tested what?

Tested t0003 and t3001 with and without USE_WILDMATCH, which is pretty
much like you patch, except that wildmatch is used instead of fnmatch.

 diff --git a/dir.c b/dir.c
 index 73a08af..0b63167 100644
 --- a/dir.c
 +++ b/dir.c
 @@ -564,7 +564,7 @@ int match_pathname(const char *pathname, int pathlen,

 return fnmatch_icase_mem(pattern, patternlen,
  name, namelen,
 -FNM_PATHNAME) == 0;
 +WM_PATHNAME) == 0;
  }

 Gives only one breakage, so we are coming closer.


 *** t3001-ls-files-others-exclude.sh ***
 [snip]
 not ok 17 - ls-files with ** patterns






-- 
Duy
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 4/6] dir.c::match_pathname(): pay attention to the length of string parameters

2013-03-29 Thread Jeff King
On Fri, Mar 29, 2013 at 03:45:35PM +0700, Nguyen Thai Ngoc Duy wrote:

 On Fri, Mar 29, 2013 at 4:48 AM, Jeff King p...@peff.net wrote:
  -   return fnmatch_icase(pattern, name, FNM_PATHNAME) == 0;
  +   return fnmatch_icase_mem(pattern, patternlen,
  +name, namelen,
  +FNM_PATHNAME) == 0;
   }
 
 I think you (or Junio) should rebase this on maint. Since c41244e
 (included in maint), this call is turned to wildmatch(WM_PATHNAME) and
 WM_PATHNAME is _not_ the same as FNM_PATHNAME for patterns like
 foo/**/bar. A diff between next and pu shows me that WM_PATHNAME is
 incorrectly converted to FNM_PATHNAME. I hope that is the cause of all
 breakages Junio found out on pu.

I don't think we want to rebase; the regression is in the v1.8.1 series,
and I suspected that Junio was planning to ship a v1.8.1.6 with the fix.
The wildmatch code comes in v1.8.2.

So we would want to do any adjustment to the fix when we merge up to
maint.

-Peff
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 4/6] dir.c::match_pathname(): pay attention to the length of string parameters

2013-03-29 Thread Duy Nguyen
On Fri, Mar 29, 2013 at 08:05:40AM -0400, Jeff King wrote:
 On Fri, Mar 29, 2013 at 03:45:35PM +0700, Nguyen Thai Ngoc Duy wrote:
 
  On Fri, Mar 29, 2013 at 4:48 AM, Jeff King p...@peff.net wrote:
   -   return fnmatch_icase(pattern, name, FNM_PATHNAME) == 0;
   +   return fnmatch_icase_mem(pattern, patternlen,
   +name, namelen,
   +FNM_PATHNAME) == 0;
}
  
  I think you (or Junio) should rebase this on maint. Since c41244e
  (included in maint), this call is turned to wildmatch(WM_PATHNAME) and
  WM_PATHNAME is _not_ the same as FNM_PATHNAME for patterns like
  foo/**/bar. A diff between next and pu shows me that WM_PATHNAME is
  incorrectly converted to FNM_PATHNAME. I hope that is the cause of all
  breakages Junio found out on pu.
 
 I don't think we want to rebase; the regression is in the v1.8.1 series,
 and I suspected that Junio was planning to ship a v1.8.1.6 with the fix.
 The wildmatch code comes in v1.8.2.
 
 So we would want to do any adjustment to the fix when we merge up to
 maint.

OK. Then Junio, you may need to resolve the conflict with something
like this. Originally match_basename uses fnmatch, not wildmatch. But
using wildmatch there too should be fine, now that both
match_{base,path}name share fnmatch_icase_mem().

-- 8 --
diff --git a/dir.c b/dir.c
index 73a08af..84744df 100644
--- a/dir.c
+++ b/dir.c
@@ -81,7 +81,9 @@ static int fnmatch_icase_mem(const char *pattern, int 
patternlen,
use_str = str_buf.buf;
}
 
-   match_status = fnmatch_icase(use_pat, use_str, flags);
+   if (ignore_case)
+   flags |= WM_CASEFOLD;
+   match_status = wildmatch(use_pat, use_str, flags, NULL);
 
strbuf_release(pat_buf);
strbuf_release(str_buf);
@@ -564,7 +566,7 @@ int match_pathname(const char *pathname, int pathlen,
 
return fnmatch_icase_mem(pattern, patternlen,
 name, namelen,
-FNM_PATHNAME) == 0;
+WM_PATHNAME) == 0;
 }
 
 /*
-- 8 --
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] rev-list: preallocate object hash table in --all --objects

2013-03-29 Thread Nguyễn Thái Ngọc Duy
Every time the object hash table grows, all entries must be
rearranged. The few last times could be really expensive when the
table contains a lot of entries.

When we do --all --objects we know in advance we may need to hash
all objects. Just prepare the hash table big enough, so there won't be
any resizing later on. The hash table is resized a couple times before
prehash_objects() is called. But that's ok because there aren't many
objects by that time (unless you have tons of refs, likely tags..)

On linux-2.6.git:

before   after
real0m34.402s0m33.288s
user0m34.111s0m32.863s
sys 0m0.205s 0m0.352s

Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
 object.c   | 21 +++--
 object.h   |  2 ++
 revision.c | 59 +++
 3 files changed, 76 insertions(+), 6 deletions(-)

diff --git a/object.c b/object.c
index 20703f5..bcfd2c6 100644
--- a/object.c
+++ b/object.c
@@ -88,10 +88,10 @@ struct object *lookup_object(const unsigned char *sha1)
return obj;
 }
 
-static void grow_object_hash(void)
+void grow_object_hash_to(unsigned long nr)
 {
int i;
-   int new_hash_size = obj_hash_size  32 ? 32 : 2 * obj_hash_size;
+   int new_hash_size = nr  32 ? 32 : nr * 2;
struct object **new_hash;
 
new_hash = xcalloc(new_hash_size, sizeof(struct object *));
@@ -106,6 +106,11 @@ static void grow_object_hash(void)
obj_hash_size = new_hash_size;
 }
 
+static void grow_object_hash(void)
+{
+   grow_object_hash_to(obj_hash_size);
+}
+
 void *create_object(const unsigned char *sha1, int type, void *o)
 {
struct object *obj = o;
@@ -307,3 +312,15 @@ void clear_object_flags(unsigned flags)
obj-flags = ~flags;
}
 }
+
+int has_object_flags(unsigned flags)
+{
+   int i;
+
+   for (i = 0; i  obj_hash_size; i++) {
+   struct object *obj = obj_hash[i];
+   if (obj  (obj-flags  flags))
+   return 1;
+   }
+   return 0;
+}
diff --git a/object.h b/object.h
index 97d384b..1e8fee8 100644
--- a/object.h
+++ b/object.h
@@ -52,6 +52,7 @@ extern struct object *get_indexed_object(unsigned int);
  */
 struct object *lookup_object(const unsigned char *sha1);
 
+extern void grow_object_hash_to(unsigned long nr);
 extern void *create_object(const unsigned char *sha1, int type, void *obj);
 
 /*
@@ -87,6 +88,7 @@ void add_object_array(struct object *obj, const char *name, 
struct object_array
 void add_object_array_with_mode(struct object *obj, const char *name, struct 
object_array *array, unsigned mode);
 void object_array_remove_duplicates(struct object_array *);
 
+int has_object_flags(unsigned flags);
 void clear_object_flags(unsigned flags);
 
 #endif /* OBJECT_H */
diff --git a/revision.c b/revision.c
index 71e62d8..f9ea2d1 100644
--- a/revision.c
+++ b/revision.c
@@ -1665,8 +1665,9 @@ static int for_each_good_bisect_ref(const char 
*submodule, each_ref_fn fn, void
 }
 
 static int handle_revision_pseudo_opt(const char *submodule,
-   struct rev_info *revs,
-   int argc, const char **argv, int *flags)
+ struct rev_info *revs,
+ int argc, const char **argv,
+ int *flags, int *all)
 {
const char *arg = argv[0];
const char *optarg;
@@ -1685,6 +1686,7 @@ static int handle_revision_pseudo_opt(const char 
*submodule,
if (!strcmp(arg, --all)) {
handle_refs(submodule, revs, *flags, for_each_ref_submodule);
handle_refs(submodule, revs, *flags, head_ref_submodule);
+   *all = 1;
} else if (!strcmp(arg, --branches)) {
handle_refs(submodule, revs, *flags, 
for_each_branch_ref_submodule);
} else if (!strcmp(arg, --bisect)) {
@@ -1738,6 +1740,49 @@ static int handle_revision_pseudo_opt(const char 
*submodule,
return 1;
 }
 
+static void preallocate_hash_table(void)
+{
+   unsigned long cnt = 0;
+   struct packed_git *p;
+   int i;
+
+   if (has_object_flags(UNINTERESTING))
+   /*
+* nope this is not simply --all --objects
+* not worth preallocation.
+*/
+   return;
+
+   for (i = 0; i  256; i++) {
+   struct dirent *ent;
+   DIR *d = opendir(git_path(objects/%02x, i));
+   if (!d)
+   continue;
+   while ((ent = readdir(d)) != NULL)
+   /*
+* We only worry about insufficient size which
+* leads to expensive growths later on. A few
+* extra slots in the hash table would not hurt.
+*/
+   cnt++;
+   closedir(d);
+   }
+
+   if 

[Toy PATCH] Avoid spilling collided entries in object hash table to the next slots

2013-03-29 Thread Nguyễn Thái Ngọc Duy
If a position in object hash table is taken, we currently check out
the next one. This could potentially create long object chains. We
could create linked lists instead and leave the next slot alone.

This patch relies on the fact that pointers are usually aligned more
than one byte and it uses the first bit as object vs linked list
indicator. Architectures that don't support this can fall back to
original implementation.

The saving is real, although not ground breaking. I'm just not sure it
is worth the ugliness that comes with this patch. Although we could
avoid the alignment problem by saving that bit in a separate bitmap.
git rev-list --objects --all on linux-2.6.git:

before   after
real0m33.407s0m31.732s
user0m32.926s0m31.460s
sys 0m0.407s 0m0.202s

lookup_object() goes down from 30% to 27% in perf reports.

Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
 object.c | 42 ++
 1 file changed, 42 insertions(+)

diff --git a/object.c b/object.c
index bcfd2c6..7b013a0 100644
--- a/object.c
+++ b/object.c
@@ -8,6 +8,17 @@
 static struct object **obj_hash;
 static int nr_objs, obj_hash_size;
 
+#ifdef USE_LINKED_LIST
+struct obj_list {
+   struct object *obj;
+   struct obj_list *next;
+};
+
+#define IS_LST(x) ((intptr_t)(x)  1)
+#define MAKE_LST(x) (struct object *)((intptr_t)(x) | 1)
+#define GET_LST(x) (struct obj_list *)((intptr_t)(x)  ~1)
+#endif
+
 unsigned int get_max_object_index(void)
 {
return obj_hash_size;
@@ -53,13 +64,30 @@ static unsigned int hash_obj(struct object *obj, unsigned 
int n)
 static void insert_obj_hash(struct object *obj, struct object **hash, unsigned 
int size)
 {
unsigned int j = hash_obj(obj, size);
+#ifdef USE_LINKED_LIST
+   struct obj_list *lst, *o;
+
+   if (!hash[j]) {
+   hash[j] = obj;
+   return;
+   }
 
+   o = xmalloc(sizeof(*o));
+   o-obj = obj;
+
+   if (IS_LST(hash[j]))
+   o-next = GET_LST(hash[j]);
+   else
+   o-next = NULL;
+   hash[j] = MAKE_LST(o);
+#else
while (hash[j]) {
j++;
if (j = size)
j = 0;
}
hash[j] = obj;
+#endif
 }
 
 static unsigned int hashtable_index(const unsigned char *sha1)
@@ -78,6 +106,19 @@ struct object *lookup_object(const unsigned char *sha1)
return NULL;
 
i = hashtable_index(sha1);
+#ifdef USE_LINKED_LIST
+   if (IS_LST(obj_hash[i])) {
+   struct obj_list *lst;
+   for (lst = GET_LST(obj_hash[i]); lst; lst = lst-next) {
+   if (!hashcmp(lst-obj-sha1, sha1))
+   return lst-obj;
+   }
+   return NULL;
+   } else {
+   struct object *obj = obj_hash[i];
+   return obj  !hashcmp(sha1, obj-sha1) ? obj : NULL;
+   }
+#else
while ((obj = obj_hash[i]) != NULL) {
if (!hashcmp(sha1, obj-sha1))
break;
@@ -86,6 +127,7 @@ struct object *lookup_object(const unsigned char *sha1)
i = 0;
}
return obj;
+#endif
 }
 
 void grow_object_hash_to(unsigned long nr)
-- 
1.8.2.83.gc99314b

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] rev-list: preallocate object hash table in --all --objects

2013-03-29 Thread Jeff King
On Fri, Mar 29, 2013 at 08:20:10PM +0700, Nguyen Thai Ngoc Duy wrote:

 Every time the object hash table grows, all entries must be
 rearranged. The few last times could be really expensive when the
 table contains a lot of entries.
 
 When we do --all --objects we know in advance we may need to hash
 all objects. Just prepare the hash table big enough, so there won't be
 any resizing later on. The hash table is resized a couple times before
 prehash_objects() is called. But that's ok because there aren't many
 objects by that time (unless you have tons of refs, likely tags..)
 
 On linux-2.6.git:
 
 before   after
 real0m34.402s0m33.288s
 user0m34.111s0m32.863s
 sys 0m0.205s 0m0.352s

This feels weirdly specific, and like we should just be tuning our hash
table growth better. You show a 3.2% speedup here. I was able to get a
2.8% speedup just by doing this:

diff --git a/object.c b/object.c
index 20703f5..8e5e12c 100644
--- a/object.c
+++ b/object.c
@@ -91,7 +91,7 @@ static void grow_object_hash(void)
 static void grow_object_hash(void)
 {
int i;
-   int new_hash_size = obj_hash_size  32 ? 32 : 2 * obj_hash_size;
+   int new_hash_size = obj_hash_size  32 ? 32 : 3 * obj_hash_size;
struct object **new_hash;
 
new_hash = xcalloc(new_hash_size, sizeof(struct object *));

It might be worth trying to figure out what the optimium growth rate is
first, which would help this use case and others. With less fragile
code.

-Peff
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] rev-list: preallocate object hash table in --all --objects

2013-03-29 Thread Duy Nguyen
On Fri, Mar 29, 2013 at 10:12 PM, Jeff King p...@peff.net wrote:
 This feels weirdly specific, and like we should just be tuning our hash
 table growth better. You show a 3.2% speedup here. I was able to get a
 2.8% speedup just by doing this:

It also uses a lot more memory. 5.8m entries for .. * 2 and 8.8m for
... * 3. Probably no big deal for modern machines..

 It might be worth trying to figure out what the optimium growth rate is
 first, which would help this use case and others. With less fragile
 code.

Agreed. Although I think it's getting out of my domain. I'm not even
sure how many factors are involved.
-- 
Duy
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] cherry-pick -x: improve handling of one-liner commit messages

2013-03-29 Thread Miklos Vajna
git cherry-pick -x normally just appends the cherry picked from commit
line at the end of the message, which is fine. However, in case the
original commit message had only one line, first append a newline,
otherwise the second line won't be empty, which is against
recommendations.
---
 sequencer.c   | 10 ++
 t/t3501-revert-cherry-pick.sh |  8 
 2 files changed, 18 insertions(+)

diff --git a/sequencer.c b/sequencer.c
index aef5e8a..1ae0e43 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -496,6 +496,16 @@ static int do_pick_commit(struct commit *commit, struct 
replay_opts *opts)
}
 
if (opts-record_origin) {
+
+   /*
+* If this the message is a one-liner, append a
+* newline, so the second line will be empty, as
+* recommended.
+*/
+   p = strstr(msgbuf.buf, \n\n);
+   if (!p)
+   strbuf_addch(msgbuf, '\n');
+
strbuf_addstr(msgbuf, (cherry picked from commit );
strbuf_addstr(msgbuf, 
sha1_to_hex(commit-object.sha1));
strbuf_addstr(msgbuf, )\n);
diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh
index 6f489e2..858c744 100755
--- a/t/t3501-revert-cherry-pick.sh
+++ b/t/t3501-revert-cherry-pick.sh
@@ -70,6 +70,14 @@ test_expect_success 'cherry-pick after renaming branch' '
 
 '
 
+test_expect_success 'cherry-pick -x of one-liner commit message' '
+
+   git checkout rename2 
+   git cherry-pick -x added 
+   git show -s --pretty=format:%s | test_must_fail grep cherry picked
+
+'
+
 test_expect_success 'revert after renaming branch' '
 
git checkout rename1 
-- 
1.8.1.4

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] rev-list: preallocate object hash table in --all --objects

2013-03-29 Thread Junio C Hamano
Jeff King p...@peff.net writes:

 This feels weirdly specific, and like we should just be tuning our hash
 table growth better. You show a 3.2% speedup here. I was able to get a
 2.8% speedup just by doing this:

 diff --git a/object.c b/object.c
 index 20703f5..8e5e12c 100644
 --- a/object.c
 +++ b/object.c
 @@ -91,7 +91,7 @@ static void grow_object_hash(void)
  static void grow_object_hash(void)
  {
   int i;
 - int new_hash_size = obj_hash_size  32 ? 32 : 2 * obj_hash_size;
 + int new_hash_size = obj_hash_size  32 ? 32 : 3 * obj_hash_size;
   struct object **new_hash;
  
   new_hash = xcalloc(new_hash_size, sizeof(struct object *));

 It might be worth trying to figure out what the optimium growth rate is
 first, which would help this use case and others. With less fragile
 code.

I agree with the general principle to avoid heuristics that is too
specific to the use case.  Thanks.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 4/6] dir.c::match_pathname(): pay attention to the length of string parameters

2013-03-29 Thread Junio C Hamano
Duy Nguyen pclo...@gmail.com writes:

 So we would want to do any adjustment to the fix when we merge up to
 maint.

 OK. Then Junio, you may need to resolve the conflict with something
 like this. Originally match_basename uses fnmatch, not wildmatch. But
 using wildmatch there too should be fine, now that both
 match_{base,path}name share fnmatch_icase_mem().

Thanks.

The result still smells somewhat funny, though.

fnmatch_icase_mem() is meant to be a wrapper of fnmatch_icase() for
counted strings and its matching semantics should be the same as
fnmatch_icase().

With the merge-fix, fnmatch_icase_mem() calls into wildmatch(), but
fnmatch_icase() still calls into fnmatch().

The latter's flags are meant to be taken from FNM_* family, but the
former takes flags from WM_* family of bits, no?

I think you are running with USE_WILDMATCH which may make the
differences harder to notice, but the name fnmatch_icase_mem() that
is not in the same family as fnmatch but is from the wildmatch()
family smells like an accident waiting to happen.

I tend to think in the longer term it may be a good idea to build
with USE_WILDMATCH unconditionally (we can lose compat/fnmatch), so
in the end this may not matter that much, but before that happens,
soon after we merge the regression fix with this merge-fix, we may
want to update the codebase as if we applied a series that were
based on 'maint' as you suggested, i.e. using raw wildmatch()
consistently in the match_{base,path}name() codepath.

Opinions?


 -- 8 --
 diff --git a/dir.c b/dir.c
 index 73a08af..84744df 100644
 --- a/dir.c
 +++ b/dir.c
 @@ -81,7 +81,9 @@ static int fnmatch_icase_mem(const char *pattern, int 
 patternlen,
   use_str = str_buf.buf;
   }
  
 - match_status = fnmatch_icase(use_pat, use_str, flags);
 + if (ignore_case)
 + flags |= WM_CASEFOLD;
 + match_status = wildmatch(use_pat, use_str, flags, NULL);
  
   strbuf_release(pat_buf);
   strbuf_release(str_buf);
 @@ -564,7 +566,7 @@ int match_pathname(const char *pathname, int pathlen,
  
   return fnmatch_icase_mem(pattern, patternlen,
name, namelen,
 -  FNM_PATHNAME) == 0;
 +  WM_PATHNAME) == 0;
  }
  
  /*
 -- 8 --
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Minor bug in git branch --set-upstream-to adding superfluous branch section to config

2013-03-29 Thread Jeff King
On Fri, Mar 29, 2013 at 09:29:14AM -0700, Phil Haack wrote:

 If you run the following set of commands:
 
 git checkout -b some-branch
 git push origin some-branch
 git branch --set-upstream-to origin/some-branch
 git branch --unset-upstream some-branch
 git branch --set-upstream-to origin/some-branch
 
 You get the following result in the .git\config file
 
 [branch some-branch]
 [branch some-branch]
 remote = origin
 merge = refs/heads/some-branch
 
 My expectation is that the very last call to: git branch --set-upstream-to
 would not add a new config section, but would instead insert this information
 into the existing [branch some-branch].

Yes, this is a known issue[1] in the config-editing code. There are
actually two separate problems. Try this:

  $ git config -f foo section.one 1
  $ cat foo
  [section]
  one = 1

Looking good so far...

  $ git config -f foo --unset section.one
  $ cat foo
  [section]

Oops, it would have been nice to clean up that now-empty section. Now
let's re-add...

  $ git config -f foo section.two 2
  $ cat foo
  [section]
  [section]
  two = 2

Oops, it would have been nice to use the existing section. What happens
if we add again...

  $ git config -f foo section.three 3
  $ cat foo
  [section]
  [section]
  two = 2
  three = 3

Now that one worked. I think what happens is that the config editor runs
through the files linearly, munging whatever lines necessary for the
requested operation, and leaving everything else untouched (as it must,
to leave comments and whitespace intact). But it does not keep a
look-behind buffer to realize that a section name is now obsolete (which
we don't know until we get to the next section, or to EOF). In the worst
case, this buffer can grow arbitrarily large, like:

  [foo]
  # the above section is now empty
  # but we have to read through all of
  # these comments to actually
  # realize it
  [bar]

In practice it should not be a big deal (and I do not think it is an
interesting attack vector for somebody trying to run you out of memory).

That brings up another point, which is that comments may get misplaced
by deletion. But that's the case for any modification we do to the file,
since we cannot understand the semantics of comments that say things
like the line below does X.

So that's the first bug. The second one is, I suspect, just laziness. We
notice that section.two is set, and put section.three after it. But we
do not make the same trigger for just section. That's probably much
easier to fix.

 In any case, from what I understand the current behavior is technically valid
 and I haven't encountered any adverse effects. It was just something I noticed
 while testing.

Yes, the config files generated by these operations parse as you would
expect them to. I think it's purely an aesthetic concern.

-Peff

[1] http://thread.gmane.org/gmane.comp.version-control.git/208113
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 4/6] dir.c::match_pathname(): pay attention to the length of string parameters

2013-03-29 Thread Jeff King
On Fri, Mar 29, 2013 at 09:44:32AM -0700, Junio C Hamano wrote:

 Duy Nguyen pclo...@gmail.com writes:
 
  So we would want to do any adjustment to the fix when we merge up to
  maint.
 
  OK. Then Junio, you may need to resolve the conflict with something
  like this. Originally match_basename uses fnmatch, not wildmatch. But
  using wildmatch there too should be fine, now that both
  match_{base,path}name share fnmatch_icase_mem().
 
 Thanks.
 
 The result still smells somewhat funny, though.
 
 fnmatch_icase_mem() is meant to be a wrapper of fnmatch_icase() for
 counted strings and its matching semantics should be the same as
 fnmatch_icase().
 
 With the merge-fix, fnmatch_icase_mem() calls into wildmatch(), but
 fnmatch_icase() still calls into fnmatch().
 
 The latter's flags are meant to be taken from FNM_* family, but the
 former takes flags from WM_* family of bits, no?

Yeah, that does not seem right. If match_pathname has learned to call
into wildmatch instead of fnmatch_icase in the interim, then the right
resolution is to convert its call to fnmatch_icase_mem to a new
wildmatch_mem.  Presumably that can be done by either tweaking
fnmatch_icase_mem, or, if wildmatch is ready to take counted strings,
calling into it with the right options.

 I think you are running with USE_WILDMATCH which may make the
 differences harder to notice, but the name fnmatch_icase_mem() that is
 not in the same family as fnmatch but is from the wildmatch() family
 smells like an accident waiting to happen.

Agreed.

 I tend to think in the longer term it may be a good idea to build with
 USE_WILDMATCH unconditionally (we can lose compat/fnmatch), so in the
 end this may not matter that much

Yeah, I think that is a sane long-term goal.

-Peff
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [Toy PATCH] Avoid spilling collided entries in object hash table to the next slots

2013-03-29 Thread Junio C Hamano
Nguyễn Thái Ngọc Duy  pclo...@gmail.com writes:

 If a position in object hash table is taken, we currently check out
 the next one. This could potentially create long object chains. We
 could create linked lists instead and leave the next slot alone.

In the current code, not just the logic in lookup_object(), but the
logic to enforce load factor when create_object() decides to call
grow_object_hash() and object enumeration implemented by
get_max_object_index() and get_indexed_object() are closely tied to
the open addressing scheme.  If you want to switch to any other
method (e.g. separate chaining) these need to be updated quite a
bit.

I do not see get_max_object_index() and get_indexed_object() updated
at all.  Do fsck, index-pack, name-rev and upload-pack still work?

This particular implementation that uses a fake union is a bit
ugly, but in general, it may be worth rethinking the object hash
implementation.  I vaguely recall trying cuckoo in the vicinity of
this code.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Minor bug in git branch --set-upstream-to adding superfluous branch section to config

2013-03-29 Thread Thomas Rast
Jeff King p...@peff.net writes:

 I think what happens is that the config editor runs
 through the files linearly, munging whatever lines necessary for the
 requested operation, and leaving everything else untouched (as it must,
 to leave comments and whitespace intact). But it does not keep a
 look-behind buffer to realize that a section name is now obsolete (which
 we don't know until we get to the next section, or to EOF). In the worst
 case, this buffer can grow arbitrarily large, like:

   [foo]
   # the above section is now empty
   # but we have to read through all of
   # these comments to actually
   # realize it
   [bar]

If we treat this case as having a bunch of comments that make the
section non-empty, then we both avoid needing an arbitrarily large
lookbehind and deleting the user's precious comments...

I.e. the rule would be that we only delete the section if there is
nothing but whitespace until the next section header.

-- 
Thomas Rast
trast@{inf,student}.ethz.ch
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Minor bug in git branch --set-upstream-to adding superfluous branch section to config

2013-03-29 Thread Jeff King
On Fri, Mar 29, 2013 at 06:20:28PM +0100, Thomas Rast wrote:

 Jeff King p...@peff.net writes:
 
  I think what happens is that the config editor runs
  through the files linearly, munging whatever lines necessary for the
  requested operation, and leaving everything else untouched (as it must,
  to leave comments and whitespace intact). But it does not keep a
  look-behind buffer to realize that a section name is now obsolete (which
  we don't know until we get to the next section, or to EOF). In the worst
  case, this buffer can grow arbitrarily large, like:
 
[foo]
# the above section is now empty
# but we have to read through all of
# these comments to actually
# realize it
[bar]
 
 If we treat this case as having a bunch of comments that make the
 section non-empty, then we both avoid needing an arbitrarily large
 lookbehind and deleting the user's precious comments...
 
 I.e. the rule would be that we only delete the section if there is
 nothing but whitespace until the next section header.

I think that is sane. Technically it does not remove the need for the
buffer, unless we are also collapsing whitespace (which I think is
probably a sane thing to do, too). I'm looking at a patch now...

-Peff
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] cherry-pick -x: improve handling of one-liner commit messages

2013-03-29 Thread Junio C Hamano
Miklos Vajna vmik...@suse.cz writes:

 git cherry-pick -x normally just appends the cherry picked from commit
 line at the end of the message, which is fine. However, in case the
 original commit message had only one line, first append a newline,
 otherwise the second line won't be empty, which is against
 recommendations.
 ---

Sign-off?

I think this is part of the bc/append-signed-off-by topic that is
about to graduate to 'master'; more specifically, b971e04f54e7
(sequencer.c: always separate (cherry picked from from commit
body, 2013-02-12) does the equivalent, no?

  sequencer.c   | 10 ++
  t/t3501-revert-cherry-pick.sh |  8 
  2 files changed, 18 insertions(+)

 diff --git a/sequencer.c b/sequencer.c
 index aef5e8a..1ae0e43 100644
 --- a/sequencer.c
 +++ b/sequencer.c
 @@ -496,6 +496,16 @@ static int do_pick_commit(struct commit *commit, struct 
 replay_opts *opts)
   }
  
   if (opts-record_origin) {
 +
 + /*
 +  * If this the message is a one-liner, append a
 +  * newline, so the second line will be empty, as
 +  * recommended.
 +  */
 + p = strstr(msgbuf.buf, \n\n);
 + if (!p)
 + strbuf_addch(msgbuf, '\n');
 +
   strbuf_addstr(msgbuf, (cherry picked from commit );
   strbuf_addstr(msgbuf, 
 sha1_to_hex(commit-object.sha1));
   strbuf_addstr(msgbuf, )\n);
 diff --git a/t/t3501-revert-cherry-pick.sh b/t/t3501-revert-cherry-pick.sh
 index 6f489e2..858c744 100755
 --- a/t/t3501-revert-cherry-pick.sh
 +++ b/t/t3501-revert-cherry-pick.sh
 @@ -70,6 +70,14 @@ test_expect_success 'cherry-pick after renaming branch' '
  
  '
  
 +test_expect_success 'cherry-pick -x of one-liner commit message' '
 +
 + git checkout rename2 
 + git cherry-pick -x added 
 + git show -s --pretty=format:%s | test_must_fail grep cherry picked
 +
 +'
 +
  test_expect_success 'revert after renaming branch' '
  
   git checkout rename1 
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Minor bug in git branch --set-upstream-to adding superfluous branch section to config

2013-03-29 Thread Junio C Hamano
Phil Haack haac...@gmail.com writes:

 Hello there! Please /cc me with responses as I'm not on the mailing list.

 I'm using git version 1.8.1.msysgit.1 and I ran into a very minor issue. It
 doesn't actually seem to affect operations, but I thought I'd report it in 
 case
 someone felt it was worth cleaning up.

I do not think this is limited to branch --set-whatever.

 If you run the following set of commands:

 git checkout -b some-branch
 git push origin some-branch
 git branch --set-upstream-to origin/some-branch
 git branch --unset-upstream some-branch

This step causes the removal of the last variable in a configuration
section, which leaves an empty section.  As the code to add a new
variable to the configuration, trying to reuse an existing section
header, does not pay attention to an empty section, you end up with
an empty section, followed by a new one.

Either removal of configuration variable should be taught to remove
the section header when a section becomes empty, or addition of
configuration variable should be taught to notice an empty section
header.



 git branch --set-upstream-to origin/some-branch

 You get the following result in the .git\config file

 [branch some-branch]
 [branch some-branch]
 remote = origin
 merge = refs/heads/some-branch
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 4/6] dir.c::match_pathname(): pay attention to the length of string parameters

2013-03-29 Thread Junio C Hamano
Jeff King p...@peff.net writes:

 On Fri, Mar 29, 2013 at 09:44:32AM -0700, Junio C Hamano wrote:
 ...
 With the merge-fix, fnmatch_icase_mem() calls into wildmatch(), but
 fnmatch_icase() still calls into fnmatch().
 
 The latter's flags are meant to be taken from FNM_* family, but the
 former takes flags from WM_* family of bits, no?

 Yeah, that does not seem right. If match_pathname has learned to call
 into wildmatch instead of fnmatch_icase in the interim, then the right
 resolution is to convert its call to fnmatch_icase_mem to a new
 wildmatch_mem.  Presumably that can be done by either tweaking
 fnmatch_icase_mem, or, if wildmatch is ready to take counted strings,
 calling into it with the right options.

 I think you are running with USE_WILDMATCH which may make the
 differences harder to notice, but the name fnmatch_icase_mem() that is
 not in the same family as fnmatch but is from the wildmatch() family
 smells like an accident waiting to happen.

 Agreed.

This may be just the matter of naming.

It smelled wrong to me only because the fnmatch in the helper
fnmatch_icase_mem() told me that it should forever use fnmatch
semantics.  After reading its (only) two callsites, they are both
the caller has transformed the inputs to this lowest level pathname
vs pattern matching function in order to reduce the cost of
matching, and now it is time to exercise the matcher.  The only
thing they care about is that they are calling the lowest level
pathname vs pattern matching function.

If we pronounce fnmatch_icase_mem() as match_path_with_pattern()
or something in the original series, the problem may go away ;-)

Does any caller pass FNM_* bits to a callchain that reach the new *_mem()
function?
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 4/6] dir.c::match_pathname(): pay attention to the length of string parameters

2013-03-29 Thread Jeff King
On Fri, Mar 29, 2013 at 10:35:17AM -0700, Junio C Hamano wrote:

 This may be just the matter of naming.
 
 It smelled wrong to me only because the fnmatch in the helper
 fnmatch_icase_mem() told me that it should forever use fnmatch
 semantics.  After reading its (only) two callsites, they are both
 the caller has transformed the inputs to this lowest level pathname
 vs pattern matching function in order to reduce the cost of
 matching, and now it is time to exercise the matcher.  The only
 thing they care about is that they are calling the lowest level
 pathname vs pattern matching function.
 
 If we pronounce fnmatch_icase_mem() as match_path_with_pattern()
 or something in the original series, the problem may go away ;-)

Yes, since there are only the two new added callers, if they both want
to switch to wildmatch, then it is fine for the helper function to
switch. The danger is if some other caller wants to start using it; I
added it with the name I did figuring that other spots might want to use
it eventually. But if all of fnmatch is going to go away in favor of
wildmatch eventually, then that helper is not all that useful (or it
would be even more useful as wildmatch_mem or similar).

 Does any caller pass FNM_* bits to a callchain that reach the new *_mem()
 function?

The series only adds two callers, and they provide constant flags;
match_basename passes no flags, and should be OK. match_pathname uses
FNM_PATHNAME, and would need to be converted to use WM_PATHNAME as part
of the conflict resolution.

-Peff
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


gitdiffbinstat - git diff --shortstat -like output for changes in binary files

2013-03-29 Thread Matthias Krüger
I use git mostly for game-development which means I have to deal with a 
lot of binary files (images, sound files etc).


When I came to a point where I had run image optimization on a branch, I 
wanted to know of course how much smaller the new branch was in 
comparison to master.
Problem was that 'git diff --stat' would only summerize per-binary-file 
size changes and 'git diff --shortstat' did skip the binary files entirely.


To solve this problem, I wrote a script (gitdiffbinstat) which 
basically runs 'git diff --stat' and summerizes the output.


The script can be found here: 
https://github.com/matthiaskrgr/gitdiffbinstat/blob/master/gitdiffbinstat.sh

Screenshot of example output is attached.

I wondered what you guys thought about the script, is there a chance to 
perhaps get it included as some kind of helper script into the official 
git repo?



Regards, Matthias
attachment: screenshot.png

Re: [Toy PATCH] Avoid spilling collided entries in object hash table to the next slots

2013-03-29 Thread Junio C Hamano
Junio C Hamano gits...@pobox.com writes:

 Nguyễn Thái Ngọc Duy  pclo...@gmail.com writes:

 If a position in object hash table is taken, we currently check out
 the next one. This could potentially create long object chains. We
 could create linked lists instead and leave the next slot alone.

 In the current code, not just the logic in lookup_object(), but the
 logic to enforce load factor when create_object() decides to call
 grow_object_hash() and object enumeration implemented by
 get_max_object_index() and get_indexed_object() are closely tied to
 the open addressing scheme.  If you want to switch to any other
 method (e.g. separate chaining) these need to be updated quite a
 bit.

 I do not see get_max_object_index() and get_indexed_object() updated
 at all.  Do fsck, index-pack, name-rev and upload-pack still work?

You may want to start with a bit more abstraction around the
hashtable API.  Perhaps like this?

The idea is to let your object enumerator to be not just a simple
unsigned int into the flat hashtable, but be something like

typedef struct {
unsigned int slot;
struct obj_list *list;
} object_enumerator;

You store the current index in obj_hash[] to enu.slot, and if that
is IS_LST(), the linked-list element you are looking at in enu.list.
When you increment the iterator in object_enumerator_next(), you
increment enu.slot only after you reach the tail of the enu.list.



 builtin/fsck.c   | 17 ++---
 builtin/index-pack.c | 11 +++
 builtin/name-rev.c   | 20 +++-
 object.c | 22 +++---
 object.h |  8 ++--
 upload-pack.c| 23 ++-
 6 files changed, 67 insertions(+), 34 deletions(-)

diff --git a/builtin/fsck.c b/builtin/fsck.c
index bb9a2cd..5688cad 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -270,22 +270,25 @@ static void check_object(struct object *obj)
 
 static void check_connectivity(void)
 {
-   int i, max;
+   int max;
+   object_enumerator enu;
 
/* Traverse the pending reachable objects */
traverse_reachable();
 
/* Look up all the requirements, warn about missing objects.. */
-   max = get_max_object_index();
+   max = begin_object_enumeration(enu);
if (verbose)
fprintf(stderr, Checking connectivity (%d objects)\n, max);
 
-   for (i = 0; i  max; i++) {
-   struct object *obj = get_indexed_object(i);
-
-   if (obj)
-   check_object(obj);
+   if (max) {
+   do {
+   struct object *obj = get_enumerated_object(enu);
+   if (obj)
+   check_object(obj);
+   } while (object_enumeration_next(enu));
}
+   end_object_enumeration(enu);
 }
 
 static int fsck_obj(struct object *obj)
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index ef62124..1d5b65c 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -195,11 +195,14 @@ static void check_object(struct object *obj)
 
 static void check_objects(void)
 {
-   unsigned i, max;
+   object_enumerator enu;
 
-   max = get_max_object_index();
-   for (i = 0; i  max; i++)
-   check_object(get_indexed_object(i));
+   if (begin_object_enumeration(enu)) {
+   do {
+   check_object(get_enumerated_object(enu));
+   } while (object_enumeration_next(enu));
+   }
+   end_object_enumeration(enu);
 }
 
 
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 6238247..239c3ef 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -286,16 +286,18 @@ int cmd_name_rev(int argc, const char **argv, const char 
*prefix)
name_rev_line(p, data);
}
} else if (all) {
-   int i, max;
-
-   max = get_max_object_index();
-   for (i = 0; i  max; i++) {
-   struct object *obj = get_indexed_object(i);
-   if (!obj || obj-type != OBJ_COMMIT)
-   continue;
-   show_name(obj, NULL,
- always, allow_undefined, data.name_only);
+   object_enumerator enu;
+
+   if (begin_object_enumeration(enu)) {
+   do {
+   struct object *obj = 
get_enumerated_object(enu);
+   if (!obj || obj-type != OBJ_COMMIT)
+   continue;
+   show_name(obj, NULL,
+ always, allow_undefined, 
data.name_only);
+   } while (object_enumeration_next(enu));
}
+   end_object_enumeration(enu);
} else {
int i;
for (i = 0; i  revs.nr; i++)

Re: gitdiffbinstat - git diff --shortstat -like output for changes in binary files

2013-03-29 Thread Jeff King
On Fri, Mar 29, 2013 at 07:07:32PM +0100, Matthias Krüger wrote:

 I use git mostly for game-development which means I have to deal with
 a lot of binary files (images, sound files etc).
 
 When I came to a point where I had run image optimization on a
 branch, I wanted to know of course how much smaller the new branch
 was in comparison to master.
 Problem was that 'git diff --stat' would only summerize
 per-binary-file size changes and 'git diff --shortstat' did skip the
 binary files entirely.

Have you tried --summary? Combined with --stat (or --shortstat) I
wonder if it would get you closer to what you want.

-Peff
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t1300: document some aesthetic failures of the config editor

2013-03-29 Thread Junio C Hamano
Jeff King p...@peff.net writes:

 diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
 index 3c96fda..d62facb 100755
 --- a/t/t1300-repo-config.sh
 +++ b/t/t1300-repo-config.sh
 @@ -1087,4 +1087,36 @@ test_expect_success 'barf on incomplete string' '
   grep  line 3  error
  '
  
 +# good section hygiene
 +test_expect_failure 'unsetting the last key in a section removes header' '
 + cat .git/config -\EOF 
 + [section]
 + # some intervening lines
 + # that should be saved
 + key = value
 + EOF
 +
 + cat expect -\EOF 
 + # some intervening lines
 + # that should be saved
 + EOF

I do not know if I agree with this expectation.

Most likely these comments are about the section, and possibly even
are specific to section.key, not applicable to the section in
general).  If we _were_ to remove the section header at this point,
we should be removing the comment two out of three cases (if it is
about section.key, it should go when section.key goes; if it is
about section, it should go when section goes; if it is a more
generic comment about this configuration file, it should stay).

A better approach may be to only insist on the when adding, reuse
an empty section header side of the coin.  Then we do not have to
worry about we keep cruft that talks about some section but what
the comment says is illegible now the crucial bit of information,
section name the comment talks about, is gone.

 +
 + git config --unset section.key 
 + test_cmp expect .git/config
 +'
 +
 +test_expect_failure 'adding a key into an empty section reuses header' '
 + cat .git/config -\EOF 
 + [section]
 + EOF
 +
 + q_to_tab expect -\EOF 
 + [section]
 + Qkey = value
 + EOF
 +
 + git config section.key value
 + test_cmp expect .git/config
 +'

This side I would agree it is unconditionally a good thing to do.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: gitdiffbinstat - git diff --shortstat -like output for changes in binary files

2013-03-29 Thread Junio C Hamano
Jeff King p...@peff.net writes:

 I use git mostly for game-development which means I have to deal with
 a lot of binary files (images, sound files etc).
 
 When I came to a point where I had run image optimization on a
 branch, I wanted to know of course how much smaller the new branch
 was in comparison to master.
 Problem was that 'git diff --stat' would only summerize
 per-binary-file size changes and 'git diff --shortstat' did skip the
 binary files entirely.

 Have you tried --summary? Combined with --stat (or --shortstat) I
 wonder if it would get you closer to what you want.

diff is not about how much did my project grow or shink.  If you
moved one block of lines up or down in the same file, you will see
double the number of lines moved in the statistics.

On the other hand, the use case to measure how much it helped to run
png optimizers only cares about the total size.

I do not think it is a good match to present the binary stat next
to the textual diff stats in the first place.  Adding two numbers do
not give us any meaningful number.

It is an interesting use case, but it just is not a problem core
Git, which is a source code management system, particularly wants to
bolt on a solution for, that does not mesh well with other parts of
the system.

We do want to make sure that people who want to deal with binaries
have access to raw statistics, so that they can build their solution
on top of, though.  ls-tree -r -l gives byte-size of each blob,
and the attribute system can let you tell which paths are binaries.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t1300: document some aesthetic failures of the config editor

2013-03-29 Thread Jeff King
On Fri, Mar 29, 2013 at 11:51:51AM -0700, Junio C Hamano wrote:

  +   cat expect -\EOF 
  +   # some intervening lines
  +   # that should be saved
  +   EOF
 
 I do not know if I agree with this expectation.
 
 Most likely these comments are about the section, and possibly even
 are specific to section.key, not applicable to the section in
 general).  If we _were_ to remove the section header at this point,
 we should be removing the comment two out of three cases (if it is
 about section.key, it should go when section.key goes; if it is
 about section, it should go when section goes; if it is a more
 generic comment about this configuration file, it should stay).

I agree that probably makes more sense (I actually wrote the test before
responding to Thomas, and then got bogged down in the code change and
forgot to update it when I decided to give up).

 A better approach may be to only insist on the when adding, reuse
 an empty section header side of the coin.  Then we do not have to
 worry about we keep cruft that talks about some section but what
 the comment says is illegible now the crucial bit of information,
 section name the comment talks about, is gone.

I think they are two separate problems. They happen to combine to
produce the behavior that Phil reported, but I would still expect
--unset not to leave cruft. It makes sense to document to me to
document both via tests; even if we end up tweaking the expected
behavior when the fix is actually implemented, the presence of the test
still serves as a reminder of the issue.

Here it is with the updated expectation. I don't care _that_ much, so if
you feel strongly and want to drop the first test, feel free.

-- 8 --
Subject: [PATCH] t1300: document some aesthetic failures of the config editor

The config-editing code used by git config var value is
built around the regular config callback parser, whose only
triggerable item is an actual key. As a result, it does not
know anything about section headers, which can result in
unnecessarily ugly output:

  1. When we delete the last key in a section, we should be
 able to delete the section header.

  2. When we add a key into a section, we should be able to
 reuse the same section header, even if that section did
 not have any keys in it already.

Unfortunately, fixing these is not trivial with the current
code. It would involve the config parser recording and
passing back information on each item it finds, including
headers, keys, and even comments (or even better, generating
an actual in-memory parse-tree).

Since these behaviors do not cause any functional problems
(i.e., the resulting config parses as expected, it is just
uglier than one would like), fixing them can wait until
somebody feels like substantially refactoring the parsing
code. In the meantime, let's document them as known issues
with some tests.

Signed-off-by: Jeff King p...@peff.net
---
 t/t1300-repo-config.sh | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index 3c96fda..213e5a8 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -1087,4 +1087,34 @@ test_expect_success 'barf on incomplete string' '
grep  line 3  error
 '
 
+# good section hygiene
+test_expect_failure 'unsetting the last key in a section removes header' '
+   cat .git/config -\EOF 
+   [section]
+   # some intervening lines
+   # that should also be dropped
+
+   key = value
+   EOF
+
+   expect 
+
+   git config --unset section.key 
+   test_cmp expect .git/config
+'
+
+test_expect_failure 'adding a key into an empty section reuses header' '
+   cat .git/config -\EOF 
+   [section]
+   EOF
+
+   q_to_tab expect -\EOF 
+   [section]
+   Qkey = value
+   EOF
+
+   git config section.key value
+   test_cmp expect .git/config
+'
+
 test_done
-- 
1.8.2.rc3.27.g5c55d5c

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t1300: document some aesthetic failures of the config editor

2013-03-29 Thread Junio C Hamano
Junio C Hamano gits...@pobox.com writes:

 ...  If we _were_ to remove the section header at this point,
 we should be removing the comment two out of three cases (if it is
 about section.key, it should go when section.key goes; if it is
 about section, it should go when section goes; if it is a more
 generic comment about this configuration file, it should stay).

The last case should end more like this:

..., it should stay, but why are you writing a comment that
is not specific to this section _inside_ the section in the
first place???

Another case we have to worry about, if we were to remove an empty
section header is this case:

# Now, let's list all the remotes I interact with.

# This is where I push all the separate topics.
[remote github]
# fetch like everybody else without auth
url = git://github.com/user/git
# push with auth
pushURL = github.com:user/git
# publish the state of my primary working area as-is
mirror

# Traditional canonical one
[remote korg]
url = k.org:/pub/scm/user/git

If I were to retire github account, removing the section while
keeping the comments would be confusing (I do not push all the
separate topics to korg).  Removing the section while removing the
comments that pertain to the section is impossible; Now, let's list
all the remotes should stay, This is where I push should go.

Removing only the keys and keeping the skelton around would give us:

# Now, let's list all the remotes I interact with.

# This is where I push all the separate topics.
[remote github]
# fetch like everybody else without auth
# push with auth
# publish the state of my primary working area as-is

# Traditional canonical one
[remote korg]
url = k.org:/pub/scm/user/git

which is still confusing, but at least the confusion is not spread
to adjacent sections.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/5] difftool: don't overwrite modified files

2013-03-29 Thread Junio C Hamano
John Keeping j...@keeping.me.uk writes:

 After running the user's diff tool, git-difftool will copy any files
 that differ between the working tree and the temporary tree.  This is
 useful when the user edits the file in their diff tool but is wrong if
 they edit the working tree file while examining the diff.

Thanks.

I should drop the t7800-modernize topic and queue this under a
better name.  Perhaps difftool-no-overwrite-on-copyback, or
something.

 Instead of copying unconditionally when the files differ, create and
 index from the working tree files and only copy the temporary file back
 if it was modified and the working tree file was not.  If both files
 have been modified, print a warning and exit with an error.

 Note that we cannot use an existing index in git-difftool since those
 contain the modified files that need to be checked out but here we are
 looking at those files which are copied from the working tree and not
 checked out.  These are precisely the files which are not in the
 existing indices.



 Signed-off-by: John Keeping j...@keeping.me.uk

 ---
 Changes since v2:
 - Set TMPDIR to $TRASH_DIRECTORY in the test where difftool fails

  git-difftool.perl   | 73 
 +++--
  t/t7800-difftool.sh | 30 ++
  2 files changed, 89 insertions(+), 14 deletions(-)

 diff --git a/git-difftool.perl b/git-difftool.perl
 index 663640d..844f619 100755
 --- a/git-difftool.perl
 +++ b/git-difftool.perl
 @@ -13,9 +13,9 @@
  use 5.008;
  use strict;
  use warnings;
 +use Error qw(:try);
  use File::Basename qw(dirname);
  use File::Copy;
 -use File::Compare;
  use File::Find;
  use File::stat;
  use File::Path qw(mkpath rmtree);
 @@ -88,14 +88,45 @@ sub use_wt_file
   my ($repo, $workdir, $file, $sha1, $symlinks) = @_;
   my $null_sha1 = '0' x 40;
  
 - if ($sha1 eq $null_sha1) {
 - return 1;
 - } elsif (not $symlinks) {
 + if ($sha1 ne $null_sha1 and not $symlinks) {
   return 0;
   }
  
   my $wt_sha1 = $repo-command_oneline('hash-object', $workdir/$file);
 - return $sha1 eq $wt_sha1;
 + my $use = ($sha1 eq $null_sha1) || ($sha1 eq $wt_sha1);
 + return ($use, $wt_sha1);
 +}
 +
 +sub changed_files
 +{
 + my ($repo_path, $index, $worktree) = @_;
 + $ENV{GIT_INDEX_FILE} = $index;
 + $ENV{GIT_WORK_TREE} = $worktree;
 + my $must_unset_git_dir = 0;
 + if (not defined($ENV{GIT_DIR})) {
 + $must_unset_git_dir = 1;
 + $ENV{GIT_DIR} = $repo_path;
 + }
 +
 + my @refreshargs = qw/update-index --really-refresh -q --unmerged/;
 + my @gitargs = qw/diff-files --name-only -z/;
 + try {
 + Git::command_oneline(@refreshargs);
 + } catch Git::Error::Command with {};
 +
 + my $line = Git::command_oneline(@gitargs);
 + my @files;
 + if (defined $line) {
 + @files = split('\0', $line);
 + } else {
 + @files = ();
 + }
 +
 + delete($ENV{GIT_INDEX_FILE});
 + delete($ENV{GIT_WORK_TREE});
 + delete($ENV{GIT_DIR}) if ($must_unset_git_dir);
 +
 + return map { $_ = 1 } @files;
  }
  
  sub setup_dir_diff
 @@ -121,6 +152,7 @@ sub setup_dir_diff
   my $null_sha1 = '0' x 40;
   my $lindex = '';
   my $rindex = '';
 + my $wtindex = '';
   my %submodule;
   my %symlink;
   my @working_tree = ();
 @@ -174,8 +206,12 @@ EOF
   }
  
   if ($rmode ne $null_mode) {
 - if (use_wt_file($repo, $workdir, $dst_path, $rsha1, 
 $symlinks)) {
 - push(@working_tree, $dst_path);
 + my ($use, $wt_sha1) = use_wt_file($repo, $workdir,
 +   $dst_path, $rsha1,
 +   $symlinks);
 + if ($use) {
 + push @working_tree, $dst_path;
 + $wtindex .= $rmode $wt_sha1\t$dst_path\0;
   } else {
   $rindex .= $rmode $rsha1\t$dst_path\0;
   }
 @@ -218,6 +254,12 @@ EOF
   $rc = system('git', 'checkout-index', '--all', --prefix=$rdir/);
   exit_cleanup($tmpdir, $rc) if $rc != 0;
  
 + $ENV{GIT_INDEX_FILE} = $tmpdir/wtindex;
 + ($inpipe, $ctx) =
 + $repo-command_input_pipe(qw(update-index --info-only -z 
 --index-info));
 + print($inpipe $wtindex);
 + $repo-command_close_pipe($inpipe, $ctx);
 +
   # If $GIT_DIR was explicitly set just for the update/checkout
   # commands, then it should be unset before continuing.
   delete($ENV{GIT_DIR}) if ($must_unset_git_dir);
 @@ -390,19 +432,22 @@ sub dir_diff
   # should be copied back to the working tree.
   # Do not copy back files when symlinks are used and the
   # external tool did not replace the original link with a file.
 + my %wt_modified = 

Re: [PATCH] t1300: document some aesthetic failures of the config editor

2013-03-29 Thread Junio C Hamano
Jeff King p...@peff.net writes:

 Here it is with the updated expectation. I don't care _that_ much, so if
 you feel strongly and want to drop the first test, feel free.

As long as we are adding expect_failure without an immediate fix,
let's document the ideal, with this patch on top.

 t/t1300-repo-config.sh | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index 213e5a8..133f26d 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -1089,16 +1089,20 @@ test_expect_success 'barf on incomplete string' '
 
 # good section hygiene
 test_expect_failure 'unsetting the last key in a section removes header' '
cat .git/config -\EOF 
+   # some generic comment on the configuration file itself
+   # a comment specific to this section section.
[section]
# some intervening lines
# that should also be dropped
 
key = value
EOF
 
-   expect 
+   cat expect -\EOF 
+   # some generic comment on the configuration file itself
+   EOF
 
git config --unset section.key 
test_cmp expect .git/config
 '
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] cherry-pick -x: improve handling of one-liner commit messages

2013-03-29 Thread Miklos Vajna
Hi,

On Fri, Mar 29, 2013 at 10:41:17AM -0700, Brandon Casey draf...@gmail.com 
wrote:
  Sign-off?

Indeed, I forgot about it, my bad.

  I think this is part of the bc/append-signed-off-by topic that is
  about to graduate to 'master'; more specifically, b971e04f54e7
  (sequencer.c: always separate (cherry picked from from commit
  body, 2013-02-12) does the equivalent, no?
 
 Yeah, I think this case is already handled.
 
 Miklos, can you check out next and see if your problem case is handled?

I just checked next and right, that solves the problem I was fixing.

So -- sorry for the noise. :-)

Miklos


signature.asc
Description: Digital signature


Re: [PATCH] cherry-pick -x: improve handling of one-liner commit messages

2013-03-29 Thread Junio C Hamano
Miklos Vajna vmik...@suse.cz writes:

 On Fri, Mar 29, 2013 at 10:41:17AM -0700, Brandon Casey draf...@gmail.com 
 wrote:

  I think this is part of the bc/append-signed-off-by topic that is
  about to graduate to 'master'; more specifically, b971e04f54e7
  (sequencer.c: always separate (cherry picked from from commit
  body, 2013-02-12) does the equivalent, no?
 
 Yeah, I think this case is already handled.
 
 Miklos, can you check out next and see if your problem case is handled?

 I just checked next and right, that solves the problem I was fixing.

 So -- sorry for the noise. :-)

Don't be sorry.

People noticing an issue, trying 'master' and 'next' to see that it
has already been resolved, is the only way for us to know we are
helping people other than those who had the original itch.

The ideal would be for more people to run 'next' and report both
problems and successes ;-)
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/2] optimize set_shared_perm()

2013-03-29 Thread Junio C Hamano
Torsten Bögershausen tbo...@web.de writes:

   optimize set_shared_perm() in path.c:

   - sometimes the chown() function is called even when not needed.
 (This can be provoced by running t1301, and adding some debug code)

 Save a chmod from 400 to 400, or from 600-600 on these files:
 .git/info/refs+
 .git/objects/info/packs+

 Save chmod on directories from 2770 to 2770:
 .git/refs
 .git/refs/heads
 .git/refs/tags

   - as all callers use mode == 0 when caling set_shared_perm(),
 the function can be simplified.
   - all callers use the macro adjust_shared_perm(path) from cache.h
 Convert adjust_shared_perm() from a macro into a function prototype

The last two points can become a separate preparation step.  The
result would be easier to read.

Your updated adjust_shared_perm() does not begin with:

if (!shared_repository)
return 0;

as the original, but it always first calls to get_st_mode_bits()
which makes a call to lstat(2).

That smells like a huge regression for !shared_repository case,
unless you have updated the existing callers of adjust_shared_perm()
not to call it when !shared_repository.

 diff --git a/path.c b/path.c
 index 2fdccc2..4bc918a 100644
 --- a/path.c
 +++ b/path.c
 @@ -1,14 +1,5 @@
  /*
 - * I'm tired of doing vsnprintf() etc just to open a
 - * file, so here's a return static buffer with printf
 - * interface for paths.
 - *
 - * It's obviously not thread-safe. Sue me. But it's quite
 - * useful for doing things like
 - *
 - *   f = open(mkpath(%s/%s.git, base, name), O_RDONLY);
 - *
 - * which is what it's designed for.
 + * Different utilitiy functions for path and path names
   */

Removing the stale I'm tired of is good; you do not have to move
it anywhere.  A single-liner

/* Utilities for paths and pathnames */

should suffice.

Will discard this step (but will keep PATCH 1/2).
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/5] difftool: don't overwrite modified files

2013-03-29 Thread John Keeping
On Fri, Mar 29, 2013 at 01:20:50PM -0700, Junio C Hamano wrote:
 John Keeping j...@keeping.me.uk writes:
 
  After running the user's diff tool, git-difftool will copy any files
  that differ between the working tree and the temporary tree.  This is
  useful when the user edits the file in their diff tool but is wrong if
  they edit the working tree file while examining the diff.
 
 Thanks.
 
 I should drop the t7800-modernize topic and queue this under a
 better name.  Perhaps difftool-no-overwrite-on-copyback, or
 something.
 
  Instead of copying unconditionally when the files differ, create and
  index from the working tree files and only copy the temporary file back
  if it was modified and the working tree file was not.  If both files
  have been modified, print a warning and exit with an error.
 
  Note that we cannot use an existing index in git-difftool since those
  contain the modified files that need to be checked out but here we are
  looking at those files which are copied from the working tree and not
  checked out.  These are precisely the files which are not in the
  existing indices.
 
 
 
  Signed-off-by: John Keeping j...@keeping.me.uk
 
  ---
  Changes since v2:
  - Set TMPDIR to $TRASH_DIRECTORY in the test where difftool fails
 
   git-difftool.perl   | 73 
  +++--
   t/t7800-difftool.sh | 30 ++
   2 files changed, 89 insertions(+), 14 deletions(-)
 
  diff --git a/git-difftool.perl b/git-difftool.perl
  index 663640d..844f619 100755
  --- a/git-difftool.perl
  +++ b/git-difftool.perl
  @@ -13,9 +13,9 @@
   use 5.008;
   use strict;
   use warnings;
  +use Error qw(:try);
   use File::Basename qw(dirname);
   use File::Copy;
  -use File::Compare;
   use File::Find;
   use File::stat;
   use File::Path qw(mkpath rmtree);
  @@ -88,14 +88,45 @@ sub use_wt_file
  my ($repo, $workdir, $file, $sha1, $symlinks) = @_;
  my $null_sha1 = '0' x 40;
   
  -   if ($sha1 eq $null_sha1) {
  -   return 1;
  -   } elsif (not $symlinks) {
  +   if ($sha1 ne $null_sha1 and not $symlinks) {
  return 0;
  }
   
  my $wt_sha1 = $repo-command_oneline('hash-object', $workdir/$file);
  -   return $sha1 eq $wt_sha1;
  +   my $use = ($sha1 eq $null_sha1) || ($sha1 eq $wt_sha1);
  +   return ($use, $wt_sha1);
  +}
  +
  +sub changed_files
  +{
  +   my ($repo_path, $index, $worktree) = @_;
  +   $ENV{GIT_INDEX_FILE} = $index;
  +   $ENV{GIT_WORK_TREE} = $worktree;
  +   my $must_unset_git_dir = 0;
  +   if (not defined($ENV{GIT_DIR})) {
  +   $must_unset_git_dir = 1;
  +   $ENV{GIT_DIR} = $repo_path;
  +   }
  +
  +   my @refreshargs = qw/update-index --really-refresh -q --unmerged/;
  +   my @gitargs = qw/diff-files --name-only -z/;
  +   try {
  +   Git::command_oneline(@refreshargs);
  +   } catch Git::Error::Command with {};
  +
  +   my $line = Git::command_oneline(@gitargs);
  +   my @files;
  +   if (defined $line) {
  +   @files = split('\0', $line);
  +   } else {
  +   @files = ();
  +   }
  +
  +   delete($ENV{GIT_INDEX_FILE});
  +   delete($ENV{GIT_WORK_TREE});
  +   delete($ENV{GIT_DIR}) if ($must_unset_git_dir);
  +
  +   return map { $_ = 1 } @files;
   }
   
   sub setup_dir_diff
  @@ -121,6 +152,7 @@ sub setup_dir_diff
  my $null_sha1 = '0' x 40;
  my $lindex = '';
  my $rindex = '';
  +   my $wtindex = '';
  my %submodule;
  my %symlink;
  my @working_tree = ();
  @@ -174,8 +206,12 @@ EOF
  }
   
  if ($rmode ne $null_mode) {
  -   if (use_wt_file($repo, $workdir, $dst_path, $rsha1, 
  $symlinks)) {
  -   push(@working_tree, $dst_path);
  +   my ($use, $wt_sha1) = use_wt_file($repo, $workdir,
  + $dst_path, $rsha1,
  + $symlinks);
  +   if ($use) {
  +   push @working_tree, $dst_path;
  +   $wtindex .= $rmode $wt_sha1\t$dst_path\0;
  } else {
  $rindex .= $rmode $rsha1\t$dst_path\0;
  }
  @@ -218,6 +254,12 @@ EOF
  $rc = system('git', 'checkout-index', '--all', --prefix=$rdir/);
  exit_cleanup($tmpdir, $rc) if $rc != 0;
   
  +   $ENV{GIT_INDEX_FILE} = $tmpdir/wtindex;
  +   ($inpipe, $ctx) =
  +   $repo-command_input_pipe(qw(update-index --info-only -z 
  --index-info));
  +   print($inpipe $wtindex);
  +   $repo-command_close_pipe($inpipe, $ctx);
  +
  # If $GIT_DIR was explicitly set just for the update/checkout
  # commands, then it should be unset before continuing.
  delete($ENV{GIT_DIR}) if ($must_unset_git_dir);
  @@ -390,19 +432,22 @@ sub dir_diff
  # should be copied back to the working tree.
  # Do not copy back files when symlinks are used and the
  # external tool 

[PATCH 2/5 v2] difftool: don't overwrite modified files

2013-03-29 Thread John Keeping
After running the user's diff tool, git-difftool will copy any files
that differ between the working tree and the temporary tree.  This is
useful when the user edits the file in their diff tool but is wrong if
they edit the working tree file while examining the diff.

Instead of copying unconditionally when the files differ, create and
index from the working tree files and only copy the temporary file back
if it was modified and the working tree file was not.  If both files
have been modified, print a warning and exit with an error.

Note that we cannot use an existing index in git-difftool since those
contain the modified files that need to be checked out but here we are
looking at those files which are copied from the working tree and not
checked out.  These are precisely the files which are not in the
existing indices.

Signed-off-by: John Keeping j...@keeping.me.uk

---
Changes since v1:
- Lazily initialize *_modified hashes to avoid executing Git commands
  in the common case where symlinks are in use and the diff tool writes
  to the file through the symlink
- Use exists consistently when checking *_modified hashes

 git-difftool.perl   | 85 -
 t/t7800-difftool.sh | 30 +++
 2 files changed, 101 insertions(+), 14 deletions(-)

diff --git a/git-difftool.perl b/git-difftool.perl
index 663640d..6780292 100755
--- a/git-difftool.perl
+++ b/git-difftool.perl
@@ -13,9 +13,9 @@
 use 5.008;
 use strict;
 use warnings;
+use Error qw(:try);
 use File::Basename qw(dirname);
 use File::Copy;
-use File::Compare;
 use File::Find;
 use File::stat;
 use File::Path qw(mkpath rmtree);
@@ -88,14 +88,45 @@ sub use_wt_file
my ($repo, $workdir, $file, $sha1, $symlinks) = @_;
my $null_sha1 = '0' x 40;
 
-   if ($sha1 eq $null_sha1) {
-   return 1;
-   } elsif (not $symlinks) {
+   if ($sha1 ne $null_sha1 and not $symlinks) {
return 0;
}
 
my $wt_sha1 = $repo-command_oneline('hash-object', $workdir/$file);
-   return $sha1 eq $wt_sha1;
+   my $use = ($sha1 eq $null_sha1) || ($sha1 eq $wt_sha1);
+   return ($use, $wt_sha1);
+}
+
+sub changed_files
+{
+   my ($repo_path, $index, $worktree) = @_;
+   $ENV{GIT_INDEX_FILE} = $index;
+   $ENV{GIT_WORK_TREE} = $worktree;
+   my $must_unset_git_dir = 0;
+   if (not defined($ENV{GIT_DIR})) {
+   $must_unset_git_dir = 1;
+   $ENV{GIT_DIR} = $repo_path;
+   }
+
+   my @refreshargs = qw/update-index --really-refresh -q --unmerged/;
+   my @gitargs = qw/diff-files --name-only -z/;
+   try {
+   Git::command_oneline(@refreshargs);
+   } catch Git::Error::Command with {};
+
+   my $line = Git::command_oneline(@gitargs);
+   my @files;
+   if (defined $line) {
+   @files = split('\0', $line);
+   } else {
+   @files = ();
+   }
+
+   delete($ENV{GIT_INDEX_FILE});
+   delete($ENV{GIT_WORK_TREE});
+   delete($ENV{GIT_DIR}) if ($must_unset_git_dir);
+
+   return map { $_ = 1 } @files;
 }
 
 sub setup_dir_diff
@@ -121,6 +152,7 @@ sub setup_dir_diff
my $null_sha1 = '0' x 40;
my $lindex = '';
my $rindex = '';
+   my $wtindex = '';
my %submodule;
my %symlink;
my @working_tree = ();
@@ -174,8 +206,12 @@ EOF
}
 
if ($rmode ne $null_mode) {
-   if (use_wt_file($repo, $workdir, $dst_path, $rsha1, 
$symlinks)) {
-   push(@working_tree, $dst_path);
+   my ($use, $wt_sha1) = use_wt_file($repo, $workdir,
+ $dst_path, $rsha1,
+ $symlinks);
+   if ($use) {
+   push @working_tree, $dst_path;
+   $wtindex .= $rmode $wt_sha1\t$dst_path\0;
} else {
$rindex .= $rmode $rsha1\t$dst_path\0;
}
@@ -218,6 +254,12 @@ EOF
$rc = system('git', 'checkout-index', '--all', --prefix=$rdir/);
exit_cleanup($tmpdir, $rc) if $rc != 0;
 
+   $ENV{GIT_INDEX_FILE} = $tmpdir/wtindex;
+   ($inpipe, $ctx) =
+   $repo-command_input_pipe(qw(update-index --info-only -z 
--index-info));
+   print($inpipe $wtindex);
+   $repo-command_close_pipe($inpipe, $ctx);
+
# If $GIT_DIR was explicitly set just for the update/checkout
# commands, then it should be unset before continuing.
delete($ENV{GIT_DIR}) if ($must_unset_git_dir);
@@ -390,19 +432,34 @@ sub dir_diff
# should be copied back to the working tree.
# Do not copy back files when symlinks are used and the
# external tool did not replace the original link with a file.
+   #
+   # These hashes are 

What's cooking in git.git (Mar 2013, #08; Fri, 29)

2013-03-29 Thread Junio C Hamano
What's cooking in git.git (Mar 2013, #08; Fri, 29)
--

Here are the topics that have been cooking.  Commits prefixed with
'-' are only in 'pu' (proposed updates) while commits prefixed with
'+' are in 'next'.

A handful of topics that have been stalled for quite a while have
been discarded; for those that are not superseded by something else,
interested parties can still resubmit a reroll, but without any
advances, we do not get any benefit from carrying them in my tree.

You can find the changes described here in the integration branches
of the repositories listed at

http://git-blame.blogspot.com/p/git-public-repositories.html

--
[Graduated to master]

* ap/combine-diff-ignore-whitespace (2013-03-14) 1 commit
  (merged to 'next' on 2013-03-19 at dfb2c98)
 + Allow combined diff to ignore white-spaces
 (this branch is used by ap/combine-diff-coalesce-lost.)

 Originally merged to 'next' on 2013-03-18

 Teach diff --cc output to honor options to ignore various forms
 of whitespace changes.


* jc/remove-treesame-parent-in-simplify-merges (2013-01-17) 1 commit
  (merged to 'next' on 2013-03-26 at 7999dbe)
 + simplify-merges: drop merge from irrelevant side branch

 The --simplify-merges logic did not cull irrelevant parents from a
 merge that is otherwise not interesting with respect to the paths
 we are following.

 This touches a fairly core part of the revision traversal
 infrastructure; even though I think this change is correct, please
 report immediately if you find any unintended side effect.


* jk/checkout-attribute-lookup (2013-03-20) 3 commits
  (merged to 'next' on 2013-03-20 at 43a89e8)
 + t2003: work around path mangling issue on Windows
  (merged to 'next' on 2013-03-19 at b063a55)
 + entry: fix filter lookup
 + t2003: modernize style

 Codepath to stream blob object contents directly from the object
 store to filesystem did not use the correct path to find conversion
 filters when writing to temporary files.


* jk/difftool-dir-diff-edit-fix (2013-03-14) 3 commits
  (merged to 'next' on 2013-03-19 at e68014a)
 + difftool --dir-diff: symlink all files matching the working tree
 + difftool: avoid double slashes in symlink targets
 + git-difftool(1): fix formatting of --symlink description

 Originally merged to 'next' on 2013-03-15

 git difftool --dir-diff made symlinks to working tree files when
 preparing a temporary directory structure, so that accidental edits
 of these files in the difftool are reflected back to the working
 tree, but the logic to decide when to do so was not quite right.


* kk/revwalk-slop-too-many-commit-within-a-second (2013-03-22) 1 commit
  (merged to 'next' on 2013-03-26 at ea90e75)
 + Fix revision walk for commits with the same dates

 Allow the revision slop code to look deeper while commits with
 exactly the same timestamps come next to each other (which can
 often happen after a large am and rebase session).


* rr/tests-dedup-test-config (2013-03-19) 1 commit
  (merged to 'next' on 2013-03-26 at d314299)
 + t4018,7810,7811: remove test_config() redefinition


* rs/archive-zip-raw-compression (2013-03-16) 1 commit
  (merged to 'next' on 2013-03-19 at 8cc1cb3)
 + archive-zip: use deflateInit2() to ask for raw compressed data

 Originally merged to 'next' on 2013-03-18


* yd/doc-is-in-asciidoc (2013-03-21) 1 commit
  (merged to 'next' on 2013-03-26 at a980af2)
 + CodingGuidelines: our documents are in AsciiDoc


* yd/doc-merge-annotated-tag (2013-03-21) 1 commit
  (merged to 'next' on 2013-03-26 at a11162f)
 + Documentation: merging a tag is a special case

 Document the 1.7.9 feature to merge a signed tag and keep that in
 the mergetag header in the resulting commit better.


* yd/use-test-config-unconfig (2013-03-25) 12 commits
  (merged to 'next' on 2013-03-26 at 55b69a9)
 + t7600: use test_config to set/unset git config variables
 + t7502: remove clear_config
 + t7502: use test_config to set/unset git config variables
 + t9500: use test_config to set/unset git config variables
 + t7508: use test_config to set/unset git config variables
 + t7500: use test_config to set/unset git config variables
 + t5541: use test_config to set/unset git config variables
 + t5520: use test_config to set/unset git config variables
 + t4202: use test_config/test_unconfig to set/unset git config variables
 + t4034: use test_config/test_unconfig to set/unset git config variables
 + t4304: use test_config to set/unset git config variables
 + t3400: use test_config to set/unset git config variables

 Bulk-update of the test suite.

--
[New Topics]

* js/log-gpg (2013-03-27) 1 commit
 - log: read gpg settings for signed commit verification

 Teach show/log honor gpg.program configuration just like other
 parts of the code that use GnuPG.

 Will merge to 'next'.


* jc/t5516-pushInsteadOf-vs-pushURL (2013-03-28) 1 commit
 - t5516: test 

Reading remote reflogs

2013-03-29 Thread Dennis Kaarsemaker
Is it possible to somehow fetch the reflog of a remote?

I would like to delegate some post-receive actions to an automatically
mirrored clone of some repositories. Mirrored repositories don't
maintain a reflog, even with core.logAllRefUpdates = true, so to be able
to know what was pushed per push, it would need to somehow know the
reflog of the origin.

Of course a post-receive hook can send this information downstream, but
I'd like to keep the origin 'dumb' and not do that.

-- 
Dennis Kaarsemaker
www.kaarsemaker.net

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Reading remote reflogs

2013-03-29 Thread Junio C Hamano
Dennis Kaarsemaker den...@kaarsemaker.net writes:

 ... Mirrored repositories don't
 maintain a reflog, even with core.logAllRefUpdates = true,...

Are you sure about this?  When log_all_ref_updates is not set, by
default we do not log for bare repositories, but other than that, we
do not do anything special with respect to reflogs.

$ (cd ..  git clone --no-local --mirror git.git victim)
$ git checkout next
$ EDITOR=: git commit --amend
$ cd ../victim
$ git config core.logallrefupdates true
$ git fetch
$ find logs
logs
logs/HEAD
logs/refs
logs/refs/heads
logs/refs/heads/next

It seems to record how a branch at its origin was updated just fine,
at least to me.

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Reading remote reflogs

2013-03-29 Thread Dennis Kaarsemaker
On vr, 2013-03-29 at 15:45 -0700, Junio C Hamano wrote:
 Dennis Kaarsemaker den...@kaarsemaker.net writes:
 
  ... Mirrored repositories don't
  maintain a reflog, even with core.logAllRefUpdates = true,...
 
 Are you sure about this?  When log_all_ref_updates is not set, by
 default we do not log for bare repositories, but other than that, we
 do not do anything special with respect to reflogs.

I was, as I tried the recipe below, though with a different repo. Must
have goofed something up, as it works now. Thanks for the braincheck :)

That gives me a reasonable approximation of distinct pushes if I pull
the mirror often enough. It's always going to be an approximation
though, so the original question still stands.
-- 
Dennis Kaarsemaker
www.kaarsemaker.net

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Reading remote reflogs

2013-03-29 Thread Junio C Hamano
Dennis Kaarsemaker den...@kaarsemaker.net writes:

 On vr, 2013-03-29 at 15:45 -0700, Junio C Hamano wrote:
 Dennis Kaarsemaker den...@kaarsemaker.net writes:
 
  ... Mirrored repositories don't
  maintain a reflog, even with core.logAllRefUpdates = true,...
 
 Are you sure about this?  When log_all_ref_updates is not set, by
 default we do not log for bare repositories, but other than that, we
 do not do anything special with respect to reflogs.

 I was, as I tried the recipe below, though with a different repo. Must
 have goofed something up, as it works now. Thanks for the braincheck :)

 That gives me a reasonable approximation of distinct pushes if I pull
 the mirror often enough.

Instead of polling, why not git push --mirror whenever the
original gets updated?
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Reading remote reflogs

2013-03-29 Thread Dennis Kaarsemaker
On vr, 2013-03-29 at 15:58 -0700, Junio C Hamano wrote:
 Dennis Kaarsemaker den...@kaarsemaker.net writes:
 
  On vr, 2013-03-29 at 15:45 -0700, Junio C Hamano wrote:
  Dennis Kaarsemaker den...@kaarsemaker.net writes:
  
   ... Mirrored repositories don't
   maintain a reflog, even with core.logAllRefUpdates = true,...
  
  Are you sure about this?  When log_all_ref_updates is not set, by
  default we do not log for bare repositories, but other than that, we
  do not do anything special with respect to reflogs.
 
  I was, as I tried the recipe below, though with a different repo. Must
  have goofed something up, as it works now. Thanks for the braincheck :)
 
  That gives me a reasonable approximation of distinct pushes if I pull
  the mirror often enough.
 
 Instead of polling, why not git push --mirror whenever the
 original gets updated?

I considered that, but it has two downsides:
- Slows down the push as it needs to wait for this to complete
- Only works if you control the master, so it won't work with e.g. 
  github hosted repositories
-- 
Dennis Kaarsemaker
www.kaarsemaker.net

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v5 0/5] Verify GPG signatures when merging and extend %G? pretty string

2013-03-29 Thread Sebastian Götte
I hope I did not introduce more problems than I fixed in this revision ;)

On 03/28/2013 11:33 PM, Junio C Hamano wrote:
 It would be much easier to read if it were unless we are not
 looking at the very first byte, the previous byte must be LF, i.e.
 
   if (found != buf  found[-1] != '\n')
 
 Is that continue correct?  Don't you want to retry from the end of
 the line that contains the mistaken hit?
Actually it is not. Sorry.
 The \n at the beginning anchors the expected string for quicker
 multi-line scan done with strstr().  If you really want to lose that
 LF and still write this function correctly and clearly, I think you
 would need to iterate over the buffer line by line.
The function now does that and calls prefixcmp on each line.

On 03/28/2013 11:33 PM, Junio C Hamano wrote: Sebastian Götte 
ja...@physik.tu-berlin.de writes:
 +if (verify_signatures) {
 +/* Verify the commit signatures */
 +for (p = remoteheads; p; p = p-next) {
 +struct commit *commit = p-item;
 +struct signature signature;
 +signature.check_result = 0;
 
 [...] 
 By the way, I think this variable and type should be called more
 like signature_check or something with check in its name, not
 signature.  After all it is _not_ a signature itself.
I renamed it signature_check. I put that into the commit moving the code to
commit.c. I also renamed the array/struct containing the GPG status output
strings since that was originally called signature_check.

 +grep does not have a GPG signature mergeerror
 
 Do we plan to make this message localized?  If so I think you would
 need to do this with test_i18ngrep.
Yes, this message should be localized since it is normal status output. I
fixed the test case, however I noticed a possible problem with the git log
 --show-signature test case (t/t7510-signed-commit.sh): Here, grep is used on
git output, but this git output is actually just passed-through GPG output, and
GPG localizes that output. Are the tests alwasy run with LANG=en_US.utf-8,
LANG=C etc.?

 +test_expect_success GPG 'merge commit with bad signature with verification' 
 '
 +test_must_fail git merge --ff-only --verify-signatures $(cat 
 forged.commit) 2 mergeerror 
 +grep has a bad GPG signature mergeerror
 +'
 +
 +test_expect_success GPG 'merge signed commit with verification' '
 +git merge -v --ff-only --verify-signatures side-signed  mergeoutput 
 +grep has a good GPG signature mergeoutput
 +'
 
 Hmph.
 
 So the caller needs to check both the standard output and the
 standard error to get the whole picture?  Is there a reason why we
 are not sending everything to the standard output consistently?
If --verify-signatures is given, everything but a good signature results in
die(_(foo)), with _(foo) being printed on stderr. I clarified that point
in merge-options.txt. If additionally --verbose is given on the command line,
git will print _(Commit %s has a good GPG signature by %s (key fingerprint
%s)\n) on stdout for each good commit.  I think it is ok that way because
the caller only needs to check the exit code to get a picture. The good GPG
signature-message is only meant to convey the signer's name and key
fingerprint in case the caller is interested. If the caller does not want to
abort the merge in case of GPG trouble, git merge may be called without
 --verify-signatures followed by a git log --show-signature on the commits
that have been merged.

Sebastian Götte (5):
  Move commit GPG signature verification to commit.c
  commit.c/GPG signature verification: Also look at the first GPG status
line
  merge/pull: verify GPG signatures of commits being merged
  merge/pull Check for untrusted good GPG signatures
  pretty printing: extend %G? to include 'N' and 'U'

 Documentation/merge-options.txt|   5 ++
 Documentation/pretty-formats.txt   |   3 +-
 builtin/merge.c|  35 +-
 commit.c   |  67 ++
 commit.h   |  10 
 git-pull.sh|  10 +++-
 gpg-interface.h|   8 
 pretty.c   |  93 ++---
 t/lib-gpg/pubring.gpg  | Bin 1164 - 2359 bytes
 t/lib-gpg/random_seed  | Bin 600 - 600 bytes
 t/lib-gpg/secring.gpg  | Bin 1237 - 3734 bytes
 t/lib-gpg/trustdb.gpg  | Bin 1280 - 1360 bytes
 t/t7612-merge-verify-signatures.sh |  61 
 13 files changed, 210 insertions(+), 82 deletions(-)
 create mode 100755 t/t7612-merge-verify-signatures.sh

-- 
1.8.1.5

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v5 2/5] commit.c/GPG signature verification: Also look at the first GPG status line

2013-03-29 Thread Sebastian Götte
Signed-off-by: Sebastian Götte ja...@physik-pool.tu-berlin.de
---
 commit.c | 34 --
 1 file changed, 20 insertions(+), 14 deletions(-)

diff --git a/commit.c b/commit.c
index e94d122..48f09e9 100644
--- a/commit.c
+++ b/commit.c
@@ -1027,27 +1027,33 @@ static struct {
char result;
const char *check;
 } sigcheck_gpg_status[] = {
-   { 'G', \n[GNUPG:] GOODSIG  },
-   { 'B', \n[GNUPG:] BADSIG  },
+   { 'G', [GNUPG:] GOODSIG  },
+   { 'B', [GNUPG:] BADSIG  },
 };
 
 static void parse_gpg_output(struct signature_check *sigc)
 {
-   const char *buf = sigc-gpg_status;
int i;
 
+   /* Iterate over all search strings */
for (i = 0; i  ARRAY_SIZE(sigcheck_gpg_status); i++) {
-   const char *found = strstr(buf, sigcheck_gpg_status[i].check);
-   const char *next;
-   if (!found)
-   continue;
-   sigc-check_result = sigcheck_gpg_status[i].result;
-   found += strlen(sigcheck_gpg_status[i].check);
-   sigc-key = xmemdupz(found, 16);
-   found += 17;
-   next = strchrnul(found, '\n');
-   sigc-signer = xmemdupz(found, next - found);
-   break;
+   const char *found = sigc-gpg_status;
+
+   /* Iterate over all lines */
+   do {
+   if (!prefixcmp(found, sigcheck_gpg_status[i].check)) {
+   const char *next;
+   
+   found += strlen(sigcheck_gpg_status[i].check);
+   sigc-check_result = 
sigcheck_gpg_status[i].result;
+   sigc-key = xmemdupz(found, 16);
+   found += 17;
+   next = strchrnul(found, '\n');
+   sigc-signer = xmemdupz(found, next - found);
+   return;
+   }
+   found = strchr(found, '\n')+1;
+   } while(found-1);
}
 }
 
-- 
1.8.1.5

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v5 1/5] Move commit GPG signature verification to commit.c

2013-03-29 Thread Sebastian Götte
Signed-off-by: Sebastian Götte ja...@physik-pool.tu-berlin.de
---
 commit.c| 59 +
 commit.h|  9 ++
 gpg-interface.h |  8 +
 pretty.c| 91 +
 4 files changed, 89 insertions(+), 78 deletions(-)

diff --git a/commit.c b/commit.c
index e8eb0ae..e94d122 100644
--- a/commit.c
+++ b/commit.c
@@ -1023,6 +1023,65 @@ free_return:
free(buf);
 }
 
+static struct {
+   char result;
+   const char *check;
+} sigcheck_gpg_status[] = {
+   { 'G', \n[GNUPG:] GOODSIG  },
+   { 'B', \n[GNUPG:] BADSIG  },
+};
+
+static void parse_gpg_output(struct signature_check *sigc)
+{
+   const char *buf = sigc-gpg_status;
+   int i;
+
+   for (i = 0; i  ARRAY_SIZE(sigcheck_gpg_status); i++) {
+   const char *found = strstr(buf, sigcheck_gpg_status[i].check);
+   const char *next;
+   if (!found)
+   continue;
+   sigc-check_result = sigcheck_gpg_status[i].result;
+   found += strlen(sigcheck_gpg_status[i].check);
+   sigc-key = xmemdupz(found, 16);
+   found += 17;
+   next = strchrnul(found, '\n');
+   sigc-signer = xmemdupz(found, next - found);
+   break;
+   }
+}
+
+void check_commit_signature(const struct commit* commit, struct 
signature_check *sigc)
+{
+   struct strbuf payload = STRBUF_INIT;
+   struct strbuf signature = STRBUF_INIT;
+   struct strbuf gpg_output = STRBUF_INIT;
+   struct strbuf gpg_status = STRBUF_INIT;
+   int status;
+
+   sigc-check_result = 'N';
+
+   if (parse_signed_commit(commit-object.sha1,
+   payload, signature) = 0)
+   goto out;
+   status = verify_signed_buffer(payload.buf, payload.len,
+ signature.buf, signature.len,
+ gpg_output, gpg_status);
+   if (status  !gpg_output.len)
+   goto out;
+   sigc-gpg_output = strbuf_detach(gpg_output, NULL);
+   sigc-gpg_status = strbuf_detach(gpg_status, NULL);
+   parse_gpg_output(sigc);
+
+ out:
+   strbuf_release(gpg_status);
+   strbuf_release(gpg_output);
+   strbuf_release(payload);
+   strbuf_release(signature);
+}
+
+
+
 void append_merge_tag_headers(struct commit_list *parents,
  struct commit_extra_header ***tail)
 {
diff --git a/commit.h b/commit.h
index 4138bb4..941f7f3 100644
--- a/commit.h
+++ b/commit.h
@@ -5,6 +5,7 @@
 #include tree.h
 #include strbuf.h
 #include decorate.h
+#include gpg-interface.h
 
 struct commit_list {
struct commit *item;
@@ -230,4 +231,12 @@ extern void print_commit_list(struct commit_list *list,
  const char *format_cur,
  const char *format_last);
 
+/*
+ * Check the signature of the given commit. The result of the check is stored 
in
+ * sig-check_result, 'G' for a good signature, 'B' for a bad signature and 'N'
+ * for no signature at all.
+ * This may allocate memory for sig-gpg_output, sig-gpg_status, sig-signer 
and sig-key.
+ */
+extern void check_commit_signature(const struct commit* commit, struct 
signature_check *sigc);
+
 #endif /* COMMIT_H */
diff --git a/gpg-interface.h b/gpg-interface.h
index cf99021..44f70aa 100644
--- a/gpg-interface.h
+++ b/gpg-interface.h
@@ -1,6 +1,14 @@
 #ifndef GPG_INTERFACE_H
 #define GPG_INTERFACE_H
 
+struct signature_check {
+   char *gpg_output;
+   char *gpg_status;
+   char check_result; /* 0 (not checked), N (checked but no further 
result), G (good) or B (bad) */
+   char *signer;
+   char *key;
+};
+
 extern int sign_buffer(struct strbuf *buffer, struct strbuf *signature, const 
char *signing_key);
 extern int verify_signed_buffer(const char *payload, size_t payload_size, 
const char *signature, size_t signature_size, struct strbuf *gpg_output, struct 
strbuf *gpg_status);
 extern int git_gpg_config(const char *, const char *, void *);
diff --git a/pretty.c b/pretty.c
index b57adef..da3c53c 100644
--- a/pretty.c
+++ b/pretty.c
@@ -756,14 +756,7 @@ struct format_commit_context {
const struct pretty_print_context *pretty_ctx;
unsigned commit_header_parsed:1;
unsigned commit_message_parsed:1;
-   unsigned commit_signature_parsed:1;
-   struct {
-   char *gpg_output;
-   char *gpg_status;
-   char good_bad;
-   char *signer;
-   char *key;
-   } signature;
+   struct signature_check signature_check;
char *message;
size_t width, indent1, indent2;
 
@@ -946,64 +939,6 @@ static void rewrap_message_tail(struct strbuf *sb,
c-indent2 = new_indent2;
 }
 
-static struct {
-   char result;
-   const char *check;
-} signature_check[] = {
-   { 'G', \n[GNUPG:] 

[PATCH v5 4/5] merge/pull Check for untrusted good GPG signatures

2013-03-29 Thread Sebastian Götte
When --verify-signatures is specified, abort the merge in case a good
GPG signature from an untrusted key is encountered.

Signed-off-by: Sebastian Götte ja...@physik-pool.tu-berlin.de
---
 Documentation/merge-options.txt|   4 ++--
 builtin/merge.c|   2 ++
 commit.c   |   2 ++
 commit.h   |   9 +
 gpg-interface.h|   2 +-
 t/lib-gpg/pubring.gpg  | Bin 1164 - 2359 bytes
 t/lib-gpg/random_seed  | Bin 600 - 600 bytes
 t/lib-gpg/secring.gpg  | Bin 1237 - 3734 bytes
 t/lib-gpg/trustdb.gpg  | Bin 1280 - 1360 bytes
 t/t7612-merge-verify-signatures.sh |   9 +
 10 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt
index 31f1067..a0f022b 100644
--- a/Documentation/merge-options.txt
+++ b/Documentation/merge-options.txt
@@ -85,8 +85,8 @@ option can be used to override --squash.
 
 --verify-signatures::
 --no-verify-signatures::
-   Verify that the commits being merged have good GPG signatures and abort 
the
-   merge in case they do not.
+   Verify that the commits being merged have good and trusted GPG 
signatures
+   and abort the merge in case they do not.
 
 --summary::
 --no-summary::
diff --git a/builtin/merge.c b/builtin/merge.c
index cb3e9ea..5b2ece1 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1251,6 +1251,8 @@ int cmd_merge(int argc, const char **argv, const char 
*prefix)
if (verbosity = 0)
printf(_(Commit %s has a good 
GPG signature by %s (key fingerprint %s)\n), hex, signature_check.signer, 
signature_check.key);
break;
+   case 'U':
+   die(_(Commit %s has a good GPG 
signature allegedly by %s, albeit from an untrusted key (fingerprint %s).), 
hex, signature_check.signer, signature_check.key);
case 'B':
die(_(Commit %s has a bad GPG 
signature allegedly by %s (key fingerprint %s).), hex, signature_check.signer, 
signature_check.key);
default: /* 'N' */
diff --git a/commit.c b/commit.c
index 48f09e9..b132c15 100644
--- a/commit.c
+++ b/commit.c
@@ -1027,6 +1027,8 @@ static struct {
char result;
const char *check;
 } sigcheck_gpg_status[] = {
+   { 'U', [GNUPG:] TRUST_UNDEFINED },
+   { 'U', [GNUPG:] TRUST_NEVER },
{ 'G', [GNUPG:] GOODSIG  },
{ 'B', [GNUPG:] BADSIG  },
 };
diff --git a/commit.h b/commit.h
index 941f7f3..27d9b36 100644
--- a/commit.h
+++ b/commit.h
@@ -232,10 +232,11 @@ extern void print_commit_list(struct commit_list *list,
  const char *format_last);
 
 /*
- * Check the signature of the given commit. The result of the check is stored 
in
- * sig-check_result, 'G' for a good signature, 'B' for a bad signature and 'N'
- * for no signature at all.
- * This may allocate memory for sig-gpg_output, sig-gpg_status, sig-signer 
and sig-key.
+ * Check the signature of the given commit. The result of the check is stored
+ * in sig-check_result, 'G' for a good signature, 'U' for a good signature
+ * from an untrusted signer, 'B' for a bad signature and 'N' for no signature
+ * at all.  This may allocate memory for sig-gpg_output, sig-gpg_status,
+ * sig-signer and sig-key.
  */
 extern void check_commit_signature(const struct commit* commit, struct 
signature_check *sigc);
 
diff --git a/gpg-interface.h b/gpg-interface.h
index 44f70aa..d2e512d 100644
--- a/gpg-interface.h
+++ b/gpg-interface.h
@@ -4,7 +4,7 @@
 struct signature_check {
char *gpg_output;
char *gpg_status;
-   char check_result; /* 0 (not checked), N (checked but no further 
result), G (good) or B (bad) */
+   char check_result; /* 0 (not checked), N (checked but no further 
result), U (untrusted, good), G (good) or B (bad) */
char *signer;
char *key;
 };
diff --git a/t/lib-gpg/pubring.gpg b/t/lib-gpg/pubring.gpg
index 
83855fa4e1c6c37afe550c17afa1e7971042ded5..1a3c2d487c2fda9169751a3068fa51e853a1e519
 100644
GIT binary patch
delta 1212
zcmV;t1Vj6b3AYlkj0As~0SyFEOqNFh2mr~8{AU1PG9!Ku9w|}@vpZJPg*#s86v-*O
zhafj(DLlFA0)`tvC$E@WHJ2r~0{0ZCh1kHo$b9ih^aD*~)oVvKyC1(yi)6x_y
zF8V3JpbIY^ZYQUk#j*ja0`;jw^J+5~!h3qc)ej%g1;Wb0U8cXSuLKdXkx2PUtB4
zzqQO;r+6QaVFd?ZkA#8Ch(2p+QaoKR;K0{BU;l_DqGU2YCt6Fr4psgB*tPou
z8C@tnj=CqkffSLs=a-5G+h;Y8bkws-iIgT{$f^j!)l`hmkz}$nZPxBoPmwU;zIH^
zLN~K=bOhGBes9{Fcqzh%Wj2h^{ZjI01*KI0kkAVa%poQL}_zlZ*pX5VIVwYX((5
za%4bdcwudDY-KKPWpqA?0XPH`0RjLb1p-k_mPY~`0|pBT2nPcK1{DYb2?`4Y76JnS
z0v-VZ7k~f?2@qikE`_%uafw)?2m1%-{uDP0Rs1|(F{OVhOSKoH$k!o)x3CO5Z^@El
zxGq=+xQGRr@3$S0@SUu@@UuxUH%pD3Q-D`?37Vg*xmo%+KD)(U~kXU^b+=70V
zFr?b3DvlFq^B*d%lz=lr!ch6nQbvcwWCD}n2DT3`r?RDkq=7r}qFvEhdfApA7yR;

[PATCH v5 5/5] pretty printing: extend %G? to include 'N' and 'U'

2013-03-29 Thread Sebastian Götte
Expand %G? in pretty format strings to 'N' in case of no GPG signature
and 'U' in case of a good but untrusted GPG signature in addition to
the previous 'G'ood and 'B'ad. This eases writing anyting parsing
git-log output.

Signed-off-by: Sebastian Götte ja...@physik-pool.tu-berlin.de
---
 Documentation/pretty-formats.txt | 3 ++-
 pretty.c | 2 ++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index 2939655..afac703 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -131,7 +131,8 @@ The placeholders are:
 - '%B': raw body (unwrapped subject and body)
 - '%N': commit notes
 - '%GG': raw verification message from GPG for a signed commit
-- '%G?': show either G for Good or B for Bad for a signed commit
+- '%G?': show G for a Good signature, B for a Bad signature, U for a 
good,
+  untrusted signature and N for no signature
 - '%GS': show the name of the signer for a signed commit
 - '%GK': show the key used to sign a signed commit
 - '%gD': reflog selector, e.g., `refs/stash@{1}`
diff --git a/pretty.c b/pretty.c
index da3c53c..bbe521b 100644
--- a/pretty.c
+++ b/pretty.c
@@ -1135,6 +1135,8 @@ static size_t format_commit_one(struct strbuf *sb, const 
char *placeholder,
switch (c-signature_check.check_result) {
case 'G':
case 'B':
+   case 'U':
+   case 'N':
strbuf_addch(sb, 
c-signature_check.check_result);
}
break;
-- 
1.8.1.5

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v5 3/5] merge/pull: verify GPG signatures of commits being merged

2013-03-29 Thread Sebastian Götte
When --verify-signatures is specified on the command-line of git-merge
or git-pull, check whether the commits being merged have good gpg
signatures and abort the merge in case they do not. This allows e.g.
auto-deployment from untrusted repo hosts.

Signed-off-by: Sebastian Götte ja...@physik-pool.tu-berlin.de
---
 Documentation/merge-options.txt|  5 
 builtin/merge.c| 33 +++-
 git-pull.sh| 10 ++--
 t/t7612-merge-verify-signatures.sh | 52 ++
 4 files changed, 97 insertions(+), 3 deletions(-)

diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt
index 0bcbe0a..31f1067 100644
--- a/Documentation/merge-options.txt
+++ b/Documentation/merge-options.txt
@@ -83,6 +83,11 @@ option can be used to override --squash.
Pass merge strategy specific option through to the merge
strategy.
 
+--verify-signatures::
+--no-verify-signatures::
+   Verify that the commits being merged have good GPG signatures and abort 
the
+   merge in case they do not.
+
 --summary::
 --no-summary::
Synonyms to --stat and --no-stat; these are deprecated and will be
diff --git a/builtin/merge.c b/builtin/merge.c
index 7c8922c..cb3e9ea 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -49,7 +49,7 @@ static const char * const builtin_merge_usage[] = {
 static int show_diffstat = 1, shortlog_len = -1, squash;
 static int option_commit = 1, allow_fast_forward = 1;
 static int fast_forward_only, option_edit = -1;
-static int allow_trivial = 1, have_message;
+static int allow_trivial = 1, have_message, verify_signatures;
 static int overwrite_ignore = 1;
 static struct strbuf merge_msg = STRBUF_INIT;
 static struct strategy **use_strategies;
@@ -199,6 +199,8 @@ static struct option builtin_merge_options[] = {
OPT_BOOLEAN(0, ff-only, fast_forward_only,
N_(abort if fast-forward is not possible)),
OPT_RERERE_AUTOUPDATE(allow_rerere_auto),
+   OPT_BOOLEAN(0, verify-signatures, verify_signatures,
+   N_(Verify that the named commit has a valid GPG signature)),
OPT_CALLBACK('s', strategy, use_strategies, N_(strategy),
N_(merge strategy to use), option_parse_strategy),
OPT_CALLBACK('X', strategy-option, xopts, N_(option=value),
@@ -1233,6 +1235,35 @@ int cmd_merge(int argc, const char **argv, const char 
*prefix)
usage_with_options(builtin_merge_usage,
builtin_merge_options);
 
+   if (verify_signatures) {
+   /* Verify the commit signatures */
+   for (p = remoteheads; p; p = p-next) {
+   struct commit *commit = p-item;
+   char hex[41];
+   struct signature_check signature_check;
+   memset(signature_check, 0, sizeof(signature_check));
+
+   check_commit_signature(commit, signature_check);
+
+   strcpy(hex, find_unique_abbrev(commit-object.sha1, 
DEFAULT_ABBREV));
+   switch(signature_check.check_result){
+   case 'G':
+   if (verbosity = 0)
+   printf(_(Commit %s has a good 
GPG signature by %s (key fingerprint %s)\n), hex, signature_check.signer, 
signature_check.key);
+   break;
+   case 'B':
+   die(_(Commit %s has a bad GPG 
signature allegedly by %s (key fingerprint %s).), hex, signature_check.signer, 
signature_check.key);
+   default: /* 'N' */
+   die(_(Commit %s does not have a good 
GPG signature. In fact, commit %s does not have a GPG signature at all.), hex, 
hex);
+   }
+
+   free(signature_check.gpg_output);
+   free(signature_check.gpg_status);
+   free(signature_check.signer);
+   free(signature_check.key);
+   }
+   }
+
strbuf_addstr(buf, merge);
for (p = remoteheads; p; p = p-next)
strbuf_addf(buf,  %s, merge_remote_util(p-item)-name);
diff --git a/git-pull.sh b/git-pull.sh
index 266e682..705940d 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -39,7 +39,7 @@ test -z $(git ls-files -u) || die_conflict
 test -f $GIT_DIR/MERGE_HEAD  die_merge
 
 strategy_args= diffstat= no_commit= squash= no_ff= ff_only=
-log_arg= verbosity= progress= recurse_submodules=
+log_arg= verbosity= progress= recurse_submodules= verify_signatures=
 merge_args= edit=
 curr_branch=$(git symbolic-ref -q HEAD)
 curr_branch_short=${curr_branch#refs/heads/}
@@ -125,6 +125,12 @@ do
--no-recurse-submodules)
recurse_submodules=--no-recurse-submodules
;;
+   

Re: [PATCH] t1300: document some aesthetic failures of the config editor

2013-03-29 Thread Jeff King
On Fri, Mar 29, 2013 at 01:35:22PM -0700, Junio C Hamano wrote:

 Jeff King p...@peff.net writes:
 
  Here it is with the updated expectation. I don't care _that_ much, so if
  you feel strongly and want to drop the first test, feel free.
 
 As long as we are adding expect_failure without an immediate fix,
 let's document the ideal, with this patch on top.
 [...]
  test_expect_failure 'unsetting the last key in a section removes header' '
   cat .git/config -\EOF 
 + # some generic comment on the configuration file itself
 + # a comment specific to this section section.
   [section]
   # some intervening lines
   # that should also be dropped
  
   key = value
   EOF
  
 - expect 
 + cat expect -\EOF 
 + # some generic comment on the configuration file itself
 + EOF

I think we may not attain that ideal without some natural language
processing of the comments. But hey, no reason not to shoot for the
stars. :)

-Peff
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [Toy PATCH] Avoid spilling collided entries in object hash table to the next slots

2013-03-29 Thread Duy Nguyen
On Sat, Mar 30, 2013 at 12:15 AM, Junio C Hamano gits...@pobox.com wrote:
 Nguyễn Thái Ngọc Duy  pclo...@gmail.com writes:

 If a position in object hash table is taken, we currently check out
 the next one. This could potentially create long object chains. We
 could create linked lists instead and leave the next slot alone.

 In the current code, not just the logic in lookup_object(), but the
 logic to enforce load factor when create_object() decides to call
 grow_object_hash() and object enumeration implemented by
 get_max_object_index() and get_indexed_object() are closely tied to
 the open addressing scheme.  If you want to switch to any other
 method (e.g. separate chaining) these need to be updated quite a
 bit.

 I do not see get_max_object_index() and get_indexed_object() updated
 at all.  Do fsck, index-pack, name-rev and upload-pack still work?

No, apparently not. I should have been hit hard by not updating
grow_object_hash(). But I think it was ok because I was on top of my
preallocation patch and there probably were not many chains before
that patch kicked in.

 This particular implementation that uses a fake union is a bit
 ugly, but in general, it may be worth rethinking the object hash
 implementation.  I vaguely recall trying cuckoo in the vicinity of
 this code.

Yeah I saw that. Need to read and maybe try again some time. Still
playing with the linked list idea. If every time we find something in
a chain, we swap it to top (with hope it'll be accessed more often),
then the number of traversing in chains goes down from 33m times to
21.5m times. If we just push it up one node in the linked list, it's
21.3m times. Interesting.
--
Duy
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 4/6] dir.c::match_pathname(): pay attention to the length of string parameters

2013-03-29 Thread Duy Nguyen
On Fri, Mar 29, 2013 at 09:44:32AM -0700, Junio C Hamano wrote:
 I tend to think in the longer term it may be a good idea to build
 with USE_WILDMATCH unconditionally (we can lose compat/fnmatch), so
 in the end this may not matter that much

I was thinking about that yesterday. After all, it's the purpose of
USE_WILDMATCH and nd/retire-fnmatch series. So how about this patch to
enable USE_WILDMATCH for a wider audience? I think it could get merged
down to master. If wildmatch's bug history is messy by the time we
enter rc cycles, we could revert the patch and cut new releases with
fnmatch. If not, after 1.9 is released, I'll submit a patch to remove
fnmatch compatiblity later and we will be on wildmatch only.

-- 8 --
diff --git a/Makefile b/Makefile
index 598d631..8a740f8 100644
--- a/Makefile
+++ b/Makefile
@@ -106,7 +106,7 @@ all::
 # Define NO_FNMATCH_CASEFOLD if your fnmatch function doesn't have the
 # FNM_CASEFOLD GNU extension.
 #
-# Define USE_WILDMATCH if you want to use Git's wildmatch
+# Define NO_USE_WILDMATCH if you do not want to use Git's wildmatch
 # implementation as fnmatch
 #
 # Define NO_GECOS_IN_PWENT if you don't have pw_gecos in struct passwd
@@ -1255,7 +1255,7 @@ ifdef NO_FNMATCH_CASEFOLD
COMPAT_OBJS += compat/fnmatch/fnmatch.o
 endif
 endif
-ifdef USE_WILDMATCH
+ifndef NO_USE_WILDMATCH
COMPAT_CFLAGS += -DUSE_WILDMATCH
 endif
 ifdef NO_SETENV
-- 8 --
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v5 2/5] commit.c/GPG signature verification: Also look at the first GPG status line

2013-03-29 Thread Junio C Hamano
Sebastian Götte ja...@physik.tu-berlin.de writes:

  static void parse_gpg_output(struct signature_check *sigc)
  {
 - const char *buf = sigc-gpg_status;
   int i;
  
 + /* Iterate over all search strings */
   for (i = 0; i  ARRAY_SIZE(sigcheck_gpg_status); i++) {
 + const char *found = sigc-gpg_status;
 +
 + /* Iterate over all lines */
 + do {
 + if (!prefixcmp(found, sigcheck_gpg_status[i].check)) {
 + const char *next;
 + 
 + found += strlen(sigcheck_gpg_status[i].check);
 + sigc-check_result = 
 sigcheck_gpg_status[i].result;
 + sigc-key = xmemdupz(found, 16);
 + found += 17;
 + next = strchrnul(found, '\n');
 + sigc-signer = xmemdupz(found, next - found);
 + return;
 + }
 + found = strchr(found, '\n')+1;
 + } while(found-1);

Yuck.  That termination condition is horrible.

Honestly speaking, I find the one I suggested the other day (which
has been queued on 'pu') much nicer than this loop.

If you really really want to do a line at a time, discarding the
allow strstr() to scan over multiple lines optimization, it is
more natural to iterate over buffer one line at a time, and check
for each expected output with an inner loop, perhaps like this:

const char *cp = buf;
while (*cp) {
for (i = 0; i  ARRAY_SIZE(sig_check); i++) {
if (!prefixcmp(cp, sig_check[i].check) 
parse_gpg_status(sigc, cp, sig_check[i]))
return;
}
cp = strchrnul(cp, '\n');
if (*cp)
cp++;
}

But I do not see much point in doing so.

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v5 1/5] Move commit GPG signature verification to commit.c

2013-03-29 Thread Junio C Hamano
Sebastian Götte ja...@physik.tu-berlin.de writes:

 @@ -230,4 +231,12 @@ extern void print_commit_list(struct commit_list *list,
 const char *format_cur,
 const char *format_last);
  
 +/*
 + * Check the signature of the given commit. The result of the check is 
 stored in
 + * sig-check_result, 'G' for a good signature, 'B' for a bad signature and 
 'N'
 + * for no signature at all.
 + * This may allocate memory for sig-gpg_output, sig-gpg_status, 
 sig-signer and sig-key.
 + */

How wide is your terminal?  These lines are a tad wider than our
standard.  We tend to keep function decls in *.h files on a single
long line (primarily to help people who grep them without using
CTAGS/ETAGS), but everywhere else we try to keep most of our lines
comfortably fit on 80-column terminals.

 +extern void check_commit_signature(const struct commit* commit, struct 
 signature_check *sigc);
 +
  #endif /* COMMIT_H */
 diff --git a/gpg-interface.h b/gpg-interface.h
 index cf99021..44f70aa 100644
 --- a/gpg-interface.h
 +++ b/gpg-interface.h
 @@ -1,6 +1,14 @@
  #ifndef GPG_INTERFACE_H
  #define GPG_INTERFACE_H
  
 +struct signature_check {
 + char *gpg_output;
 + char *gpg_status;
 + char check_result; /* 0 (not checked), N (checked but no further 
 result), G (good) or B (bad) */

Listing the possible values is a good idea, but not on a single
line.

Also now the structure screams with its name that it is about
checking, I do not see a reason for its field to repeat check.
Calling it result (or result_code) would avoid stuttering when
you use them, e.g.

struct signature_check signature_check;

switch (signature_check.check_result) {
...

would be less nice than

switch (signature_check.result) {
...

no?
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v5 3/5] merge/pull: verify GPG signatures of commits being merged

2013-03-29 Thread Junio C Hamano
Sebastian Götte ja...@physik.tu-berlin.de writes:

 + OPT_BOOLEAN(0, verify-signatures, verify_signatures,
 + N_(Verify that the named commit has a valid GPG signature)),

Please use OPT_BOOL() in new code.  Verifying existing OPT_BOOLEAN()
can safely converted to OPT_BOOL() and doing so would be a separate
matter and should not be part of this series.

 @@ -1233,6 +1235,35 @@ int cmd_merge(int argc, const char **argv, const char 
 *prefix)
   usage_with_options(builtin_merge_usage,
   builtin_merge_options);
  
 + if (verify_signatures) {
 + /* Verify the commit signatures */

This boolean variable is named clearly enough that you do not need
this comment.

 + for (p = remoteheads; p; p = p-next) {
 + struct commit *commit = p-item;
 + char hex[41];
 + struct signature_check signature_check;
 + memset(signature_check, 0, sizeof(signature_check));
 +
 + check_commit_signature(commit, signature_check);
 +
 + strcpy(hex, find_unique_abbrev(commit-object.sha1, 
 DEFAULT_ABBREV));
 + switch(signature_check.check_result){
 + case 'G':
 + if (verbosity = 0)
 + printf(_(Commit %s has a good 
 GPG signature by %s (key fingerprint %s)\n), hex, signature_check.signer, 
 signature_check.key);
 + break;
 + case 'B':
 + die(_(Commit %s has a bad GPG 
 signature allegedly by %s (key fingerprint %s).), hex, 
 signature_check.signer, signature_check.key);
 + default: /* 'N' */
 + die(_(Commit %s does not have a good 
 GPG signature. In fact, commit %s does not have a GPG signature at all.), 
 hex, hex);
 + }

Style.

switch (expr) {
case 'G':
do_something_for_G();
break;
...
}

Also avoid overlong lines, both in the source, but pay extra
attention to what we show the user.  For example:

Commit %s has a bad GPG signature allegedly by %s (key fingerprint %s).

The first %s will expand to 40 places, the other two are likely to
be around 20-30 places.

Commit %s does not have a good GPG signature. In fact, commit %s does not 
have a GPG signature at all.

Drop everything from the beginning up to In fact, , perhaps:

Commit '%s' does not have any GPG signature.

is sufficient?  You may also want to consider

die(_(Commit '%.*s...' does not have any GPG signature.),
8, hex);


--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Bug in git rev-parse --verify

2013-03-29 Thread Michael Haggerty
On 03/28/2013 05:52 PM, Junio C Hamano wrote:
 You could force rev-parse to resolve the input to an existing
 object, with something like this:
 
   git rev-parse --verify $ARG^{}
 
 It will unwrap a tag, so the output may end up pointing at a object
 that is different from $ARG in such a case.

Yes, if unwrapping tags is OK then this would work.

 But what is the purpose of turning a random string to a random
 40-hex in the first place?

In non-trivial scripts, it makes sense to convert user input into a
known and verified quantity (SHA1) once, while processing external
inputs, and not have to think about it afterwards.  Verifying and
converting to pure-SHA1s as soon as possible has several advantages:

1. An SHA1 is a canonical representation of the argument, useful for
example as the key in a hash map for for looking for the presence of a
commit in a rev-list output.

2. An SHA1 is persistent.  For example, I use them when caching
benchmark results across versions.  Moreover, they are safe for use in
filenames.  The persistence also makes scripts more robust against
simultaneous changes to the repo by other processes, whereas if I use a
string like branch^ multiple times, there is no guarantee that it
always refers to the same commit.

3. Verifying arguments at one spot centralizes error-checking at the
start of a script and eliminates one reason for random git commands to
fail later (when error recovery is perhaps more difficult).

4. Converting once avoids the overhead of repeated conversion from a
free-form committish into an object name if the argument needs to be
passed to multiple git commands (though presumably the overhead is
insignificant in most cases).

Undoubtedly in many cases this practice of
early-verification-and-conversion is unnecessary, or the same benefit
could be had from either verifying or converting without doing both.
But verifying-and-converting is easy, cheap, and means not having to
decide on a case-by-case basis whether it could have been avoided.

Michael

-- 
Michael Haggerty
mhag...@alum.mit.edu
http://softwareswirl.blogspot.com/
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Bug in git rev-parse --verify

2013-03-29 Thread Junio C Hamano
Michael Haggerty mhag...@alum.mit.edu writes:

 1. An SHA1 is a canonical representation of the argument, useful for
 example as the key in a hash map for for looking for the presence of a
 commit in a rev-list output.

 2. An SHA1 is persistent.  For example, I use them when caching
 benchmark results across versions.  Moreover, they are safe for use in
 filenames.  The persistence also makes scripts more robust against
 simultaneous changes to the repo by other processes, whereas if I use a
 string like branch^ multiple times, there is no guarantee that it
 always refers to the same commit.

These two are half-irrelevant; they only call for use of the current
rev-parse --verify that always gives you 40-hex.  The more
important one is the next one.

 3. Verifying arguments at one spot centralizes error-checking at the
 start of a script and eliminates one reason for random git commands to
 fail later (when error recovery is perhaps more difficult).

Not necessarily, unless your script is a very narrow corner case
that is satisfied with any kind of object goes.  When a parameter
has to be commit for some purpose and another parameter can be any
tree-ish, you would want to validate them _with_ type requirement.

If you are using the object name persistency to create a cache of
how many times the word 'gogopuff' appears in the entire tree?,
you want to cache the result keyed with the object name of the tree,
whether your user gives you v1.8.0 (tag), v1.8.0^0 (commit), or
v1.8.0^{tree} (tree), and you want to unwrap the user input down to
tree object name to look up the pre-computed result for the cache to
be any useful.

 4. Converting once avoids the overhead of repeated conversion from a
 free-form committish into an object name if the argument needs to be
 passed to multiple git commands (though presumably the overhead is
 insignificant in most cases).

True.

So why not verify arguments while making sure of their type early
with 'rev-parse --verify $userinput^{desiredtype}?


--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Bug in git rev-parse --verify

2013-03-29 Thread Junio C Hamano
Junio C Hamano gits...@pobox.com writes:

 3. Verifying arguments at one spot centralizes error-checking at the
 start of a script and eliminates one reason for random git commands to
 fail later (when error recovery is perhaps more difficult).

 Not necessarily, unless your script is a very narrow corner case
 that is satisfied with any kind of object goes.

Clarification.  I meant A single central point to check is a useful
concept, but centrally checking 'does this exist? I do not care what
it is' is not necessarily useful and I suspect it is not useful more
often than it is.  When you care if something exists, you often
want to know what it is and other aspects of that thing at the same
time.

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


You might Select links of london charm bracelet In between An array of Searching

2013-03-29 Thread myhamilton
Kochi along with Trivandrum are the actual popular websites meant for
searching with this specific The lord's Distinctive Condition. Searching
Along with Tamil Nadu. This particular handicrafts associated with Tamil
Nadu may get rid of the drop inside your budget. Towards the top of superb
along with  [b][url=http://buylinksoflondonstore.co.uk/]links of london
friendship bracelet[/url][/b]  elegance, this particular projects tend to be
certainly thrilling along with tempting.




[b]   http://buylinksoflondonstore.co.uk/[/b]





--
View this message in context: 
http://git.661346.n2.nabble.com/You-might-Select-links-of-london-charm-bracelet-In-between-An-array-of-Searching-tp7581098.html
Sent from the git mailing list archive at Nabble.com.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Bug in git rev-parse --verify

2013-03-29 Thread Michael Haggerty
On 03/30/2013 05:09 AM, Junio C Hamano wrote:
 So why not verify arguments while making sure of their type early
 with 'rev-parse --verify $userinput^{desiredtype}?

Yes, that's a better solution in almost all cases.  Thanks for the tip.

(It doesn't change my opinion that the documentation for rev-parse
--verify is misleading, but given that you don't appear to want to
change its behavior I will submit a documentation patch.)

Michael

-- 
Michael Haggerty
mhag...@alum.mit.edu
http://softwareswirl.blogspot.com/
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


thomas sabo sale Are Verified When Obtaining Well-known To Its Avidnes

2013-03-29 Thread cup562013

This is a reasonably irritating thing should you ever're unable to choose a
great reward * thomas sabo charms http://www.cheapthomassaboukshop.co.uk/ 
* goods in your personalized buddy and also cherished one particular,
becoming transferred in nearly special day. The initial thomas sabo charms
listing which comes to your mind and body after all this should be Jones
Sabo. This identification has become incredible into a great style of modern
and stylish necklaces around the globe. Due to this states history the
appropriate method for anyone stress on the options associated with a
present.




*http://www.cheapthomassaboukshop.co.uk/*



--
View this message in context: 
http://git.661346.n2.nabble.com/thomas-sabo-sale-Are-Verified-When-Obtaining-Well-known-To-Its-Avidnes-tp7581100.html
Sent from the git mailing list archive at Nabble.com.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html