[PATCH v4 0/3] git config cache special querying api utilizing the cache

2014-07-02 Thread Tanay Abhra
Hi,

[PATCH v4]: Introduced `config_set` construct which points to a ordered set of
config-files cached as hashmaps. Added relevant API functions. For more
details see the documentation. Rewrote the git_config_get* family to use
`config_set` internally. Added tests for both config_set API and 
git_config_get
family. Added type specific API functions which parses the found value 
and
converts it into a specific type.
Most of the changes implemented are the result of discussion in [6].
Thanks to Eric, Ramsay, Junio, Matthieu  Karsten for their suggestions
and review.


[PATCH v3]: Added flag for NULL values that were causing segfaults in some 
cases.
Added test-config for usage examples.
Minor changes and corrections. Refer to discussion thread[5] for more 
details.
Thanks to Matthieu, Jeff and Junio for their valuable suggestions.

[PATCH v2]:Changed the string_list to a struct instead of pointer to a struct.
Added string-list initilization functions.
Minor mistakes corrected acoording to review comments[4]. Thanks to
Eric and Matthieu for their review.

[PATCH V1]:Most of the invaluable suggestions by Eric Sunshine, Torsten 
Bogershausen and
Jeff King has been implemented[1]. Complete rewrite of config_cache*() 
family
using git_config() as hook as suggested by Jeff. Thanks for the review.

[RFC V2]: Improved according to the suggestions by Eric Sunshine and Torsten 
Bogershausen.
Added cache invalidation when config file is changed.[2]
I am using git_config_set_multivar_in_file() as an update hook.

This is patch is for this year's GSoC. My project is
Git Config API improvements. The link of my proposal is appended below [3].

The aim of this patch series is to generate a cache for querying values from
the config files in a non-callback manner as the current method reads and
parses the config files every time a value is queried for.

The cache is generated from hooking the update_cache function to the current
parsing and callback mechanism in config.c. It is implemented as an hashmap
using the hashmap-api with variables and its corresponding values list as
its members. The values in the list are sorted in order of increasing priority.
The cache is initialised the first time when any of the new query functions is
called. It is invalidated by using git_config_set_multivar_in_file() as an
update hook.

We add two new functions to the config-api, git_config_get_string() and
git_config_get_string_multi() for querying in a non callback manner from
the cache.

[1] http://marc.info/?t=14017206626r=1w=2
[2] 
http://git.661346.n2.nabble.com/RFC-PATCH-0-2-Git-config-cache-amp-special-querying-api-utilizing-the-cache-td7611691.html
[3] 
https://drive.google.com/file/d/0B4suZ-aHqDcnSUZJRXVTTnZUN1E/edit?usp=sharing
[4] http://thread.gmane.org/gmane.comp.version-control.git/251073/focus=251369
[5] http://thread.gmane.org/gmane.comp.version-control.git/251704/
[6] http://thread.gmane.org/gmane.comp.version-control.git/252329/

Tanay Abhra (2):
  config-hash.c
  test-config

 .gitignore |   1 +
 Documentation/technical/api-config.txt | 144 
 Makefile   |   2 +
 cache.h|  41 
 config-hash.c  | 405 +
 config.c   |   3 +
 t/t1308-config-hash.sh | 163 +
 test-config.c  | 129 +++
 8 files changed, 888 insertions(+)
 create mode 100644 config-hash.c
 create mode 100755 t/t1308-config-hash.sh
 create mode 100644 test-config.c

-- 
1.9.0.GIT

--
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 v4 1/2] add `config_set` API for caching config files

2014-07-02 Thread Tanay Abhra
Currently `git_config()` uses a callback mechanism and file rereads for
config values. Due to this approach, it is not uncommon for the config
files to be parsed several times during the run of a git program, with
different callbacks picking out different variables useful to themselves.

Add a `config_set` construct that points to an ordered set of config files
specified by the user, each of which represents what was read and cached
in core as hashmaps. Add two external functions `git_configset_get_value`
and `git_configset_get_value_multi` for querying from the config sets,
which follow `last one wins` semantic(i.e. if there are multiple matches
for the queried key in the files of the configset the value returned will
the last value in the last matching file of the configset) Add type
specific query functions like `git_configset_get_bool` and similar.

Add a default `config_set`, `the_config_set` to cache all key-value pairs
read from usual config files(repo specific .git/config, user wide
~/.gitconfig and the global /etc/gitconfig). `the_config_set` uses a
single hashmap populated using git_config(). The reason for doing so is
twofold, one is to honour include directives, another is to guarantee O(1)
lookups for usual config values, as values are queried for hundred of
times during a run of a git program.
Add two external functions `git_config_get_value` and 
`git_config_get_value_multi` for querying in a non-callback manner from
`the_config_set`. Also, add type specific query functions that are
implemented as a thin wrapper around the `config_set` API.

Signed-off-by: Tanay Abhra tanay...@gmail.com
---
 Documentation/technical/api-config.txt | 144 
 Makefile   |   1 +
 cache.h|  41 
 config-hash.c  | 405 +
 config.c   |   3 +
 5 files changed, 594 insertions(+)
 create mode 100644 config-hash.c

diff --git a/Documentation/technical/api-config.txt 
b/Documentation/technical/api-config.txt
index 230b3a0..2c02fee 100644
--- a/Documentation/technical/api-config.txt
+++ b/Documentation/technical/api-config.txt
@@ -77,6 +77,75 @@ To read a specific file in git-config format, use
 `git_config_from_file`. This takes the same callback and data parameters
 as `git_config`.
 
+Querying For Specific Variables
+---
+
+For programs wanting to query for specific variables in a non-callback
+manner, the config API provides two functions `git_config_get_value`
+and `git_config_get_value_multi`.They both read values from an internal
+cache generated previously from reading the config files.
+
+`git_config_get_value` takes two parameters,
+
+- a key string in canonical flat form for which the corresponding value
+  with the highest priority (i.e. value in the repo config will be
+  preferred over value in user wide config for the same variable) will
+  be retrieved.
+
+- a pointer to a string which will point to the retrieved value. The caller
+  should not free or modify the value returned as it is owned by the cache.
+
+`git_config_get_value` returns 0 on success, or -1 for no value found.
+
+`git_config_get_value_multi` allocates and returns a `string_list`
+containing all the values for the key passed as parameter, sorted in order
+of increasing priority (Note: caller has to call `string_list_clear` on
+the returned pointer and then free it).
+
+`git_config_get_value_multi` returns NULL for no value found.
+
+`git_config_clear` is provided for resetting and invalidating the cache.
+
+`git_config_iter` gives a way to iterate over the keys in cache. Existing
+`git_config` callback function signature is used for iterating.
+
+The config API also provides type specific API functions which do conversion
+as well as retrieval for the queried variable, including:
+
+`git_config_get_int`::
+Parse the retrieved value to an integer, including unit factors. Dies on
+error; otherwise, allocates and copies the integer into the dest parameter.
+Returns 0 on success, or 1 if no value was found.
+
+`git_config_get_ulong`::
+Identical to `git_config_get_int` but for unsigned longs.
+
+`git_config_bool`::
+Parse the retrieved value into a boolean value, respecting keywords like
+true and false. Integer values are converted into true/false values
+(when they are non-zero or zero, respectively). Other values cause a die().
+If parsing is successful, allocates and copies the result into the dest
+parameter. Returns 0 on success, or 1 if no value is found.
+
+`git_config_get_bool_or_int`::
+Same as `git_config_get_bool`, except that integers are copied as-is, and
+an `is_bool` flag is unset.
+
+`git_config_get_maybe_bool`::
+Same as `git_config_get_bool`, except that it returns -1 on error rather
+than dying.
+
+`git_config_get_string`::
+Allocates and copies the retrieved value string into the `dest` parameter;
+if NULL string is given, prints an error 

[PATCH 2/2] test-config: Add tests for the config_set API

2014-07-02 Thread Tanay Abhra
Expose the `config_set` C API as a set of simple commands in order to
facilitate testing. Add tests for the `config_set` API as well as for
`git_config_get_*()` family for the usual config files.

Signed-off-by: Tanay Abhra tanay...@gmail.com
---
 .gitignore |   1 +
 Makefile   |   1 +
 t/t1308-config-hash.sh | 163 +
 test-config.c  | 129 ++
 4 files changed, 294 insertions(+)
 create mode 100755 t/t1308-config-hash.sh
 create mode 100644 test-config.c

diff --git a/.gitignore b/.gitignore
index 42294e5..eeb66e2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -176,6 +176,7 @@
 /gitweb/static/gitweb.js
 /gitweb/static/gitweb.min.*
 /test-chmtime
+/test-config
 /test-ctype
 /test-date
 /test-delta
diff --git a/Makefile b/Makefile
index d503f78..e875070 100644
--- a/Makefile
+++ b/Makefile
@@ -548,6 +548,7 @@ X =
 PROGRAMS += $(patsubst %.o,git-%$X,$(PROGRAM_OBJS))
 
 TEST_PROGRAMS_NEED_X += test-chmtime
+TEST_PROGRAMS_NEED_X += test-config
 TEST_PROGRAMS_NEED_X += test-ctype
 TEST_PROGRAMS_NEED_X += test-date
 TEST_PROGRAMS_NEED_X += test-delta
diff --git a/t/t1308-config-hash.sh b/t/t1308-config-hash.sh
new file mode 100755
index 000..6c059c5
--- /dev/null
+++ b/t/t1308-config-hash.sh
@@ -0,0 +1,163 @@
+#!/bin/sh
+
+test_description='Test git config-hash API in different settings'
+
+. ./test-lib.sh
+
+test_expect_success 'clear default config' '
+   rm -f .git/config
+'
+
+cat  .git/config  EOF
+[core]
+   penguin = very blue
+   Movie = BadPhysics
+   UPPERCASE = true
+   MixedCase = true
+   my =
+   foo
+   baz = sam
+[Cores]
+   WhatEver = Second
+[my Foo bAr]
+   hi = hello
+[core]
+   baz = bat
+   baz = hask
+[lamb]
+   chop = 65
+   head = none
+[goat]
+   legs = 4
+   head = true
+   skin = false
+   nose = 1
+   horns
+EOF
+
+test_expect_success 'get value for a simple key' '
+   echo very blue expect 
+   test-config get_value core.penguin actual 
+   test_cmp expect actual
+'
+
+test_expect_success 'get value for a key with value as an empty string' '
+   echo  expect 
+   test-config get_value core.my actual 
+   test_cmp expect actual
+'
+
+test_expect_success 'get value for a key with value as NULL' '
+   echo (NULL) expect 
+   test-config get_value core.foo actual 
+   test_cmp expect actual
+'
+test_expect_success 'upper case key' '
+   echo true expect 
+   test-config get_value core.UPPERCASE actual 
+   test_cmp expect actual
+'
+test_expect_success 'mixed case key' '
+   echo true expect 
+   test-config get_value core.MixedCase actual 
+   test_cmp expect actual
+'
+test_expect_success 'key and value with mixed case' '
+   echo BadPhysics expect 
+   test-config get_value core.Movie actual 
+   test_cmp expect actual
+'
+
+test_expect_success 'key with case sensitive subsection' '
+   echo hello expect 
+   test-config get_value my.Foo bAr.hiactual 
+   test_cmp expect actual
+'
+
+test_expect_success 'find value with misspelled key' '
+   echo Value not found for \my.fOo Bar.hi\ expect 
+   test_must_fail test-config get_value my.fOo Bar.hiactual 
+   test_cmp expect actual
+'
+
+test_expect_success 'find value with the highest priority' '
+   echo hask expect 
+   test-config get_value core.bazactual 
+   test_cmp expect actual
+'
+
+test_expect_success 'find integer value for a key' '
+   echo 65 expect 
+   test-config get_int lamb.chop actual 
+   test_cmp expect actual
+'
+
+test_expect_success 'find integer if value is non parse-able' '
+   echo 65 expect 
+   test_must_fail test-config get_int lamb.head actual 
+   test_must_fail test_cmp expect actual
+'
+
+cat  expect  EOF
+1
+0
+1
+1
+1
+EOF
+
+test_expect_success 'find bool value for the entered key' '
+   test-config get_bool goat.head actual 
+   test-config get_bool goat.skin actual 
+   test-config get_bool goat.nose actual 
+   test-config get_bool goat.horns actual 
+   test-config get_bool goat.legs actual 
+   test_cmp expect actual
+'
+
+cat  expect  EOF
+sam
+bat
+hask
+EOF
+
+test_expect_success 'find multiple values' '
+   test-config get_value_multi core.bazactual 
+   test_cmp expect actual
+'
+
+cat  config2  EOF
+[core]
+   baz = lama
+[my]
+   new = silk
+[core]
+   baz = ball
+EOF
+
+test_expect_success 'find value from a configset' '
+   echo silk  expect 
+   test-config configset_get_value 2 config2 .git/config my.new actual 
+   test_cmp expect actual
+'
+
+test_expect_success 'find value with highest priority from a configset' '
+   echo hask  expect 
+   test-config configset_get_value 2 config2 .git/config core.baz actual 

+   test_cmp expect actual
+'
+
+cat  except  EOF
+sam
+bat
+hask
+lama
+ball
+EOF
+

[PATCH] git-am: add option to extract email Message-Id: tag into commit log

2014-07-02 Thread Avi Kivity
Some workflows prefer to track exactly which email message was used to
generate a commit.  This can be used, for example, to generate an
automated acknowledgement when a patch is committed as a response to
the patch email, or as a reference to the thread which introduced the
patch.

Support this by adding a --message-id option (abbreviated as -m) to
git-am, which will then extract the message ID and append it to the
email commit log.

Signed-off-by: Avi Kivity a...@cloudius-systems.com
---
 Documentation/git-am.txt |  6 ++
 builtin/mailinfo.c   |  2 +-
 git-am.sh| 10 +-
 3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt
index 9adce37..8a251a1 100644
--- a/Documentation/git-am.txt
+++ b/Documentation/git-am.txt
@@ -15,6 +15,7 @@ SYNOPSIS
 [--whitespace=option] [-Cn] [-pn] [--directory=dir]
 [--exclude=path] [--include=path] [--reject] [-q | --quiet]
 [--[no-]scissors] [-S[keyid]] [--patch-format=format]
+[--message-id]
 [(mbox | Maildir)...]
 'git am' (--continue | --skip | --abort)
 
@@ -121,6 +122,11 @@ default.   You can use `--no-utf8` to override this.
user to lie about the author date by using the same
value as the committer date.
 
+-m::
+--message-id::
+   Extract the Message-Id: header from the e-mail and
+   append it to the commit message's tag stanza.
+
 --skip::
Skip the current patch.  This is only meaningful when
restarting an aborted patch.
diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c
index cf11c8d..f1e1fed 100644
--- a/builtin/mailinfo.c
+++ b/builtin/mailinfo.c
@@ -278,7 +278,7 @@ static void cleanup_space(struct strbuf *sb)
 
 static void decode_header(struct strbuf *line);
 static const char *header[MAX_HDR_PARSED] = {
-   From,Subject,Date,
+   From,Subject,Date,Message-Id
 };
 
 static inline int cmp_header(const struct strbuf *line, const char *hdr)
diff --git a/git-am.sh b/git-am.sh
index ee61a77..22799ff 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -39,6 +39,7 @@ committer-date-is-author-datelie about committer date
 ignore-date use current timestamp for author date
 rerere-autoupdate update the index with reused conflict resolution if possible
 S,gpg-sign? GPG-sign commits
+m,message-idcopy the Message-Id: header to the commit's tag stanza
 rebasing*   (internal use for git-rebase)
 
 . git-sh-setup
@@ -371,7 +372,7 @@ split_patches () {
 prec=4
 dotest=$GIT_DIR/rebase-apply
 sign= utf8=t keep= keepcr= skip= interactive= resolved= rebasing= abort=
-resolvemsg= resume= scissors= no_inbody_headers=
+resolvemsg= resume= scissors= no_inbody_headers= message_id=
 git_apply_opt=
 committer_date_is_author_date=
 ignore_date=
@@ -442,6 +443,8 @@ it will be removed. Please do not use it anymore.
gpg_sign_opt=-S ;;
--gpg-sign=*)
gpg_sign_opt=-S${1#--gpg-sign=} ;;
+   -m|--message-id)
+   message_id=t ;;
--)
shift; break ;;
*)
@@ -565,6 +568,7 @@ Use \git am --abort\ to remove it.)
echo  $git_apply_opt $dotest/apply-opt
echo $threeway $dotest/threeway
echo $sign $dotest/sign
+   echo $message_id  $dotest/message-id
echo $utf8 $dotest/utf8
echo $keep $dotest/keep
echo $scissors $dotest/scissors
@@ -757,6 +761,10 @@ To restore the original branch and stop patching run 
\\$cmdline --abort\.
then
cat $dotest/msg-clean
fi
+   if test 't' == $message_id
+   then
+   grep ^Message-Id: $dotest/info
+   fi
if test '' != $ADD_SIGNOFF
then
echo $ADD_SIGNOFF
-- 
1.9.3

--
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 v2] git-am: add option to extract email Message-Id: tag into commit log

2014-07-02 Thread Avi Kivity
Some workflows prefer to track exactly which email message was used to
generate a commit.  This can be used, for example, to generate an
automated acknowledgement when a patch is committed as a response to
the patch email, or as a reference to the thread which introduced the
patch.

Support this by adding a --message-id option (abbreviated as -m) to
git-am, which will then extract the message ID and append it to the
email commit log.

Signed-off-by: Avi Kivity a...@cloudius-systems.com
---

v2: adjust to pass test suite (t5100)

 Documentation/git-am.txt |  6 ++
 builtin/mailinfo.c   |  2 +-
 git-am.sh| 10 +-
 t/t5100/info0004 |  1 +
 t/t5100/info0005 |  1 +
 t/t5100/info0012 |  1 +
 6 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt
index 9adce37..8a251a1 100644
--- a/Documentation/git-am.txt
+++ b/Documentation/git-am.txt
@@ -15,6 +15,7 @@ SYNOPSIS
 [--whitespace=option] [-Cn] [-pn] [--directory=dir]
 [--exclude=path] [--include=path] [--reject] [-q | --quiet]
 [--[no-]scissors] [-S[keyid]] [--patch-format=format]
+[--message-id]
 [(mbox | Maildir)...]
 'git am' (--continue | --skip | --abort)
 
@@ -121,6 +122,11 @@ default.   You can use `--no-utf8` to override this.
user to lie about the author date by using the same
value as the committer date.
 
+-m::
+--message-id::
+   Extract the Message-Id: header from the e-mail and
+   append it to the commit message's tag stanza.
+
 --skip::
Skip the current patch.  This is only meaningful when
restarting an aborted patch.
diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c
index cf11c8d..f1e1fed 100644
--- a/builtin/mailinfo.c
+++ b/builtin/mailinfo.c
@@ -278,7 +278,7 @@ static void cleanup_space(struct strbuf *sb)
 
 static void decode_header(struct strbuf *line);
 static const char *header[MAX_HDR_PARSED] = {
-   From,Subject,Date,
+   From,Subject,Date,Message-Id
 };
 
 static inline int cmp_header(const struct strbuf *line, const char *hdr)
diff --git a/git-am.sh b/git-am.sh
index ee61a77..c0e7bdd 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -39,6 +39,7 @@ committer-date-is-author-datelie about committer date
 ignore-date use current timestamp for author date
 rerere-autoupdate update the index with reused conflict resolution if possible
 S,gpg-sign? GPG-sign commits
+m,message-idcopy the Message-Id: header to the commit's tag stanza
 rebasing*   (internal use for git-rebase)
 
 . git-sh-setup
@@ -371,7 +372,7 @@ split_patches () {
 prec=4
 dotest=$GIT_DIR/rebase-apply
 sign= utf8=t keep= keepcr= skip= interactive= resolved= rebasing= abort=
-resolvemsg= resume= scissors= no_inbody_headers=
+resolvemsg= resume= scissors= no_inbody_headers= message_id=
 git_apply_opt=
 committer_date_is_author_date=
 ignore_date=
@@ -442,6 +443,8 @@ it will be removed. Please do not use it anymore.
gpg_sign_opt=-S ;;
--gpg-sign=*)
gpg_sign_opt=-S${1#--gpg-sign=} ;;
+   -m|--message-id)
+   message_id=t ;;
--)
shift; break ;;
*)
@@ -565,6 +568,7 @@ Use \git am --abort\ to remove it.)
echo  $git_apply_opt $dotest/apply-opt
echo $threeway $dotest/threeway
echo $sign $dotest/sign
+   echo $message_id  $dotest/message-id
echo $utf8 $dotest/utf8
echo $keep $dotest/keep
echo $scissors $dotest/scissors
@@ -757,6 +761,10 @@ To restore the original branch and stop patching run 
\\$cmdline --abort\.
then
cat $dotest/msg-clean
fi
+   if test 't' == $message_id
+   then
+   grep ^Message-Id: $dotest/info || true
+   fi
if test '' != $ADD_SIGNOFF
then
echo $ADD_SIGNOFF
diff --git a/t/t5100/info0004 b/t/t5100/info0004
index 616c309..f7e2983 100644
--- a/t/t5100/info0004
+++ b/t/t5100/info0004
@@ -2,4 +2,5 @@ Author: YOSHIFUJI Hideaki / 吉藤英明
 Email: yoshf...@linux-ipv6.org
 Subject: GIT: Try all addresses for given remote name
 Date: Thu, 21 Jul 2005 09:10:36 -0400 (EDT)
+Message-Id: 20050721.091036.01119516.yoshf...@linux-ipv6.org
 
diff --git a/t/t5100/info0005 b/t/t5100/info0005
index 46a46fc..592388f 100644
--- a/t/t5100/info0005
+++ b/t/t5100/info0005
@@ -2,4 +2,5 @@ Author: David Kågedal
 Email: dav...@lysator.liu.se
 Subject: Fixed two bugs in git-cvsimport-script.
 Date: Mon, 15 Aug 2005 20:18:25 +0200
+Message-Id: u5tacjjdpxq@lysator.liu.se
 
diff --git a/t/t5100/info0012 b/t/t5100/info0012
index ac1216f..b5d89a1 100644
--- a/t/t5100/info0012
+++ b/t/t5100/info0012
@@ -2,4 +2,5 @@ Author: Dmitriy Blinov
 Email: b...@mnsspb.ru
 Subject: Изменён список пакетов необходимых для сборки
 Date: Wed, 12 Nov 2008 17:54:41 +0300
+Message-Id: 

Re: [PATCH v4 1/2] add `config_set` API for caching config files

2014-07-02 Thread Matthieu Moy
Tanay Abhra tanay...@gmail.com writes:

 Add a `config_set` construct that points to an ordered set of config files
 specified by the user, each of which represents what was read and cached
 in core as hashmaps. Add two external functions `git_configset_get_value`
 and `git_configset_get_value_multi` for querying from the config sets,
 which follow `last one wins` semantic(i.e. if there are multiple matches

Space before (

 for the queried key in the files of the configset the value returned will
 the last value in the last matching file of the configset) Add type

will _be_ ?

Does this remark also apply to git_configset_get_value_multi? My
understanding was that last one wins applied only to
git_configset_get_value.

 Add a default `config_set`, `the_config_set` to cache all key-value pairs

I don't like the name the_config_set. It's not the only one. Perhaps
repo_config_set? (not totally satisfactory as it does not contain only
the repo, but the repo+user+system)

What do others think?

 read from usual config files(repo specific .git/config, user wide

(You always forget space before '('...)

 ~/.gitconfig and the global /etc/gitconfig). `the_config_set` uses a
 single hashmap populated using git_config(). The reason for doing so is
 twofold, one is to honour include directives, another is to guarantee O(1)
 lookups for usual config values, as values are queried for hundred of
 times during a run of a git program.

What is the reason to deal with `the_config_set` and other config sets
differently? You're giving arguments to store `the_config_set` as a
single hashmap, but what is the reason to store others as multiple
hashmaps?

And actually, I don't completely buy your arguments: having 3 or 4
hashmaps (.git/config, ~/.gitconfig, ~/.config/git/config and
/etc/gitconfig) would be a O(4) lookup, which is still O(1), and you
could deal with include directives by having .git/config and included
files in a hashmap, ~/.gitconfig and included files in a second
hashmap, ...

My guess is that the real argument is git_config already does what I
want and I'm too lazy to change it. And I do consider lazyness as a
quality for a computer-scientist ;-).

I would personally find it much simpler to have a single hashmap. We'd
lose the ability to invalidate the cache for only a single file, but I'm
not sure it's worth the code complexity.

 +Querying For Specific Variables
 +---
 +
 +For programs wanting to query for specific variables in a non-callback
 +manner, the config API provides two functions `git_config_get_value`
 +and `git_config_get_value_multi`.They both read values from an internal

Space after .

 +`git_config_iter` gives a way to iterate over the keys in cache. Existing
 +`git_config` callback function signature is used for iterating.

Existing refers to the old state. It's OK in a commit message, but
won't make sense in the future, when your non-callback API and the old
callback API will live side by side.

 +The config API also provides type specific API functions which do conversion
 +as well as retrieval for the queried variable, including:
 +
 +`git_config_get_int`::
 +Parse the retrieved value to an integer, including unit factors. Dies on
 +error; otherwise, allocates and copies the integer into the dest parameter.
 +Returns 0 on success, or 1 if no value was found.

It seems strange to me to return 1 here, and -1 in git_config_get_value
to mean the same thing.

 +`git_config_bool`::

Isn't it git_config_get_bool?

 +/* config-hash.c */

You may point to the documentation in the comment too.

 +#define CONFIG_SET_INIT { NULL, 0, 0 }
 +
 +struct config_set {
 + struct config_set_item *item;
 + unsigned int nr, alloc;
 +};
 +
 +struct config_set_item {
 + struct hashmap config_hash;
 + char *filename;

Perhaps const char *?

 +static struct hashmap *add_config_hash(const char *filename, struct 
 config_set *cs)
 +{
 + int ret = 0;
 + struct config_set_item *ct;
 + struct config_set_cb cb;
 + ALLOC_GROW(cs-item, cs-nr + 1, cs-alloc);
 + ct = cs-item[cs-nr++];
 + ct-filename = xstrdup(filename);
 + config_hash_init(ct-config_hash);
 + cb.cs = cs;
 + cb.ct = ct;
 + /*
 +  * When filename is default, hashmap is constructed from the usual 
 set of
 +  * config files (i.e repo specific .git/config, user wide ~/.gitconfig 
 and the
 +  * global /etc/gitconfig), used in `the_config_set`
 +  */
 + if (!strcmp(filename, default))

How does one read a file actually called default with this API?

More generally, why do you need a special-case here? I think it would be
much better to leave this part unaware of the default, and have a
separate function like create_repo_config_hash (or
create_the_config_hash) that would call git_config(...). There actually
isn't much shared code between the default case and the others in your
function.

 +static struct hashmap *get_config_hash(const char *filename, struct 
 

Re: [PATCH 2/2] test-config: Add tests for the config_set API

2014-07-02 Thread Matthieu Moy
Tanay Abhra tanay...@gmail.com writes:

 +test_expect_success 'clear default config' '
 + rm -f .git/config
 +'
 +
 +cat  .git/config  EOF

t/README says:

 - Put all code inside test_expect_success and other assertions.

   Even code that isn't a test per se, but merely some setup code
   should be inside a test assertion.

Even these cat  would better be in a test_expect_success 'initialize
config'.

(Not applied everywhere in Git's code essentially because some tests
were written before the guideline was set and never updated).

 +[core]
 + penguin = very blue
 + Movie = BadPhysics
 + UPPERCASE = true
 + MixedCase = true
 + my =
 + foo
 + baz = sam
 +[Cores]
 + WhatEver = Second
 +[my Foo bAr]
 + hi = hello

To really stress the case sensitive middle part case, you should also
have other sections like

[my foo bar]
hi = lower-case
[my FOO BAR]
hi = upper-case

and check that you get the right value for my.*.hi

Similarly, I'd add a [CORE] and a [CoRe] section to check that their
content is actually merged with [core].

 +test_expect_success 'get value for a key with value as an empty string' '
 + echo  expect 
 + test-config get_value core.my actual 
 + test_cmp expect actual
 +'
 +
 +test_expect_success 'get value for a key with value as NULL' '
 + echo (NULL) expect 
 + test-config get_value core.foo actual 
 + test_cmp expect actual
 +'
 +test_expect_success 'upper case key' '

Keep the style consistent, if you separate tests with a single blank
line, do it everywhere.

 +cat  expect  EOF

See above, should be in test_expect_success.

Also, expect, not  expect.

There are other instances.

 +1
 +0
 +1
 +1
 +1
 +EOF
 +
 +test_expect_success 'find bool value for the entered key' '
 + test-config get_bool goat.head actual 

The first one should be a single , or you should clear actual before
the test.

 +int main(int argc, char **argv)
 +{
 + int i, no_of_files;
 + int ret = 0;
 + const char *v;
 + int val;
 + const struct string_list *strptr;
 + struct config_set cs = CONFIG_SET_INIT;



 + if (argc == 3  !strcmp(argv[1], get_value)) {
 + if (!git_config_get_value(argv[2], v)) {
 + if (!v)
 + printf((NULL)\n);
 + else
 + printf(%s\n, v);
 + return 0;
 + } else {
 + printf(Value not found for \%s\\n, argv[2]);
 + return -1;
 + }
 + } else if (argc == 3  !strcmp(argv[1], get_value_multi)) {
 + strptr = git_config_get_value_multi(argv[2]);
 + if (strptr) {
 + for (i = 0; i  strptr-nr; i++) {
 + v = strptr-items[i].string;
 + if (!v)
 + printf((NULL)\n);
 + else
 + printf(%s\n, v);
 + }
 + return 0;
 + } else {
 + printf(Value not found for \%s\\n, argv[2]);
 + return -1;
 + }
 + } else if (argc == 3  !strcmp(argv[1], get_int)) {
 + if (!git_config_get_int(argv[2], val)) {
 + printf(%d\n, val);
 + return 0;
 + } else {
 + printf(Value not found for \%s\\n, argv[2]);
 + return -1;
 + }
 + } else if (argc == 3  !strcmp(argv[1], get_bool)) {
 + if (!git_config_get_bool(argv[2], val)) {
 + printf(%d\n, val);
 + return 0;
 + } else {
 + printf(Value not found for \%s\\n, argv[2]);
 + return -1;
 + }
 + } else if (!strcmp(argv[1], configset_get_value)) {
 + no_of_files = git_config_int(unused, argv[2]);

Why ask the user to give a number of files on the command-line. With a
syntax like

test-config configset_get_value key files...

you could just use argc to iterate over argv. Here, you trust the user
to provide the right value, and most likely segfault otherwise (and this
is not really documented). I know this is only test code, but why not do
it right anyway ;-).

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/
--
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 v2] git-am: add option to extract email Message-Id: tag into commit log

2014-07-02 Thread Torsten Bögershausen
 --- a/git-am.sh
 +++ b/git-am.sh
 @@ -39,6 +39,7 @@ committer-date-is-author-datelie about committer date
  ignore-date use current timestamp for author date
  rerere-autoupdate update the index with reused conflict resolution if 
 possible
  S,gpg-sign? GPG-sign commits
 +m,message-idcopy the Message-Id: header to the commit's tag stanza
  rebasing*   (internal use for git-rebase)
  
  . git-sh-setup
 @@ -371,7 +372,7 @@ split_patches () {
  prec=4
  dotest=$GIT_DIR/rebase-apply
  sign= utf8=t keep= keepcr= skip= interactive= resolved= rebasing= abort=
 -resolvemsg= resume= scissors= no_inbody_headers=
 +resolvemsg= resume= scissors= no_inbody_headers= message_id=
  git_apply_opt=
  committer_date_is_author_date=
  ignore_date=
 @@ -442,6 +443,8 @@ it will be removed. Please do not use it anymore.
   gpg_sign_opt=-S ;;
   --gpg-sign=*)
   gpg_sign_opt=-S${1#--gpg-sign=} ;;
 + -m|--message-id)
 + message_id=t ;;
   --)
   shift; break ;;
   *)
 @@ -565,6 +568,7 @@ Use \git am --abort\ to remove it.)
   echo  $git_apply_opt $dotest/apply-opt
   echo $threeway $dotest/threeway
   echo $sign $dotest/sign
 + echo $message_id  $dotest/message-id
   echo $utf8 $dotest/utf8
   echo $keep $dotest/keep
   echo $scissors $dotest/scissors
 @@ -757,6 +761,10 @@ To restore the original branch and stop patching run 
 \\$cmdline --abort\.
   then
   cat $dotest/msg-clean
   fi
 + if test 't' == $message_id

The == is bash special, please use = instead
And the 't' can be written as t, so that the whole line looks like this:
if test t = $message_id

--
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 v4 1/2] add `config_set` API for caching config files

2014-07-02 Thread Tanay Abhra


On 7/2/2014 2:44 PM, Matthieu Moy wrote:
 Tanay Abhra tanay...@gmail.com writes:
 
 Add a `config_set` construct that points to an ordered set of config files
 specified by the user, each of which represents what was read and cached
 in core as hashmaps. Add two external functions `git_configset_get_value`
 and `git_configset_get_value_multi` for querying from the config sets,
 which follow `last one wins` semantic(i.e. if there are multiple matches
 
 Space before (
 

Noted. Sorry about that.

 for the queried key in the files of the configset the value returned will
 the last value in the last matching file of the configset) Add type

 Does this remark also apply to git_configset_get_value_multi? My
 understanding was that last one wins applied only to
 git_configset_get_value.
 

Maybe a reworded sentence may work,
`git_configset_get_value_multi` returns a list of values sorted in order of
increasing priority (i.e. last match will be at the end of the list.)

 Add a default `config_set`, `the_config_set` to cache all key-value pairs
 
 I don't like the name the_config_set. It's not the only one. Perhaps
 repo_config_set? (not totally satisfactory as it does not contain only
 the repo, but the repo+user+system)
 
 What do others think?
 
 read from usual config files(repo specific .git/config, user wide
 ~/.gitconfig and the global /etc/gitconfig). `the_config_set` uses a
 single hashmap populated using git_config(). The reason for doing so is
 twofold, one is to honour include directives, another is to guarantee O(1)
 lookups for usual config values, as values are queried for hundred of
 times during a run of a git program.
 
 What is the reason to deal with `the_config_set` and other config sets
 differently? You're giving arguments to store `the_config_set` as a
 single hashmap, but what is the reason to store others as multiple
 hashmaps?
 
 And actually, I don't completely buy your arguments: having 3 or 4
 hashmaps (.git/config, ~/.gitconfig, ~/.config/git/config and
 /etc/gitconfig) would be a O(4) lookup, which is still O(1), and you
 could deal with include directives by having .git/config and included
 files in a hashmap, ~/.gitconfig and included files in a second
 hashmap, ...
 
 My guess is that the real argument is git_config already does what I
 want and I'm too lazy to change it. And I do consider lazyness as a
 quality for a computer-scientist ;-).
 
 I would personally find it much simpler to have a single hashmap. We'd
 lose the ability to invalidate the cache for only a single file, but I'm
 not sure it's worth the code complexity.
 

Point noted. I can take the multiple hashmap route for `the_config_set`.
Still, since it will be the most used config set in the code and for each
query it would have to look through n hashmaps hampering performance. I
can change it if you want but like you, I don't think it is worth the code
complexity.

 +Querying For Specific Variables
 +---
 +
 +For programs wanting to query for specific variables in a non-callback
 +manner, the config API provides two functions `git_config_get_value`
 +and `git_config_get_value_multi`. They both read values from an internal
 +`git_config_iter` gives a way to iterate over the keys in cache. Existing
 +`git_config` callback function signature is used for iterating.
 
 Existing refers to the old state. It's OK in a commit message, but
 won't make sense in the future, when your non-callback API and the old
 callback API will live side by side.


Noted.

 +The config API also provides type specific API functions which do conversion
 +as well as retrieval for the queried variable, including:
 +
 +`git_config_get_int`::
 +Parse the retrieved value to an integer, including unit factors. Dies on
 +error; otherwise, allocates and copies the integer into the dest parameter.
 +Returns 0 on success, or 1 if no value was found.
 
 It seems strange to me to return 1 here, and -1 in git_config_get_value
 to mean the same thing.
 

Noted. Some of the type specific function return -1 on wrong parsing, I will
put return value 1 for no value found in all of the cases.

 +`git_config_bool`::
 +/* config-hash.c */

 +#define CONFIG_SET_INIT { NULL, 0, 0 }
 +
 +struct config_set {
 +struct config_set_item *item;
 +unsigned int nr, alloc;
 +};
 +
 +struct config_set_item {
 +struct hashmap config_hash;
 +char *filename;
 +static struct hashmap *add_config_hash(const char *filename, struct 
 config_set *cs)
 +{
 +int ret = 0;
 +struct config_set_item *ct;
 +struct config_set_cb cb;
 +ALLOC_GROW(cs-item, cs-nr + 1, cs-alloc);
 +ct = cs-item[cs-nr++];
 +ct-filename = xstrdup(filename);
 +config_hash_init(ct-config_hash);
 +cb.cs = cs;
 +cb.ct = ct;
 +/*
 + * When filename is default, hashmap is constructed from the usual 
 set of
 + * config files (i.e repo specific .git/config, user wide ~/.gitconfig 
 and the
 + * global /etc/gitconfig), used 

Re: [PATCH 2/2] test-config: Add tests for the config_set API

2014-07-02 Thread Tanay Abhra


On 7/2/2014 2:59 PM, Matthieu Moy wrote:
 Tanay Abhra tanay...@gmail.com writes:
 
 +test_expect_success 'clear default config' '
 +rm -f .git/config
 +'
 +
 +cat  .git/config  EOF
 
 t/README says:
 
  - Put all code inside test_expect_success and other assertions.
 
Even code that isn't a test per se, but merely some setup code
should be inside a test assertion.
 
 Even these cat  would better be in a test_expect_success 'initialize
 config'.
 
 (Not applied everywhere in Git's code essentially because some tests
 were written before the guideline was set and never updated).

Sorry about that. I followed t1300-repo-config.sh which has these mistakes
also.

 +[core]
 +penguin = very blue
 +Movie = BadPhysics
 +UPPERCASE = true
 +MixedCase = true
 +my =
 +foo
 +baz = sam
 +[Cores]
 +WhatEver = Second
 +[my Foo bAr]
 +hi = hello
 
 To really stress the case sensitive middle part case, you should also
 have other sections like
 
 [my foo bar]
   hi = lower-case
 [my FOO BAR]
   hi = upper-case
 
 and check that you get the right value for my.*.hi
 
 Similarly, I'd add a [CORE] and a [CoRe] section to check that their
 content is actually merged with [core].


Noted.

 +test_expect_success 'get value for a key with value as an empty string' '
 +echo  expect 
 +test-config get_value core.my actual 
 +test_cmp expect actual
 +'
 +
 +test_expect_success 'get value for a key with value as NULL' '
 +echo (NULL) expect 
 +test-config get_value core.foo actual 
 +test_cmp expect actual
 +'
 +test_expect_success 'upper case key' '
 
 Keep the style consistent, if you separate tests with a single blank
 line, do it everywhere.
 
 +cat  expect  EOF
 
 See above, should be in test_expect_success.
 
 Also, expect, not  expect.
 
 There are other instances.


Noted. Again copied t1300-repo-config.sh style for cat.

 +1
 +0
 +1
 +1
 +1
 +EOF
 +
 +test_expect_success 'find bool value for the entered key' '
 +test-config get_bool goat.head actual 
 
 The first one should be a single , or you should clear actual before
 the test.
 

Noted.

 +int main(int argc, char **argv)
 +{
 +int i, no_of_files;
 +int ret = 0;
 +const char *v;
 +int val;
 +const struct string_list *strptr;
 +struct config_set cs = CONFIG_SET_INIT;
 
 
 
 +if (argc == 3  !strcmp(argv[1], get_value)) {
 +if (!git_config_get_value(argv[2], v)) {
 +if (!v)
 +printf((NULL)\n);
 +else
 +printf(%s\n, v);
 +return 0;
 +} else {
 +printf(Value not found for \%s\\n, argv[2]);
 +return -1;
 +}
 +} else if (argc == 3  !strcmp(argv[1], get_value_multi)) {
 +strptr = git_config_get_value_multi(argv[2]);
 +if (strptr) {
 +for (i = 0; i  strptr-nr; i++) {
 +v = strptr-items[i].string;
 +if (!v)
 +printf((NULL)\n);
 +else
 +printf(%s\n, v);
 +}
 +return 0;
 +} else {
 +printf(Value not found for \%s\\n, argv[2]);
 +return -1;
 +}
 +} else if (argc == 3  !strcmp(argv[1], get_int)) {
 +if (!git_config_get_int(argv[2], val)) {
 +printf(%d\n, val);
 +return 0;
 +} else {
 +printf(Value not found for \%s\\n, argv[2]);
 +return -1;
 +}
 +} else if (argc == 3  !strcmp(argv[1], get_bool)) {
 +if (!git_config_get_bool(argv[2], val)) {
 +printf(%d\n, val);
 +return 0;
 +} else {
 +printf(Value not found for \%s\\n, argv[2]);
 +return -1;
 +}
 +} else if (!strcmp(argv[1], configset_get_value)) {
 +no_of_files = git_config_int(unused, argv[2]);
 
 Why ask the user to give a number of files on the command-line. With a
 syntax like
 
 test-config configset_get_value key files...
 
 you could just use argc to iterate over argv. Here, you trust the user
 to provide the right value, and most likely segfault otherwise (and this
 is not really documented). I know this is only test code, but why not do
 it right anyway ;-).
 

Yup, your way is much better, thanks for the review.
Tanay.
--
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 v3] git-am: add option to extract email Message-Id: tag into commit log

2014-07-02 Thread Avi Kivity
Some workflows prefer to track exactly which email message was used to
generate a commit.  This can be used, for example, to generate an
automated acknowledgement when a patch is committed as a response to
the patch email, or as a reference to the thread which introduced the
patch.

Support this by adding a --message-id option (abbreviated as -m) to
git-am, which will then extract the message ID and append it to the
email commit log.

Signed-off-by: Avi Kivity a...@cloudius-systems.com
---

v3: remove bashism and unneeded quoting

v2: adjust to pass test suite (t5100)

 Documentation/git-am.txt |  6 ++
 builtin/mailinfo.c   |  2 +-
 git-am.sh| 10 +-
 t/t5100/info0004 |  1 +
 t/t5100/info0005 |  1 +
 t/t5100/info0012 |  1 +
 6 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt
index 9adce37..8a251a1 100644
--- a/Documentation/git-am.txt
+++ b/Documentation/git-am.txt
@@ -15,6 +15,7 @@ SYNOPSIS
 [--whitespace=option] [-Cn] [-pn] [--directory=dir]
 [--exclude=path] [--include=path] [--reject] [-q | --quiet]
 [--[no-]scissors] [-S[keyid]] [--patch-format=format]
+[--message-id]
 [(mbox | Maildir)...]
 'git am' (--continue | --skip | --abort)
 
@@ -121,6 +122,11 @@ default.   You can use `--no-utf8` to override this.
user to lie about the author date by using the same
value as the committer date.
 
+-m::
+--message-id::
+   Extract the Message-Id: header from the e-mail and
+   append it to the commit message's tag stanza.
+
 --skip::
Skip the current patch.  This is only meaningful when
restarting an aborted patch.
diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c
index cf11c8d..f1e1fed 100644
--- a/builtin/mailinfo.c
+++ b/builtin/mailinfo.c
@@ -278,7 +278,7 @@ static void cleanup_space(struct strbuf *sb)
 
 static void decode_header(struct strbuf *line);
 static const char *header[MAX_HDR_PARSED] = {
-   From,Subject,Date,
+   From,Subject,Date,Message-Id
 };
 
 static inline int cmp_header(const struct strbuf *line, const char *hdr)
diff --git a/git-am.sh b/git-am.sh
index ee61a77..9fae315 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -39,6 +39,7 @@ committer-date-is-author-datelie about committer date
 ignore-date use current timestamp for author date
 rerere-autoupdate update the index with reused conflict resolution if possible
 S,gpg-sign? GPG-sign commits
+m,message-idcopy the Message-Id: header to the commit's tag stanza
 rebasing*   (internal use for git-rebase)
 
 . git-sh-setup
@@ -371,7 +372,7 @@ split_patches () {
 prec=4
 dotest=$GIT_DIR/rebase-apply
 sign= utf8=t keep= keepcr= skip= interactive= resolved= rebasing= abort=
-resolvemsg= resume= scissors= no_inbody_headers=
+resolvemsg= resume= scissors= no_inbody_headers= message_id=
 git_apply_opt=
 committer_date_is_author_date=
 ignore_date=
@@ -442,6 +443,8 @@ it will be removed. Please do not use it anymore.
gpg_sign_opt=-S ;;
--gpg-sign=*)
gpg_sign_opt=-S${1#--gpg-sign=} ;;
+   -m|--message-id)
+   message_id=t ;;
--)
shift; break ;;
*)
@@ -565,6 +568,7 @@ Use \git am --abort\ to remove it.)
echo  $git_apply_opt $dotest/apply-opt
echo $threeway $dotest/threeway
echo $sign $dotest/sign
+   echo $message_id  $dotest/message-id
echo $utf8 $dotest/utf8
echo $keep $dotest/keep
echo $scissors $dotest/scissors
@@ -757,6 +761,10 @@ To restore the original branch and stop patching run 
\\$cmdline --abort\.
then
cat $dotest/msg-clean
fi
+   if test t = $message_id
+   then
+   grep ^Message-Id: $dotest/info || true
+   fi
if test '' != $ADD_SIGNOFF
then
echo $ADD_SIGNOFF
diff --git a/t/t5100/info0004 b/t/t5100/info0004
index 616c309..f7e2983 100644
--- a/t/t5100/info0004
+++ b/t/t5100/info0004
@@ -2,4 +2,5 @@ Author: YOSHIFUJI Hideaki / 吉藤英明
 Email: yoshf...@linux-ipv6.org
 Subject: GIT: Try all addresses for given remote name
 Date: Thu, 21 Jul 2005 09:10:36 -0400 (EDT)
+Message-Id: 20050721.091036.01119516.yoshf...@linux-ipv6.org
 
diff --git a/t/t5100/info0005 b/t/t5100/info0005
index 46a46fc..592388f 100644
--- a/t/t5100/info0005
+++ b/t/t5100/info0005
@@ -2,4 +2,5 @@ Author: David Kågedal
 Email: dav...@lysator.liu.se
 Subject: Fixed two bugs in git-cvsimport-script.
 Date: Mon, 15 Aug 2005 20:18:25 +0200
+Message-Id: u5tacjjdpxq@lysator.liu.se
 
diff --git a/t/t5100/info0012 b/t/t5100/info0012
index ac1216f..b5d89a1 100644
--- a/t/t5100/info0012
+++ b/t/t5100/info0012
@@ -2,4 +2,5 @@ Author: Dmitriy Blinov
 Email: b...@mnsspb.ru
 Subject: Изменён список пакетов необходимых для сборки
 Date: Wed, 12 Nov 2008 17:54:41 

Re: [PATCH v2] git-am: add option to extract email Message-Id: tag into commit log

2014-07-02 Thread Avi Kivity


On 07/02/2014 12:58 PM, Torsten Bögershausen wrote:

@@ -757,6 +761,10 @@ To restore the original branch and stop patching run \\$cmdline 
--abort\.
then
cat $dotest/msg-clean
fi
+   if test 't' == $message_id

The == is bash special, please use = instead
And the 't' can be written as t, so that the whole line looks like this:
if test t = $message_id



Thanks.  v3 posted with these changes.
--
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 v2 2/2] git-merge-file: do not add LF at EOF while applying unrelated change

2014-07-02 Thread Johannes Schindelin
Hi Max,

On Wed, 2 Jul 2014, Max Kirillov wrote:

 On Mon, Jun 30, 2014 at 04:55:10PM +0200, Johannes Schindelin wrote:
  I just wish the tests were a little easier to understand...
 
 What could be improved with them?

Oh, I would name the files more appropriately, for example. That is,
instead of test1.txt I would call it mixed-endings.txt or lf-only.txt or
some such.

And instead of the Latin version of Psalm 23, I would put lines into the
files that describe their own role in the test, i.e.

unchanged
ends with a carriage return
ends with a line feed
unchanged

or similar.

Please keep in mind that this critique is most likely on my *own* work,
for all I know *I* introduced those files.

 By the way, for \r\n eol it did even worse, adding just \n. And I
 guess it still adds just \n for union merge.  Should file merge
 consider the core.eol? I think it should, and for the conflict markers
 also, it looks ugly when whole file has \r\n but the conflict markers
 have \n. But then git-merge-file could not be used outside of
 repository, I guess.

Oh, why not? It could read the configuration if it's inside a working
directory, and just read /etc/gitconfig and $HOME/.gitconfig when
outside...

 In general, I wish file merging (and diffing) were more tolerant of the
 line endings in input. Because in windows environment, when people have
 different core.autocrlf, it becomes quite frustrating to always get
 conflicts and changes.

Amen!

Ciao,
Dscho
--
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 v2] git-am: add option to extract email Message-Id: tag into commit log

2014-07-02 Thread Fabian Ruch
Hi Avi,

On 07/02/2014 10:51 AM, Avi Kivity wrote:
 Some workflows prefer to track exactly which email message was used to
 generate a commit.  This can be used, for example, to generate an
 automated acknowledgement when a patch is committed as a response to
 the patch email, or as a reference to the thread which introduced the
 patch.
 
 Support this by adding a --message-id option (abbreviated as -m) to
 git-am, which will then extract the message ID and append it to the
 email commit log.
 
 Signed-off-by: Avi Kivity a...@cloudius-systems.com
 ---
 
 v2: adjust to pass test suite (t5100)
 
  Documentation/git-am.txt |  6 ++
  builtin/mailinfo.c   |  2 +-
  git-am.sh| 10 +-
  t/t5100/info0004 |  1 +
  t/t5100/info0005 |  1 +
  t/t5100/info0012 |  1 +
  6 files changed, 19 insertions(+), 2 deletions(-)
 
 diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt
 index 9adce37..8a251a1 100644
 --- a/Documentation/git-am.txt
 +++ b/Documentation/git-am.txt
 @@ -15,6 +15,7 @@ SYNOPSIS
[--whitespace=option] [-Cn] [-pn] [--directory=dir]
[--exclude=path] [--include=path] [--reject] [-q | --quiet]
[--[no-]scissors] [-S[keyid]] [--patch-format=format]
 +  [--message-id]
[(mbox | Maildir)...]
  'git am' (--continue | --skip | --abort)
  
 @@ -121,6 +122,11 @@ default.   You can use `--no-utf8` to override this.
   user to lie about the author date by using the same
   value as the committer date.
  
 +-m::
 +--message-id::
 + Extract the Message-Id: header from the e-mail and
 + append it to the commit message's tag stanza.
 +
  --skip::
   Skip the current patch.  This is only meaningful when
   restarting an aborted patch.
 diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c
 index cf11c8d..f1e1fed 100644
 --- a/builtin/mailinfo.c
 +++ b/builtin/mailinfo.c
 @@ -278,7 +278,7 @@ static void cleanup_space(struct strbuf *sb)
  
  static void decode_header(struct strbuf *line);
  static const char *header[MAX_HDR_PARSED] = {
 - From,Subject,Date,
 + From,Subject,Date,Message-Id
  };
  
  static inline int cmp_header(const struct strbuf *line, const char *hdr)
 diff --git a/git-am.sh b/git-am.sh
 index ee61a77..c0e7bdd 100755
 --- a/git-am.sh
 +++ b/git-am.sh
 @@ -39,6 +39,7 @@ committer-date-is-author-datelie about committer date
  ignore-date use current timestamp for author date
  rerere-autoupdate update the index with reused conflict resolution if 
 possible
  S,gpg-sign? GPG-sign commits
 +m,message-idcopy the Message-Id: header to the commit's tag stanza
  rebasing*   (internal use for git-rebase)
  
  . git-sh-setup
 @@ -371,7 +372,7 @@ split_patches () {
  prec=4
  dotest=$GIT_DIR/rebase-apply
  sign= utf8=t keep= keepcr= skip= interactive= resolved= rebasing= abort=
 -resolvemsg= resume= scissors= no_inbody_headers=
 +resolvemsg= resume= scissors= no_inbody_headers= message_id=
  git_apply_opt=
  committer_date_is_author_date=
  ignore_date=
 @@ -442,6 +443,8 @@ it will be removed. Please do not use it anymore.
   gpg_sign_opt=-S ;;
   --gpg-sign=*)
   gpg_sign_opt=-S${1#--gpg-sign=} ;;
 + -m|--message-id)
 + message_id=t ;;

Doesn't the message-id line in OPTIONS_SPEC make the negated long
option --no-message-id available as well? If that's the case, then
the corresponding case arm is missing from here.

   --)
   shift; break ;;
   *)
 @@ -565,6 +568,7 @@ Use \git am --abort\ to remove it.)
   echo  $git_apply_opt $dotest/apply-opt
   echo $threeway $dotest/threeway
   echo $sign $dotest/sign
 + echo $message_id  $dotest/message-id

To match the local style conventions, the space character after the
redirection operator should be removed.

Also, isn't the patch missing the bits where the state of message-id
is read? Like so:

if test $(cat $dotest/message-id) = t
then
message_id=t
fi

   echo $utf8 $dotest/utf8
   echo $keep $dotest/keep
   echo $scissors $dotest/scissors
 @@ -757,6 +761,10 @@ To restore the original branch and stop patching run 
 \\$cmdline --abort\.
   then
   cat $dotest/msg-clean
   fi
 + if test 't' == $message_id
 + then
 + grep ^Message-Id: $dotest/info || true

Why is the true guard needed here? The exit status of grep seems to
never be checked.

Although I cannot come up with an example where this would matter,
you might want to consider using the grep wrapper sane_grep from
git-sh-setup.sh instead. It resets the environment variable
GREP_OPTIONS before calling grep so that no unexpected user options
come into play.

 + fi
   if test '' != $ADD_SIGNOFF
   then
   echo $ADD_SIGNOFF
 
 [..]

   Fabian
--
To unsubscribe from this list: send the line unsubscribe git in
the body of 

Re: [PATCH v4 1/2] add `config_set` API for caching config files

2014-07-02 Thread Matthieu Moy
Tanay Abhra tanay...@gmail.com writes:
 On 7/2/2014 2:44 PM, Matthieu Moy wrote:
 Tanay Abhra tanay...@gmail.com writes:

 Maybe a reworded sentence may work,
 `git_configset_get_value_multi` returns a list of values sorted in order of
 increasing priority (i.e. last match will be at the end of the list.)

OK.

 read from usual config files(repo specific .git/config, user wide
 ~/.gitconfig and the global /etc/gitconfig). `the_config_set` uses a
 single hashmap populated using git_config(). The reason for doing so is
 twofold, one is to honour include directives, another is to guarantee O(1)
 lookups for usual config values, as values are queried for hundred of
 times during a run of a git program.
 
 What is the reason to deal with `the_config_set` and other config sets
 differently? You're giving arguments to store `the_config_set` as a
 single hashmap, but what is the reason to store others as multiple
 hashmaps?
 
 And actually, I don't completely buy your arguments: having 3 or 4
 hashmaps (.git/config, ~/.gitconfig, ~/.config/git/config and
 /etc/gitconfig) would be a O(4) lookup, which is still O(1), and you
 could deal with include directives by having .git/config and included
 files in a hashmap, ~/.gitconfig and included files in a second
 hashmap, ...
 
 My guess is that the real argument is git_config already does what I
 want and I'm too lazy to change it. And I do consider lazyness as a
 quality for a computer-scientist ;-).
 
 I would personally find it much simpler to have a single hashmap. We'd
 lose the ability to invalidate the cache for only a single file, but I'm
 not sure it's worth the code complexity.
 

 Point noted. I can take the multiple hashmap route for `the_config_set`.
 Still, since it will be the most used config set in the code and for each
 query it would have to look through n hashmaps hampering performance. I
 can change it if you want but like you, I don't think it is worth the code
 complexity.

That's why my suggestion is to use a single hashmap everywhere.

I don't have strong opinion either way, but whichever way you go, you
should justify the choice better in the commit message.

 +The config API also provides type specific API functions which do 
 conversion
 +as well as retrieval for the queried variable, including:
 +
 +`git_config_get_int`::
 +Parse the retrieved value to an integer, including unit factors. Dies on
 +error; otherwise, allocates and copies the integer into the dest parameter.
 +Returns 0 on success, or 1 if no value was found.
 
 It seems strange to me to return 1 here, and -1 in git_config_get_value
 to mean the same thing.
 

 Noted. Some of the type specific function return -1 on wrong parsing, I will
 put return value 1 for no value found in all of the cases.

I'm not sure I fully get the existing convention. My understanding is
that when the extracted value is returned, -1 is used as a special value
to mean no value (e.g. git_config_maybe_bool can return 1, 0 or -1),
but when the extracted value is written to a by-address parameter, then
the return value is 1 or 0.

 +static struct hashmap *get_config_hash(const char *filename, struct 
 config_set *cs)
 +{
 +   int i;
 +   for(i = 0; i  cs-nr; i++) {
 +   if (!strcmp(cs-item[i].filename, filename))
 +   return cs-item[i].config_hash;
 +   }
 +   return add_config_hash(filename, cs);
 +}
 +
 +static struct config_hash_entry *config_hash_find_entry(const char *key, 
 const char* filename,
 +   struct config_set *cs)
 
 I don't get the logic here.
 
 Either the caller explicitly manages a config_set variable like
 
   config_set my_set = git_configset_init();
   git_configset_add_file(my_set, my-file);
   git_configset_get_value(my_set, some.variable.name);
 
 Or there's an implicit singleton mapping files to hashmaps to allow the
 user to say
 
   git_configset_get_value(my-file, some.variable.name);
 
 without asking the user to explicitly manipulate config_set variables.
 
 It seems to me that your solution is a bad compromise between both
 solutions: you do require the user to manipulate config_set variables,
 but you also require a filename to look for the right entry in the list.
 
 Did you miss the end of Junio's message:
 
   http://thread.gmane.org/gmane.comp.version-control.git/252567
 
 ?


 This is an internal function which is used to iterate over every `config_set`
 item which contains a hashmap and filename as an identifier.
 The exposed API which I documented above doesn't require the user to pass the
 filename when querying for a value.

 The API works like this, suppose there are two files,
 A.config  B.config
 [foo] [foo]
 a = b a = d
 a = c a = e

 config_set *my_set = git_configset_init();
 git_configset_add_file(my_set, A.config);
 git_configset_add_file(my_set, B.config);
 git_configset_get_value(my_set, foo.a);

 Here get_value calls config_hash_find_entry once for each 

Re: [PATCH v2] git-am: add option to extract email Message-Id: tag into commit log

2014-07-02 Thread Avi Kivity


On 07/02/2014 05:18 PM, Fabian Ruch wrote:

Hi Avi,

On 07/02/2014 10:51 AM, Avi Kivity wrote:

Some workflows prefer to track exactly which email message was used to
generate a commit.  This can be used, for example, to generate an
automated acknowledgement when a patch is committed as a response to
the patch email, or as a reference to the thread which introduced the
patch.

Support this by adding a --message-id option (abbreviated as -m) to
git-am, which will then extract the message ID and append it to the
email commit log.

Signed-off-by: Avi Kivity a...@cloudius-systems.com
---

v2: adjust to pass test suite (t5100)

  Documentation/git-am.txt |  6 ++
  builtin/mailinfo.c   |  2 +-
  git-am.sh| 10 +-
  t/t5100/info0004 |  1 +
  t/t5100/info0005 |  1 +
  t/t5100/info0012 |  1 +
  6 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt
index 9adce37..8a251a1 100644
--- a/Documentation/git-am.txt
+++ b/Documentation/git-am.txt
@@ -15,6 +15,7 @@ SYNOPSIS
 [--whitespace=option] [-Cn] [-pn] [--directory=dir]
 [--exclude=path] [--include=path] [--reject] [-q | --quiet]
 [--[no-]scissors] [-S[keyid]] [--patch-format=format]
+[--message-id]
 [(mbox | Maildir)...]
  'git am' (--continue | --skip | --abort)
  
@@ -121,6 +122,11 @@ default.   You can use `--no-utf8` to override this.

user to lie about the author date by using the same
value as the committer date.
  
+-m::

+--message-id::
+   Extract the Message-Id: header from the e-mail and
+   append it to the commit message's tag stanza.
+
  --skip::
Skip the current patch.  This is only meaningful when
restarting an aborted patch.
diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c
index cf11c8d..f1e1fed 100644
--- a/builtin/mailinfo.c
+++ b/builtin/mailinfo.c
@@ -278,7 +278,7 @@ static void cleanup_space(struct strbuf *sb)
  
  static void decode_header(struct strbuf *line);

  static const char *header[MAX_HDR_PARSED] = {
-   From,Subject,Date,
+   From,Subject,Date,Message-Id
  };
  
  static inline int cmp_header(const struct strbuf *line, const char *hdr)

diff --git a/git-am.sh b/git-am.sh
index ee61a77..c0e7bdd 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -39,6 +39,7 @@ committer-date-is-author-datelie about committer date
  ignore-date use current timestamp for author date
  rerere-autoupdate update the index with reused conflict resolution if possible
  S,gpg-sign? GPG-sign commits
+m,message-idcopy the Message-Id: header to the commit's tag stanza
  rebasing*   (internal use for git-rebase)
  
  . git-sh-setup

@@ -371,7 +372,7 @@ split_patches () {
  prec=4
  dotest=$GIT_DIR/rebase-apply
  sign= utf8=t keep= keepcr= skip= interactive= resolved= rebasing= abort=
-resolvemsg= resume= scissors= no_inbody_headers=
+resolvemsg= resume= scissors= no_inbody_headers= message_id=
  git_apply_opt=
  committer_date_is_author_date=
  ignore_date=
@@ -442,6 +443,8 @@ it will be removed. Please do not use it anymore.
gpg_sign_opt=-S ;;
--gpg-sign=*)
gpg_sign_opt=-S${1#--gpg-sign=} ;;
+   -m|--message-id)
+   message_id=t ;;

Doesn't the message-id line in OPTIONS_SPEC make the negated long
option --no-message-id available as well? If that's the case, then
the corresponding case arm is missing from here.


I don't know, but some other booleans don't supply negations, for 
example --reject.



--)
shift; break ;;
*)
@@ -565,6 +568,7 @@ Use \git am --abort\ to remove it.)
echo  $git_apply_opt $dotest/apply-opt
echo $threeway $dotest/threeway
echo $sign $dotest/sign
+   echo $message_id  $dotest/message-id

To match the local style conventions, the space character after the
redirection operator should be removed.


Sure.


Also, isn't the patch missing the bits where the state of message-id
is read? Like so:

 if test $(cat $dotest/message-id) = t
 then
message_id=t
 fi


Good catch, I guess this fixes a restarted am.




echo $utf8 $dotest/utf8
echo $keep $dotest/keep
echo $scissors $dotest/scissors
@@ -757,6 +761,10 @@ To restore the original branch and stop patching run \\$cmdline 
--abort\.
then
cat $dotest/msg-clean
fi
+   if test 't' == $message_id
+   then
+   grep ^Message-Id: $dotest/info || true

Why is the true guard needed here? The exit status of grep seems to
never be checked.


I usually code scripts with -e, but here it's unneeded.



Although I cannot come up with an example where this would matter,
you might want to consider using the grep wrapper sane_grep from
git-sh-setup.sh instead. It resets the environment variable
GREP_OPTIONS before calling grep so that no 

[PATCH v4] git-am: add option to extract email Message-Id: tag into commit log

2014-07-02 Thread Avi Kivity
Some workflows prefer to track exactly which email message was used to
generate a commit.  This can be used, for example, to generate an
automated acknowledgement when a patch is committed as a response to
the patch email, or as a reference to the thread which introduced the
patch.

Support this by adding a --message-id option (abbreviated as -m) to
git-am, which will then extract the message ID and append it to the
email commit log.

Signed-off-by: Avi Kivity a...@cloudius-systems.com
---

v4: adjust coding style
recover message_id variable after a resumed git-am
use sane_grep
drop unneeded grep error handling

v3: remove bashism and unneeded quoting

v2: adjust to pass test suite (t5100)

 Documentation/git-am.txt |  6 ++
 builtin/mailinfo.c   |  2 +-
 git-am.sh| 14 +-
 t/t5100/info0004 |  1 +
 t/t5100/info0005 |  1 +
 t/t5100/info0012 |  1 +
 6 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt
index 9adce37..8a251a1 100644
--- a/Documentation/git-am.txt
+++ b/Documentation/git-am.txt
@@ -15,6 +15,7 @@ SYNOPSIS
 [--whitespace=option] [-Cn] [-pn] [--directory=dir]
 [--exclude=path] [--include=path] [--reject] [-q | --quiet]
 [--[no-]scissors] [-S[keyid]] [--patch-format=format]
+[--message-id]
 [(mbox | Maildir)...]
 'git am' (--continue | --skip | --abort)
 
@@ -121,6 +122,11 @@ default.   You can use `--no-utf8` to override this.
user to lie about the author date by using the same
value as the committer date.
 
+-m::
+--message-id::
+   Extract the Message-Id: header from the e-mail and
+   append it to the commit message's tag stanza.
+
 --skip::
Skip the current patch.  This is only meaningful when
restarting an aborted patch.
diff --git a/builtin/mailinfo.c b/builtin/mailinfo.c
index cf11c8d..f1e1fed 100644
--- a/builtin/mailinfo.c
+++ b/builtin/mailinfo.c
@@ -278,7 +278,7 @@ static void cleanup_space(struct strbuf *sb)
 
 static void decode_header(struct strbuf *line);
 static const char *header[MAX_HDR_PARSED] = {
-   From,Subject,Date,
+   From,Subject,Date,Message-Id
 };
 
 static inline int cmp_header(const struct strbuf *line, const char *hdr)
diff --git a/git-am.sh b/git-am.sh
index ee61a77..fd0181f 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -39,6 +39,7 @@ committer-date-is-author-datelie about committer date
 ignore-date use current timestamp for author date
 rerere-autoupdate update the index with reused conflict resolution if possible
 S,gpg-sign? GPG-sign commits
+m,message-idcopy the Message-Id: header to the commit's tag stanza
 rebasing*   (internal use for git-rebase)
 
 . git-sh-setup
@@ -371,7 +372,7 @@ split_patches () {
 prec=4
 dotest=$GIT_DIR/rebase-apply
 sign= utf8=t keep= keepcr= skip= interactive= resolved= rebasing= abort=
-resolvemsg= resume= scissors= no_inbody_headers=
+resolvemsg= resume= scissors= no_inbody_headers= message_id=
 git_apply_opt=
 committer_date_is_author_date=
 ignore_date=
@@ -442,6 +443,8 @@ it will be removed. Please do not use it anymore.
gpg_sign_opt=-S ;;
--gpg-sign=*)
gpg_sign_opt=-S${1#--gpg-sign=} ;;
+   -m|--message-id)
+   message_id=t ;;
--)
shift; break ;;
*)
@@ -565,6 +568,7 @@ Use \git am --abort\ to remove it.)
echo  $git_apply_opt $dotest/apply-opt
echo $threeway $dotest/threeway
echo $sign $dotest/sign
+   echo $message_id $dotest/message-id
echo $utf8 $dotest/utf8
echo $keep $dotest/keep
echo $scissors $dotest/scissors
@@ -651,6 +655,10 @@ then
 else
SIGNOFF=
 fi
+if test $(cat $dotest/message-id) = t
+then
+   message_id=t
+fi
 
 last=$(cat $dotest/last)
 this=$(cat $dotest/next)
@@ -757,6 +765,10 @@ To restore the original branch and stop patching run 
\\$cmdline --abort\.
then
cat $dotest/msg-clean
fi
+   if test t = $message_id
+   then
+   sane_grep ^Message-Id: $dotest/info
+   fi
if test '' != $ADD_SIGNOFF
then
echo $ADD_SIGNOFF
diff --git a/t/t5100/info0004 b/t/t5100/info0004
index 616c309..f7e2983 100644
--- a/t/t5100/info0004
+++ b/t/t5100/info0004
@@ -2,4 +2,5 @@ Author: YOSHIFUJI Hideaki / 吉藤英明
 Email: yoshf...@linux-ipv6.org
 Subject: GIT: Try all addresses for given remote name
 Date: Thu, 21 Jul 2005 09:10:36 -0400 (EDT)
+Message-Id: 20050721.091036.01119516.yoshf...@linux-ipv6.org
 
diff --git a/t/t5100/info0005 b/t/t5100/info0005
index 46a46fc..592388f 100644
--- a/t/t5100/info0005
+++ b/t/t5100/info0005
@@ -2,4 +2,5 @@ Author: David Kågedal
 Email: dav...@lysator.liu.se
 Subject: Fixed two bugs in git-cvsimport-script.
 Date: Mon, 15 Aug 2005 20:18:25 +0200

Re: [PATCH 00/14] Add submodule test harness

2014-07-02 Thread Torsten Bögershausen
(Not sure if this is the right thread)
(I haven't checked if this is fixed in your latest version)

On what I have on pu 7a0da7902cbbc9a876b90c9, Tue Jul 1 14:51:53 2014 -0700

Many submodule tests are broken.
One problem is here:

lib-submodule-update.sh:264: possible problem: echo -n is not portable (please 
use printf): echo -n sub1 
lib-submodule-update.sh:507: possible problem: echo -n is not portable (please 
use printf): echo -n sub1 

You can remove the empty echo -n to create an empty file:
sub1 




--
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


Show containing branches in log?

2014-07-02 Thread Robert Dailey
I know that with the `git branch` command I can determine which
branches contain a commit. Is there a way to represent this
graphically with `git log`? Sometimes I just have a commit, and I need
to find out what branch contains that commit. The reason why `git
branch --contains` doesn't solve this problem for me is that it names
almost all branches because of merge commits. Too much ancestry has
been built since this commit, so there is no way to find the closest
branch that contains that commit.

Is there a way to graphically see what is the nearest named ref to
the specified commit in the logs?
--
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 v4] git-am: add option to extract email Message-Id: tag into commit log

2014-07-02 Thread Torsten Bögershausen
 diff --git a/git-am.sh b/git-am.sh
 index ee61a77..fd0181f 100755
 --- a/git-am.sh
 +++ b/git-am.sh
 @@ -39,6 +39,7 @@ committer-date-is-author-datelie about committer date
  ignore-date use current timestamp for author date
  rerere-autoupdate update the index with reused conflict resolution if 
 possible
  S,gpg-sign? GPG-sign commits
 +m,message-idcopy the Message-Id: header to the commit's tag stanza
  rebasing*   (internal use for git-rebase)
  
  . git-sh-setup
 @@ -371,7 +372,7 @@ split_patches () {
  prec=4
  dotest=$GIT_DIR/rebase-apply
  sign= utf8=t keep= keepcr= skip= interactive= resolved= rebasing= abort=
 -resolvemsg= resume= scissors= no_inbody_headers=
 +resolvemsg= resume= scissors= no_inbody_headers= message_id=
  git_apply_opt=
  committer_date_is_author_date=
  ignore_date=
 @@ -442,6 +443,8 @@ it will be removed. Please do not use it anymore.
   gpg_sign_opt=-S ;;
   --gpg-sign=*)
   gpg_sign_opt=-S${1#--gpg-sign=} ;;
 + -m|--message-id)
 + message_id=t ;;
   --)
   shift; break ;;
   *)
 @@ -565,6 +568,7 @@ Use \git am --abort\ to remove it.)
   echo  $git_apply_opt $dotest/apply-opt
   echo $threeway $dotest/threeway
   echo $sign $dotest/sign
 + echo $message_id $dotest/message-id
   echo $utf8 $dotest/utf8
   echo $keep $dotest/keep
   echo $scissors $dotest/scissors
 @@ -651,6 +655,10 @@ then
  else
   SIGNOFF=
  fi
 +if test $(cat $dotest/message-id) = t
Does the usage of '' inside of '' look good, or can we write like this:
if test $(cat $dotest/message-id) = t

--
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/9] add strip_suffix function

2014-07-02 Thread Junio C Hamano
Jeff King p...@peff.net writes:

 For that reason, the mem form puts its length parameter
 next to the buffer (since they are a pair), and the string
 form puts it at the end (since it is an out-parameter). The
 compiler can notice when you get the order wrong, which
 should help prevent writing one when you meant the other.

Very sensible consideration.  I like commits that careful thinking
behind them shows through them.

 Signed-off-by: Jeff King p...@peff.net
 ---
 I hope the word strip is OK, as it does not actually NUL-terminate
 (doing so would make it unusable for many cases). Between the comment
 below and the const in the parameter, I think it should be pretty
 clear that it does not touch the string. And I could not think of a
 better word.

All other words I can think of offhand, trim, chomp, etc., hint
shortening of the input string, and by definition shortening of a
string implies NUL-termination.

The mem variant deals with a counted string, however, so its
shortening implies NUL-termination a lot less [*1*] and should be
fine.

If we want to avoid implying NUL-termination, the only way to do so
would be to use wording that does not hint shortening.  At least for
the C-string variant, which is measuring the length of the basename
part (i.e. `basename $str $suffix`) without touching anything else,
e.g. basename_length(hello.c, .c, len), but at the same time
you want to make it a boolean to signal if the string ends with the
suffix, so perhaps has_suffix(hello.c, .c, len)?

[Footnote]

 *1* ... but not entirely, because we often NUL-terminate even
 counted strings (the buffer returned from read_sha1_file() and
 the payload of strbuf are two examples).

  git-compat-util.h | 27 +++
  1 file changed, 27 insertions(+)

 diff --git a/git-compat-util.h b/git-compat-util.h
 index b6f03b3..d044c42 100644
 --- a/git-compat-util.h
 +++ b/git-compat-util.h
 @@ -358,6 +358,33 @@ static inline const char *skip_prefix(const char *str, 
 const char *prefix)
   return NULL;
  }
  
 +/*
 + * If buf ends with suffix, return 1 and subtract the length of the suffix
 + * from *len. Otherwise, return 0 and leave *len untouched.
 + */
 +static inline int strip_suffix_mem(const char *buf, size_t *len,
 +const char *suffix)
 +{
 + size_t suflen = strlen(suffix);
 + if (*len  suflen || memcmp(buf + (*len - suflen), suffix, suflen))
 + return 0;
 + *len -= suflen;
 + return 1;
 +}
 +
 +/*
 + * If str ends with suffix, return 1 and set *len to the size of the string
 + * without the suffix. Otherwise, return 0 and set *len to the size of the
 + * string.
 + *
 + * Note that we do _not_ NUL-terminate str to the new length.
 + */
 +static inline int strip_suffix(const char *str, const char *suffix, size_t 
 *len)
 +{
 + *len = strlen(str);
 + return strip_suffix_mem(str, len, suffix);
 +}
 +
  #if defined(NO_MMAP) || defined(USE_WIN32_MMAP)
  
  #ifndef PROT_READ
--
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


Compile Error on Git 2.0.1 on Redhat 5.9 with Fix

2014-07-02 Thread Eldon Nelson
When compiling Git 2.0.1 on RedHat 5.9 as a non-root user I get the
following error:

BUILD ERROR

```
make prefix=/home/eldon/local all doc info
...
CC zlib.o
CC unix-socket.o
CC thread-utils.o
CC compat/strlcpy.o
AR libgit.a
/bin/sh: gar: command not found
make: *** [libgit.a] Error 127
```

My fix was to make a symlink below:

SYMLINK

```
gar - /usr/bin/ar
```

LINUX VERSION

```
 lsb_release -i -r
Distributor ID: RedHatEnterpriseClient
Release:5.9
```

I think the fix is to allow the use of ar if gar does not exist. I
don't know if this exists for every Redhat install but gar is not
available in /usr/bin but ar does.

```
 /usr/bin/ar --version
GNU ar 2.17.50.0.6-20.el5_8.3 20061020
Copyright 2005 Free Software Foundation, Inc.
```

It could just be my corporate install of RedHat that is weird, but
thought this might be at least a point to describe a fix.

```
gcc --version
gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-54)
Copyright (C) 2006 Free Software Foundation, Inc.
```


Eldon Nelson
eldon_nel...@ieee.org
Cell: 952-393-3481
--
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 v4] git-am: add option to extract email Message-Id: tag into commit log

2014-07-02 Thread Avi Kivity


On 07/02/2014 06:03 PM, Torsten Bögershausen wrote:

@@ -565,6 +568,7 @@ Use \git am --abort\ to remove it.)
echo  $git_apply_opt $dotest/apply-opt
echo $threeway $dotest/threeway
echo $sign $dotest/sign
+   echo $message_id $dotest/message-id
echo $utf8 $dotest/utf8
echo $keep $dotest/keep
echo $scissors $dotest/scissors
@@ -651,6 +655,10 @@ then
  else
SIGNOFF=
  fi
+if test $(cat $dotest/message-id) = t

Does the usage of '' inside of '' look good, or can we write like this:
if test $(cat $dotest/message-id) = t


With your change, it will fail if the file is missing or empty.

Complex shell scripts cannot be made to look good.  If that's a 
requirement then the script should be rewritten in a reasonable language.

--
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: Compile Error on Git 2.0.1 on Redhat 5.9 with Fix

2014-07-02 Thread Matthieu Moy
Eldon Nelson eldon_nel...@ieee.org writes:

 make prefix=/home/eldon/local all doc info
 ...
 CC zlib.o
 CC unix-socket.o
 CC thread-utils.o
 CC compat/strlcpy.o
 AR libgit.a
 /bin/sh: gar: command not found
[...]
 I think the fix is to allow the use of ar if gar does not exist.

It is already the case. The Makefile defaults to ar and does not even
contain any mention of gar. The configure script checks for both:

configure.ac:AC_CHECK_TOOLS(AR, [gar ar], :)

My guess is that you ran the configure script on a machine where gar is
present, and then used the result on a machine where it isn't.

Normally, at configure time you should see this:

checking for ar... ar

You actually don't need to run the configure script, the Makefile runs
fine without it. Delete config.mak.autogen to cancel the effect of
./configure.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/
--
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: Compile Error on Git 2.0.1 on Redhat 5.9 with Fix

2014-07-02 Thread Jeff King
On Wed, Jul 02, 2014 at 10:56:25AM -0500, Eldon Nelson wrote:

 When compiling Git 2.0.1 on RedHat 5.9 as a non-root user I get the
 following error:
 
 BUILD ERROR
 
 ```
 make prefix=/home/eldon/local all doc info
 ...
 CC zlib.o
 CC unix-socket.o
 CC thread-utils.o
 CC compat/strlcpy.o
 AR libgit.a
 /bin/sh: gar: command not found
 make: *** [libgit.a] Error 127
 ```

The Makefile defines AR as:

  $ git grep ^AR Makefile
  Makefile:AR = ar

so it should already do what you want by default.  But that make
variable can be overridden. Can you show us the contents of your
config.mak and config.mak.autogen files (if either exists)?

It's also possible that you have AR set in your environment (show us
echo $AR), but that would usually not override the Makefile unless
make -e is used (and that is not in your command-line above, but it's
possible that make is a shell alias or something).

 My fix was to make a symlink below:
 
 SYMLINK
 
 ```
 gar - /usr/bin/ar
 ```

A simpler workaround is probably:

  make AR=ar ...

but probably the right solution is to eliminate whatever is providing
the bogus override in the first place.

-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: Show containing branches in log?

2014-07-02 Thread Jeff King
On Wed, Jul 02, 2014 at 09:50:57AM -0500, Robert Dailey wrote:

 I know that with the `git branch` command I can determine which
 branches contain a commit. Is there a way to represent this
 graphically with `git log`? Sometimes I just have a commit, and I need
 to find out what branch contains that commit. The reason why `git
 branch --contains` doesn't solve this problem for me is that it names
 almost all branches because of merge commits. Too much ancestry has
 been built since this commit, so there is no way to find the closest
 branch that contains that commit.
 
 Is there a way to graphically see what is the nearest named ref to
 the specified commit in the logs?

Have you tried git describe --contains --all commit?

To some degree, I fear your question isn't something git can answer. If
the branch containing the commit has been merged into other branches,
then they all contain the commit. There is not really any reason to
prefer one over the other (describe --contains will try to find the
closest branch, but that is based on heuristics and is not necessarily
well-defined).

-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 2/9] add strip_suffix function

2014-07-02 Thread Jeff King
On Wed, Jul 02, 2014 at 08:54:44AM -0700, Junio C Hamano wrote:

 Jeff King p...@peff.net writes:
 
  For that reason, the mem form puts its length parameter
  next to the buffer (since they are a pair), and the string
  form puts it at the end (since it is an out-parameter). The
  compiler can notice when you get the order wrong, which
  should help prevent writing one when you meant the other.
 
 Very sensible consideration.  I like commits that careful thinking
 behind them shows through them.

I would like to take credit for advanced thinking, but I actually did
what felt natural, and only noticed the compiler will tell you when you
are wrong effect when I got it wrong while writing a later patch in the
series. :)

 If we want to avoid implying NUL-termination, the only way to do so
 would be to use wording that does not hint shortening.  At least for
 the C-string variant, which is measuring the length of the basename
 part (i.e. `basename $str $suffix`) without touching anything else,
 e.g. basename_length(hello.c, .c, len), but at the same time
 you want to make it a boolean to signal if the string ends with the
 suffix, so perhaps has_suffix(hello.c, .c, len)?

I think that invites some confusion with ends_with, which is the same
thing (but just does not take the len parameter). We could just add
this feature to ends_with, and ask callers who do not care to pass NULL,
but that makes those call sites uglier.

Having had a day to mull it over, and having read your email, I think I
still prefer strip_suffix.

-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: Show containing branches in log?

2014-07-02 Thread Robert Dailey
On Wed, Jul 2, 2014 at 11:34 AM, Jeff King p...@peff.net wrote:
 Have you tried git describe --contains --all commit?

 To some degree, I fear your question isn't something git can answer. If
 the branch containing the commit has been merged into other branches,
 then they all contain the commit. There is not really any reason to
 prefer one over the other (describe --contains will try to find the
 closest branch, but that is based on heuristics and is not necessarily
 well-defined).

I have not tried that command. Note I mentioned named refs, so
nameless branches I'm not worried about. Even if I merge branch A into
branch B, branch A is still closest in terms of number of steps to get
to the commit, because to get to the commit through B you have to
cross over a merge commit. Basically the priority should be directness
and distance. The more direct a branch is (i.e. the lesser number of
merge commits it goes through to get to the commit) the more relevant
it is. As a second condition, distance would be used in cases where
the directness of it is the same.

Sorting this in the log graph and seeing it visually (I could even use
--simplify-by-decoration) would help me understand the topography of
git's history relative to the commit(s) I specify.
--
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: Show containing branches in log?

2014-07-02 Thread Jason Pyeron
 -Original Message-
 From: Jeff King
 Sent: Wednesday, July 02, 2014 12:35
 
 On Wed, Jul 02, 2014 at 09:50:57AM -0500, Robert Dailey wrote:
 
  I know that with the `git branch` command I can determine which
  branches contain a commit. Is there a way to represent this
  graphically with `git log`? Sometimes I just have a commit, 
 and I need
  to find out what branch contains that commit. The reason why `git
  branch --contains` doesn't solve this problem for me is 
 that it names
  almost all branches because of merge commits. Too much ancestry has
  been built since this commit, so there is no way to find 
 the closest
  branch that contains that commit.
  
  Is there a way to graphically see what is the nearest named ref to
  the specified commit in the logs?
 
 Have you tried git describe --contains --all commit?
 
 To some degree, I fear your question isn't something git can 
 answer. If
 the branch containing the commit has been merged into other branches,
 then they all contain the commit. There is not really any reason to
 prefer one over the other (describe --contains will try to find the
 closest branch, but that is based on heuristics and is not 
 necessarily
 well-defined).

Another way I answer this question is git log --oneline --graph --all and then
search for the commit and follow the lines.


--
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-   -
- Jason Pyeron  PD Inc. http://www.pdinc.us -
- Principal Consultant  10 West 24th Street #100-
- +1 (443) 269-1555 x333Baltimore, Maryland 21218   -
-   -
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
This message is copyright PD Inc, subject to license 20080407P00.

 

--
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: Show containing branches in log?

2014-07-02 Thread Robert Dailey
On Wed, Jul 2, 2014 at 11:52 AM, Jason Pyeron jpye...@pdinc.us wrote:
 -Original Message-
 From: Jeff King
 Sent: Wednesday, July 02, 2014 12:35

 On Wed, Jul 02, 2014 at 09:50:57AM -0500, Robert Dailey wrote:

  I know that with the `git branch` command I can determine which
  branches contain a commit. Is there a way to represent this
  graphically with `git log`? Sometimes I just have a commit,
 and I need
  to find out what branch contains that commit. The reason why `git
  branch --contains` doesn't solve this problem for me is
 that it names
  almost all branches because of merge commits. Too much ancestry has
  been built since this commit, so there is no way to find
 the closest
  branch that contains that commit.
 
  Is there a way to graphically see what is the nearest named ref to
  the specified commit in the logs?

 Have you tried git describe --contains --all commit?

 To some degree, I fear your question isn't something git can
 answer. If
 the branch containing the commit has been merged into other branches,
 then they all contain the commit. There is not really any reason to
 prefer one over the other (describe --contains will try to find the
 closest branch, but that is based on heuristics and is not
 necessarily
 well-defined).

 Another way I answer this question is git log --oneline --graph --all and then
 search for the commit and follow the lines.

If that were a practical solution I wouldn't be here asking this
question. Unfortunately, in a repository with multiple parallel
release branches, it is impossible to just eye-ball the graph and
find what you're looking for. Especially when the last 4 weeks worth
of commits consumes over 10 pages of log graph.
--
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 v4 1/2] add `config_set` API for caching config files

2014-07-02 Thread Junio C Hamano
Tanay Abhra tanay...@gmail.com writes:

 diff --git a/Documentation/technical/api-config.txt 
 b/Documentation/technical/api-config.txt
 index 230b3a0..2c02fee 100644
 --- a/Documentation/technical/api-config.txt
 +++ b/Documentation/technical/api-config.txt
 @@ -77,6 +77,75 @@ To read a specific file in git-config format, use
  `git_config_from_file`. This takes the same callback and data parameters
  as `git_config`.
  
 +Querying For Specific Variables
 +---
 +
 +For programs wanting to query for specific variables in a non-callback
 +manner, the config API provides two functions `git_config_get_value`
 +and `git_config_get_value_multi`.They both read values from an internal
 +cache generated previously from reading the config files.
 +
 +`git_config_get_value` takes two parameters,
 +
 +- a key string in canonical flat form for which the corresponding value

What is canonical flat form?

 +  with the highest priority (i.e. value in the repo config will be
 +  preferred over value in user wide config for the same variable) will
 +  be retrieved.
 +
 +- a pointer to a string which will point to the retrieved value. The caller
 +  should not free or modify the value returned as it is owned by the cache.
 +
 +`git_config_get_value` returns 0 on success, or -1 for no value found.
 +
 +`git_config_get_value_multi` allocates and returns a `string_list`
 +containing all the values for the key passed as parameter, sorted in order
 +of increasing priority (Note: caller has to call `string_list_clear` on
 +the returned pointer and then free it).
 +
 +`git_config_get_value_multi` returns NULL for no value found.
 +
 +`git_config_clear` is provided for resetting and invalidating the cache.
 +
 +`git_config_iter` gives a way to iterate over the keys in cache. Existing
 +`git_config` callback function signature is used for iterating.

Instead of doing prose above and then enumeration below,
consistently using the enumeration-style would make the descriptions
of API functions easier to find and read.  Also show what parameters
each function takes.  E.g.

`git_config_get_value(const char *key, const char **value)`::
Find the highest-priority value for the
configuration variable `key`, store the pointer to
it in `value` and return 0.  When the configuration
variable `key` is not found, return -1 without
touching `value`.

A few random thoughts.

 - Are a value for the variable is found and no value for the
   variable is found the only possible outcome?  Should somebody
   (not necessarily the calling code) be notified of an error---for
   example, if you opened a config file successfully but later found
   that the file could not be parsed due to a syntax error or an I/O
   error, is it possible the caller of this function to tell, or are
   these just some special cases of variable not found?

 - The same goes for the multi variant but it is a bit more grave,
   as a function that returns an int can later be updated to
   return different negative values to signal different kinds of
   errors, but a function that returns a pointer to string-list can
   only return one kind of NULL ;-)

 - For the purpose of git_config_get_value(), what is the value
   returned for core.filemode when the configuration file says
   [core] filemode\n, i.e. when git_config() callback would get a
   NULL for value to signal a boolean true?

 - Is there a reason why you need a separate and new config_iter?
   What does it do differently from the good-old git_config() and
   how?  It does not belong to Querying for Specific Variables
   anyway.

 +The config API also provides type specific API functions which do conversion
 +as well as retrieval for the queried variable, including:
 +
 +`git_config_get_int`::
 +Parse the retrieved value to an integer, including unit factors. Dies on
 +error; otherwise, allocates and copies the integer into the dest parameter.
 +Returns 0 on success, or 1 if no value was found.

allocates and copies  Is a caller forced to do something like
this?

int *val;

if (!git_config_get_int(int.one, val)) {
use(*val);
free(val);
}

I'd expect it to be more like:

int val;
if (!git_config_get_int(int.one, val))
use(val);

Also, is there a reason why the not found signal is 1 (as
opposed to -1 for the lower-level get_value() API)?

 +`git_config_get_ulong`::
 +Identical to `git_config_get_int` but for unsigned longs.

Obviously this is not identical but merely Similar to.

 +`git_config_bool`::

git_config_get_bool, perhaps?

 +Custom Configsets
 +-
 +
 +A `config_set` points at an ordered set of config files, each of
 +which represents what was read and cached in-core from a file.

This over-specifies the implementation.  Judging from the list of
API functions below, an 

Re: [PATCH v4 1/2] add `config_set` API for caching config files

2014-07-02 Thread Junio C Hamano
Matthieu Moy matthieu@grenoble-inp.fr writes:

 I don't like the name the_config_set. It's not the only one. Perhaps
 repo_config_set? (not totally satisfactory as it does not contain only
 the repo, but the repo+user+system)

 What do others think?

I actually do like the_configset, which goes nicely parallel to
the_index.  Neither is the only one, but most of the time our code
operates on the primary one and the_frotz refers to it (and
convenience wrappers that does not specify which set defaults to
it).

 What is the reason to deal with `the_config_set` and other config sets
 differently? You're giving arguments to store `the_config_set` as a
 single hashmap, but what is the reason to store others as multiple
 hashmaps?

Confusion, probably.  the_configset should be just a singleton
instance used to store the values we use for the default config
system, but its shape should be exactly the same as the other ones
users can use to read .gitmodules and friends with.

 And actually, I don't completely buy your arguments: having 3 or 4
 hashmaps (.git/config, ~/.gitconfig, ~/.config/git/config and
 /etc/gitconfig) would be a O(4) lookup, which is still O(1), and you
 could deal with include directives by having .git/config and included
 files in a hashmap, ~/.gitconfig and included files in a second
 hashmap, ...

OK.

 I would personally find it much simpler to have a single hashmap. We'd
 lose the ability to invalidate the cache for only a single file, but I'm
 not sure it's worth the code complexity.

OK, too.
--
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: Experimental TDB support for GIT REFS

2014-07-02 Thread Ronnie Sahlberg
On Fri, Jun 27, 2014 at 5:37 PM, Shawn Pearce spea...@spearce.org wrote:
 On Fri, Jun 27, 2014 at 2:30 PM, Ronnie Sahlberg sahlb...@google.com wrote:
 List,

 One of my ref transaction aims is to make define a stable public API
 for accessing refs.
 Once this is done I want to make it possible to replace the current
 .git/refs/* model with a
 different type of backend.
 In my case I want to add support to store all refs and reflogs in a TDB 
 database
 but once we have a pluggable backend framework for refs, if someone
 wants to store the refs
 in a SQL database, that should be fairly trivial too.

 There are a few series queued before this becomes possible, but is
 anyone wants to test or play with my git can use TDB database you
 can find an implementation of this at

 https://github.com/rsahlberg/git/tree/backend-struct-tdb

 Interesting! But the link 404s :(


Yeah, sorry but there were issues :-(   Issues solved now though and
refactoring done.

Please see
https://github.com/rsahlberg/git/tree/backend-struct-db

This branch adds a refs backend that communicates via a domain socket
to a refs daemon.
The refs daemon in turn interfaces with the actual database.

My branch contains one hack refs daemon that uses a TDB database for
the refs storage.
This daemon is only about 600 lines of code, most of which is
marshalling and socket handling and only a small amount of
TDB specific code.
This small daemon should make it easy for folks to add arbitrary
database interfaces easily.
Taking refsd-tdb.c  and modifying it to instead attach to a SQL
database should only take a few hundred lines of changes or so.


To build the daemon and start it :

$ gcc refsd-tdb.c -o refsd-tdb -ltdb
create /var/lib/git and /var/log/git
$ ./refsd-tdb /var/lib/git/refs.socket /var/lib/git /var/log/git/refsd.log

Then you can inspect the database with
tdbdump /var/lib/git/refs.tdb


You can then create a repository that uses this database :
$ git init --db-repo-name=ROCC --db-socket=/var/lib/git/refs.socket .

Then further commands will operate on the refs tdb.

See this as a prototype to experiment with and see the direction of
the refs transaction and pluggable backend support.
There is a lot additional work and cleanup that needs to be done
before this will become production code.

(yes I know we should not do hand marshalling and unmarshalling for
the PDUs on the domain socket. We should use some lightweight encoding
library like XDR and rpcgen or similar.)


Please test, comment and have fun.

regards
ronnie sahlberg
--
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 v4 1/2] add `config_set` API for caching config files

2014-07-02 Thread Matthieu Moy
Junio C Hamano gits...@pobox.com writes:

 Tanay Abhra tanay...@gmail.com writes:

 diff --git a/Documentation/technical/api-config.txt 
 b/Documentation/technical/api-config.txt
 index 230b3a0..2c02fee 100644
 --- a/Documentation/technical/api-config.txt
 +++ b/Documentation/technical/api-config.txt
 @@ -77,6 +77,75 @@ To read a specific file in git-config format, use
  `git_config_from_file`. This takes the same callback and data parameters
  as `git_config`.
  
 +Querying For Specific Variables
 +---
 +
 +For programs wanting to query for specific variables in a non-callback
 +manner, the config API provides two functions `git_config_get_value`
 +and `git_config_get_value_multi`.They both read values from an internal
 +cache generated previously from reading the config files.
 +
 +`git_config_get_value` takes two parameters,
 +
 +- a key string in canonical flat form for which the corresponding value

 What is canonical flat form?

Actually, it's defined above in the same file (was here before the
patch):

  - the name of the parsed variable. This is in canonical flat form: the
section, subsection, and variable segments will be separated by dots,
and the section and variable segments will be all lowercase. E.g.,

But it might make sense to reword the doc, e.g. introduce a glossary
section at the beginning.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/
--
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 v2] git-am: add option to extract email Message-Id: tag into commit log

2014-07-02 Thread Junio C Hamano
Avi Kivity a...@cloudius-systems.com writes:

 + if test 't' == $message_id
 + then
 + grep ^Message-Id: $dotest/info || true
 + fi
   if test '' != $ADD_SIGNOFF
   then
   echo $ADD_SIGNOFF

Seeing how existing code carefully makes sure that ADD_SIGNOFF has
an empty line before it when and only when necessary to ensure that
there is a blank after the existing log message, I would suspect
that this patch that blindly inserts a line is doubly wrong.  The
output from grep may be appended without adding a blank when
necessary, and appending of ADD_SIGNOFF may end up adding an extra
blank after Message-Id.  Am I reading the patch wrong?
--
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/9] add strip_suffix function

2014-07-02 Thread Junio C Hamano
Jeff King p...@peff.net writes:

 Having had a day to mull it over, and having read your email, I think I
 still prefer strip_suffix.

That's OK.  I was only trying to help you explore different avenues,
without having strong preference myself either way.
--
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 RFC v2 00/19] Enable options --signoff, --reset-author for pick, reword

2014-07-02 Thread Fabian Ruch
Hi,

this reroll applies the comments from Eric, Junio and Michael. In
particular,

 * It turned out that `pick_one` does not need option handling at all
   and the option-like argument `-n` determines whether `pick_one` or
   `do_pick` creates the replay commit. The latter happens if the
   task wants to rewrite the commit being picked (f.i., for the
   purpose of editing the log message or resetting the authorship).

   `do_pick` still seems to require a flexible parsing of options,
   i.e. a relatively expensive loop, since it receives the
   whitelisted user-supplied options. Unsupported and unknown options
   are treated as an unknown command error.

 * The `do_pick` options are documented in the same order they are
   listed in the function signature. Moreover, it is mentioned which
   options rewrite commits being picked.

 * The test cases output differing actual values as changes to the
   expected values and not the other way around. Moreover, the failed
   rebases are not cleaned up until the respective test succeeds.

Two stages (and two sub-stages) can be identified in the rerolled
patch series:

 1. Route primary to-do list commands through `do_pick`

 a. Implement reword in terms of do_pick (5/19)
 b. Implement squash in terms of do_pick (14/19)

 2. Add user options to main commands

Enable options --signoff, --reset-author for pick, reword (19/19)

The last stage was added in this reroll. It enables the parsing of
line options for to-do list commands, which is still restricted to
options without arguments because it is unclear how spaces can be
parsed as characters rather than separators where needed. For
instance, if we were to support

pick --author=A U Thor fa1afe1 Some changes

then read(1) would hand us the tokens `--author=A`, `U` and `Thor`
instead of `--author=A U Thor`, which we would want to relay to
`do_pick`. Interpreting the shell quoting would help. However,
eval(1) seems to disqualify itself as an interpreter because the
to-do list entry could potentially contain any shell command line.
This could be both a security and a usability issue. For this reason,
the patch series still hasn't graduated from being RFC.

   Fabian

Fabian Ruch (19):
  rebase -i: Failed reword prints redundant error message
  rebase -i: reword complains about empty commit despite --keep-empty
  rebase -i: reword executes pre-commit hook on interim commit
  rebase -i: Teach do_pick the option --edit
  rebase -i: Implement reword in terms of do_pick
  rebase -i: Stop on root commits with empty log messages
  rebase -i: The replay of root commits is not shown with --verbose
  rebase -i: Root commits are replayed with an unnecessary option
  rebase -i: Commit only once when rewriting picks
  rebase -i: Do not die in do_pick
  rebase -i: Teach do_pick the option --amend
  rebase -i: Teach do_pick the option --file
  rebase -i: Prepare for squash in terms of do_pick --amend
  rebase -i: Implement squash in terms of do_pick
  rebase -i: Explicitly distinguish replay commands and exec tasks
  rebase -i: Parse to-do list command line options
  rebase -i: Teach do_pick the option --reset-author
  rebase -i: Teach do_pick the option --signoff
  rebase -i: Enable options --signoff, --reset-author for pick, reword

 git-rebase--interactive.sh| 277 ++
 t/t3404-rebase-interactive.sh |   8 ++
 t/t3412-rebase-root.sh|  39 ++
 3 files changed, 273 insertions(+), 51 deletions(-)

-- 
2.0.0

--
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 RFC v2 03/19] rebase -i: reword executes pre-commit hook on interim commit

2014-07-02 Thread Fabian Ruch
The to-do list command `reword` replays a commit like `pick` but lets
the user also edit the commit's log message. This happens in two
steps. Firstly, the named commit is cherry-picked. Secondly, the
commit created in the first step is amended using an unchanged index
to edit the log message. The pre-commit hook is meant to verify the
changes introduced by a commit (for instance, catching inserted
trailing white space). Since the committed tree is not changed
between the two steps, do not execute the pre-commit hook in the
second step.

Specify the git-commit option `--no-verify` to disable the pre-commit
hook when editing the log message. Because `--no-verify` also skips
the commit-msg hook, execute the hook from within
git-rebase--interactive after the commit is created. Fortunately, the
commit message is still available in `$GIT_DIR/COMMIT_EDITMSG` after
git-commit terminates. Caveat: In case the commit-msg hook finds the
new log message ill-formatted, the user is only notified of the
failed commit-msg hook but the log message is used for the commit
anyway. git-commit ought to offer more fine-grained control over
which hooks are executed.

Signed-off-by: Fabian Ruch baf...@gmail.com
---
 git-rebase--interactive.sh | 17 +
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 689400e..b50770d 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -504,10 +504,19 @@ do_next () {
 
mark_action_done
do_pick $sha1 $rest
-   git commit --allow-empty --amend --no-post-rewrite 
${gpg_sign_opt:+$gpg_sign_opt} || {
-   warn Could not amend commit after successfully picking 
$sha1... $rest
-   exit_with_patch $sha1 1
-   }
+   # TODO: Work around the fact that git-commit lets us
+   # disable either both the pre-commit and the commit-msg
+   # hook or none. Disable the pre-commit hook because the
+   # tree is left unchanged but run the commit-msg hook
+   # from here because the log message is altered.
+   git commit --allow-empty --amend --no-post-rewrite -n 
${gpg_sign_opt:+$gpg_sign_opt} 
+   if test -x $GIT_DIR/hooks/commit-msg
+   then
+   $GIT_DIR/hooks/commit-msg 
$GIT_DIR/COMMIT_EDITMSG
+   fi || {
+   warn Could not amend commit after successfully 
picking $sha1... $rest
+   exit_with_patch $sha1 1
+   }
record_in_rewritten $sha1
;;
edit|e)
-- 
2.0.0

--
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 RFC v2 01/19] rebase -i: Failed reword prints redundant error message

2014-07-02 Thread Fabian Ruch
The to-do list command `reword` replays a commit like `pick` but lets
the user also edit the commit's log message. If the edited log
message is empty or is found ill-formatted by one of the commit
hooks, git-rebase--interactive prints three error messages to the
console.

1. The git-commit output, which contains all the output from hook
   scripts.
2. A rebase diagnosis saying at which task on the to-do list it
   got stuck.
3. Generic presumptions about what could have triggered the
   error.

The third message contains redundant information and does not add any
enlightenment either, which makes the output unnecessarily longish
and different from the other command's output. For instance, this is
what the output looks like if the log message is empty (contains
duplicate Signed-off-by lines).

(1.) Aborting commit due to empty commit message. (Duplicate Signed-off-by 
lines.)
(2.) Could not amend commit after successfully picking fa1afe1... Some 
change
(3.) This is most likely due to an empty commit message, or the pre-commit 
hook
 failed. If the pre-commit hook failed, you may need to resolve the 
issue before
 you are able to reword the commit.

Discard the third message.

It is true that a failed hook script might not output any diagnosis
but then the generic message is not of much help either. Since this
lack of information affects the built-in git commands for commit,
merge and cherry-pick first, the solution would be to keep track of
the failed hooks in their output so that the user knows which of her
hooks require improvement.

Signed-off-by: Fabian Ruch baf...@gmail.com
---
 git-rebase--interactive.sh | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 7e1eda0..e733d7f 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -506,9 +506,6 @@ do_next () {
do_pick $sha1 $rest
git commit --amend --no-post-rewrite 
${gpg_sign_opt:+$gpg_sign_opt} || {
warn Could not amend commit after successfully picking 
$sha1... $rest
-   warn This is most likely due to an empty commit 
message, or the pre-commit hook
-   warn failed. If the pre-commit hook failed, you may 
need to resolve the issue before
-   warn you are able to reword the commit.
exit_with_patch $sha1 1
}
record_in_rewritten $sha1
-- 
2.0.0

--
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 RFC v2 02/19] rebase -i: reword complains about empty commit despite --keep-empty

2014-07-02 Thread Fabian Ruch
The to-do list command `reword` replays a commit like `pick` but lets
the user also edit the commit's log message. If `--keep-empty` is
passed as option to git-rebase--interactive, empty commits ought to
be replayed without complaints. However, if the users chooses to
reword an empty commit by changing the respective to-do list entry
from

pick fa1afe1 Empty commit

to

reword fa1afe1 Empty commit

, then git-rebase--interactive suddenly fails to replay the empty
commit. This is especially counterintuitive because `reword` is
thought of as a `pick` that alters the log message in some way but
nothing more and the unchanged to-do list entry would not fail.

Handle `reword` by cherry-picking the named commit and editing the
log message using

git commit --allow-empty --amend

instead of

git commit --amend.

Add test.

Signed-off-by: Fabian Ruch baf...@gmail.com
---
 git-rebase--interactive.sh| 2 +-
 t/t3404-rebase-interactive.sh | 8 
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index e733d7f..689400e 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -504,7 +504,7 @@ do_next () {
 
mark_action_done
do_pick $sha1 $rest
-   git commit --amend --no-post-rewrite 
${gpg_sign_opt:+$gpg_sign_opt} || {
+   git commit --allow-empty --amend --no-post-rewrite 
${gpg_sign_opt:+$gpg_sign_opt} || {
warn Could not amend commit after successfully picking 
$sha1... $rest
exit_with_patch $sha1 1
}
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 8197ed2..9931143 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -75,6 +75,14 @@ test_expect_success 'rebase --keep-empty' '
test_line_count = 6 actual
 '
 
+test_expect_success 'rebase --keep-empty' '
+   git checkout emptybranch 
+   set_fake_editor 
+   FAKE_LINES=1 reword 2 git rebase --keep-empty -i HEAD~2 
+   git log --oneline actual 
+   test_line_count = 6 actual
+'
+
 test_expect_success 'rebase -i with the exec command' '
git checkout master 
(
-- 
2.0.0

--
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 RFC v2 05/19] rebase -i: Implement reword in terms of do_pick

2014-07-02 Thread Fabian Ruch
The to-do list command `reword` replays a commit like `pick` but lets
the user also edit the commit's log message. If one thinks of `pick`
entries as scheduled `cherry-pick` command lines, then `reword`
becomes an alias for the command line `cherry-pick --edit`. The
porcelain `rebase--interactive` defines a function `do_pick` for
processing the `pick` entries on to-do lists. Reimplement `reword` in
terms of `do_pick --edit`.

If the user picks a commit using the to-do list line

reword fa1afe1 Some change

execute the command `do_pick --edit fa1afe1 Some change` which
carries out exactly the same steps as the case arm for `reword` in
`do_next` so far.

Signed-off-by: Fabian Ruch baf...@gmail.com
---
 git-rebase--interactive.sh | 15 +--
 1 file changed, 1 insertion(+), 14 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index e06d9b6..4c875d5 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -555,20 +555,7 @@ do_next () {
comment_for_reflog reword
 
mark_action_done
-   do_pick $sha1 $rest
-   # TODO: Work around the fact that git-commit lets us
-   # disable either both the pre-commit and the commit-msg
-   # hook or none. Disable the pre-commit hook because the
-   # tree is left unchanged but run the commit-msg hook
-   # from here because the log message is altered.
-   git commit --allow-empty --amend --no-post-rewrite -n 
${gpg_sign_opt:+$gpg_sign_opt} 
-   if test -x $GIT_DIR/hooks/commit-msg
-   then
-   $GIT_DIR/hooks/commit-msg 
$GIT_DIR/COMMIT_EDITMSG
-   fi || {
-   warn Could not amend commit after successfully 
picking $sha1... $rest
-   exit_with_patch $sha1 1
-   }
+   do_pick --edit $sha1 $rest
record_in_rewritten $sha1
;;
edit|e)
-- 
2.0.0

--
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 RFC v2 10/19] rebase -i: Do not die in do_pick

2014-07-02 Thread Fabian Ruch
Since `do_pick` might be executed in a sub-shell (a modified author
environment for instance), calling `die` in `do_pick` has no effect
but exiting the sub-shell with a failure exit status. The
git-rebase--interactive script is not terminated. Moreover, if
`do_pick` is called while a squash or fixup is in effect,
`die_with_patch` will discard `$squash_msg` as commit message.
Lastly, after a `die` in `do_pick` `do_next` has no chance to
reschedule tasks that failed before changes could be applied.

Indicate an error in `do_pick` using return statements and properly
kill the script at the call sites. Although possible in principle,
the issued error messages are no more indicating whether `do_pick`
failed while applying or while committing the changes. This reduces
code complexity at the call site and does not matter from a user's
point of view because a glance at the index reveals whether there are
conflicts or not and in-depth troubleshooting is still possible using
the `--verbose` option.

Remove the commit message title argument from `do_pick`'s interface,
which has become unused.

Signed-off-by: Fabian Ruch baf...@gmail.com
---
 git-rebase--interactive.sh | 37 -
 1 file changed, 20 insertions(+), 17 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 46b2db1..0070b3e 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -464,7 +464,7 @@ record_in_rewritten() {
 
 # Apply the changes introduced by the given commit to the current head.
 #
-# do_pick [--edit] commit title
+# do_pick [--edit] commit
 #
 # Wrapper around git-cherry-pick.
 #
@@ -476,9 +476,11 @@ record_in_rewritten() {
 # commit
 # The commit to cherry-pick.
 #
-# title
-# The commit message title of commit. Used for information
-# purposes only.
+# The return value is 1 if applying the changes resulted in a conflict
+# and 2 if the specified arguments were incorrect. If the changes could
+# be applied successfully but creating the commit failed, a value
+# greater than 2 is returned. No commit is created in either case and
+# the index is left with the (conflicting) changes in place.
 do_pick () {
rewrite=
rewrite_amend=
@@ -491,7 +493,8 @@ do_pick () {
rewrite_edit=y
;;
-*)
-   die do_pick: unrecognized option -- $1
+   warn do_pick: unrecognized option -- $1
+   return 2
;;
*)
break
@@ -499,7 +502,11 @@ do_pick () {
esac
shift
done
-   test $# -ne 2  die do_pick: wrong number of arguments
+   if test $# -ne 1
+   then
+   warn do_pick: wrong number of arguments
+   return 2
+   fi
 
if test $(git rev-parse HEAD) = $squash_onto
then
@@ -517,11 +524,9 @@ do_pick () {
# rebase --continue.
git commit --allow-empty --allow-empty-message --amend \
   --no-post-rewrite -n -q -C $1 
-   pick_one -n $1 ||
-   die_with_patch $1 Could not apply $1... $2
+   pick_one -n $1 || return 1
else
-   pick_one ${rewrite:+-n} $1 ||
-   die_with_patch $1 Could not apply $1... $2
+   pick_one ${rewrite:+-n} $1 || return 1
fi
 
if test -n $rewrite
@@ -529,8 +534,7 @@ do_pick () {
git commit --allow-empty --no-post-rewrite -n --no-edit \
   ${rewrite_amend:+--amend} \
   ${rewrite_edit:+--edit} \
-  ${gpg_sign_opt:+$gpg_sign_opt} ||
-   die_with_patch $1 Could not rewrite commit after 
successfully picking $1... $2
+  ${gpg_sign_opt:+$gpg_sign_opt} || return 3
fi
 
# TODO: Work around the fact that git-commit lets us
@@ -543,8 +547,7 @@ do_pick () {
if test -x $GIT_DIR/hooks/commit-msg
then
$GIT_DIR/hooks/commit-msg $GIT_DIR/COMMIT_EDITMSG
-   fi ||
-   die_with_patch $1 Could not rewrite commit after 
successfully picking $1... $2
+   fi || return 3
fi
 }
 
@@ -559,21 +562,21 @@ do_next () {
comment_for_reflog pick
 
mark_action_done
-   do_pick $sha1 $rest
+   do_pick $sha1 || die_with_patch $sha1 Could not apply $sha1... 
$rest
record_in_rewritten $sha1
;;
reword|r)
comment_for_reflog reword
 
mark_action_done
-   do_pick --edit $sha1 $rest
+   do_pick --edit $sha1 || die_with_patch $sha1 Could not apply 
$sha1... $rest
record_in_rewritten $sha1
;;
  

[PATCH RFC v2 04/19] rebase -i: Teach do_pick the option --edit

2014-07-02 Thread Fabian Ruch
`do_pick` is the git-cherry-pick wrapper in git-rebase--interactive
that is used to implement the to-do list command `pick`. To cater for
the different pick behaviours (like `reword`), `do_pick` accepts
several options not only from the git-cherry-pick but also the
git-commit interface. Add the common option `--edit` to let the user
edit the log message of the named commit.

Loop over `$@` to parse the `do_pick` arguments. Assign the local
variable `edit` if one of the options is `--edit` so that the
remainder of `do_pick` can easily check whether the client code asked
to edit the commit message. If one of the options is unknown, mention
it on the console and `die`. Break the loop on the first non-option
and do some sanity checking to ensure that there exactly two
non-options, which are interpreted by the remainder as `commit` and
`title` like before.

`do_pick` ought to act as a wrapper around `cherry-pick`.
Unfortunately, it cannot just forward `--edit` to the `cherry-pick`
command line. The assembled command line is executed within a command
substitution for controlling the verbosity of `rebase--interactive`.
Passing `--edit` would either hang the terminal or clutter the
substituted command output with control sequences. Execute the
`reword` code from `do_next` instead if the option `--edit` is
specified.

Signed-off-by: Fabian Ruch baf...@gmail.com
---
 git-rebase--interactive.sh | 52 ++
 1 file changed, 52 insertions(+)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index b50770d..e06d9b6 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -461,7 +461,42 @@ record_in_rewritten() {
esac
 }
 
+# Apply the changes introduced by the given commit to the current head.
+#
+# do_pick [--edit] commit title
+#
+# Wrapper around git-cherry-pick.
+#
+# -e, --edit
+# After picking commit, open an editor and let the user edit the
+# commit message. The editor contents becomes the commit message of
+# the new head. This creates a fresh commit.
+#
+# commit
+# The commit to cherry-pick.
+#
+# title
+# The commit message title of commit. Used for information
+# purposes only.
 do_pick () {
+   edit=
+   while test $# -gt 0
+   do
+   case $1 in
+   -e|--edit)
+   edit=y
+   ;;
+   -*)
+   die do_pick: unrecognized option -- $1
+   ;;
+   *)
+   break
+   ;;
+   esac
+   shift
+   done
+   test $# -ne 2  die do_pick: wrong number of arguments
+
if test $(git rev-parse HEAD) = $squash_onto
then
# Set the correct commit message and author info on the
@@ -483,6 +518,23 @@ do_pick () {
pick_one $1 ||
die_with_patch $1 Could not apply $1... $2
fi
+
+   if test -n $edit
+   then
+   # TODO: Work around the fact that git-commit lets us
+   # disable either both the pre-commit and the commit-msg
+   # hook or none. Disable the pre-commit hook because the
+   # tree is left unchanged but run the commit-msg hook
+   # from here because the log message is altered.
+   git commit --allow-empty --amend --no-post-rewrite -n 
${gpg_sign_opt:+$gpg_sign_opt} 
+   if test -x $GIT_DIR/hooks/commit-msg
+   then
+   $GIT_DIR/hooks/commit-msg 
$GIT_DIR/COMMIT_EDITMSG
+   fi || {
+   warn Could not amend commit after successfully 
picking $1... $2
+   exit_with_patch $1 1
+   }
+   fi
 }
 
 do_next () {
-- 
2.0.0

--
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 RFC v2 15/19] rebase -i: Explicitly distinguish replay commands and exec tasks

2014-07-02 Thread Fabian Ruch
There are two kinds of to-do list commands available. One kind
replays a commit (`pick`, `reword`, `edit`, `squash` and `fixup` that
is) and the other executes a shell command (`exec`). We will call the
first kind replay commands.

The two kinds of tasks are scheduled using different line formats.
Replay commands expect a commit hash argument following the command
name and exec concatenates all arguments to assemble a command line.

Adhere to the distinction of formats by not trying to parse the
`sha1` field unless we are dealing with a replay command. Move the
replay command handling code to a new function `do_replay` which
assumes the first argument to be a commit hash and make no more such
assumptions in `do_next`.

Signed-off-by: Fabian Ruch baf...@gmail.com
---
 git-rebase--interactive.sh | 42 --
 1 file changed, 28 insertions(+), 14 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 008f3a0..9de7441 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -585,13 +585,12 @@ do_pick () {
fi
 }
 
-do_next () {
-   rm -f $msg $author_script $amend || exit
-   read -r command sha1 rest  $todo
+do_replay () {
+   command=$1
+   sha1=$2
+   rest=$3
+
case $command in
-   $comment_char*|''|noop)
-   mark_action_done
-   ;;
pick|p)
comment_for_reflog pick
 
@@ -656,6 +655,28 @@ do_next () {
esac
record_in_rewritten $sha1
;;
+   *)
+   read -r command $todo
+   warn Unknown command: $command
+   fixtodo=Please fix this using 'git rebase --edit-todo'.
+   if git rev-parse --verify -q $sha1 /dev/null
+   then
+   die_with_patch $sha1 $fixtodo
+   else
+   die $fixtodo
+   fi
+   ;;
+   esac
+}
+
+do_next () {
+   rm -f $msg $author_script $amend || exit
+   read -r command sha1 rest $todo
+
+   case $command in
+   $comment_char*|''|noop)
+   mark_action_done
+   ;;
x|exec)
read -r command rest  $todo
mark_action_done
@@ -695,14 +716,7 @@ do_next () {
fi
;;
*)
-   warn Unknown command: $command $sha1 $rest
-   fixtodo=Please fix this using 'git rebase --edit-todo'.
-   if git rev-parse --verify -q $sha1 /dev/null
-   then
-   die_with_patch $sha1 $fixtodo
-   else
-   die $fixtodo
-   fi
+   do_replay $command $sha1 $rest
;;
esac
test -s $todo  return
-- 
2.0.0

--
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 RFC v2 09/19] rebase -i: Commit only once when rewriting picks

2014-07-02 Thread Fabian Ruch
The options passed to `do_pick` determine whether the picked commit
will be rewritten or not. If the commit gets rewritten, because the
user requested to edit the commit message for instance, let
`pick_one` merely apply the changes introduced by the commit and do
not commit the resulting tree yet. If the commit is replayed as is,
leave it to `pick_one` to recreate the commit (possibly by
fast-forwarding the head). This makes it easier to combine git-commit
options like `--edit` and `--amend` in `do_pick` because
git-cherry-pick does not support `--amend`.

In the case of `--edit`, do not `exit_with_patch` but assign
`rewrite` to pick the changes with `-n`. If the pick conflicts, no
commit is created which we would have to amend when continuing the
rebase. To complete the pick after the conflicts are resolved the
user just resumes with `git rebase --continue`.

git-commit lets the user edit the commit log message by default. We
do not want that for the rewriting git-commit command line because
the default behaviour of git-cherry-pick is exactly the opposite.
Pass `--no-edit` when rewriting a picked commit. An explicit `--edit`
passed to `do_pick` (for instance, when reword is executed) enables
the editor launch again.

If `rebase--interactive` is used to rebase a complete branch onto
some head, `rebase` creates a sentinel commit that requires special
treatment by `do_pick`. Do not finalize the pick here either because
its commit message can be altered as for any other pick. Since the
orphaned root commit gets a temporary parent, it is always rewritten.
Safely use the rewrite infrastructure of `do_pick` to create the
final commit.

Signed-off-by: Fabian Ruch baf...@gmail.com
---
 git-rebase--interactive.sh | 55 +++---
 1 file changed, 33 insertions(+), 22 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 17836d5..46b2db1 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -63,7 +63,8 @@ msgnum=$state_dir/msgnum
 author_script=$state_dir/author-script
 
 # When an edit rebase command is being processed, the SHA1 of the
-# commit to be edited is recorded in this file.  When git rebase
+# commit to be edited is recorded in this file.  The same happens when
+# rewriting a commit fails, for instance reword.  When git rebase
 # --continue is executed, if there are any staged changes then they
 # will be amended to the HEAD commit, but only provided the HEAD
 # commit is still the commit to be edited.  When any other rebase
@@ -479,12 +480,15 @@ record_in_rewritten() {
 # The commit message title of commit. Used for information
 # purposes only.
 do_pick () {
-   edit=
+   rewrite=
+   rewrite_amend=
+   rewrite_edit=
while test $# -gt 0
do
case $1 in
-e|--edit)
-   edit=y
+   rewrite=y
+   rewrite_edit=y
;;
-*)
die do_pick: unrecognized option -- $1
@@ -499,6 +503,10 @@ do_pick () {
 
if test $(git rev-parse HEAD) = $squash_onto
then
+   rewrite=y
+   rewrite_amend=y
+   git rev-parse --verify HEAD $amend
+
# Set the correct commit message and author info on the
# sentinel root before cherry-picking the original changes
# without committing (-n).  Finally, update the sentinel again
@@ -509,31 +517,34 @@ do_pick () {
# rebase --continue.
git commit --allow-empty --allow-empty-message --amend \
   --no-post-rewrite -n -q -C $1 
-   pick_one -n $1 
-   git commit --allow-empty \
-  --amend --no-post-rewrite -n --no-edit \
-  ${gpg_sign_opt:+$gpg_sign_opt} ||
+   pick_one -n $1 ||
die_with_patch $1 Could not apply $1... $2
else
-   pick_one $1 ||
+   pick_one ${rewrite:+-n} $1 ||
die_with_patch $1 Could not apply $1... $2
fi
 
-   if test -n $edit
+   if test -n $rewrite
then
-   # TODO: Work around the fact that git-commit lets us
-   # disable either both the pre-commit and the commit-msg
-   # hook or none. Disable the pre-commit hook because the
-   # tree is left unchanged but run the commit-msg hook
-   # from here because the log message is altered.
-   git commit --allow-empty --amend --no-post-rewrite -n 
${gpg_sign_opt:+$gpg_sign_opt} 
-   if test -x $GIT_DIR/hooks/commit-msg
-   then
-   $GIT_DIR/hooks/commit-msg 
$GIT_DIR/COMMIT_EDITMSG
-   fi || {
-  

[PATCH RFC v2 19/19] rebase -i: Enable options --signoff, --reset-author for pick, reword

2014-07-02 Thread Fabian Ruch
pick and reword are atomic to-do list commands in the sense that they
open a new task which is closed after the respective command is
completed. squash and fixup are not atomic. They create a new task
which is not completed until the last squash or fixup is processed.

Lift the general unknown option blockade for the pick and reword
commands. If `do_cmd` comes across one of the options `--signoff` and
`--reset-author` while parsing a to-do entry and the scheduled
command is either `pick` or `reword`, relay the option to `do_pick`.

The `do_pick` options `--gpg-sign` and `--file` are not yet supported
because `do_cmd` cannot handle option arguments and options with
spaces at the moment. It is true that edit is one of the atomic
commands but it displays hash information when the rebase is stopped
and some options rewrite the picked commit which alters that
information. squash and fixup still do not accept user options as the
interplay of `--reset-author` and the author script are yet to be
determined.

Signed-off-by: Fabian Ruch baf...@gmail.com
---
 git-rebase--interactive.sh | 19 ---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index bb258bb..c34a9a7 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -624,6 +624,16 @@ do_replay () {
while test $# -gt 0
do
case $1 in
+   --signoff|--reset-author)
+   case $command in
+   pick|reword)
+   ;;
+   *)
+   warn Unsupported option: $1
+   command=unknown
+   ;;
+   esac
+   ;;
-*)
warn Unknown option: $1
command=unknown
@@ -644,21 +654,24 @@ do_replay () {
comment_for_reflog pick
 
mark_action_done
-   do_pick $sha1 || die_with_patch $sha1 Could not apply $sha1... 
$rest
+   eval do_pick $opts $sha1 \
+   || die_with_patch $sha1 Could not apply $sha1... $rest
record_in_rewritten $sha1
;;
reword|r)
comment_for_reflog reword
 
mark_action_done
-   do_pick --edit $sha1 || die_with_patch $sha1 Could not apply 
$sha1... $rest
+   eval do_pick --edit $opts $sha1 \
+   || die_with_patch $sha1 Could not apply $sha1... $rest
record_in_rewritten $sha1
;;
edit|e)
comment_for_reflog edit
 
mark_action_done
-   do_pick $sha1 || die_with_patch $sha1 Could not apply $sha1... 
$rest
+   eval do_pick $opts $sha1 \
+   || die_with_patch $sha1 Could not apply $sha1... $rest
warn Stopped at $sha1... $rest
exit_with_patch $sha1 0
;;
-- 
2.0.0

--
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 RFC v2 07/19] rebase -i: The replay of root commits is not shown with --verbose

2014-07-02 Thread Fabian Ruch
The command line used to recreate root commits specifies the
erroneous option `-q` which suppresses the commit summary message.
However, git-rebase--interactive tends to tell the user about the
commits it creates, if she wishes (cf. command line option
`--verbose`). The code parts handling non-root commits or squash
commits all output commit summary messages. Do not make the replay of
root commits an exception. Remove the option.

It is OK to suppress the commit summary when git-commit is used to
initialize the authorship of the sentinel commit because the
existence of this additional commit is a detail of
git-rebase--interactive's implementation. The option `-q` was
probably introduced as a copy-and-paste error stemming from that part
of the root commit handling code.

Signed-off-by: Fabian Ruch baf...@gmail.com
---
 git-rebase--interactive.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 0af96f2..ff04d5d 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -511,7 +511,7 @@ do_pick () {
   --no-post-rewrite -n -q -C $1 
pick_one -n $1 
git commit --allow-empty \
-  --amend --no-post-rewrite -n -q -C $1 \
+  --amend --no-post-rewrite -n -C $1 \
   ${gpg_sign_opt:+$gpg_sign_opt} ||
die_with_patch $1 Could not apply $1... $2
else
-- 
2.0.0

--
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 RFC v2 17/19] rebase -i: Teach do_pick the option --reset-author

2014-07-02 Thread Fabian Ruch
`do_pick` is the git-cherry-pick wrapper in git-rebase--interactive
that is used to implement many of the to-do list commands.
Eventually, the complete `do_pick` interface will be exposed to the
user in some form or another and those commands will become simple
aliases for the `do_pick` options now used to implement them.

Add the git-commit option `--reset-author` to the options pool of
`do_pick`. It rewrites the author date and name of the picked commit
to match the committer date and name.

If `--reset-author` is passed to `do_pick`, set the `rewrite` flag
and relay the option to the git-commit command line which creates the
final commit. If `--amend` is not passed as well, the fresh
authorship effect is achieved by the mere fact that we are creating a
new commit.

Signed-off-by: Fabian Ruch baf...@gmail.com
---
 git-rebase--interactive.sh | 23 ++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 2119d00..a9fcb76 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -464,10 +464,18 @@ record_in_rewritten() {
 
 # Apply the changes introduced by the given commit to the current head.
 #
-# do_pick [--amend] [--file file] [--edit] commit
+# do_pick [--reset-author] [--amend] [--file file] [--edit] commit
 #
 # Wrapper around git-cherry-pick.
 #
+# --reset-author
+# Pretend the changes were made for the first time. Declare that the
+# authorship of the resulting commit now belongs to the committer.
+# This also renews the author timestamp. This creates a fresh
+# commit.
+#
+# _This is not a git-cherry-pick option._
+#
 # --amend
 # After picking commit, replace the current head commit with a new
 # commit that also introduces the changes of commit.
@@ -501,6 +509,10 @@ do_pick () {
while test $# -gt 0
do
case $1 in
+   --reset-author)
+   rewrite=y
+   rewrite_author=y
+   ;;
--amend)
if test $(git rev-parse HEAD) = $squash_onto || ! 
git rev-parse --verify HEAD
then
@@ -562,12 +574,21 @@ do_pick () {
pick_one ${rewrite:+-n} $1 || return 1
fi
 
+   if test -n $rewrite_author  test -z $rewrite_amend
+   then
+   # keep rewrite flag to create a new commit, rewrite
+   # without --reset-author though because it can only be
+   # used with -C, -c or --amend
+   rewrite_author=
+   fi
+
if test -n $rewrite
then
git commit --allow-empty --no-post-rewrite -n --no-edit \
   ${rewrite_amend:+--amend} \
   ${rewrite_edit:+--edit} \
   ${rewrite_message:+--file $rewrite_message} \
+  ${rewrite_author:+--reset-author} \
   ${gpg_sign_opt:+$gpg_sign_opt} || return 3
fi
 
-- 
2.0.0

--
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 RFC v2 14/19] rebase -i: Implement squash in terms of do_pick

2014-07-02 Thread Fabian Ruch
The to-do list command `squash` and its close relative `fixup` replay
the changes of a commit like `pick` but do not recreate the commit.
Instead they replace the previous commit with a new commit that also
introduces the changes of the squashed commit. This is roughly like
cherry-picking without committing and using git-commit to amend the
previous commit.

The to-do list

pick   a Some changes
squash b Some more changes

gets translated into the sequence of git commands

git cherry-pick a
git cherry-pick -n b
git commit --amend

and if git-cherry-pick supported `--amend` this would look even more
like the to-do list it is based on

git cherry-pick a
git cherry-pick --amend b.

Since `do_pick` takes care of `pick` entries and the above suggests
`squash` as an alias for `pick --amend`, reimplement `squash` in
terms of `do_pick --amend`. Introduce `$squash_msg` as the commit
message via the `--file` option. When the last commit of a squash
series is processed, the user is asked to review the log message.
Pass `--edit` as additional option in this case. The only difference
in the options passed to git-commit and `do_pick` is the omitted
`--no-verify`. However, `do_pick` does not execute the verification
hooks anyway because it solely replays commits and assumes that they
have been verified before.

Signed-off-by: Fabian Ruch baf...@gmail.com
---
 git-rebase--interactive.sh | 30 ++
 1 file changed, 6 insertions(+), 24 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 37800be..008f3a0 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -637,37 +637,19 @@ do_next () {
squash|s|fixup|f)
# This is an intermediate commit; its message will only 
be
# used in case of trouble.  So use the long version:
-   if ! pick_one -n $sha1
-   then
-   git rev-parse --verify HEAD $amend
-   die_failed_squash $sha1 Could not apply 
$sha1... $rest
-   fi
-   do_with_author output git commit --amend --no-verify -F 
$squash_msg \
-   ${gpg_sign_opt:+$gpg_sign_opt} ||
-   die_failed_squash $sha1 $rest
+   do_with_author do_pick --amend -F $squash_msg $sha1 \
+   || die_failed_squash $sha1 Could not apply 
$sha1... $rest
;;
*)
# This is the final command of this squash/fixup group
if test -f $fixup_msg
then
-   if ! pick_one -n $sha1
-   then
-   git rev-parse --verify HEAD $amend
-   die_failed_squash $sha1 Could not 
apply $sha1... $rest
-   fi
-   do_with_author git commit --amend --no-verify 
-F $fixup_msg \
-   ${gpg_sign_opt:+$gpg_sign_opt} ||
-   die_failed_squash $sha1 $rest
+   do_with_author do_pick --amend -F $fixup_msg 
$sha1 \
+   || die_failed_squash $sha1 Could not 
apply $sha1... $rest
else
cp $squash_msg $GIT_DIR/SQUASH_MSG || exit
-   if ! pick_one -n $sha1
-   then
-   git rev-parse --verify HEAD $amend
-   die_failed_squash $sha1 Could not 
apply $sha1... $rest
-   fi
-   do_with_author git commit --amend --no-verify 
-F $GIT_DIR/SQUASH_MSG -e \
-   ${gpg_sign_opt:+$gpg_sign_opt} ||
-   die_failed_squash $sha1 $rest
+   do_with_author do_pick --amend -F 
$GIT_DIR/SQUASH_MSG -e $sha1 \
+   || die_failed_squash $sha1 Could not 
apply $sha1... $rest
fi
rm -f $squash_msg $fixup_msg
;;
-- 
2.0.0

--
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 RFC v2 18/19] rebase -i: Teach do_pick the option --signoff

2014-07-02 Thread Fabian Ruch
`do_pick` is the git-cherry-pick wrapper in git-rebase--interactive
that is currently used to implement most of the to-do list commands
and offers additional options that will eventually find their way
onto to-do lists.

To extend the repertoire of available options, add the git-commit and
git-cherry-pick option `--signoff` to the `do_pick` interface. It
appends a Signed-off-by: line using the committer identity to the log
message of the picked commit.

Signed-off-by: Fabian Ruch baf...@gmail.com
---
 git-rebase--interactive.sh | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index a9fcb76..bb258bb 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -464,10 +464,15 @@ record_in_rewritten() {
 
 # Apply the changes introduced by the given commit to the current head.
 #
-# do_pick [--reset-author] [--amend] [--file file] [--edit] commit
+# do_pick [--signoff] [--reset-author] [--amend] [--file file]
+# [--edit] commit
 #
 # Wrapper around git-cherry-pick.
 #
+# -s, --signoff
+# Insert a Signed-off-by: line using the committer identity at the
+# end of the commit log message. This creates a fresh commit.
+#
 # --reset-author
 # Pretend the changes were made for the first time. Declare that the
 # authorship of the resulting commit now belongs to the committer.
@@ -509,6 +514,10 @@ do_pick () {
while test $# -gt 0
do
case $1 in
+   -s|--signoff)
+   rewrite=y
+   rewrite_signoff=y
+   ;;
--reset-author)
rewrite=y
rewrite_author=y
@@ -585,6 +594,7 @@ do_pick () {
if test -n $rewrite
then
git commit --allow-empty --no-post-rewrite -n --no-edit \
+  ${rewrite_signoff:+--signoff} \
   ${rewrite_amend:+--amend} \
   ${rewrite_edit:+--edit} \
   ${rewrite_message:+--file $rewrite_message} \
-- 
2.0.0

--
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 RFC v2 12/19] rebase -i: Teach do_pick the option --file

2014-07-02 Thread Fabian Ruch
`do_pick` is the git-cherry-pick wrapper in git-rebase--interactive
that is used to implement the to-do list command `pick`, `reword` and
`edit`. To cater for the different pick behaviours (like `squash`),
`do_pick` accepts several options not only from the git-cherry-pick
but also the git-commit interface.

Add the option `--file` from the git-commit interface to the options
pool of `do_pick`. It expects an argument itself which is interpreted
as a file path and takes the commit message from the given file. If
`--file` is passed to `do_pick`, assign the given file path to the
local variable `rewrite_message` and relay the option

--file $rewrite_message

to the git-commit command line which creates the commit.

Signed-off-by: Fabian Ruch baf...@gmail.com
---
 git-rebase--interactive.sh | 20 +++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 046d358..47e3edf 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -464,7 +464,7 @@ record_in_rewritten() {
 
 # Apply the changes introduced by the given commit to the current head.
 #
-# do_pick [--amend] [--edit] commit
+# do_pick [--amend] [--file file] [--edit] commit
 #
 # Wrapper around git-cherry-pick.
 #
@@ -474,6 +474,12 @@ record_in_rewritten() {
 #
 # _This is not a git-cherry-pick option._
 #
+# -F file, --file file
+# Take the commit message from the given file. This creates a fresh
+# commit.
+#
+# _This is not a git-cherry-pick option._
+#
 # -e, --edit
 # After picking commit, open an editor and let the user edit the
 # commit message. The editor contents becomes the commit message of
@@ -491,6 +497,7 @@ do_pick () {
rewrite=
rewrite_amend=
rewrite_edit=
+   rewrite_message=
while test $# -gt 0
do
case $1 in
@@ -504,6 +511,16 @@ do_pick () {
rewrite_amend=y
git rev-parse --verify HEAD $amend
;;
+   -F|--file)
+   if test $# -eq 0
+   then
+   warn do_pick: option --file specified but no 
file given
+   return 2
+   fi
+   rewrite=y
+   rewrite_message=$2
+   shift
+   ;;
-e|--edit)
rewrite=y
rewrite_edit=y
@@ -550,6 +567,7 @@ do_pick () {
git commit --allow-empty --no-post-rewrite -n --no-edit \
   ${rewrite_amend:+--amend} \
   ${rewrite_edit:+--edit} \
+  ${rewrite_message:+--file $rewrite_message} \
   ${gpg_sign_opt:+$gpg_sign_opt} || return 3
fi
 
-- 
2.0.0

--
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 RFC v2 11/19] rebase -i: Teach do_pick the option --amend

2014-07-02 Thread Fabian Ruch
`do_pick` is the git-cherry-pick wrapper in git-rebase--interactive
that is used to implement the to-do list commands `pick`, `reword`
and `edit`. To cater for the different pick behaviours (like
`squash`), `do_pick` accepts several options not only from the
git-cherry-pick but also the git-commit interface.

Add the option `--amend` from the git-commit interface to the options
pool of `do_pick`. It creates a new commit for the changes introduced
by the picked commit and the previous one. The previous commit is
then replaced with the new commit. If no other options are specified,
the log message of the previous commit is used.

Be careful when `--amend` is used to pick a root commit because HEAD
might point to the sentinel commit but there is still nothing to
amend. Be sure to initialize `amend` so that commits are squashed
even when git-rebase--interactive is interrupted for resolving
conflicts. It is not a mistake to do the initialization regardless of
any conflicts because `amend` is always cleared before the next to-do
item is processed.

Signed-off-by: Fabian Ruch baf...@gmail.com
---
 git-rebase--interactive.sh | 18 +-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 0070b3e..046d358 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -464,10 +464,16 @@ record_in_rewritten() {
 
 # Apply the changes introduced by the given commit to the current head.
 #
-# do_pick [--edit] commit
+# do_pick [--amend] [--edit] commit
 #
 # Wrapper around git-cherry-pick.
 #
+# --amend
+# After picking commit, replace the current head commit with a new
+# commit that also introduces the changes of commit.
+#
+# _This is not a git-cherry-pick option._
+#
 # -e, --edit
 # After picking commit, open an editor and let the user edit the
 # commit message. The editor contents becomes the commit message of
@@ -488,6 +494,16 @@ do_pick () {
while test $# -gt 0
do
case $1 in
+   --amend)
+   if test $(git rev-parse HEAD) = $squash_onto || ! 
git rev-parse --verify HEAD
+   then
+   warn do_pick: nothing to amend
+   return 2
+   fi
+   rewrite=y
+   rewrite_amend=y
+   git rev-parse --verify HEAD $amend
+   ;;
-e|--edit)
rewrite=y
rewrite_edit=y
-- 
2.0.0

--
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 RFC v2 16/19] rebase -i: Parse to-do list command line options

2014-07-02 Thread Fabian Ruch
Read in to-do list lines as

command args

instead of

command sha1 rest

so that to-do list command lines can specify additional arguments
apart from the commit hash and the log message title, which become
the non-options in `args`. Loop over `args`, put all options (an
argument beginning with a dash) in `opts`, stop the loop on the first
non-option and assign it to `sha1`. The loop does not know the
options it parses so that options that take an argument themselves
are not supported at the moment. Neither are options that contain
spaces because the shell expansion of `args` in `do_next` interprets
white space characters as argument separator, that is a command line
like

pick --author A U Thor fa1afe1 Some change

is parsed as the pick command

pick --author

and the commit hash

A

which obviously results in an unknown revision error. For the sake of
completeness, in the example above the message title variable `rest`
is assigned the string 'U Thor fa1afe1 Some change' (without the
single quotes).

Print an error message for unknown or unsupported command line
options, which means an error for all specified options at the
moment. Cleanly break the `do_next` loop by assigning the special
value 'unknown' to the local variable `command`, which triggers the
unknown command case in `do_cmd`.

The to-do list is also parsed when the commit hashes are translated
between long and short format before and after the to-do list is
edited. Apply the same procedure as in `do_cmd` with the exception
that we only care about where the options stop and the commit hash
begins. Do not reject any options when transforming the commit
hashes.

Signed-off-by: Fabian Ruch baf...@gmail.com
---
 git-rebase--interactive.sh | 49 ++
 1 file changed, 41 insertions(+), 8 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 9de7441..2119d00 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -587,8 +587,26 @@ do_pick () {
 
 do_replay () {
command=$1
-   sha1=$2
-   rest=$3
+   shift
+
+   opts=
+   while test $# -gt 0
+   do
+   case $1 in
+   -*)
+   warn Unknown option: $1
+   command=unknown
+   ;;
+   *)
+   break
+   ;;
+   esac
+   opts=$opts $(git rev-parse --sq-quote $1)
+   shift
+   done
+   sha1=$1
+   shift
+   rest=$*
 
case $command in
pick|p)
@@ -671,7 +689,7 @@ do_replay () {
 
 do_next () {
rm -f $msg $author_script $amend || exit
-   read -r command sha1 rest $todo
+   read -r command args $todo
 
case $command in
$comment_char*|''|noop)
@@ -716,7 +734,7 @@ do_next () {
fi
;;
*)
-   do_replay $command $sha1 $rest
+   do_replay $command $args
;;
esac
test -s $todo  return
@@ -796,19 +814,34 @@ skip_unnecessary_picks () {
 }
 
 transform_todo_ids () {
-   while read -r command rest
+   while read -r command args
do
case $command in
$comment_char* | exec)
# Be careful for oddball commands like 'exec'
# that do not have a SHA-1 at the beginning of $rest.
+   newargs=\ $args
;;
*)
-   sha1=$(git rev-parse --verify --quiet $@ ${rest%% *}) 

-   rest=$sha1 ${rest#* }
+   newargs=
+   sha1=
+   for arg in $args
+   do
+   case $arg in
+   -*)
+   newargs=$newargs $arg
+   ;;
+   *)
+   test -z $sha1 
+   sha1=$(git rev-parse --verify 
--quiet $@ $arg) 
+   arg=$sha1
+   newargs=$newargs $arg
+   ;;
+   esac
+   done
;;
esac
-   printf '%s\n' $command${rest:+ }$rest
+   printf '%s\n' $command$newargs
done $todo $todo.new 
mv -f $todo.new $todo
 }
-- 
2.0.0

--
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 RFC v2 13/19] rebase -i: Prepare for squash in terms of do_pick --amend

2014-07-02 Thread Fabian Ruch
Rewrite `squash` and `fixup` handling in `do_next` using the sequence

pick_one
commit

in order to test the correctness of a single `do_squash` or
parameterised `do_pick` and make the subsequent patch reimplementing
`squash` in terms of such a single function more readable.

Do not call `rm -f $GIT_DIR/MERGE_MSG` since it has no effect on
the state after git-rebase--interactive terminates. The option `-F`
makes git-commit ignore `MERGE_MSG` for the log message. If
git-commit succeeds, `MERGE_MSG` is removed, and if it fails,
`MERGE_MSG` is overwritten by the error sequence `die_failed_squash`.
In summary, removing `MERGE_MSG` neither influences the squash commit
message nor the file state after git-commit returns.

Moreover, `pick_one` ignores `$GIT_DIR/SQUASH_MSG` and does not touch
`$squash_msg` so that it is correct to execute `pick_one` immediately
before git-commit.

Might be squashed into the subsequent commit.

Signed-off-by: Fabian Ruch baf...@gmail.com
---
 git-rebase--interactive.sh | 21 +++--
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 47e3edf..37800be 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -633,15 +633,15 @@ do_next () {
author_script_content=$(get_author_ident_from_commit HEAD)
echo $author_script_content  $author_script
eval $author_script_content
-   if ! pick_one -n $sha1
-   then
-   git rev-parse --verify HEAD $amend
-   die_failed_squash $sha1 $rest
-   fi
case $(peek_next_command) in
squash|s|fixup|f)
# This is an intermediate commit; its message will only 
be
# used in case of trouble.  So use the long version:
+   if ! pick_one -n $sha1
+   then
+   git rev-parse --verify HEAD $amend
+   die_failed_squash $sha1 Could not apply 
$sha1... $rest
+   fi
do_with_author output git commit --amend --no-verify -F 
$squash_msg \
${gpg_sign_opt:+$gpg_sign_opt} ||
die_failed_squash $sha1 $rest
@@ -650,12 +650,21 @@ do_next () {
# This is the final command of this squash/fixup group
if test -f $fixup_msg
then
+   if ! pick_one -n $sha1
+   then
+   git rev-parse --verify HEAD $amend
+   die_failed_squash $sha1 Could not 
apply $sha1... $rest
+   fi
do_with_author git commit --amend --no-verify 
-F $fixup_msg \
${gpg_sign_opt:+$gpg_sign_opt} ||
die_failed_squash $sha1 $rest
else
cp $squash_msg $GIT_DIR/SQUASH_MSG || exit
-   rm -f $GIT_DIR/MERGE_MSG
+   if ! pick_one -n $sha1
+   then
+   git rev-parse --verify HEAD $amend
+   die_failed_squash $sha1 Could not 
apply $sha1... $rest
+   fi
do_with_author git commit --amend --no-verify 
-F $GIT_DIR/SQUASH_MSG -e \
${gpg_sign_opt:+$gpg_sign_opt} ||
die_failed_squash $sha1 $rest
-- 
2.0.0

--
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 v7 04/16] trace: improve trace performance

2014-07-02 Thread Junio C Hamano
Karsten Blees karsten.bl...@gmail.com writes:

 Replace the 'const char *key' parameter in the API with a pointer to a
 'struct trace_key' that bundles the environment variable name with
 additional, trace-internal state. Change the call sites of these APIs to
 use a static 'struct trace_key' instead of a string constant.

Nice.  Very nice ;-).

 In trace.c::get_trace_fd(), save and reuse the file descriptor in 'struct
 trace_key'.

 Add a 'trace_disable()' API, so that packet_trace() can cleanly disable
 tracing when it encounters packed data (instead of using unsetenv()).

Again, very nice.

 Signed-off-by: Karsten Blees bl...@dcon.de
 ---
  builtin/receive-pack.c |   2 +-
  commit.h   |   1 +
  pkt-line.c |   8 ++--
  shallow.c  |  10 ++---
  trace.c| 100 
 ++---
  trace.h|  16 ++--
  6 files changed, 78 insertions(+), 59 deletions(-)

 diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
 index c323081..1451050 100644
 --- a/builtin/receive-pack.c
 +++ b/builtin/receive-pack.c
 @@ -438,7 +438,7 @@ static int update_shallow_ref(struct command *cmd, struct 
 shallow_info *si)
   uint32_t mask = 1  (cmd-index % 32);
   int i;
  
 - trace_printf_key(GIT_TRACE_SHALLOW,
 + trace_printf_key(trace_shallow,
shallow: update_shallow_ref %s\n, cmd-ref_name);
   for (i = 0; i  si-shallow-nr; i++)
   if (si-used_shallow[i] 
 diff --git a/commit.h b/commit.h
 index a9f177b..08ef643 100644
 --- a/commit.h
 +++ b/commit.h
 @@ -235,6 +235,7 @@ extern void assign_shallow_commits_to_refs(struct 
 shallow_info *info,
  int *ref_status);
  extern int delayed_reachability_test(struct shallow_info *si, int c);
  extern void prune_shallow(int show_only);
 +extern struct trace_key trace_shallow;
  
  int is_descendant_of(struct commit *, struct commit_list *);
  int in_merge_bases(struct commit *, struct commit *);
 diff --git a/pkt-line.c b/pkt-line.c
 index bc63b3b..8bc89b1 100644
 --- a/pkt-line.c
 +++ b/pkt-line.c
 @@ -3,7 +3,7 @@
  
  char packet_buffer[LARGE_PACKET_MAX];
  static const char *packet_trace_prefix = git;
 -static const char trace_key[] = GIT_TRACE_PACKET;
 +static struct trace_key trace_packet = TRACE_KEY_INIT(PACKET);
  
  void packet_trace_identity(const char *prog)
  {
 @@ -15,7 +15,7 @@ static void packet_trace(const char *buf, unsigned int len, 
 int write)
   int i;
   struct strbuf out;
  
 - if (!trace_want(trace_key))
 + if (!trace_want(trace_packet))
   return;
  
   /* +32 is just a guess for header + quoting */
 @@ -27,7 +27,7 @@ static void packet_trace(const char *buf, unsigned int len, 
 int write)
   if ((len = 4  starts_with(buf, PACK)) ||
   (len = 5  starts_with(buf+1, PACK))) {
   strbuf_addstr(out, PACK ...);
 - unsetenv(trace_key);
 + trace_disable(trace_packet);
   }
   else {
   /* XXX we should really handle printable utf8 */
 @@ -43,7 +43,7 @@ static void packet_trace(const char *buf, unsigned int len, 
 int write)
   }
  
   strbuf_addch(out, '\n');
 - trace_strbuf(trace_key, out);
 + trace_strbuf(trace_packet, out);
   strbuf_release(out);
  }
  
 diff --git a/shallow.c b/shallow.c
 index 0b267b6..de07709 100644
 --- a/shallow.c
 +++ b/shallow.c
 @@ -325,7 +325,7 @@ void prune_shallow(int show_only)
   strbuf_release(sb);
  }
  
 -#define TRACE_KEY GIT_TRACE_SHALLOW
 +struct trace_key trace_shallow = TRACE_KEY_INIT(SHALLOW);
  
  /*
   * Step 1, split sender shallow commits into ours and theirs
 @@ -334,7 +334,7 @@ void prune_shallow(int show_only)
  void prepare_shallow_info(struct shallow_info *info, struct sha1_array *sa)
  {
   int i;
 - trace_printf_key(TRACE_KEY, shallow: prepare_shallow_info\n);
 + trace_printf_key(trace_shallow, shallow: prepare_shallow_info\n);
   memset(info, 0, sizeof(*info));
   info-shallow = sa;
   if (!sa)
 @@ -365,7 +365,7 @@ void remove_nonexistent_theirs_shallow(struct 
 shallow_info *info)
  {
   unsigned char (*sha1)[20] = info-shallow-sha1;
   int i, dst;
 - trace_printf_key(TRACE_KEY, shallow: 
 remove_nonexistent_theirs_shallow\n);
 + trace_printf_key(trace_shallow, shallow: 
 remove_nonexistent_theirs_shallow\n);
   for (i = dst = 0; i  info-nr_theirs; i++) {
   if (i != dst)
   info-theirs[dst] = info-theirs[i];
 @@ -516,7 +516,7 @@ void assign_shallow_commits_to_refs(struct shallow_info 
 *info,
   int *shallow, nr_shallow = 0;
   struct paint_info pi;
  
 - trace_printf_key(TRACE_KEY, shallow: 
 assign_shallow_commits_to_refs\n);
 + trace_printf_key(trace_shallow, shallow: 
 assign_shallow_commits_to_refs\n);
   shallow = xmalloc(sizeof(*shallow) * (info-nr_ours + info-nr_theirs));
   for (i = 0; i  

[PATCH] enums: remove trailing ',' after last item in enum

2014-07-02 Thread Ronnie Sahlberg
Signed-off-by: Ronnie Sahlberg sahlb...@google.com
---
 builtin/clean.c | 2 +-
 builtin/tag.c   | 2 +-
 pretty.c| 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/builtin/clean.c b/builtin/clean.c
index 9a91515..27701d2 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -48,7 +48,7 @@ enum color_clean {
CLEAN_COLOR_PROMPT = 2,
CLEAN_COLOR_HEADER = 3,
CLEAN_COLOR_HELP = 4,
-   CLEAN_COLOR_ERROR = 5,
+   CLEAN_COLOR_ERROR = 5
 };
 
 #define MENU_OPTS_SINGLETON01
diff --git a/builtin/tag.c b/builtin/tag.c
index c6e8a71..ef76556 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -83,7 +83,7 @@ static int in_commit_list(const struct commit_list *want, 
struct commit *c)
 enum contains_result {
CONTAINS_UNKNOWN = -1,
CONTAINS_NO = 0,
-   CONTAINS_YES = 1,
+   CONTAINS_YES = 1
 };
 
 /*
diff --git a/pretty.c b/pretty.c
index 4f51287..924bc61 100644
--- a/pretty.c
+++ b/pretty.c
@@ -274,7 +274,7 @@ static void add_rfc822_quoted(struct strbuf *out, const 
char *s, int len)
 
 enum rfc2047_type {
RFC2047_SUBJECT,
-   RFC2047_ADDRESS,
+   RFC2047_ADDRESS
 };
 
 static int is_rfc2047_special(char ch, enum rfc2047_type type)
-- 
2.0.1.442.g7fe6834.dirty

--
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: Re* [PATCH v3 04/14] refs.c: add a new update_type field to ref_update

2014-07-02 Thread Ronnie Sahlberg
On Wed, Jun 18, 2014 at 2:10 PM, Junio C Hamano gits...@pobox.com wrote:
 Junio C Hamano gits...@pobox.com writes:

 Ronnie Sahlberg sahlb...@google.com writes:

 Add a field that describes what type of update this refers to. For now
 the only type is UPDATE_SHA1 but we will soon add more types.

 Signed-off-by: Ronnie Sahlberg sahlb...@google.com
 ---
  refs.c | 25 +
  1 file changed, 21 insertions(+), 4 deletions(-)

 diff --git a/refs.c b/refs.c
 index 4e3d4c3..4129de6 100644
 --- a/refs.c
 +++ b/refs.c
 @@ -3374,6 +3374,10 @@ int for_each_reflog(each_ref_fn fn, void *cb_data)
  return retval;
  }

 +enum transaction_update_type {
 +   UPDATE_SHA1 = 0,

 indent with SP?

 Unlike an array initialisation, e.g.

   int foo[] = { 1,2,3,4,5, };

 some compilers we support complain if enum definition ends with a
 trailing comma.

 I do recall we had fixes to drop the comma after the last element in
 enum definition in the past, in response real compilation breakages
 on some platforms.

You are right. I think I recall this too on old c compilers on legacy
unix boxens.

I have fixed this and will resend the series.


I have also checked additional enums in the sources and found 3 more places.
I sent this as a single patch to the list with the subject :

Subject: [PATCH] enums: remove trailing ',' after last item in enum



  But there is a curious thing:

 git grep -Asomenumber 'enum ' master -- \*.c

 tells me that builtin/clean.c would fail to compile for those folks.

Most likely.  It might be that there are less and less people on
really old c-compilers these days.



 Here is an off-topic fix that may no longer be needed.

  builtin/clean.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

 diff --git a/builtin/clean.c b/builtin/clean.c
 index 9a91515..27701d2 100644
 --- a/builtin/clean.c
 +++ b/builtin/clean.c
 @@ -48,7 +48,7 @@ enum color_clean {
 CLEAN_COLOR_PROMPT = 2,
 CLEAN_COLOR_HEADER = 3,
 CLEAN_COLOR_HELP = 4,
 -   CLEAN_COLOR_ERROR = 5,
 +   CLEAN_COLOR_ERROR = 5
  };

  #define MENU_OPTS_SINGLETON01


Thanks
ronnie sahlberg
--
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] t7300: repair filesystem permissions with test_when_finished

2014-07-02 Thread Jeff King
We create a directory that cannot be removed, confirm that
it cannot be removed, and then fix it like:

  chmod 0 foo 
  test_must_fail git clean -d -f 
  chmod 755 foo

If the middle step fails but leaves the directory (e.g., the
bug is that clean does not notice the failure), this
pollutes the test repo with an unremovable directory. Not
only does this cause further tests to fail, but it means
that rm -rf fails on the whole trash directory, and the
user has to intervene manually to even re-run the test script.

We can bump the chmod 755 recovery to a test_when_finished
block to be sure that it always runs.

Signed-off-by: Jeff King p...@peff.net
---
 t/t7300-clean.sh | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
index 74de814..04118ad 100755
--- a/t/t7300-clean.sh
+++ b/t/t7300-clean.sh
@@ -426,10 +426,10 @@ test_expect_success SANITY 'removal failure' '
 
mkdir foo 
touch foo/bar 
+   test_when_finished chmod 755 foo 
(exec foo/bar 
 chmod 0 foo 
-test_must_fail git clean -f -d 
-chmod 755 foo)
+test_must_fail git clean -f -d)
 '
 
 test_expect_success 'nested git work tree' '
-- 
2.0.0.566.gfe3e6b2
--
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 v7 11/16] trace: add 'file:line' to all trace output

2014-07-02 Thread Junio C Hamano
Karsten Blees karsten.bl...@gmail.com writes:

 +#else
 +
 +/*
 + * Macros to add file:line - see above for C-style declarations of how these
 + * should be used.
 + *
 + * TRACE_CONTEXT may be set to __FUNCTION__ if the compiler supports it. The
 + * default is __FILE__, as it is consistent with assert(), and static 
 function
 + * names are not necessarily unique.
 + */
 +#define TRACE_CONTEXT __FILE__

Hmph, seeing may be set to forces me to wonder how.  Perhaps #ifndef/#endif
around it?

Also, can it be set to something like __FILE__ : __FUNCTION__
which may alleviate the alleged problem of not necessarily unique
perhaps?
--
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] t7300: repair filesystem permissions with test_when_finished

2014-07-02 Thread Jonathan Nieder
Jeff King wrote:

 Signed-off-by: Jeff King p...@peff.net
 ---
  t/t7300-clean.sh | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

Does the later git clean -d with an unreadable empty directory test
need the same treatment?

Thanks,
Jonathan
--
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] t7300: repair filesystem permissions with test_when_finished

2014-07-02 Thread Jeff King
On Wed, Jul 02, 2014 at 12:01:59PM -0700, Jonathan Nieder wrote:

 Jeff King wrote:
 
  Signed-off-by: Jeff King p...@peff.net
  ---
   t/t7300-clean.sh | 4 ++--
   1 file changed, 2 insertions(+), 2 deletions(-)
 
 Does the later git clean -d with an unreadable empty directory test
 need the same treatment?

I don't think so, because it is also failing during the experiments I'm
doing and it is not causing the same problem.

-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


[RFH] git clean deletes excluded files in untracked directories

2014-07-02 Thread Jeff King
If you have an untracked directory that contains excluded files, like
this:

  mkdir foo
  echo content foo/one
  echo content foo/two
  echo foo/one .gitignore

then git clean -d will notice that foo is untracked and recursively
delete it and its contents, including the ignored foo/one.

Our stance has always been that ignored files are not precious, so in
that sense it is not a big loss. But git clean does provide a -x
option, and takes care to avoid deleting ignored files when it is not
given. So I'd argue that we should delete foo/two but retain
foo/one, unless -x is given.

I'm not sure of the best way to go about that, though. The patch below
is my first attempt. It stops using DIR_SHOW_OTHER_DIRECTORIES when we
find the list of files to delete, which means we get the full set of
paths (so instead of foo/, we see foo/one and foo/two after
calling fill_directory). But then we have to notice that foo should go
away if all of its contents do. For that, I use remove_path, which just
walks up the pathname, removing leading directories until we hit a
non-empty one.

But there are a few problems:

  1. Is it possible that we want to remove foo/bar but not foo? The
 obvious case would be that foo is excluded but foo/bar is not. I
 guess you could get that with negative excludes, like:

   foo/
   !foo/bar

  2. The output is different (we report each file we are removing,
 rather than just the root directory).

  3. The error handling is different. If we have an unreadable untracked
 directory now, fill_directory does not recurse into it; we get the
 directory name and complain when we cannot remove it. But with this
 patch, fill_directory tries to enter it, can't, and simply fails to
 report any entries inside it (this causes test failures in t7300).

So this is probably not the right way to go about it.  I'm not sure of
the best way.

One option is to actually teach clean's recursive remove_dirs function
to actually check excludes itself for each file. That feels hacky,
though, since we should be checking them already in fill_directory.

Another is to add a flag to fill_directory to indicate that it should
recurse into directories to find excluded files, but not otherwise (we
usually avoid it for reasons of efficiency, but since we would be
immediately entering them to delete anyway, I don't think that's a
concern here). I think this makes the fill_directory logic quite
complicated, though.

Suggestions?

---
diff --git a/builtin/clean.c b/builtin/clean.c
index 9a91515..f159eed 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -914,7 +914,8 @@ int cmd_clean(int argc, const char **argv, const char 
*prefix)
if (force  1)
rm_flags = 0;
 
-   dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
+   if (!remove_directories)
+   dir.flags |= DIR_SHOW_OTHER_DIRECTORIES;
 
if (read_cache()  0)
die(_(index file corrupt));
@@ -985,7 +986,7 @@ int cmd_clean(int argc, const char **argv, const char 
*prefix)
printf(dry_run ? _(msg_would_remove) : 
_(msg_remove), qname);
}
} else {
-   res = dry_run ? 0 : unlink(abs_path.buf);
+   res = dry_run ? 0 : remove_path(abs_path.buf);
if (res) {
qname = quote_path_relative(item-string, NULL, 
buf);
warning(_(msg_warn_remove_failed), qname);
diff --git a/t/t7300-clean.sh b/t/t7300-clean.sh
index 04118ad..647844f 100755
--- a/t/t7300-clean.sh
+++ b/t/t7300-clean.sh
@@ -527,4 +527,12 @@ test_expect_success 'git clean -d respects pathspecs 
(pathspec is prefix of dir)
test_path_is_dir foobar
 '
 
+test_expect_success 'clean -d does not clean ignored files' '
+   mkdir -p foo 
+   echo content foo/file 
+   echo foo/* .gitignore 
+   git clean -df /dev/tty 
+   test_path_is_file foo/file
+'
+
 test_done
--
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 v7 11/16] trace: add 'file:line' to all trace output

2014-07-02 Thread Junio C Hamano
Karsten Blees karsten.bl...@gmail.com writes:

 Also, can it be set to something like __FILE__ : __FUNCTION__
 which may alleviate the alleged problem of not necessarily unique
 perhaps?

 Should work with MSVC. With GCC, however, __FUNCTION__ is a string constant
 supplied by the compiler, so string literal concatenation doesn't work.

Shucks, but not too big a deal, I guess ;-)

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 v7 11/16] trace: add 'file:line' to all trace output

2014-07-02 Thread Karsten Blees
Am 02.07.2014 20:57, schrieb Junio C Hamano:
 Karsten Blees karsten.bl...@gmail.com writes:
 
 +#else
 +
 +/*
 + * Macros to add file:line - see above for C-style declarations of how these
 + * should be used.
 + *
 + * TRACE_CONTEXT may be set to __FUNCTION__ if the compiler supports it. The
 + * default is __FILE__, as it is consistent with assert(), and static 
 function
 + * names are not necessarily unique.
 + */
 +#define TRACE_CONTEXT __FILE__
 
 Hmph, seeing may be set to forces me to wonder how.  Perhaps #ifndef/#endif
 around it?
 

Right, shame on me. I didn't think it would be important enough to warrant a
Makefile option, but #ifndef sure wouldn't hurt.

 Also, can it be set to something like __FILE__ : __FUNCTION__
 which may alleviate the alleged problem of not necessarily unique
 perhaps?
 

Should work with MSVC. With GCC, however, __FUNCTION__ is a string constant
supplied by the compiler, so string literal concatenation doesn't work.

--
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 00/14] Add submodule test harness

2014-07-02 Thread Jens Lehmann
Am 02.07.2014 16:54, schrieb Torsten Bögershausen:
 (Not sure if this is the right thread)
 (I haven't checked if this is fixed in your latest version)

Yes, this is the right thread and no, it isn't fixed yet.

 On what I have on pu 7a0da7902cbbc9a876b90c9, Tue Jul 1 14:51:53 2014 -0700
 
 Many submodule tests are broken.
 One problem is here:
 
 lib-submodule-update.sh:264: possible problem: echo -n is not portable 
 (please use printf): echo -n sub1 
 lib-submodule-update.sh:507: possible problem: echo -n is not portable 
 (please use printf): echo -n sub1 
 
 You can remove the empty echo -n to create an empty file:
 sub1 

Thanks for spotting and diagnosing this. Running make lint in the
test directory only feeds the tests to check-non-portable-shell.pl,
but not the *lib*.sh helper scripts, which made me miss this one.

The following diff should fix it for you. Am I understanding you
correctly that you are experiencing other failures too? I see no
other incompatibilities when running ./check-non-portable-shell.pl
on all the shell scripts in the repo.

-8
diff --git a/t/lib-submodule-update.sh b/t/lib-submodule-update.sh
index 24c9fd7..3584755 100755
--- a/t/lib-submodule-update.sh
+++ b/t/lib-submodule-update.sh
@@ -304,7 +304,7 @@ test_submodule_switch () {
(
cd submodule_update 
git branch -t add_sub1 origin/add_sub1 
-   echo -n sub1 
+   sub1 
test_must_fail $command add_sub1 
test_superproject_content origin/no_submodule 
test_must_be_empty sub1
@@ -547,7 +547,7 @@ test_submodule_forced_switch () {
(
cd submodule_update 
git branch -t add_sub1 origin/add_sub1 
-   echo -n sub1 
+   sub1 
$command add_sub1 
test_superproject_content origin/add_sub1 
test_dir_is_empty sub1
-- 
2.0.1.458.gf680257.dirty


--
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] enums: remove trailing ',' after last item in enum

2014-07-02 Thread Jonathan Nieder
Ronnie Sahlberg wrote:

 Signed-off-by: Ronnie Sahlberg sahlb...@google.com
 ---
  builtin/clean.c | 2 +-
  builtin/tag.c   | 2 +-
  pretty.c| 2 +-
  3 files changed, 3 insertions(+), 3 deletions(-)

Is there some gcc option or other tool that can automatically detect
this kind of problem so the regress/fix cycle doesn't have to repeat
too many times?

Looks like v1.7.2-rc0~32^2~16 (2010-03-14) and v1.7.4.2~34 (2011-03-16)
tried to fix this in the past.

Using the test from v1.7.4.2~34 also finds enums with trailing comma
in

 grep.h
 log-tree.c

Thanks,
Jonathan
--
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] t7300: repair filesystem permissions with test_when_finished

2014-07-02 Thread Junio C Hamano
Jeff King p...@peff.net writes:

 On Wed, Jul 02, 2014 at 12:01:59PM -0700, Jonathan Nieder wrote:

 Jeff King wrote:
 
  Signed-off-by: Jeff King p...@peff.net
  ---
   t/t7300-clean.sh | 4 ++--
   1 file changed, 2 insertions(+), 2 deletions(-)
 
 Does the later git clean -d with an unreadable empty directory test
 need the same treatment?

 I don't think so, because it is also failing during the experiments I'm
 doing and it is not causing the same problem.

It tests that clean -d is happy if a blind rmdir(2) removes the
directory.  If it fails for whatever reason (e.g. add exit(0) at
the beginning of cmd_clean(), for example) to remove the directory,
we do leave an empty unreadable directory behind.

But as long as that directory is empty, that will not cause us to
remove the trash directory at the end, so we should be OK.

--
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] enums: remove trailing ',' after last item in enum

2014-07-02 Thread Ronnie Sahlberg
GCC can check/error for this with

--pedantic -Werror




On Wed, Jul 2, 2014 at 12:58 PM, Jonathan Nieder jrnie...@gmail.com wrote:
 Ronnie Sahlberg wrote:

 Signed-off-by: Ronnie Sahlberg sahlb...@google.com
 ---
  builtin/clean.c | 2 +-
  builtin/tag.c   | 2 +-
  pretty.c| 2 +-
  3 files changed, 3 insertions(+), 3 deletions(-)

 Is there some gcc option or other tool that can automatically detect
 this kind of problem so the regress/fix cycle doesn't have to repeat
 too many times?

 Looks like v1.7.2-rc0~32^2~16 (2010-03-14) and v1.7.4.2~34 (2011-03-16)
 tried to fix this in the past.

 Using the test from v1.7.4.2~34 also finds enums with trailing comma
 in

  grep.h
  log-tree.c

 Thanks,
 Jonathan
--
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/7] replace: add test for --graft

2014-07-02 Thread Junio C Hamano
Christian Couder chrisc...@tuxfamily.org writes:

 Signed-off-by: Christian Couder chrisc...@tuxfamily.org
 Signed-off-by: Junio C Hamano gits...@pobox.com
 ---
  t/t6050-replace.sh | 12 
  1 file changed, 12 insertions(+)

 diff --git a/t/t6050-replace.sh b/t/t6050-replace.sh
 index 68b3cb2..ca45a84 100755
 --- a/t/t6050-replace.sh
 +++ b/t/t6050-replace.sh
 @@ -351,4 +351,16 @@ test_expect_success 'replace ref cleanup' '
   test -z $(git replace)
  '
  
 +test_expect_success '--graft with and without already replaced object' '
 + test $(git log --oneline | wc -l) = 7 
 + git replace --graft $HASH5 
 + test $(git log --oneline | wc -l) = 3 
 + git cat-file -p $HASH5 | test_must_fail grep parent 

Please do not run non-git command under test_must_fail.

 + test_must_fail git replace --graft $HASH5 $HASH4 $HASH3 
 + git replace --force -g $HASH5 $HASH4 $HASH3 
 + git cat-file -p $HASH5 | grep parent $HASH4 
 + git cat-file -p $HASH5 | grep parent $HASH3 
 + git replace -d $HASH5
 +'
 +
  test_done

For all these git cat-file -p $commit | grep ..., I would think
you should add commit_has_parents helper function to allow a bit
more careful testing.  As written, the test will mistake a commit
with string parent $HASHx anywhere, not in the header part, and
the test does not ensure that $HASH{3,4} is the {first,second}
parent.

commit_has_parents $HASH5 $HASH4 $HASH3

would then may be implemented like:

commit_has_parents () {
git cat-file commit $1 payload 
sed -n -e '/^$/q' -e 's/^parent //p' payload actual 
shift 
printf 'parent %s\n' $@ expect 
test_cmp expect actual
}

--
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 5/7] replace: refactor replacing parents

2014-07-02 Thread Junio C Hamano
Christian Couder chrisc...@tuxfamily.org writes:

 Signed-off-by: Christian Couder chrisc...@tuxfamily.org
 ---
  builtin/replace.c | 42 +-
  1 file changed, 25 insertions(+), 17 deletions(-)

 diff --git a/builtin/replace.c b/builtin/replace.c
 index 3515979..ad47237 100644
 --- a/builtin/replace.c
 +++ b/builtin/replace.c
 @@ -295,27 +295,14 @@ static int edit_and_replace(const char *object_ref, int 
 force)
   return replace_object_sha1(object_ref, old, replacement, new, force);
  }
  
 -static int create_graft(int argc, const char **argv, int force)
 +static void replace_parents(struct strbuf *buf, int argc, const char **argv)

It is somewhat strange to see that a new function introduced earlier
in the series is rewritten with a refactoring.  Shouldn't the new
function have been done right from the beginning instead?

  {
 - unsigned char old[20], new[20];
 - const char *old_ref = argv[0];
 - struct commit *commit;
 - struct strbuf buf = STRBUF_INIT;
   struct strbuf new_parents = STRBUF_INIT;
   const char *parent_start, *parent_end;
 - const char *buffer;
 - unsigned long size;
   int i;
  
 - if (get_sha1(old_ref, old)  0)
 - die(_(Not a valid object name: '%s'), old_ref);
 - commit = lookup_commit_or_die(old, old_ref);
 -
   /* find existing parents */
 - buffer = get_commit_buffer(commit, size);
 - strbuf_add(buf, buffer, size);
 - unuse_commit_buffer(commit, buffer);
 - parent_start = buf.buf;
 + parent_start = buf-buf;
   parent_start += 46; /* tree  + hex sha1 + \n */
   parent_end = parent_start;
  
 @@ -332,13 +319,34 @@ static int create_graft(int argc, const char **argv, 
 int force)
   }
  
   /* replace existing parents with new ones */
 - strbuf_splice(buf, parent_start - buf.buf, parent_end - parent_start,
 + strbuf_splice(buf, parent_start - buf-buf, parent_end - parent_start,
 new_parents.buf, new_parents.len);
  
 + strbuf_release(new_parents);
 +}
 +
 +static int create_graft(int argc, const char **argv, int force)
 +{
 + unsigned char old[20], new[20];
 + const char *old_ref = argv[0];
 + struct commit *commit;
 + struct strbuf buf = STRBUF_INIT;
 + const char *buffer;
 + unsigned long size;
 +
 + if (get_sha1(old_ref, old)  0)
 + die(_(Not a valid object name: '%s'), old_ref);
 + commit = lookup_commit_or_die(old, old_ref);
 +
 + buffer = get_commit_buffer(commit, size);
 + strbuf_add(buf, buffer, size);
 + unuse_commit_buffer(commit, buffer);
 +
 + replace_parents(buf, argc, argv);
 +
   if (write_sha1_file(buf.buf, buf.len, commit_type, new))
   die(_(could not write replacement commit for: '%s'), old_ref);
  
 - strbuf_release(new_parents);
   strbuf_release(buf);
  
   if (!hashcmp(old, new))
--
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 6/7] replace: remove signature when using --graft

2014-07-02 Thread Junio C Hamano
Christian Couder chrisc...@tuxfamily.org writes:

 It could be misleading to keep a signature in a
 replacement commit, so let's remove it.

 Note that there should probably be a way to sign
 the replacement commit created when using --graft,
 but this can be dealt with in another commit or
 patch series.

Both paragraphs read very sensibly.


 Signed-off-by: Christian Couder chrisc...@tuxfamily.org
 ---
  builtin/replace.c |  5 +
  commit.c  | 34 ++
  commit.h  |  2 ++
  3 files changed, 41 insertions(+)

 diff --git a/builtin/replace.c b/builtin/replace.c
 index ad47237..000db65 100644
 --- a/builtin/replace.c
 +++ b/builtin/replace.c
 @@ -344,6 +344,11 @@ static int create_graft(int argc, const char **argv, int 
 force)
  
   replace_parents(buf, argc, argv);
  
 + if (remove_signature(buf))
 + warning(_(the original commit '%s' has a gpg signature.\n
 +   It will be removed in the replacement commit!),

Hmmm...  does the second line of this message start with the usual
warning: prefix?

 diff --git a/commit.c b/commit.c
 index fb7897c..54e157d 100644
 --- a/commit.c
 +++ b/commit.c
 @@ -1177,6 +1177,40 @@ int parse_signed_commit(const struct commit *commit,
   return saw_signature;
  }
  
 +int remove_signature(struct strbuf *buf)
 +{
 + const char *line = buf-buf;
 + const char *tail = buf-buf + buf-len;
 + int in_signature = 0;
 + const char *sig_start = NULL;
 + const char *sig_end = NULL;
 +
 + while (line  tail) {
 + const char *next = memchr(line, '\n', tail - line);
 + next = next ? next + 1 : tail;

This almost makes me wonder if we want something similar to
strchrnul() we use for NUL-terminated strings, and I suspect that
you would find more instances by running git grep -A2 memchr.

I don't know what such a helper function should be named, though.
Certainly not memchrnul().

 +
 + if (in_signature  line[0] == ' ')
 + sig_end = next;
 + else if (starts_with(line, gpg_sig_header) 
 +  line[gpg_sig_header_len] == ' ') {
 + sig_start = line;
 + sig_end = next;
 + in_signature = 1;
 + } else {
 + if (*line == '\n')
 + /* dump the whole remainder of the buffer */
 + next = tail;
 + in_signature = 0;
 + }
 + line = next;
 + }
 +
 + if (sig_start)
 + strbuf_remove(buf, sig_start - buf-buf, sig_end - sig_start);

If there are two instances of gpg_sig, this will remove only the
last one, but there is no chance both signatures of such a commit
can validate OK, and we won't be losing something in between anyway,
so it should be fine.

 + return sig_start != NULL;
 +}
 +
  static void handle_signed_tag(struct commit *parent, struct 
 commit_extra_header ***tail)
  {
   struct merge_remote_desc *desc;
 diff --git a/commit.h b/commit.h
 index 2e1492a..4234dae 100644
 --- a/commit.h
 +++ b/commit.h
 @@ -327,6 +327,8 @@ struct commit *get_merge_parent(const char *name);
  
  extern int parse_signed_commit(const struct commit *commit,
  struct strbuf *message, struct strbuf 
 *signature);
 +extern int remove_signature(struct strbuf *buf);
 +
  extern void print_commit_list(struct commit_list *list,
 const char *format_cur,
 const char *format_last);
--
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


Race condition in git push --mirror can cause silent ref rewinding

2014-07-02 Thread Alex Vandiver
Heya,

We recently ran into a particularly troubling race condition, discovered
in git 2.0.0.  The setup for it is as follows:

The repository is a bare repository, which developers push to via ssh;
it mirrors its changes out onto github.  In its config:

[remote github]
url = g...@github.com:bestpractical/rt.git
fetch = +refs/*:refs/*
mirror = yes

It has a post-receive hook which does:

sudo -u git -H /usr/bin/git push github


We recently saw a situation where a push of a new branch caused a
simultaneous update of a different branch (by a different user) to be
rewound.  From the reflog of the created branch (4.2/html-gumbo-loading):


1aefd600fcbb5ded14376f77d77a14758668fb39 Wallace Reis
wr...@bestpractical.com 1404326443 -0400   push

And the updated branch (4.2-trunk), which was rewound:

44dc8ad0e4603e3f674b7c00deacc122ca52707a
1e743b6225d502ad1a265929fb873f4c0bf4f8a5 Kevin Falcone
falc...@bestpractical.com 1404326446 -0400push
1e743b6225d502ad1a265929fb873f4c0bf4f8a5
44dc8ad0e4603e3f674b7c00deacc122ca52707a git g...@bestpractical.com
1404326446 -0400update by push

It is my belief that this comes because the --mirror argument causes
the local refs to be treated as tracking refs -- and thus updates all of
them during the push.  I believe the race condition is thus:

  1. User A starts a push --mirror; git records the values of the refs

  2. User B updates a ref, commit mail goes out, etc

  3. User A's push completes, updates tracking branch to value at (1).


Needless to say, silently losing commits which appeared for all purposes
to be pushed successfully (neither User A nor User B sees anything out
of the ordinary) is extremely troubling.

 - Alex
--
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 v1 0/4] hashmap improvements

2014-07-02 Thread Karsten Blees
Here are a few small hashmap improvements, partly resulting from recent
discussion of the config-cache topic.

Karsten Blees (4):
  hashmap: factor out getting an int hash code from a SHA1
  hashmap: improve struct hashmap member documentation
  hashmap: add simplified hashmap_get_from_hash() API
  hashmap: add string interning API

 Documentation/technical/api-hashmap.txt | 54 ++---
 builtin/describe.c  | 13 ++--
 decorate.c  |  5 +--
 diffcore-rename.c   | 11 +++
 hashmap.c   | 38 +++
 hashmap.h   | 27 +
 khash.h | 11 ++-
 name-hash.c |  5 ++-
 object.c| 13 +---
 pack-objects.c  |  5 ++-
 t/t0011-hashmap.sh  | 13 
 test-hashmap.c  | 25 ++-
 12 files changed, 159 insertions(+), 61 deletions(-)

-- 
1.9.4.msysgit.0.dirty

--
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: Race condition in git push --mirror can cause silent ref rewinding

2014-07-02 Thread Junio C Hamano
Alex Vandiver a...@chmrr.net writes:

 [remote github]
 url = g...@github.com:bestpractical/rt.git
 fetch = +refs/*:refs/*
 mirror = yes

git push github master^:master must stay a usable way to update
the published repository to an arbitrary commit, so if set to
mirror, do not pretend that a fetch in reverse has happened during
'git push' will not be a solution to this issue.

Perhaps removing remote.github.fetch would be one sane way forward.
Otherwise, even if your git push does not pretend to immediately
fetch from there (i.e. even if the reported behaviour was a bug,
without doing anything to trigger it) somebody running git fetch
in this repository can destroy what other person pushes into this
repository at the same time exactly the same way, I would think.
--
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 v1 1/4] hashmap: factor out getting an int hash code from a, SHA1

2014-07-02 Thread Karsten Blees
Copying the first bytes of a SHA1 is duplicated in six places, however,
the implications (wrong byte order on little-endian systems) is documented
only once.

Add a properly documented API for this.

Signed-off-by: Karsten Blees bl...@dcon.de
---
 Documentation/technical/api-hashmap.txt |  9 +
 builtin/describe.c  | 11 ++-
 decorate.c  |  5 +
 diffcore-rename.c   |  4 +---
 hashmap.h   | 11 +++
 khash.h | 11 ++-
 object.c| 13 +
 pack-objects.c  |  5 ++---
 8 files changed, 29 insertions(+), 40 deletions(-)

diff --git a/Documentation/technical/api-hashmap.txt 
b/Documentation/technical/api-hashmap.txt
index b977ae8..4689968 100644
--- a/Documentation/technical/api-hashmap.txt
+++ b/Documentation/technical/api-hashmap.txt
@@ -58,6 +58,15 @@ Functions
 +
 `strihash` and `memihash` are case insensitive versions.
 
+`unsigned int sha1hash(const unsigned char *sha1)`::
+
+   Converts a cryptographic hash (e.g. SHA-1) into an int-sized hash code
+   for use in hash tables. Cryptographic hashes are supposed to have
+   uniform distribution, so in contrast to `memhash()`, this just copies
+   the first `sizeof(int)` bytes without shuffling any bits. Note that
+   the results will be different on big-endian and little-endian
+   platforms, so they should not be stored or transferred over the net!
+
 `void hashmap_init(struct hashmap *map, hashmap_cmp_fn equals_function, size_t 
initial_size)`::
 
Initializes a hashmap structure.
diff --git a/builtin/describe.c b/builtin/describe.c
index 24d740c..57e84c8 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -56,17 +56,10 @@ static int commit_name_cmp(const struct commit_name *cn1,
return hashcmp(cn1-peeled, peeled ? peeled : cn2-peeled);
 }
 
-static inline unsigned int hash_sha1(const unsigned char *sha1)
-{
-   unsigned int hash;
-   memcpy(hash, sha1, sizeof(hash));
-   return hash;
-}
-
 static inline struct commit_name *find_commit_name(const unsigned char *peeled)
 {
struct commit_name key;
-   hashmap_entry_init(key, hash_sha1(peeled));
+   hashmap_entry_init(key, sha1hash(peeled));
return hashmap_get(names, key, peeled);
 }
 
@@ -114,7 +107,7 @@ static void add_to_known_names(const char *path,
if (!e) {
e = xmalloc(sizeof(struct commit_name));
hashcpy(e-peeled, peeled);
-   hashmap_entry_init(e, hash_sha1(peeled));
+   hashmap_entry_init(e, sha1hash(peeled));
hashmap_add(names, e);
e-path = NULL;
}
diff --git a/decorate.c b/decorate.c
index 7cb5d29..b2aac90 100644
--- a/decorate.c
+++ b/decorate.c
@@ -8,10 +8,7 @@
 
 static unsigned int hash_obj(const struct object *obj, unsigned int n)
 {
-   unsigned int hash;
-
-   memcpy(hash, obj-sha1, sizeof(unsigned int));
-   return hash % n;
+   return sha1hash(obj-sha1) % n;
 }
 
 static void *insert_decoration(struct decoration *n, const struct object 
*base, void *decoration)
diff --git a/diffcore-rename.c b/diffcore-rename.c
index 749a35d..6fa97d4 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -242,14 +242,12 @@ struct file_similarity {
 
 static unsigned int hash_filespec(struct diff_filespec *filespec)
 {
-   unsigned int hash;
if (!filespec-sha1_valid) {
if (diff_populate_filespec(filespec, 0))
return 0;
hash_sha1_file(filespec-data, filespec-size, blob, 
filespec-sha1);
}
-   memcpy(hash, filespec-sha1, sizeof(hash));
-   return hash;
+   return sha1hash(filespec-sha1);
 }
 
 static int find_identical_files(struct hashmap *srcs,
diff --git a/hashmap.h b/hashmap.h
index a816ad4..ed5425a 100644
--- a/hashmap.h
+++ b/hashmap.h
@@ -13,6 +13,17 @@ extern unsigned int strihash(const char *buf);
 extern unsigned int memhash(const void *buf, size_t len);
 extern unsigned int memihash(const void *buf, size_t len);
 
+static inline unsigned int sha1hash(const unsigned char *sha1)
+{
+   /*
+* Equivalent to 'return *(int *)sha1;', but safe on platforms that
+* don't support unaligned reads.
+*/
+   unsigned int hash;
+   memcpy(hash, sha1, sizeof(hash));
+   return hash;
+}
+
 /* data structures */
 
 struct hashmap_entry {
diff --git a/khash.h b/khash.h
index 57ff603..06c7906 100644
--- a/khash.h
+++ b/khash.h
@@ -320,19 +320,12 @@ static const double __ac_HASH_UPPER = 0.77;
code;   
\
} }
 
-static inline khint_t __kh_oid_hash(const unsigned char *oid)
-{
-   khint_t hash;
-

[PATCH v1 2/4] hashmap: improve struct hashmap member documentation

2014-07-02 Thread Karsten Blees
Signed-off-by: Karsten Blees bl...@dcon.de
---
 Documentation/technical/api-hashmap.txt | 16 
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/Documentation/technical/api-hashmap.txt 
b/Documentation/technical/api-hashmap.txt
index 4689968..dc21a7c 100644
--- a/Documentation/technical/api-hashmap.txt
+++ b/Documentation/technical/api-hashmap.txt
@@ -8,11 +8,19 @@ Data Structures
 
 `struct hashmap`::
 
-   The hash table structure.
+   The hash table structure. Members can be used as follows, but should
+   not be modified directly:
 +
-The `size` member keeps track of the total number of entries. The `cmpfn`
-member is a function used to compare two entries for equality. The `table` and
-`tablesize` members store the hash table and its size, respectively.
+The `size` member keeps track of the total number of entries (0 means the
+hashmap is empty).
++
+`tablesize` is the allocated size of the hash table. A non-0 value indicates
+that the hashmap is initialized. It may also be useful for statistical purposes
+(i.e. `size / tablesize` is the current load factor).
++
+`cmpfn` stores the comparison function specified in `hashmap_init()`. In
+advanced scenarios, it may be useful to change this, e.g. to switch between
+case-sensitive and case-insensitive lookup.
 
 `struct hashmap_entry`::
 
-- 
1.9.4.msysgit.0.dirty

--
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 v1 4/4] hashmap: add string interning API

2014-07-02 Thread Karsten Blees
Interning short strings with high probability of duplicates can reduce the
memory footprint and speed up comparisons.

Add strintern() and memintern() APIs that use a hashmap to manage the pool
of unique, interned strings.

Note: strintern(getenv()) could be used to sanitize git's use of getenv(),
in case we ever encounter a platform where a call to getenv() invalidates
previous getenv() results (which is allowed by POSIX).

Signed-off-by: Karsten Blees bl...@dcon.de
---
 Documentation/technical/api-hashmap.txt | 15 +
 hashmap.c   | 38 +
 hashmap.h   |  8 +++
 t/t0011-hashmap.sh  | 13 +++
 test-hashmap.c  | 14 
 5 files changed, 88 insertions(+)

diff --git a/Documentation/technical/api-hashmap.txt 
b/Documentation/technical/api-hashmap.txt
index f9215d6..00c4c29 100644
--- a/Documentation/technical/api-hashmap.txt
+++ b/Documentation/technical/api-hashmap.txt
@@ -193,6 +193,21 @@ more entries.
 `hashmap_iter_first` is a combination of both (i.e. initializes the iterator
 and returns the first entry, if any).
 
+`const char *strintern(const char *string)`::
+`const void *memintern(const void *data, size_t len)`::
+
+   Returns the unique, interned version of the specified string or data,
+   similar to the `String.intern` API in Java and .NET, respectively.
+   Interned strings remain valid for the entire lifetime of the process.
++
+Can be used as `[x]strdup()` or `xmemdupz` replacement, except that interned
+strings / data must not be modified or freed.
++
+Interned strings are best used for short strings with high probability of
+duplicates.
++
+Uses a hashmap to store the pool of interned strings.
+
 Usage example
 -
 
diff --git a/hashmap.c b/hashmap.c
index d1b8056..f693839 100644
--- a/hashmap.c
+++ b/hashmap.c
@@ -226,3 +226,41 @@ void *hashmap_iter_next(struct hashmap_iter *iter)
current = iter-map-table[iter-tablepos++];
}
 }
+
+struct pool_entry {
+   struct hashmap_entry ent;
+   size_t len;
+   unsigned char data[FLEX_ARRAY];
+};
+
+static int pool_entry_cmp(const struct pool_entry *e1,
+ const struct pool_entry *e2,
+ const unsigned char *keydata)
+{
+   return e1-data != keydata 
+  (e1-len != e2-len || memcmp(e1-data, keydata, e1-len));
+}
+
+const void *memintern(const void *data, size_t len)
+{
+   static struct hashmap map;
+   struct pool_entry key, *e;
+
+   /* initialize string pool hashmap */
+   if (!map.tablesize)
+   hashmap_init(map, (hashmap_cmp_fn) pool_entry_cmp, 0);
+
+   /* lookup interned string in pool */
+   hashmap_entry_init(key, memhash(data, len));
+   key.len = len;
+   e = hashmap_get(map, key, data);
+   if (!e) {
+   /* not found: create it */
+   e = xmallocz(sizeof(struct pool_entry) + len);
+   hashmap_entry_init(e, key.ent.hash);
+   e-len = len;
+   memcpy(e-data, data, len);
+   hashmap_add(map, e);
+   }
+   return e-data;
+}
diff --git a/hashmap.h b/hashmap.h
index 12f0668..507884b 100644
--- a/hashmap.h
+++ b/hashmap.h
@@ -87,4 +87,12 @@ static inline void *hashmap_iter_first(struct hashmap *map,
return hashmap_iter_next(iter);
 }
 
+/* string interning */
+
+extern const void *memintern(const void *data, size_t len);
+static inline const char *strintern(const char *string)
+{
+   return memintern(string, strlen(string));
+}
+
 #endif
diff --git a/t/t0011-hashmap.sh b/t/t0011-hashmap.sh
index 391e2b6..f97c805 100755
--- a/t/t0011-hashmap.sh
+++ b/t/t0011-hashmap.sh
@@ -237,4 +237,17 @@ test_expect_success 'grow / shrink' '
 
 '
 
+test_expect_success 'string interning' '
+
+test_hashmap intern value1
+intern Value1
+intern value2
+intern value2
+ value1
+Value1
+value2
+value2
+
+'
+
 test_done
diff --git a/test-hashmap.c b/test-hashmap.c
index 3c9f67b..07aa7ec 100644
--- a/test-hashmap.c
+++ b/test-hashmap.c
@@ -234,6 +234,20 @@ int main(int argc, char *argv[])
/* print table sizes */
printf(%u %u\n, map.tablesize, map.size);
 
+   } else if (!strcmp(intern, cmd)  l1) {
+
+   /* test that strintern works */
+   const char *i1 = strintern(p1);
+   const char *i2 = strintern(p1);
+   if (strcmp(i1, p1))
+   printf(strintern(%s) returns %s\n, p1, i1);
+   else if (i1 == p1)
+   printf(strintern(%s) returns input pointer\n, 
p1);
+   else if (i1 != i2)
+   printf(strintern(%s) != strintern(%s), i1, 
i2);
+   else
+   

[PATCH v1 3/4] hashmap: add simplified hashmap_get_from_hash() API

2014-07-02 Thread Karsten Blees
Hashmap entries are typically looked up by just a key. The hashmap_get()
API expects an initialized entry structure instead, to support compound
keys. This flexibility is currently only needed by find_dir_entry() in
name-hash.c (and compat/win32/fscache.c in the msysgit fork). All other
(currently five) call sites of hashmap_get() have to set up a near emtpy
entry structure, resulting in duplicate code like this:

  struct hashmap_entry keyentry;
  hashmap_entry_init(keyentry, hash(key));
  return hashmap_get(map, keyentry, key);

Add a hashmap_get_from_hash() API that allows hashmap lookups by just
specifying the key and its hash code, i.e.:

  return hashmap_get_from_hash(map, hash(key), key);

Signed-off-by: Karsten Blees bl...@dcon.de
---
 Documentation/technical/api-hashmap.txt | 14 ++
 builtin/describe.c  |  4 +---
 diffcore-rename.c   |  7 +++
 hashmap.h   |  8 
 name-hash.c |  5 ++---
 test-hashmap.c  | 11 +++
 6 files changed, 31 insertions(+), 18 deletions(-)

diff --git a/Documentation/technical/api-hashmap.txt 
b/Documentation/technical/api-hashmap.txt
index dc21a7c..f9215d6 100644
--- a/Documentation/technical/api-hashmap.txt
+++ b/Documentation/technical/api-hashmap.txt
@@ -118,6 +118,20 @@ hashmap_entry) that has at least been initialized with the 
proper hash code
 If an entry with matching hash code is found, `key` and `keydata` are passed
 to `hashmap_cmp_fn` to decide whether the entry matches the key.
 
+`void *hashmap_get_from_hash(const struct hashmap *map, unsigned int hash, 
const void *keydata)`::
+
+   Returns the hashmap entry for the specified hash code and key data,
+   or NULL if not found.
++
+`map` is the hashmap structure.
++
+`hash` is the hash code of the entry to look up.
++
+If an entry with matching hash code is found, `keydata` is passed to
+`hashmap_cmp_fn` to decide whether the entry matches the key. The
+`entry_or_key` parameter points to a bogus hashmap_entry structure that
+should not be used in the comparison.
+
 `void *hashmap_get_next(const struct hashmap *map, const void *entry)`::
 
Returns the next equal hashmap entry, or NULL if not found. This can be
diff --git a/builtin/describe.c b/builtin/describe.c
index 57e84c8..ee6a3b9 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -58,9 +58,7 @@ static int commit_name_cmp(const struct commit_name *cn1,
 
 static inline struct commit_name *find_commit_name(const unsigned char *peeled)
 {
-   struct commit_name key;
-   hashmap_entry_init(key, sha1hash(peeled));
-   return hashmap_get(names, key, peeled);
+   return hashmap_get_from_hash(names, sha1hash(peeled), peeled);
 }
 
 static int replace_name(struct commit_name *e,
diff --git a/diffcore-rename.c b/diffcore-rename.c
index 6fa97d4..2e44a37 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -257,15 +257,14 @@ static int find_identical_files(struct hashmap *srcs,
int renames = 0;
 
struct diff_filespec *target = rename_dst[dst_index].two;
-   struct file_similarity *p, *best, dst;
+   struct file_similarity *p, *best = NULL;
int i = 100, best_score = -1;
 
/*
 * Find the best source match for specified destination.
 */
-   best = NULL;
-   hashmap_entry_init(dst, hash_filespec(target));
-   for (p = hashmap_get(srcs, dst, NULL); p; p = hashmap_get_next(srcs, 
p)) {
+   p = hashmap_get_from_hash(srcs, hash_filespec(target), NULL);
+   for (; p; p = hashmap_get_next(srcs, p)) {
int score;
struct diff_filespec *source = p-filespec;
 
diff --git a/hashmap.h b/hashmap.h
index ed5425a..12f0668 100644
--- a/hashmap.h
+++ b/hashmap.h
@@ -68,6 +68,14 @@ extern void *hashmap_put(struct hashmap *map, void *entry);
 extern void *hashmap_remove(struct hashmap *map, const void *key,
const void *keydata);
 
+static inline void *hashmap_get_from_hash(const struct hashmap *map,
+   unsigned int hash, const void *keydata)
+{
+   struct hashmap_entry key;
+   hashmap_entry_init(key, hash);
+   return hashmap_get(map, key, keydata);
+}
+
 /* hashmap_iter functions */
 
 extern void hashmap_iter_init(struct hashmap *map, struct hashmap_iter *iter);
diff --git a/name-hash.c b/name-hash.c
index 49fd508..702cd05 100644
--- a/name-hash.c
+++ b/name-hash.c
@@ -213,12 +213,11 @@ struct cache_entry *index_dir_exists(struct index_state 
*istate, const char *nam
 struct cache_entry *index_file_exists(struct index_state *istate, const char 
*name, int namelen, int icase)
 {
struct cache_entry *ce;
-   struct hashmap_entry key;
 
lazy_init_name_hash(istate);
 
-   hashmap_entry_init(key, memihash(name, namelen));
-   ce = hashmap_get(istate-name_hash, key, NULL);
+   ce = hashmap_get_from_hash(istate-name_hash,
+ 

Re: Experimental TDB support for GIT REFS

2014-07-02 Thread Ronnie Sahlberg
On Wed, Jul 2, 2014 at 10:11 AM, Ronnie Sahlberg sahlb...@google.com wrote:
 On Fri, Jun 27, 2014 at 5:37 PM, Shawn Pearce spea...@spearce.org wrote:
 On Fri, Jun 27, 2014 at 2:30 PM, Ronnie Sahlberg sahlb...@google.com wrote:
 List,

 One of my ref transaction aims is to make define a stable public API
 for accessing refs.
 Once this is done I want to make it possible to replace the current
 .git/refs/* model with a
 different type of backend.
 In my case I want to add support to store all refs and reflogs in a TDB 
 database
 but once we have a pluggable backend framework for refs, if someone
 wants to store the refs
 in a SQL database, that should be fairly trivial too.

 There are a few series queued before this becomes possible, but is
 anyone wants to test or play with my git can use TDB database you
 can find an implementation of this at

 https://github.com/rsahlberg/git/tree/backend-struct-tdb

 Interesting! But the link 404s :(


 Yeah, sorry but there were issues :-(   Issues solved now though and
 refactoring done.

 Please see
 https://github.com/rsahlberg/git/tree/backend-struct-db

 This branch adds a refs backend that communicates via a domain socket
 to a refs daemon.
 The refs daemon in turn interfaces with the actual database.

 My branch contains one hack refs daemon that uses a TDB database for
 the refs storage.
 This daemon is only about 600 lines of code, most of which is
 marshalling and socket handling and only a small amount of
 TDB specific code.
 This small daemon should make it easy for folks to add arbitrary
 database interfaces easily.
 Taking refsd-tdb.c  and modifying it to instead attach to a SQL
 database should only take a few hundred lines of changes or so.


 To build the daemon and start it :

 $ gcc refsd-tdb.c -o refsd-tdb -ltdb
 create /var/lib/git and /var/log/git
 $ ./refsd-tdb /var/lib/git/refs.socket /var/lib/git /var/log/git/refsd.log

 Then you can inspect the database with
 tdbdump /var/lib/git/refs.tdb


 You can then create a repository that uses this database :
 $ git init --db-repo-name=ROCC --db-socket=/var/lib/git/refs.socket .

 Then further commands will operate on the refs tdb.

 See this as a prototype to experiment with and see the direction of
 the refs transaction and pluggable backend support.
 There is a lot additional work and cleanup that needs to be done
 before this will become production code.

 (yes I know we should not do hand marshalling and unmarshalling for
 the PDUs on the domain socket. We should use some lightweight encoding
 library like XDR and rpcgen or similar.)


 Please test, comment and have fun.

One enhancement to this could be to make it easier to use for trivial
users that do not want to share one database across multiple repos.

We could have something like
$ git init --db=tdb .

core.db=tdb could then mean that instead of connecting to a domain
socket for a shared daemon instead it would just
popen(refsd-core.db ..., rw)
and automaticallt set the asguments ro refsd-tdb to point to the local
.git directory.

This would make the setup simpler for the trivial usecase since it
would avoid having to manuallt initializing a dedicated daemon before
the git commands will start working.
--
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: Race condition in git push --mirror can cause silent ref rewinding

2014-07-02 Thread Alex Vandiver
On 07/02/2014 06:20 PM, Junio C Hamano wrote:
 Alex Vandiver a...@chmrr.net writes:
 
 [remote github]
 url = g...@github.com:bestpractical/rt.git
 fetch = +refs/*:refs/*
 mirror = yes
 
 git push github master^:master must stay a usable way to update
 the published repository to an arbitrary commit, so if set to
 mirror, do not pretend that a fetch in reverse has happened during
 'git push' will not be a solution to this issue.

Hm?  I'm confused, as mirror isn't compatible with refspecs:

$ git push github master^:master
error: --mirror can't be combined with refspecs

 Perhaps removing remote.github.fetch would be one sane way forward.

Ahh -- I see.  The repository predates a9f5a355, which split `git remote
add --mirror` into `--mirror=push` and `--mirror=fetch`, because of more
or less this exact problem.  Of course, there is nothing much that can
be done for existing repositories in this situation as it's a legitimate
combination.
 - Alex
--
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


Support for EBCDIC

2014-07-02 Thread Scott McKellar
Is Git supposed to be usable in an environment where the execution character 
set is EBCDIC?

I ask because, in browsing the source code (version 2.0.0), I stumbled across 
three functions 

that won't work as presumably intended in an EBCDIC environment (strihash(), 
memihash(), and 

git_user_agent_sanitized()).  I can report them as bugs, but if EBCDIC is 
considered out of 

scope, then they aren't bugs.

These three functions can be readily fixed to make them portable across 
character sets.  There may be other spots that are harder to fix.

I have done a lot of grepping and Googling, but I haven't found a clear, 
authoritative answer 

to this question.  From searching this mailing list, it appears that nobody is 
interested in 

supporting EBCDIC.  However I found one wiki page describing how to run Git on 
an IBM i, which 

is an EBCDIC-based successor to the AS/400 series.  See:

    http://wsip-174-79-32-155.ph.ph.cox.net/wiki/index.php/PASE/Git

That installation was reportedly running version 1.7.9.4, which I believe 
predates the 

introduction of strihash() and memihash(); I don't know about 
git_user_agent_sanitized().

Mind you, I'm not advocating for EBCDIC.  I escaped from the EBCDIC world about 
fifteen years 

ago, and have no desire to return.  I just want to know if character set issues 
are worth 

reporting.  The same issues may arise for other, more obscure character sets.


Scott McKellar

--
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 v2 2/2] git-merge-file: do not add LF at EOF while applying unrelated change

2014-07-02 Thread Max Kirillov
On Wed, Jul 02, 2014 at 04:08:28PM +0200, Johannes Schindelin wrote:
 What could be improved with them?
 
 Oh, I would name the files more appropriately, for example. That is,
 instead of test1.txt I would call it mixed-endings.txt or lf-only.txt or
 some such.
 
 And instead of the Latin version of Psalm 23, I would put lines into the
 files that describe their own role in the test, i.e.
 
   unchanged
   ends with a carriage return
   ends with a line feed
   unchanged
 
 or similar.
 
 Please keep in mind that this critique is most likely on my *own* work,
 for all I know *I* introduced those files.

I asked to have something in mind if I return to this.
 
Thanks for the notes.

-- 
Max
--
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 00/14] Add submodule test harness

2014-07-02 Thread Torsten Bögershausen

On 07/02/2014 09:57 PM, Jens Lehmann wrote:

Am 02.07.2014 16:54, schrieb Torsten Bögershausen:

(Not sure if this is the right thread)
(I haven't checked if this is fixed in your latest version)

Yes, this is the right thread and no, it isn't fixed yet.


On what I have on pu 7a0da7902cbbc9a876b90c9, Tue Jul 1 14:51:53 2014 -0700

Many submodule tests are broken.
One problem is here:

lib-submodule-update.sh:264: possible problem: echo -n is not portable (please use 
printf): echo -n sub1 
lib-submodule-update.sh:507: possible problem: echo -n is not portable (please use 
printf): echo -n sub1 

You can remove the empty echo -n to create an empty file:

sub1 

Thanks for spotting and diagnosing this. Running make lint in the
test directory only feeds the tests to check-non-portable-shell.pl,
but not the *lib*.sh helper scripts, which made me miss this one.

The following diff should fix it for you. Am I understanding you
correctly that you are experiencing other failures too? I see no
other incompatibilities when running ./check-non-portable-shell.pl
on all the shell scripts in the repo.

The longer story is that I run the test suite once a week or so.
Most often under Mac OS, sometimes cygwin or Linux.
Whenever there is a breakage under Mac OS which I can not
debug within some minutes, I run it under Linux to see if there
is the same breakage.

The ./check-non-portable-shell.pl can sometimes give an indication
why some test fail.
You can run it from command line:
 ./check-non-portable-shell.pl *.sh
and it will find the echo -n which I reported.
On the longer run it could probably check all *.sh files,
not only the ones under t/
I do not have the time to test the snipped patch below, but I can check pu
when the next round of your patch is in and give you some more info.


--
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