Re: [PATCH] imap-send: clarify CRAM-MD5 vs LOGIN documentation

2014-07-31 Thread Tony Finch
Junio C Hamano gits...@pobox.com wrote:

 Both patches make sense to me, but can you please sign-off your
 patches?

Oops, sorry about that. Re-roll on its way...

Tony.
-- 
f.anthony.n.finch  d...@dotat.at  http://dotat.at/
Thames, Dover: Southwest 4 or 5, increasing 6 at times. Slight or moderate.
Fair. Good.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/2] imap-send: create target mailbox if it is missing

2014-07-31 Thread Tony Finch
Some MUAs delete their drafts folder when it is empty, so
git imap-send should be able to create it if necessary.

This change checks that the folder exists immediately after
login and tries to create it if it is missing.

There was some vestigial code to handle a [TRYCREATE] response
from the server when an APPEND target is missing. However this
code never ran (the create and trycreate flags were never set)
and when I tried to make it run I found that the code had already
thrown away the contents of the message it was trying to append.

Signed-off-by: Tony Finch d...@dotat.at
---
 imap-send.c | 56 +---
 1 file changed, 25 insertions(+), 31 deletions(-)

diff --git a/imap-send.c b/imap-send.c
index 524fbab..5e4a24e 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -128,7 +128,6 @@ struct imap_cmd_cb {
char *data;
int dlen;
int uid;
-   unsigned create:1, trycreate:1;
 };

 struct imap_cmd {
@@ -714,8 +713,8 @@ static int parse_response_code(struct imap_store *ctx, 
struct imap_cmd_cb *cb,
 static int get_cmd_result(struct imap_store *ctx, struct imap_cmd *tcmd)
 {
struct imap *imap = ctx-imap;
-   struct imap_cmd *cmdp, **pcmdp, *ncmdp;
-   char *cmd, *arg, *arg1, *p;
+   struct imap_cmd *cmdp, **pcmdp;
+   char *cmd, *arg, *arg1;
int n, resp, resp2, tag;

for (;;) {
@@ -801,30 +800,9 @@ static int get_cmd_result(struct imap_store *ctx, struct 
imap_cmd *tcmd)
if (!strcmp(OK, arg))
resp = DRV_OK;
else {
-   if (!strcmp(NO, arg)) {
-   if (cmdp-cb.create  cmd  
(cmdp-cb.trycreate || !memcmp(cmd, [TRYCREATE], 11))) { /* SELECT, APPEND or 
UID COPY */
-   p = strchr(cmdp-cmd, '');
-   if (!issue_imap_cmd(ctx, NULL, 
CREATE \%.*s\, (int)(strchr(p + 1, '') - p + 1), p)) {
-   resp = RESP_BAD;
-   goto normal;
-   }
-   /* not waiting here violates 
the spec, but a server that does not
-  grok this nonetheless 
violates it too. */
-   cmdp-cb.create = 0;
-   if (!(ncmdp = 
issue_imap_cmd(ctx, cmdp-cb, %s, cmdp-cmd))) {
-   resp = RESP_BAD;
-   goto normal;
-   }
-   free(cmdp-cmd);
-   free(cmdp);
-   if (!tcmd)
-   return 0;   /* 
ignored */
-   if (cmdp == tcmd)
-   tcmd = ncmdp;
-   continue;
-   }
+   if (!strcmp(NO, arg))
resp = RESP_NO;
-   } else /*if (!strcmp(BAD, arg))*/
+   else /*if (!strcmp(BAD, arg))*/
resp = RESP_BAD;
fprintf(stderr, IMAP command '%s' returned 
response (%s) - %s\n,
 memcmp(cmdp-cmd, LOGIN, 5) ?
@@ -833,7 +811,6 @@ static int get_cmd_result(struct imap_store *ctx, struct 
imap_cmd *tcmd)
}
if ((resp2 = parse_response_code(ctx, cmdp-cb, cmd)) 
 resp)
resp = resp2;
-   normal:
if (cmdp-cb.done)
cmdp-cb.done(ctx, cmdp, resp);
free(cmdp-cb.data);
@@ -944,7 +921,7 @@ static int auth_cram_md5(struct imap_store *ctx, struct 
imap_cmd *cmd, const cha
return 0;
 }

-static struct imap_store *imap_open_store(struct imap_server_conf *srvc)
+static struct imap_store *imap_open_store(struct imap_server_conf *srvc, char 
*folder)
 {
struct credential cred = CREDENTIAL_INIT;
struct imap_store *ctx;
@@ -1156,6 +1133,25 @@ static struct imap_store *imap_open_store(struct 
imap_server_conf *srvc)
credential_approve(cred);
credential_clear(cred);

+   /* check the target mailbox exists */
+   ctx-name = folder;
+   switch (imap_exec(ctx, NULL, EXAMINE \%s\, ctx-name)) {
+   case RESP_OK:
+   /* ok */
+   break;
+   case RESP_BAD:
+  

[PATCH 1/2] imap-send: clarify CRAM-MD5 vs LOGIN documentation

2014-07-31 Thread Tony Finch
Explicitly mention that leaving imap.authMethod unset makes
git imap-send use the basic IMAP plaintext LOGIN command.

Signed-off-by: Tony Finch d...@dotat.at
---
 Documentation/git-imap-send.txt | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Documentation/git-imap-send.txt b/Documentation/git-imap-send.txt
index 875d283..770cbe8 100644
--- a/Documentation/git-imap-send.txt
+++ b/Documentation/git-imap-send.txt
@@ -76,7 +76,8 @@ imap.preformattedHTML::

 imap.authMethod::
Specify authenticate method for authentication with IMAP server.
-   Current supported method is 'CRAM-MD5' only.
+   Current supported method is 'CRAM-MD5' only. If this is not set
+   then 'git imap-send' uses the basic IMAP plaintext LOGIN command.

 Examples
 
-- 
2.1.0.rc0.229.gaee38de


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


[PATCH v5 3/7] change `git_config()` return value to void

2014-07-31 Thread Tanay Abhra
Currently `git_config()` returns an integer signifying an error code.
During a previous rewrite of the function most of the code was shifted
to `git_config_with_options()`. `git_config_with_options()` normally
returns positive values if its `config_source` parameter is set as NULL,
as most errors are fatal, and non-fatal potential errors are guarded
by if statements that are entered only when no error is possible.

Still a negative value can be returned in case of race condition between
`access_or_die()`  `git_config_from_file()`. Also, all callers of
`git_config()` ignore the return value except for one case in branch.c.

Change `git_config()` return value to void and make it die if it receives
a negative return value from `git_config_with_options()`.

Signed-off-by: Tanay Abhra tanay...@gmail.com
---
 branch.c |  5 +
 cache.h  |  2 +-
 config.c | 16 ++--
 3 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/branch.c b/branch.c
index 46e8aa8..735767d 100644
--- a/branch.c
+++ b/branch.c
@@ -161,10 +161,7 @@ int read_branch_desc(struct strbuf *buf, const char 
*branch_name)
strbuf_addf(name, branch.%s.description, branch_name);
cb.config_name = name.buf;
cb.value = NULL;
-   if (git_config(read_branch_desc_cb, cb)  0) {
-   strbuf_release(name);
-   return -1;
-   }
+   git_config(read_branch_desc_cb, cb);
if (cb.value)
strbuf_addstr(buf, cb.value);
strbuf_release(name);
diff --git a/cache.h b/cache.h
index 7292aef..c61919d 100644
--- a/cache.h
+++ b/cache.h
@@ -1294,7 +1294,7 @@ extern int git_config_from_buf(config_fn_t fn, const char 
*name,
   const char *buf, size_t len, void *data);
 extern void git_config_push_parameter(const char *text);
 extern int git_config_from_parameters(config_fn_t fn, void *data);
-extern int git_config(config_fn_t fn, void *);
+extern void git_config(config_fn_t fn, void *);
 extern int git_config_with_options(config_fn_t fn, void *,
   struct git_config_source *config_source,
   int respect_includes);
diff --git a/config.c b/config.c
index 4a15383..c0faaca 100644
--- a/config.c
+++ b/config.c
@@ -1235,9 +1235,21 @@ struct key_value_info {
int linenr;
 };
 
-int git_config(config_fn_t fn, void *data)
+void git_config(config_fn_t fn, void *data)
 {
-   return git_config_with_options(fn, data, NULL, 1);
+   if (git_config_with_options(fn, data, NULL, 1)  0)
+   /*
+* git_config_with_options() normally returns only
+* positive values, as most errors are fatal, and
+* non-fatal potential errors are guarded by if
+* statements that are entered only when no error is
+* possible.
+*
+* If we ever encounter a non-fatal error, it means
+* something went really wrong and we should stop
+* immediately.
+*/
+   die(Unknown error occured while reading the configuration 
files);
 }
 
 static struct config_set_element *configset_find_element(struct config_set 
*cs, const char *key)
-- 
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 v5 1/7] config.c: fix accuracy of line number in errors

2014-07-31 Thread Tanay Abhra
From: Matthieu Moy matthieu@grenoble-inp.fr

If a callback returns a negative value to `git_config*()` family,
they call `die()` while printing the line number and the file name.
Currently the printed line number is off by one, thus printing the
wrong line number.

Make `linenr` point to the line we just parsed during the call
to callback to get accurate line number in error messages.

Commit-message-by: Tanay Abhra tanay...@gmail.com
Signed-off-by: Tanay Abhra tanay...@gmail.com
---
 config.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/config.c b/config.c
index a191328..ed5fc8e 100644
--- a/config.c
+++ b/config.c
@@ -244,6 +244,7 @@ static int get_next_char(void)
cf-linenr++;
if (c == EOF) {
cf-eof = 1;
+   cf-linenr++;
c = '\n';
}
return c;
@@ -319,6 +320,7 @@ static int get_value(config_fn_t fn, void *data, struct 
strbuf *name)
 {
int c;
char *value;
+   int ret;
 
/* Get the full name */
for (;;) {
@@ -341,7 +343,15 @@ static int get_value(config_fn_t fn, void *data, struct 
strbuf *name)
if (!value)
return -1;
}
-   return fn(name-buf, value, data);
+   /*
+* We already consumed the \n, but we need linenr to point to
+* the line we just parsed during the call to fn to get
+* accurate line number in error messages.
+*/
+   cf-linenr--;
+   ret = fn(name-buf, value, data);
+   cf-linenr++;
+   return ret;
 }
 
 static int get_extended_base_var(struct strbuf *name, int 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 7/7] add tests for `git_config_get_string_const()`

2014-07-31 Thread Tanay Abhra
Add tests for `git_config_get_string_const()`, check whether it
dies printing the line number and the file name if a NULL
value is retrieved for the given key.

Signed-off-by: Tanay Abhra tanay...@gmail.com
---
 t/t1308-config-set.sh | 10 ++
 test-config.c | 10 ++
 2 files changed, 20 insertions(+)

diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index e2f9d0b..f012dd6 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -119,6 +119,16 @@ test_expect_success 'find integer value for a key' '
check_config get_int lamb.chop 65
 '
 
+test_expect_success 'find string value for a key' '
+   check_config get_string case.baz hask 
+   check_config expect_code 1 get_string case.ba Value not found for 
\case.ba\
+'
+
+test_expect_success 'check line error when NULL string is queried' '
+   test_expect_code 128 test-config get_string case.foo 2result 
+   grep fatal: bad config variable '\''case.foo'\'' at file line 7 in 
.git/config result
+'
+
 test_expect_success 'find integer if value is non parse-able' '
check_config expect_code 128 get_int lamb.head
 '
diff --git a/test-config.c b/test-config.c
index 9dd1b22..6a77552 100644
--- a/test-config.c
+++ b/test-config.c
@@ -16,6 +16,8 @@
  *
  * get_bool - print bool value for the entered key or die
  *
+ * get_string - print string value for the entered key or die
+ *
  * configset_get_value - returns value with the highest priority for the 
entered key
  * from a config_set constructed from files entered as 
arguments.
  *
@@ -84,6 +86,14 @@ int main(int argc, char **argv)
printf(Value not found for \%s\\n, argv[2]);
goto exit1;
}
+   } else if (argc == 3  !strcmp(argv[1], get_string)) {
+   if (!git_config_get_string_const(argv[2], v)) {
+   printf(%s\n, v);
+   goto exit0;
+   } else {
+   printf(Value not found for \%s\\n, argv[2]);
+   goto exit1;
+   }
} else if (!strcmp(argv[1], configset_get_value)) {
for (i = 3; i  argc; i++) {
int err;
-- 
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 v5 5/7] add a test for semantic errors in config files

2014-07-31 Thread Tanay Abhra
Semantic errors (for example, for alias.* variables NULL values are
not allowed) in configuration files cause a die printing the line
number and file name of the offending value.

Add a test documenting that such errors cause a die printing the
accurate line number and file name.

Signed-off-by: Tanay Abhra tanay...@gmail.com
---
 t/t1308-config-set.sh | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index 7fdf840..e2f9d0b 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -197,4 +197,15 @@ test_expect_success 'proper error on error in custom 
config files' '
test_cmp expect actual
 '
 
+test_expect_success 'check line errors for malformed values' '
+   mv .git/config .git/config.old 
+   test_when_finished mv .git/config.old .git/config 
+   cat .git/config -\EOF 
+   [alias]
+   br
+   EOF
+   test_expect_code 128 git br 2result 
+   grep fatal: bad config variable '\''alias.br'\'' at file line 2 in 
.git/config result
+'
+
 test_done
-- 
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 v5 2/7] add line number and file name info to `config_set`

2014-07-31 Thread Tanay Abhra
Store file name and line number for each key-value pair in the cache
during parsing of the configuration files.

Signed-off-by: Tanay Abhra tanay...@gmail.com
---
 config.c | 21 +++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/config.c b/config.c
index ed5fc8e..4a15383 100644
--- a/config.c
+++ b/config.c
@@ -1230,6 +1230,11 @@ int git_config_with_options(config_fn_t fn, void *data,
return ret;
 }
 
+struct key_value_info {
+   const char *filename;
+   int linenr;
+};
+
 int git_config(config_fn_t fn, void *data)
 {
return git_config_with_options(fn, data, NULL, 1);
@@ -1260,6 +1265,9 @@ static struct config_set_element 
*configset_find_element(struct config_set *cs,
 static int configset_add_value(struct config_set *cs, const char *key, const 
char *value)
 {
struct config_set_element *e;
+   struct string_list_item *si;
+   struct key_value_info *kv_info = xmalloc(sizeof(*kv_info));
+
e = configset_find_element(cs, key);
/*
 * Since the keys are being fed by git_config*() callback mechanism, 
they
@@ -1272,7 +1280,16 @@ static int configset_add_value(struct config_set *cs, 
const char *key, const cha
string_list_init(e-value_list, 1);
hashmap_add(cs-config_hash, e);
}
-   string_list_append_nodup(e-value_list, value ? xstrdup(value) : NULL);
+   si = string_list_append_nodup(e-value_list, value ? xstrdup(value) : 
NULL);
+   if (cf) {
+   kv_info-filename = strintern(cf-name);
+   kv_info-linenr = cf-linenr;
+   } else {
+   /* for values read from `git_config_from_parameters()` */
+   kv_info-filename = strintern(parameter);
+   kv_info-linenr = 0;
+   }
+   si-util = kv_info;
 
return 0;
 }
@@ -1299,7 +1316,7 @@ void git_configset_clear(struct config_set *cs)
hashmap_iter_init(cs-config_hash, iter);
while ((entry = hashmap_iter_next(iter))) {
free(entry-key);
-   string_list_clear(entry-value_list, 0);
+   string_list_clear(entry-value_list, 1);
}
hashmap_free(cs-config_hash, 1);
cs-hash_initialized = 0;
-- 
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 6/7] config: add `git_die_config()` to the config-set API

2014-07-31 Thread Tanay Abhra
Add `git_die_config` that dies printing the line number and the file name
of the highest priority value for the configuration variable `key`.

It has usage in non-callback based config value retrieval where we can
raise an error and die if there is a semantic error.
For example,

if (!git_config_get_value(key, value)) {
/* NULL values not allowed */
if (!value)
git_config_die(key);
else
/* do work */
}

Signed-off-by: Tanay Abhra tanay...@gmail.com
---
 Documentation/technical/api-config.txt |  5 +
 cache.h|  1 +
 config.c   | 27 +--
 3 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/Documentation/technical/api-config.txt 
b/Documentation/technical/api-config.txt
index 815c1ee..e7ec7cc 100644
--- a/Documentation/technical/api-config.txt
+++ b/Documentation/technical/api-config.txt
@@ -155,6 +155,11 @@ as well as retrieval for the queried variable, including:
Similar to `git_config_get_string`, but expands `~` or `~user` into
the user's home directory when found at the beginning of the path.
 
+`void git_die_config(const char *key)`::
+
+   Dies printing the line number and the file name of the highest
+   priority value for the configuration variable `key`.
+
 See test-config.c for usage examples.
 
 Value Parsing Helpers
diff --git a/cache.h b/cache.h
index 4d3c6bd..243f618 100644
--- a/cache.h
+++ b/cache.h
@@ -1406,6 +1406,7 @@ extern int git_config_get_bool(const char *key, int 
*dest);
 extern int git_config_get_bool_or_int(const char *key, int *is_bool, int 
*dest);
 extern int git_config_get_maybe_bool(const char *key, int *dest);
 extern int git_config_get_pathname(const char *key, const char **dest);
+extern void git_die_config(const char *key);
 
 extern int committer_ident_sufficiently_given(void);
 extern int author_ident_sufficiently_given(void);
diff --git a/config.c b/config.c
index 4937515..03369b8 100644
--- a/config.c
+++ b/config.c
@@ -1515,8 +1515,12 @@ const struct string_list 
*git_config_get_value_multi(const char *key)
 
 int git_config_get_string_const(const char *key, const char **dest)
 {
+   int ret;
git_config_check_init();
-   return git_configset_get_string_const(the_config_set, key, dest);
+   ret = git_configset_get_string_const(the_config_set, key, dest);
+   if (ret  0)
+   git_die_config(key);
+   return ret;
 }
 
 int git_config_get_string(const char *key, char **dest)
@@ -1557,10 +1561,29 @@ int git_config_get_maybe_bool(const char *key, int 
*dest)
 
 int git_config_get_pathname(const char *key, const char **dest)
 {
+   int ret;
git_config_check_init();
-   return git_configset_get_pathname(the_config_set, key, dest);
+   ret = git_configset_get_pathname(the_config_set, key, dest);
+   if (ret  0)
+   git_die_config(key);
+   return ret;
 }
 
+void git_die_config(const char *key)
+{
+   const struct string_list *values;
+   struct key_value_info *kv_info;
+   values = git_config_get_value_multi(key);
+   kv_info = values-items[values-nr - 1].util;
+   if (!kv_info-linenr)
+   die(unable to parse '%s' from command-line config, key);
+   else
+   die(bad config variable '%s' at file line %d in %s,
+   key,
+   kv_info-linenr,
+   kv_info-filename);
+ }
+
 /*
  * Find all the stuff for git_config_set() below.
  */
-- 
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 v5 4/7] rewrite git_config() to use the config-set API

2014-07-31 Thread Tanay Abhra
Of all the functions in `git_config*()` family, `git_config()` has the
most invocations in the whole code base. Each `git_config()` invocation
causes config file rereads which can be avoided using the config-set API.

Use the config-set API to rewrite `git_config()` to use the config caching
layer to avoid config file rereads on each invocation during a git process
lifetime. First invocation constructs the cache, and after that for each
successive invocation, `git_config()` feeds values from the config cache
instead of rereading the configuration files.

Signed-off-by: Tanay Abhra tanay...@gmail.com
---
 cache.h | 24 +
 config.c| 57 ++---
 t/t4055-diff-context.sh |  2 +-
 3 files changed, 74 insertions(+), 9 deletions(-)

diff --git a/cache.h b/cache.h
index c61919d..4d3c6bd 100644
--- a/cache.h
+++ b/cache.h
@@ -8,6 +8,7 @@
 #include gettext.h
 #include convert.h
 #include trace.h
+#include string-list.h
 
 #include SHA1_HEADER
 #ifndef git_SHA_CTX
@@ -1351,9 +1352,32 @@ extern int parse_config_key(const char *var,
const char **subsection, int *subsection_len,
const char **key);
 
+struct config_set_element {
+   struct hashmap_entry ent;
+   char *key;
+   struct string_list value_list;
+};
+
+struct configset_list_item {
+   struct config_set_element *e;
+   int value_index;
+};
+
+/*
+ * the contents of the list are ordered according to their
+ * position in the config files and order of parsing the files.
+ * (i.e. key-value pair at the last position of .git/config will
+ * be at the last item of the list)
+ */
+struct configset_list {
+   struct configset_list_item *items;
+   unsigned int nr, alloc;
+};
+
 struct config_set {
struct hashmap config_hash;
int hash_initialized;
+   struct configset_list list;
 };
 
 extern void git_configset_init(struct config_set *cs);
diff --git a/config.c b/config.c
index c0faaca..4937515 100644
--- a/config.c
+++ b/config.c
@@ -35,12 +35,6 @@ struct config_source {
long (*do_ftell)(struct config_source *c);
 };
 
-struct config_set_element {
-   struct hashmap_entry ent;
-   char *key;
-   struct string_list value_list;
-};
-
 static struct config_source *cf;
 
 static int zlib_compression_seen;
@@ -1235,7 +1229,7 @@ struct key_value_info {
int linenr;
 };
 
-void git_config(config_fn_t fn, void *data)
+static void git_config_raw(config_fn_t fn, void *data)
 {
if (git_config_with_options(fn, data, NULL, 1)  0)
/*
@@ -1252,6 +1246,39 @@ void git_config(config_fn_t fn, void *data)
die(Unknown error occured while reading the configuration 
files);
 }
 
+static void configset_iter(struct config_set *cs, config_fn_t fn, void *data)
+{
+   int i, value_index;
+   struct string_list *values;
+   struct config_set_element *entry;
+   struct configset_list *list = cs-list;
+   struct key_value_info *kv_info;
+
+   for (i = 0; i  list-nr; i++) {
+   entry = list-items[i].e;
+   value_index = list-items[i].value_index;
+   values = entry-value_list;
+   if (fn(entry-key, values-items[value_index].string, data)  
0) {
+   kv_info = values-items[value_index].util;
+   if (!kv_info-linenr)
+   die(unable to parse '%s' from command-line 
config, entry-key);
+   else
+   die(bad config variable '%s' at file line %d 
in %s,
+   entry-key,
+   kv_info-linenr,
+   kv_info-filename);
+   }
+   }
+}
+
+static void git_config_check_init(void);
+
+void git_config(config_fn_t fn, void *data)
+{
+   git_config_check_init();
+   configset_iter(the_config_set, fn, data);
+}
+
 static struct config_set_element *configset_find_element(struct config_set 
*cs, const char *key)
 {
struct config_set_element k;
@@ -1278,6 +1305,7 @@ static int configset_add_value(struct config_set *cs, 
const char *key, const cha
 {
struct config_set_element *e;
struct string_list_item *si;
+   struct configset_list_item *l_item;
struct key_value_info *kv_info = xmalloc(sizeof(*kv_info));
 
e = configset_find_element(cs, key);
@@ -1293,6 +1321,12 @@ static int configset_add_value(struct config_set *cs, 
const char *key, const cha
hashmap_add(cs-config_hash, e);
}
si = string_list_append_nodup(e-value_list, value ? xstrdup(value) : 
NULL);
+
+   ALLOC_GROW(cs-list.items, cs-list.nr + 1, cs-list.alloc);
+   l_item = cs-list.items[cs-list.nr++];
+   l_item-e = e;
+   l_item-value_index = e-value_list.nr - 1;
+
if (cf) {

[PATCH v5 0/7] Rewrite `git_config()` using config-set API

2014-07-31 Thread Tanay Abhra
[PATCH v5]: New patch added (3/7). git_config() now returns void.

[PATCH v4]: One style nit corrected, also added key to error messages.
Diff with v3 at the bottom for easy review.

[PATCH V3]:All the suggestions in [3] applied. Built on top of [1].

[PATCH V2]: All the suggestions in [2] incorporated. git_config() now follows
correct parsing order. Reordered the patches. Removed xfuncname patch
as it was unnecssary.

This series builds on the top of topic[1] in the mailing list with name
git config cache  special querying API utilizing the cache.

This series aims to do these three things,

* Use the config-set API to rewrite git_config().

* Solve any legacy bugs in the previous system while at it.

* To be feature complete compared to the previous git_config() implementation,
  which I think it is now. (added the line number and file name info just for
  completeness)

Also, I haven't yet checked the exact improvements but still as a teaser,
git status now only rereads the configuration files twice instead of four
times.

[1]: http://thread.gmane.org/gmane.comp.version-control.git/254286
[2]: http://thread.gmane.org/gmane.comp.version-control.git/254101
[3]: http://thread.gmane.org/gmane.comp.version-control.git/254211

Tanay Abhra (7):
  config.c: fix accuracy of line number in errors
  add line number and file name info to `config_set`
  change `git_config()` return value to void
  rewrite git_config() to use the config-set API
  add a test for semantic errors in config files
  config: add `git_die_config()` to the config-set API
  add tests for `git_config_get_string_const()`

 Documentation/technical/api-config.txt |   5 ++
 branch.c   |   5 +-
 cache.h|  27 ++-
 config.c   | 131 +
 t/t1308-config-set.sh  |  21 ++
 t/t4055-diff-context.sh|   2 +-
 test-config.c  |  10 +++
 7 files changed, 181 insertions(+), 20 deletions(-)

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


Re: [PATCH v2 2/2] Make locked paths absolute when current directory is changed

2014-07-31 Thread Duy Nguyen
On Thu, Jul 31, 2014 at 10:01 AM, Yue Lin Ho yuelinho...@gmail.com wrote:
 Hi:
 How do I trace these patches applied?

They are not applied yet. I'll needto redo them on top of rs/strbuf-getcwd.
-- 
Duy
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 0/5] nd/multiple-work-trees follow-ups

2014-07-31 Thread Duy Nguyen
On Thu, Jul 31, 2014 at 12:51 AM, Junio C Hamano gits...@pobox.com wrote:
 Nguyễn Thái Ngọc Duy pclo...@gmail.com writes:

 The series has entered 'next' so I can't replace patches any more.
 Besides the brown paper bag fixes, checkout now rejects if a branch is
 already checked out elsewhere.

 I do not think we would want to rush the entire series to 'master'
 before the upcoming release, so we could squash these fixes into the
 original when we rewind 'next' post release, if you wanted to.

Great. Please remove it from next at the next rewind.

 The fix-ups are easier to review than wholesale replacements; keep
 them coming as needed.

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


Re: [PATCH v5 3/7] change `git_config()` return value to void

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

 Signed-off-by: Tanay Abhra tanay...@gmail.com

I think I deserve a bit of credit here ;-).

  {
 - return git_config_with_options(fn, data, NULL, 1);
 + if (git_config_with_options(fn, data, NULL, 1)  0)
 + /*
 +  * git_config_with_options() normally returns only
 +  * positive values, as most errors are fatal, and
 +  * non-fatal potential errors are guarded by if
 +  * statements that are entered only when no error is
 +  * possible.
 +  *
 +  * If we ever encounter a non-fatal error, it means
 +  * something went really wrong and we should stop
 +  * immediately.
 +  */
 + die(Unknown error occured while reading the configuration 
 files);
  }

My bad, but this should be die(_(...));, so that the message can be
translated. Not really serious since it's not really meant to be seen by
the user, though.

-- 
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 v5 4/7] rewrite git_config() to use the config-set API

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

 + if (!kv_info-linenr)
 + die(unable to parse '%s' from command-line 
 config, entry-key);
 + else
 + die(bad config variable '%s' at file line %d 
 in %s,

Also two missing _(...) here.

Note that there are missing _(...) in config.c before your patch too.
I'll send a patch to fix this regardless of your series.

-- 
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 6/7] config: add `git_die_config()` to the config-set API

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

 + if (!kv_info-linenr)
 + die(unable to parse '%s' from command-line config, key);
 + else
 + die(bad config variable '%s' at file line %d in %s,

And two more missing _(...).

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


[PATCH] config.c: mark error and warnings strings for translation

2014-07-31 Thread Matthieu Moy
Signed-off-by: Matthieu Moy matthieu@imag.fr
---
Noticed while reviewing Tanay's patches, but this one is independant
from his series, both syntactically and semantically.

 config.c | 20 ++--
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/config.c b/config.c
index a191328..76eeb63 100644
--- a/config.c
+++ b/config.c
@@ -457,9 +457,9 @@ static int git_parse_source(config_fn_t fn, void *data)
break;
}
if (cf-die_on_error)
-   die(bad config file line %d in %s, cf-linenr, cf-name);
+   die(_(bad config file line %d in %s), cf-linenr, cf-name);
else
-   return error(bad config file line %d in %s, cf-linenr, 
cf-name);
+   return error(_(bad config file line %d in %s), cf-linenr, 
cf-name);
 }
 
 static int parse_unit_factor(const char *end, uintmax_t *val)
@@ -575,9 +575,9 @@ static void die_bad_number(const char *name, const char 
*value)
value = ;
 
if (cf  cf-name)
-   die(bad numeric config value '%s' for '%s' in %s: %s,
+   die(_(bad numeric config value '%s' for '%s' in %s: %s),
value, name, cf-name, reason);
-   die(bad numeric config value '%s' for '%s': %s, value, name, reason);
+   die(_(bad numeric config value '%s' for '%s': %s), value, name, 
reason);
 }
 
 int git_config_int(const char *name, const char *value)
@@ -662,7 +662,7 @@ int git_config_pathname(const char **dest, const char *var, 
const char *value)
return config_error_nonbool(var);
*dest = expand_user_path(value);
if (!*dest)
-   die(Failed to expand user dir in: '%s', value);
+   die(_(Failed to expand user dir in: '%s'), value);
return 0;
 }
 
@@ -740,7 +740,7 @@ static int git_default_core_config(const char *var, const 
char *value)
if (level == -1)
level = Z_DEFAULT_COMPRESSION;
else if (level  0 || level  Z_BEST_COMPRESSION)
-   die(bad zlib compression level %d, level);
+   die(_(bad zlib compression level %d), level);
zlib_compression_level = level;
zlib_compression_seen = 1;
return 0;
@@ -751,7 +751,7 @@ static int git_default_core_config(const char *var, const 
char *value)
if (level == -1)
level = Z_DEFAULT_COMPRESSION;
else if (level  0 || level  Z_BEST_COMPRESSION)
-   die(bad zlib compression level %d, level);
+   die(_(bad zlib compression level %d), level);
core_compression_level = level;
core_compression_seen = 1;
if (!zlib_compression_seen)
@@ -873,7 +873,7 @@ static int git_default_core_config(const char *var, const 
char *value)
else if (!strcmp(value, link))
object_creation_mode = OBJECT_CREATION_USES_HARDLINKS;
else
-   die(Invalid mode for object creation: %s, value);
+   die(_(Invalid mode for object creation: %s), value);
return 0;
}
 
@@ -1173,7 +1173,7 @@ int git_config_early(config_fn_t fn, void *data, const 
char *repo_config)
 
switch (git_config_from_parameters(fn, data)) {
case -1: /* error */
-   die(unable to parse command-line config);
+   die(_(unable to parse command-line config));
break;
case 0: /* found nothing */
break;
@@ -1514,7 +1514,7 @@ static int store_aux(const char *key, const char *value, 
void *cb)
case KEY_SEEN:
if (matches(key, value)) {
if (store.seen == 1  store.multi_replace == 0) {
-   warning(%s has multiple values, key);
+   warning(_(%s has multiple values), key);
}
 
ALLOC_GROW(store.offset, store.seen + 1,
-- 
2.0.2.737.gfb43bde

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


Re: [PATCH v5 3/7] change `git_config()` return value to void

2014-07-31 Thread Matthieu Moy
Matthieu Moy matthieu@grenoble-inp.fr writes:

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

 Signed-off-by: Tanay Abhra tanay...@gmail.com

 I think I deserve a bit of credit here ;-).

  {
 -return git_config_with_options(fn, data, NULL, 1);
 +if (git_config_with_options(fn, data, NULL, 1)  0)
 +/*
 + * git_config_with_options() normally returns only
 + * positive values, as most errors are fatal, and
 + * non-fatal potential errors are guarded by if
 + * statements that are entered only when no error is
 + * possible.
 + *
 + * If we ever encounter a non-fatal error, it means
 + * something went really wrong and we should stop
 + * immediately.
 + */
 +die(Unknown error occured while reading the configuration 
 files);
  }

 My bad, but this should be die(_(...));, so that the message can be
 translated. Not really serious since it's not really meant to be seen by
 the user, though.

Also, other error messages do not start with a capital, hence it should
be unknown..., not Unknown. My bad again.

-- 
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 v4 0/5] git_config callers rewritten with the new config cache API

2014-07-31 Thread Ramsay Jones
On 30/07/14 17:45, Matthieu Moy wrote:
 Tanay Abhra tanay...@gmail.com writes:
 Also, any thoughts on what to do with git_default_config()? We can,

 1 make a new function git_load_default_config(), use it for the rewrites.
 
 That seems the most sensible option. It could be called it git.c before
 the command-dependant part, so that any call to git loads this.
 
 I didn't check if it was correct (e.g. do some command rely on the fact
 that the default config is not loaded?)
 

Hmm, here be dragons ... :-P

I don't know that there has actually been any kind of policy
regarding the reading of config files/variables in git (or if
there is a different policy for plumbing vs porcelain), but it
has always seemed to be somewhat ad-hoc; each command decides
for itself what it wants to read.

However, with increased use of common code which _uses_ certain
config variables for correct operation, the 'choice' is much
harder to make (and may change after the fact!).

For example, about a year ago I submitted a couple of patches
which added a call to git_config(git_default_config, NULL) to
both 'git pack-refs' and 'git show-refs'. This was as a result
of the 'mh/ref-races' branch which introduced a 'stat_validity'
api for checking if the packed-refs file had changed on the
filesystem since last you looked. This re-used some of the same
code used to handle index updates that used config variables
like core.checkstat and core.trustctime. These config variables
can affect the correctness and/or the efficiency of the code on
some platforms (e.g. cygwin, mingw).

[Note: 'stat_validity' has since been re-used again (why not?)
in some shallow clone code, so similar comments may apply ...
I haven't looked.]

However, those patches were dropped, because it resulted in an
(unwanted) change in behaviour. In particular, 'git show-refs'
changed behaviour because it now 'listened' to core.abbrev!

I started to look at splitting the 'core config variables' into
two groups; essential variables that _all_ git commands should
read for correct/efficient/consistent behaviour and everything
else (mainly UI related variables).

However, something else came up ...

Just an FYI.

ATB,
Ramsay Jones


--
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 2/5] notes.c: replace `git_config()` with `git_config_get_value_multi()`

2014-07-31 Thread Matthieu Moy
Matthieu Moy matthieu@grenoble-inp.fr writes:

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

 On 7/30/2014 7:43 PM, Matthieu Moy wrote:
 * if (!values-items[i].string)
   config_error_nonbool(
 
   = This check could be done once and for all in a function, say
   git_config_get_value_multi_nonbool, a trivial wrapper around
   git_config_get_value_multi like
 
 const struct string_list *git_configset_get_value_multi_nonbool(struct 
 config_set *cs, const char *key)
 {
 struct string_list l = git_configset_get_value_multi(cs, key);
 // possibly if(l) depending on the point above.
 for (i = 0; i  values-nr; i++) {
 if (!values-items[i].string)
 git_config_die(key);
 }
 return l;
 }


 Not worth it, most the multi value calls do not die on a nonbool.

 Can you cite some multi-value variables that can be nonbool? I can't
 find many multi-valued variables, and I can't find any which would allow
 bool and nonbool.

Thinking a bit more about it: we actually need more than your patch and
my code example above to give accurate error messages. Your code gives
no error message, and mine uses git_config_die(key); which gives the
line of the _last_ entry, but not necessarily the right line.

The right line number should be extracted from the info field of the
string_list. It's not completely trivial, hence I'd rather have a helper
doing it well in config.c than letting callers re-do the check and
possibly give wrong line in their error message as I did in my first
attempt.

I think you can introduce a helper git_config_die_linenr(key, linenr)
that displays the right error message. Then git_config_die becomes a
wrapper around it that does the lookup to find linenr from the hash.

You already have a duplicate piece of code in your other series:

if (!kv_info-linenr)
die(unable to parse '%s' from command-line 
config, entry-key);
else
die(bad config variable '%s' at file line %d 
in %s,
entry-key,
kv_info-linenr,
kv_info-filename);

That would be the content of git_config_die_linenr().

-- 
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 v5 3/7] change `git_config()` return value to void

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

 On 7/31/2014 4:52 PM, Matthieu Moy wrote:
 Tanay Abhra tanay...@gmail.com writes:
 
 Signed-off-by: Tanay Abhra tanay...@gmail.com
 
 I think I deserve a bit of credit here ;-).


 Yes, but to show credit would I have to write from you or
 signed-off-by? :)

Original-patch-by: would be fine.

 My bad, but this should be die(_(...));, so that the message can be
 translated. Not really serious since it's not really meant to be seen by
 the user, though.


 Noted. Though there are not many cases till I have read where error messages 
 are marked
 for translation.

Yes, see my other message.

Overall, there are still many untranslated messages in Git's codebase:

$ git grep 'die(_(' | wc -l
517
$ git grep 'die(' | wc -l 
1247

Part of the reason is that die() was written and used far before the
translation effort has started.

-- 
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 v5 3/7] change `git_config()` return value to void

2014-07-31 Thread Tanay Abhra


On 7/31/2014 4:52 PM, Matthieu Moy wrote:
 Tanay Abhra tanay...@gmail.com writes:
 
 Signed-off-by: Tanay Abhra tanay...@gmail.com
 
 I think I deserve a bit of credit here ;-).


Yes, but to show credit would I have to write from you or
signed-off-by? :)

  {
 -return git_config_with_options(fn, data, NULL, 1);
 +if (git_config_with_options(fn, data, NULL, 1)  0)
 +/*
 + * git_config_with_options() normally returns only
 + * positive values, as most errors are fatal, and
 + * non-fatal potential errors are guarded by if
 + * statements that are entered only when no error is
 + * possible.
 + *
 + * If we ever encounter a non-fatal error, it means
 + * something went really wrong and we should stop
 + * immediately.
 + */
 +die(Unknown error occured while reading the configuration 
 files);
  }
 
 My bad, but this should be die(_(...));, so that the message can be
 translated. Not really serious since it's not really meant to be seen by
 the user, though.


Noted. Though there are not many cases till I have read where error messages 
are marked
for translation.
--
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] config.c: mark error and warnings strings for translation

2014-07-31 Thread Tanay Abhra
On 7/31/2014 5:01 PM, Matthieu Moy wrote:
 Signed-off-by: Matthieu Moy matthieu@imag.fr
 ---
 Noticed while reviewing Tanay's patches, but this one is independant
 from his series, both syntactically and semantically.
 
  config.c | 20 ++--
  1 file changed, 10 insertions(+), 10 deletions(-)
 
 diff --git a/config.c b/config.c
 index a191328..76eeb63 100644
 --- a/config.c
 +++ b/config.c
 @@ -457,9 +457,9 @@ static int git_parse_source(config_fn_t fn, void *data)
   break;
   }
   if (cf-die_on_error)
 - die(bad config file line %d in %s, cf-linenr, cf-name);
 + die(_(bad config file line %d in %s), cf-linenr, cf-name);
   else
 - return error(bad config file line %d in %s, cf-linenr, 
 cf-name);
 + return error(_(bad config file line %d in %s), cf-linenr, 
 cf-name);

Can I package your patch with mine in which I am going to change the
error message to print the variable name also?

  }
  
  static int parse_unit_factor(const char *end, uintmax_t *val)
 @@ -575,9 +575,9 @@ static void die_bad_number(const char *name, const char 
 *value)
   value = ;
  
   if (cf  cf-name)
 - die(bad numeric config value '%s' for '%s' in %s: %s,
 + die(_(bad numeric config value '%s' for '%s' in %s: %s),
   value, name, cf-name, reason);
 - die(bad numeric config value '%s' for '%s': %s, value, name, reason);
 + die(_(bad numeric config value '%s' for '%s': %s), value, name, 
 reason);
  }
  
  int git_config_int(const char *name, const char *value)
 @@ -662,7 +662,7 @@ int git_config_pathname(const char **dest, const char 
 *var, const char *value)
   return config_error_nonbool(var);
   *dest = expand_user_path(value);
   if (!*dest)
 - die(Failed to expand user dir in: '%s', value);
 + die(_(Failed to expand user dir in: '%s'), value);

nit : error messages start with a small letter. same case below for Invalid. 
;)

   return 0;
  }
  
 @@ -740,7 +740,7 @@ static int git_default_core_config(const char *var, const 
 char *value)
   if (level == -1)
   level = Z_DEFAULT_COMPRESSION;
   else if (level  0 || level  Z_BEST_COMPRESSION)
 - die(bad zlib compression level %d, level);
 + die(_(bad zlib compression level %d), level);
   zlib_compression_level = level;
   zlib_compression_seen = 1;
   return 0;
 @@ -751,7 +751,7 @@ static int git_default_core_config(const char *var, const 
 char *value)
   if (level == -1)
   level = Z_DEFAULT_COMPRESSION;
   else if (level  0 || level  Z_BEST_COMPRESSION)
 - die(bad zlib compression level %d, level);
 + die(_(bad zlib compression level %d), level);
   core_compression_level = level;
   core_compression_seen = 1;
   if (!zlib_compression_seen)
 @@ -873,7 +873,7 @@ static int git_default_core_config(const char *var, const 
 char *value)
   else if (!strcmp(value, link))
   object_creation_mode = OBJECT_CREATION_USES_HARDLINKS;
   else
 - die(Invalid mode for object creation: %s, value);
 + die(_(Invalid mode for object creation: %s), value);
   return 0;
   }
  
 @@ -1173,7 +1173,7 @@ int git_config_early(config_fn_t fn, void *data, const 
 char *repo_config)
  
   switch (git_config_from_parameters(fn, data)) {
   case -1: /* error */
 - die(unable to parse command-line config);
 + die(_(unable to parse command-line config));
   break;
   case 0: /* found nothing */
   break;
 @@ -1514,7 +1514,7 @@ static int store_aux(const char *key, const char 
 *value, void *cb)
   case KEY_SEEN:
   if (matches(key, value)) {
   if (store.seen == 1  store.multi_replace == 0) {
 - warning(%s has multiple values, key);
 + warning(_(%s has multiple values), key);
   }
  
   ALLOC_GROW(store.offset, store.seen + 1,
 
--
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 2/5] notes.c: replace `git_config()` with `git_config_get_value_multi()`

2014-07-31 Thread Tanay Abhra


On 7/31/2014 5:08 PM, Matthieu Moy wrote:
 Matthieu Moy matthieu@grenoble-inp.fr writes:
 
 Tanay Abhra tanay...@gmail.com writes:

 On 7/30/2014 7:43 PM, Matthieu Moy wrote:
 * if (!values-items[i].string)
   config_error_nonbool(

   = This check could be done once and for all in a function, say
   git_config_get_value_multi_nonbool, a trivial wrapper around
   git_config_get_value_multi like

 const struct string_list *git_configset_get_value_multi_nonbool(struct 
 config_set *cs, const char *key)
 {
struct string_list l = git_configset_get_value_multi(cs, key);
 // possibly if(l) depending on the point above.
for (i = 0; i  values-nr; i++) {
if (!values-items[i].string)
git_config_die(key);
}
return l;
 }


 Not worth it, most the multi value calls do not die on a nonbool.

 Can you cite some multi-value variables that can be nonbool? I can't
 find many multi-valued variables, and I can't find any which would allow
 bool and nonbool.
 
 Thinking a bit more about it: we actually need more than your patch and
 my code example above to give accurate error messages. Your code gives
 no error message, and mine uses git_config_die(key); which gives the
 line of the _last_ entry, but not necessarily the right line.
 
 The right line number should be extracted from the info field of the
 string_list. It's not completely trivial, hence I'd rather have a helper
 doing it well in config.c than letting callers re-do the check and
 possibly give wrong line in their error message as I did in my first
 attempt.
 
 I think you can introduce a helper git_config_die_linenr(key, linenr)
 that displays the right error message. Then git_config_die becomes a
 wrapper around it that does the lookup to find linenr from the hash.
 
 You already have a duplicate piece of code in your other series:
 
   if (!kv_info-linenr)
   die(unable to parse '%s' from command-line 
 config, entry-key);
   else
   die(bad config variable '%s' at file line %d 
 in %s,
   entry-key,
   kv_info-linenr,
   kv_info-filename);
 
 That would be the content of git_config_die_linenr().
 

Thanks. I will add it in the next reroll.
--
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] config.c: mark error and warnings strings for translation

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

 On 7/31/2014 5:01 PM, Matthieu Moy wrote:
 Signed-off-by: Matthieu Moy matthieu@imag.fr
 ---
 Noticed while reviewing Tanay's patches, but this one is independant
 from his series, both syntactically and semantically.
 
  config.c | 20 ++--
  1 file changed, 10 insertions(+), 10 deletions(-)
 
 diff --git a/config.c b/config.c
 index a191328..76eeb63 100644
 --- a/config.c
 +++ b/config.c
 @@ -457,9 +457,9 @@ static int git_parse_source(config_fn_t fn, void *data)
  break;
  }
  if (cf-die_on_error)
 -die(bad config file line %d in %s, cf-linenr, cf-name);
 +die(_(bad config file line %d in %s), cf-linenr, cf-name);
  else
 -return error(bad config file line %d in %s, cf-linenr, 
 cf-name);
 +return error(_(bad config file line %d in %s), cf-linenr, 
 cf-name);

 Can I package your patch with mine in which I am going to change the
 error message to print the variable name also?

Yes, you can include it as PATCH 1 for example, and then build on top.

 @@ -662,7 +662,7 @@ int git_config_pathname(const char **dest, const char 
 *var, const char *value)
  return config_error_nonbool(var);
  *dest = expand_user_path(value);
  if (!*dest)
 -die(Failed to expand user dir in: '%s', value);
 +die(_(Failed to expand user dir in: '%s'), value);

 nit : error messages start with a small letter. same case below for 
 Invalid. ;)

Indeed. Then I'm letting you continue on the patch.

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


[BUG?] log -g does not respect pathspec

2014-07-31 Thread Duy Nguyen
git log -g and git log -g -- something show the same thing. From
the implementation point of view, I guess that's understandable
because reflog takes a different codepath. But I think the user does
not expect that..
-- 
Duy
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/5] gitweb: fix typo in man page

2014-07-31 Thread Tony Finch
Signed-off-by: Tony Finch d...@dotat.at
---
 Documentation/gitweb.conf.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/gitweb.conf.txt b/Documentation/gitweb.conf.txt
index ebe7a6c..29f1e06 100644
--- a/Documentation/gitweb.conf.txt
+++ b/Documentation/gitweb.conf.txt
@@ -487,7 +487,7 @@ By default it is set to (), i.e. an empty list.  This means 
that gitweb
 would not try to create project URL (to fetch) from project name.

 $projects_list_group_categories::
-   Whether to enables the grouping of projects by category on the project
+   Whether to enable the grouping of projects by category on the project
list page. The category of a project is determined by the
`$GIT_DIR/category` file or the `gitweb.category` variable in each
repository's configuration.  Disabled by default (set to 0).
-- 
2.1.0.rc0.229.gaee38de


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


[PATCH 0/5] gitweb: improve directory hierarchy handling

2014-07-31 Thread Tony Finch
There are two main things in this little seris:

The second and third patches improve gitweb's project filter feature,
which is for listing just the projects in a subdirectory.

The fourth and fifth allow the admin to use a directory hierarchy
to automatically categorize projects in gitweb.

Tony Finch (5):
  gitweb: fix typo in man page
  gitweb: if the PATH_INFO is incomplete, use it as a project_filter
  gitweb: add a link under the search box to clear a project filter
  gitweb: optionally set project category from its pathname
  gitweb: make category headings into links when they are directories

 Documentation/gitweb.conf.txt |  8 +-
 gitweb/gitweb.perl| 62 ---
 2 files changed, 59 insertions(+), 11 deletions(-)

-- 
2.1.0.rc0.229.gaee38de

--
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 3/5] gitweb: add a link under the search box to clear a project filter

2014-07-31 Thread Tony Finch
Previously when a project filter was active, the only simple way
to clear it was by clicking the home link in the breadcrumbs, which
is not very obvious.

This change adds another home link under the search box which clears
both project filter and search, next to the existing link that
clears the search and keeps the project filter.

Signed-off-by: Tony Finch d...@dotat.at
---
 gitweb/gitweb.perl | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 12aba8f..d1e6b79 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -5545,10 +5545,13 @@ sub git_project_search_form {
  /span\n .
  $cgi-submit(-name = 'btnS', -value = 'Search') .
  $cgi-end_form() . \n .
- $cgi-a({-href = href(project = undef, searchtext = undef,
-project_filter = $project_filter)},
- esc_html(List all projects$limit)) . br /\n;
-   print /div\n;
+ $cgi-a({-href = $my_uri}, esc_html(List all projects));
+   print  /  .
+ $cgi-a({-href = href(project = undef, action = project_list,
+project_filter = $project_filter)},
+ esc_html(List projects$limit))
+   if $project_filter;
+   print br /\n/div\n;
 }

 # entry for given @keys needs filling if at least one of keys in list
-- 
2.1.0.rc0.229.gaee38de


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


[PATCH 4/5] gitweb: optionally set project category from its pathname

2014-07-31 Thread Tony Finch
When repositories are organized in a hierarchial directory tree
it is convenient if gitweb project categories can be set
automatically based on their parent directory, so that users
do not have to set the same information twice.

Signed-off-by: Tony Finch d...@dotat.at
---
 Documentation/gitweb.conf.txt |  6 ++
 gitweb/gitweb.perl| 13 ++---
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/Documentation/gitweb.conf.txt b/Documentation/gitweb.conf.txt
index 29f1e06..7c0de18 100644
--- a/Documentation/gitweb.conf.txt
+++ b/Documentation/gitweb.conf.txt
@@ -492,6 +492,12 @@ $projects_list_group_categories::
`$GIT_DIR/category` file or the `gitweb.category` variable in each
repository's configuration.  Disabled by default (set to 0).

+$projects_list_directory_is_category::
+   Whether to set a project's category to its parent directory, i.e. its
+   pathname excluding the `/repo.git` leaf name. This is only used if
+   the repo has no explicit setting, and if the pathname has more than
+   one component. Disabled by default (set to 0).
+
 $project_list_default_category::
Default category for projects for which none is specified.  If this is
set to the empty string, such projects will remain uncategorized and
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index d1e6b79..edbc058 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -129,6 +129,10 @@ our $projects_list_description_width = 25;
 # (enabled if this variable evaluates to true)
 our $projects_list_group_categories = 0;

+# project's category defaults to its parent directory
+# (enabled if this variable evaluates to true)
+our $projects_list_directory_is_category = 0;
+
 # default category if none specified
 # (leave the empty string for no category)
 our $project_list_default_category = ;
@@ -2904,7 +2908,11 @@ sub git_get_project_description {

 sub git_get_project_category {
my $path = shift;
-   return git_get_file_or_project_config($path, 'category');
+   my $cat = git_get_file_or_project_config($path, 'category');
+   return $cat if $cat;
+   return $1 if $projects_list_directory_is_category
+  $path =~ m,^(.*)/[^/]*$,;
+   return $project_list_default_category;
 }


@@ -5618,8 +5626,7 @@ sub fill_project_list_info {
}
if ($projects_list_group_categories 
project_info_needs_filling($pr, $filter_set-('category'))) 
{
-   my $cat = git_get_project_category($pr-{'path'}) ||
-  
$project_list_default_category;
+   my $cat = git_get_project_category($pr-{'path'});
$pr-{'category'} = to_utf8($cat);
}

-- 
2.1.0.rc0.229.gaee38de


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


[PATCH 5/5] gitweb: make category headings into links when they are directories

2014-07-31 Thread Tony Finch
When $projects_list_category_is_directory is turned on, project
categories can be useful as project filters, so with that setting
gitweb now makes the category headings into project_filter links
(like the breadcrumbs).

Signed-off-by: Tony Finch d...@dotat.at
---
 gitweb/gitweb.perl | 14 --
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index edbc058..32e65ae 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -5834,8 +5834,18 @@ sub git_project_list_body {
if ($check_forks) {
print td/td\n;
}
-   print td class=\category\ 
colspan=\5\.esc_html($cat)./td\n;
-   print /tr\n;
+   print td class=\category\ colspan=\5\;
+   if ($projects_list_directory_is_category) {
+   print $cgi-a({-href =
+   href(project = undef,
+   project_filter = $cat,
+   action = project_list),
+   -class = list},
+   esc_html($cat));
+   } else {
+   print esc_html($cat);
+   }
+   print /td\n/tr\n;
}

git_project_list_rows($categories{$cat}, undef, undef, 
$check_forks);
-- 
2.1.0.rc0.229.gaee38de

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


[PATCH 2/5] gitweb: if the PATH_INFO is incomplete, use it as a project_filter

2014-07-31 Thread Tony Finch
Previously gitweb would ignore partial PATH_INFO. For example,
it would produce a project list for the top URL
https://www.example.org/projects/
and a project summary for
https://www.example.org/projects/git/git.git
but if you tried to list just the git-related projects with
https://www.example.org/projects/git/
you would get a list of all projects, same as the top URL.

As well as fixing that omission, this change also makes gitweb
generate PATH_INFO-style URLs for project filter links, such
as in the breadcrumbs.

Signed-off-by: Tony Finch d...@dotat.at
---
 gitweb/gitweb.perl | 24 +++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index a9f57d6..12aba8f 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -891,7 +891,17 @@ sub evaluate_path_info {
while ($project  !check_head_link($projectroot/$project)) {
$project =~ s,/*[^/]*$,,;
}
-   return unless $project;
+   # If there is no project, use the PATH_INFO as a project filter if it
+   # is a directory in the projectroot. (It can't be a subdirectory of a
+   # repo because we just verified that isn't the case.)
+   unless ($project) {
+   if (-d $projectroot/$path_info) {
+   $path_info =~ s,/+$,,;
+   $input_params{'project_filter'} = $path_info;
+   $path_info = ;
+   }
+   return;
+   }
$input_params{'project'} = $project;

# do not change any parameters if an action is given using the query 
string
@@ -1356,6 +1366,18 @@ sub href {
}

my $use_pathinfo = gitweb_check_feature('pathinfo');
+
+   # we have to check for a project_filter first because handling the full
+   # project-plus-parameters deletes some of the paramaters we check here
+   if (!defined $params{'project'}  $params{'project_filter'} 
+   $params{'action'} eq project_list 
+   (exists $params{-path_info} ? $params{-path_info} : $use_pathinfo)) 
{
+   $href =~ s,/$,,;
+   $href .= /.esc_path_info($params{'project_filter'})./;
+   delete $params{'project_filter'};
+   delete $params{'action'};
+   }
+
if (defined $params{'project'} 
(exists $params{-path_info} ? $params{-path_info} : $use_pathinfo)) 
{
# try to put as many parameters as possible in PATH_INFO:
-- 
2.1.0.rc0.229.gaee38de


--
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 0/3] Keep .lock file paths absolute

2014-07-31 Thread Nguyễn Thái Ngọc Duy
v3 requires rs/strbuf-getcwd, turns paths to absolute from the
beginning, and kills the last use of PATH_MAX in lockfile.c thanks to
strbuf_readlink().

Nguyễn Thái Ngọc Duy (3):
  lockfile.c: remove PATH_MAX limitation (except in resolve_symlink)
  lockfile.c: remove PATH_MAX limit in resolve_symlink()
  lockfile.c: store absolute path

 cache.h   |  2 +-
 lockfile.c| 95 +++
 t/t2107-update-index-basic.sh | 15 +++
 3 files changed, 58 insertions(+), 54 deletions(-)

-- 
2.1.0.rc0.78.gc0d8480

--
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 2/3] lockfile.c: remove PATH_MAX limit in resolve_symlink()

2014-07-31 Thread Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
 lockfile.c | 47 ++-
 1 file changed, 14 insertions(+), 33 deletions(-)

diff --git a/lockfile.c b/lockfile.c
index 968b28f..154915f 100644
--- a/lockfile.c
+++ b/lockfile.c
@@ -85,52 +85,33 @@ static char *last_path_elm(char *p)
 
 static char *resolve_symlink(const char *in)
 {
-   static char p[PATH_MAX];
-   size_t s = sizeof(p);
+   static struct strbuf p = STRBUF_INIT;
+   struct strbuf link = STRBUF_INIT;
int depth = MAXDEPTH;
 
-   if (strlen(in) = sizeof(p))
-   return NULL;
-   strcpy(p, in);
+   strbuf_reset(p);
+   strbuf_addstr(p, in);
 
while (depth--) {
-   char link[PATH_MAX];
-   int link_len = readlink(p, link, sizeof(link));
-   if (link_len  0) {
-   /* not a symlink anymore */
-   return p;
-   }
-   else if (link_len  sizeof(link))
-   /* readlink() never null-terminates */
-   link[link_len] = '\0';
-   else {
-   warning(%s: symlink too long, p);
-   return p;
-   }
+   if (strbuf_readlink(link, p.buf, 0)  0)
+   break;  /* not a symlink anymore */
 
-   if (is_absolute_path(link)) {
+   if (is_absolute_path(link.buf)) {
/* absolute path simply replaces p */
-   if (link_len  s)
-   strcpy(p, link);
-   else {
-   warning(%s: symlink too long, p);
-   return p;
-   }
+   strbuf_reset(p);
+   strbuf_addbuf(p, link);
} else {
/*
 * link is a relative path, so I must replace the
 * last element of p with it.
 */
-   char *r = (char *)last_path_elm(p);
-   if (r - p + link_len  s)
-   strcpy(r, link);
-   else {
-   warning(%s: symlink too long, p);
-   return p;
-   }
+   char *r = (char *)last_path_elm(p.buf);
+   strbuf_setlen(p, r - p.buf);
+   strbuf_addbuf(p, link);
}
}
-   return p;
+   strbuf_release(link);
+   return p.buf;
 }
 
 
-- 
2.1.0.rc0.78.gc0d8480

--
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 1/3] lockfile.c: remove PATH_MAX limitation (except in resolve_symlink)

2014-07-31 Thread Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
 cache.h|  2 +-
 lockfile.c | 56 
 2 files changed, 33 insertions(+), 25 deletions(-)

diff --git a/cache.h b/cache.h
index cc46be4..0d8dce7 100644
--- a/cache.h
+++ b/cache.h
@@ -539,7 +539,7 @@ struct lock_file {
int fd;
pid_t owner;
char on_list;
-   char filename[PATH_MAX];
+   char *filename;
 };
 #define LOCK_DIE_ON_ERROR 1
 #define LOCK_NODEREF 2
diff --git a/lockfile.c b/lockfile.c
index 8fbcb6a..968b28f 100644
--- a/lockfile.c
+++ b/lockfile.c
@@ -7,13 +7,19 @@
 static struct lock_file *lock_file_list;
 static const char *alternate_index_output;
 
+static void clear_filename(struct lock_file *lk)
+{
+   free(lk-filename);
+   lk-filename = NULL;
+}
+
 static void remove_lock_file(void)
 {
pid_t me = getpid();
 
while (lock_file_list) {
if (lock_file_list-owner == me 
-   lock_file_list-filename[0]) {
+   lock_file_list-filename) {
if (lock_file_list-fd = 0)
close(lock_file_list-fd);
unlink_or_warn(lock_file_list-filename);
@@ -77,10 +83,16 @@ static char *last_path_elm(char *p)
  * Always returns p.
  */
 
-static char *resolve_symlink(char *p, size_t s)
+static char *resolve_symlink(const char *in)
 {
+   static char p[PATH_MAX];
+   size_t s = sizeof(p);
int depth = MAXDEPTH;
 
+   if (strlen(in) = sizeof(p))
+   return NULL;
+   strcpy(p, in);
+
while (depth--) {
char link[PATH_MAX];
int link_len = readlink(p, link, sizeof(link));
@@ -124,17 +136,12 @@ static char *resolve_symlink(char *p, size_t s)
 
 static int lock_file(struct lock_file *lk, const char *path, int flags)
 {
-   /*
-* subtract 5 from size to make sure there's room for adding
-* .lock for the lock file name
-*/
-   static const size_t max_path_len = sizeof(lk-filename) - 5;
-
-   if (strlen(path) = max_path_len)
+   int len;
+   if (!(flags  LOCK_NODEREF)  !(path = resolve_symlink(path)))
return -1;
+   len = strlen(path) + 5; /* .lock */
+   lk-filename = xmallocz(len);
strcpy(lk-filename, path);
-   if (!(flags  LOCK_NODEREF))
-   resolve_symlink(lk-filename, max_path_len);
strcat(lk-filename, .lock);
lk-fd = open(lk-filename, O_RDWR | O_CREAT | O_EXCL, 0666);
if (0 = lk-fd) {
@@ -153,7 +160,7 @@ static int lock_file(struct lock_file *lk, const char 
*path, int flags)
 lk-filename);
}
else
-   lk-filename[0] = 0;
+   clear_filename(lk);
return lk-fd;
 }
 
@@ -231,16 +238,17 @@ int close_lock_file(struct lock_file *lk)
 
 int commit_lock_file(struct lock_file *lk)
 {
-   char result_file[PATH_MAX];
-   size_t i;
-   if (lk-fd = 0  close_lock_file(lk))
+   char *result_file;
+   if ((lk-fd = 0  close_lock_file(lk)) || !lk-filename)
return -1;
-   strcpy(result_file, lk-filename);
-   i = strlen(result_file) - 5; /* .lock */
-   result_file[i] = 0;
-   if (rename(lk-filename, result_file))
+   result_file = xmemdupz(lk-filename,
+  strlen(lk-filename) - 5 /* .lock */);
+   if (rename(lk-filename, result_file)) {
+   free(result_file);
return -1;
-   lk-filename[0] = 0;
+   }
+   free(result_file);
+   clear_filename(lk);
return 0;
 }
 
@@ -260,11 +268,11 @@ void set_alternate_index_output(const char *name)
 int commit_locked_index(struct lock_file *lk)
 {
if (alternate_index_output) {
-   if (lk-fd = 0  close_lock_file(lk))
+   if ((lk-fd = 0  close_lock_file(lk)) || !lk-filename)
return -1;
if (rename(lk-filename, alternate_index_output))
return -1;
-   lk-filename[0] = 0;
+   clear_filename(lk);
return 0;
}
else
@@ -273,10 +281,10 @@ int commit_locked_index(struct lock_file *lk)
 
 void rollback_lock_file(struct lock_file *lk)
 {
-   if (lk-filename[0]) {
+   if (lk-filename) {
if (lk-fd = 0)
close(lk-fd);
unlink_or_warn(lk-filename);
}
-   lk-filename[0] = 0;
+   clear_filename(lk);
 }
-- 
2.1.0.rc0.78.gc0d8480

--
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 3/3] lockfile.c: store absolute path

2014-07-31 Thread Nguyễn Thái Ngọc Duy
Locked paths can be saved in a linked list so that if something wrong
happens, *.lock are removed. For relative paths, this works fine if we
keep cwd the same, which is true 99% of time except:

- update-index and read-tree hold the lock on $GIT_DIR/index really
  early, then later on may call setup_work_tree() to move cwd.

- Suppose a lock is being held (e.g. by git add) then somewhere
  down the line, somebody calls real_path (e.g. link_alt_odb_entry),
  which temporarily moves cwd away and back.

During that time when cwd is moved (either permanently or temporarily)
and we decide to die(), attempts to remove relative *.lock will fail,
and the next operation will complain that some files are still locked.

Avoid this case by turning relative paths to absolute before storing
the path in filename field.

Reported-by: Yue Lin Ho yuelinho...@gmail.com
Helped-by: Ramsay Jones ram...@ramsay1.demon.co.uk
Helped-by: Johannes Sixt j...@kdbg.org
Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
 lockfile.c| 10 +-
 t/t2107-update-index-basic.sh | 15 +++
 2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/lockfile.c b/lockfile.c
index 154915f..0aa70a5 100644
--- a/lockfile.c
+++ b/lockfile.c
@@ -117,13 +117,13 @@ static char *resolve_symlink(const char *in)
 
 static int lock_file(struct lock_file *lk, const char *path, int flags)
 {
-   int len;
+   struct strbuf sb = STRBUF_INIT;
+
if (!(flags  LOCK_NODEREF)  !(path = resolve_symlink(path)))
return -1;
-   len = strlen(path) + 5; /* .lock */
-   lk-filename = xmallocz(len);
-   strcpy(lk-filename, path);
-   strcat(lk-filename, .lock);
+   strbuf_add_absolute_path(sb, path);
+   strbuf_addstr(sb, .lock);
+   lk-filename = strbuf_detach(sb, NULL);
lk-fd = open(lk-filename, O_RDWR | O_CREAT | O_EXCL, 0666);
if (0 = lk-fd) {
if (!lock_file_list) {
diff --git a/t/t2107-update-index-basic.sh b/t/t2107-update-index-basic.sh
index 1bafb90..dfe02f4 100755
--- a/t/t2107-update-index-basic.sh
+++ b/t/t2107-update-index-basic.sh
@@ -65,4 +65,19 @@ test_expect_success '--cacheinfo mode,sha1,path (new 
syntax)' '
test_cmp expect actual
 '
 
+test_expect_success '.lock files cleaned up' '
+   mkdir cleanup 
+   (
+   cd cleanup 
+   mkdir worktree 
+   git init repo 
+   cd repo 
+   git config core.worktree ../../worktree 
+   # --refresh triggers late setup_work_tree,
+   # active_cache_changed is zero, rollback_lock_file fails
+   git update-index --refresh 
+   ! test -f .git/index.lock
+   )
+'
+
 test_done
-- 
2.1.0.rc0.78.gc0d8480

--
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 1/2] config.c: mark error and warnings strings for translation

2014-07-31 Thread Tanay Abhra
From: Matthieu Moy matthieu@imag.fr

Signed-off-by: Matthieu Moy matthieu@imag.fr
---
v2: error messages now start with a small letter.

 config.c | 20 ++--
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/config.c b/config.c
index 058505c..7330789 100644
--- a/config.c
+++ b/config.c
@@ -442,9 +442,9 @@ static int git_parse_source(config_fn_t fn, void *data)
break;
}
if (cf-die_on_error)
-   die(bad config file line %d in %s, cf-linenr, cf-name);
+   die(_(bad config file line %d in %s), cf-linenr, cf-name);
else
-   return error(bad config file line %d in %s, cf-linenr, 
cf-name);
+   return error(_(bad config file line %d in %s), cf-linenr, 
cf-name);
 }
 
 static int parse_unit_factor(const char *end, uintmax_t *val)
@@ -560,9 +560,9 @@ static void die_bad_number(const char *name, const char 
*value)
value = ;
 
if (cf  cf-name)
-   die(bad numeric config value '%s' for '%s' in %s: %s,
+   die(_(bad numeric config value '%s' for '%s' in %s: %s),
value, name, cf-name, reason);
-   die(bad numeric config value '%s' for '%s': %s, value, name, reason);
+   die(_(bad numeric config value '%s' for '%s': %s), value, name, 
reason);
 }
 
 int git_config_int(const char *name, const char *value)
@@ -647,7 +647,7 @@ int git_config_pathname(const char **dest, const char *var, 
const char *value)
return config_error_nonbool(var);
*dest = expand_user_path(value);
if (!*dest)
-   die(Failed to expand user dir in: '%s', value);
+   die(_(failed to expand user dir in: '%s'), value);
return 0;
 }
 
@@ -725,7 +725,7 @@ static int git_default_core_config(const char *var, const 
char *value)
if (level == -1)
level = Z_DEFAULT_COMPRESSION;
else if (level  0 || level  Z_BEST_COMPRESSION)
-   die(bad zlib compression level %d, level);
+   die(_(bad zlib compression level %d), level);
zlib_compression_level = level;
zlib_compression_seen = 1;
return 0;
@@ -736,7 +736,7 @@ static int git_default_core_config(const char *var, const 
char *value)
if (level == -1)
level = Z_DEFAULT_COMPRESSION;
else if (level  0 || level  Z_BEST_COMPRESSION)
-   die(bad zlib compression level %d, level);
+   die(_(bad zlib compression level %d), level);
core_compression_level = level;
core_compression_seen = 1;
if (!zlib_compression_seen)
@@ -858,7 +858,7 @@ static int git_default_core_config(const char *var, const 
char *value)
else if (!strcmp(value, link))
object_creation_mode = OBJECT_CREATION_USES_HARDLINKS;
else
-   die(Invalid mode for object creation: %s, value);
+   die(_(invalid mode for object creation: %s), value);
return 0;
}
 
@@ -1158,7 +1158,7 @@ int git_config_early(config_fn_t fn, void *data, const 
char *repo_config)
 
switch (git_config_from_parameters(fn, data)) {
case -1: /* error */
-   die(unable to parse command-line config);
+   die(_(unable to parse command-line config));
break;
case 0: /* found nothing */
break;
@@ -1243,7 +1243,7 @@ static int store_aux(const char *key, const char *value, 
void *cb)
case KEY_SEEN:
if (matches(key, value)) {
if (store.seen == 1  store.multi_replace == 0) {
-   warning(%s has multiple values, key);
+   warning(_(%s has multiple values), key);
}
 
ALLOC_GROW(store.offset, store.seen + 1,
-- 
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 2/2] add variable name to `git_config_*()` error message

2014-07-31 Thread Tanay Abhra
Whenever a callback returns a negative value, the functions
of `git_config_*()` family die printing the line number and
file name. In addition to them, add the variable name to the
error message.

Signed-off-by: Tanay Abhra tanay...@gmail.com
---
 config.c| 4 ++--
 t/t4055-diff-context.sh | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/config.c b/config.c
index 7330789..77407da 100644
--- a/config.c
+++ b/config.c
@@ -442,9 +442,9 @@ static int git_parse_source(config_fn_t fn, void *data)
break;
}
if (cf-die_on_error)
-   die(_(bad config file line %d in %s), cf-linenr, cf-name);
+   die(_(bad config variable '%s' at file line %d in %s), 
var-buf, cf-linenr, cf-name);
else
-   return error(_(bad config file line %d in %s), cf-linenr, 
cf-name);
+   return error(_(bad config variable '%s' at file line %d in 
%s), var-buf, cf-linenr, cf-name);
 }
 
 static int parse_unit_factor(const char *end, uintmax_t *val)
diff --git a/t/t4055-diff-context.sh b/t/t4055-diff-context.sh
index cd04543..741e080 100755
--- a/t/t4055-diff-context.sh
+++ b/t/t4055-diff-context.sh
@@ -79,7 +79,7 @@ test_expect_success 'non-integer config parsing' '
 test_expect_success 'negative integer config parsing' '
git config diff.context -1 
test_must_fail git diff 2output 
-   test_i18ngrep bad config file output
+   test_i18ngrep bad config variable output
 '
 
 test_expect_success '-U0 is valid, so is diff.context=0' '
-- 
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


Re: [PATCH v2 1/2] config.c: mark error and warnings strings for translation

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

 From: Matthieu Moy matthieu@imag.fr

 Signed-off-by: Matthieu Moy matthieu@imag.fr
 ---
 v2: error messages now start with a small letter.

Thanks. Ack on both patches.

Is there any reason not to include these two patches in the larger
series? (There's a semantic dependency on the changed error message and
test)

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


[PATCH] git-push: fix link in man page

2014-07-31 Thread Tony Finch
Signed-off-by: Tony Finch d...@dotat.at
---
 Documentation/git-push.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 21cd455..c0d7403 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -33,7 +33,7 @@ When the command line does not specify what to push with 
`refspec...`
 arguments or `--all`, `--mirror`, `--tags` options, the command finds
 the default `refspec` by consulting `remote.*.push` configuration,
 and if it is not found, honors `push.default` configuration to decide
-what to push (See gitlink:git-config[1] for the meaning of `push.default`).
+what to push (See linkgit:git-config[1] for the meaning of `push.default`).


 OPTIONS[[OPTIONS]]
-- 
2.1.0.rc0.229.gaee38de

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


Re: [PATCH 2/2] add variable name to `git_config_*()` error message

2014-07-31 Thread Tanay Abhra
Junio, drop (2/2) of this series, it has conflicts with ta/config-set in pu.
This patch can easily come later. Sorry for the inconvenience.

Patch 1/2 is OK.

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


[PATCH v6 1/7] config.c: fix accuracy of line number in errors

2014-07-31 Thread Tanay Abhra
From: Matthieu Moy matthieu@grenoble-inp.fr

If a callback returns a negative value to `git_config*()` family,
they call `die()` while printing the line number and the file name.
Currently the printed line number is off by one, thus printing the
wrong line number.

Make `linenr` point to the line we just parsed during the call
to callback to get accurate line number in error messages.

Commit-message-by: Tanay Abhra tanay...@gmail.com
Signed-off-by: Tanay Abhra tanay...@gmail.com
---
 config.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/config.c b/config.c
index a191328..ed5fc8e 100644
--- a/config.c
+++ b/config.c
@@ -244,6 +244,7 @@ static int get_next_char(void)
cf-linenr++;
if (c == EOF) {
cf-eof = 1;
+   cf-linenr++;
c = '\n';
}
return c;
@@ -319,6 +320,7 @@ static int get_value(config_fn_t fn, void *data, struct 
strbuf *name)
 {
int c;
char *value;
+   int ret;
 
/* Get the full name */
for (;;) {
@@ -341,7 +343,15 @@ static int get_value(config_fn_t fn, void *data, struct 
strbuf *name)
if (!value)
return -1;
}
-   return fn(name-buf, value, data);
+   /*
+* We already consumed the \n, but we need linenr to point to
+* the line we just parsed during the call to fn to get
+* accurate line number in error messages.
+*/
+   cf-linenr--;
+   ret = fn(name-buf, value, data);
+   cf-linenr++;
+   return ret;
 }
 
 static int get_extended_base_var(struct strbuf *name, int 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 v6 0/7] Rewrite `git_config()` using config-set API

2014-07-31 Thread Tanay Abhra
[Patch v6]: Added _() to error messages.
Diff between v6 and v4 at the bottom.

[PATCH v5]: New patch added (3/7). git_config() now returns void.

[PATCH v4]: One style nit corrected, also added key to error messages.

[PATCH V3]:All the suggestions in [3] applied. Built on top of [1].

[PATCH V2]: All the suggestions in [2] incorporated. git_config() now follows
correct parsing order. Reordered the patches. Removed xfuncname patch
as it was unnecssary.

This series builds on the top of topic[1] in the mailing list with name
git config cache  special querying API utilizing the cache.

This series aims to do these three things,

* Use the config-set API to rewrite git_config().

* Solve any legacy bugs in the previous system while at it.

* To be feature complete compared to the previous git_config() implementation,
  which I think it is now. (added the line number and file name info just for
  completeness)

Also, I haven't yet checked the exact improvements but still as a teaser,
git status now only rereads the configuration files twice instead of four
times.

[1]: http://thread.gmane.org/gmane.comp.version-control.git/254286
[2]: http://thread.gmane.org/gmane.comp.version-control.git/254101
[3]: http://thread.gmane.org/gmane.comp.version-control.git/254211

Tanay Abhra (7):
  config.c: fix accuracy of line number in errors
  add line number and file name info to `config_set`
  change `git_config()` return value to void
  rewrite git_config() to use the config-set API
  add a test for semantic errors in config files
  config: add `git_die_config()` to the config-set API
  add tests for `git_config_get_string_const()`

 Documentation/technical/api-config.txt |   5 ++
 branch.c   |   5 +-
 cache.h|  27 ++-
 config.c   | 131 +
 t/t1308-config-set.sh  |  21 ++
 t/t4055-diff-context.sh|   2 +-
 test-config.c  |  10 +++
 7 files changed, 181 insertions(+), 20 deletions(-)

-- 
1.9.0.GIT

-- 8 --
diff --git a/branch.c b/branch.c
index 46e8aa8..735767d 100644
--- a/branch.c
+++ b/branch.c
@@ -161,10 +161,7 @@ int read_branch_desc(struct strbuf *buf, const char 
*branch_name)
strbuf_addf(name, branch.%s.description, branch_name);
cb.config_name = name.buf;
cb.value = NULL;
-   if (git_config(read_branch_desc_cb, cb)  0) {
-   strbuf_release(name);
-   return -1;
-   }
+   git_config(read_branch_desc_cb, cb);
if (cb.value)
strbuf_addstr(buf, cb.value);
strbuf_release(name);
diff --git a/cache.h b/cache.h
index 8512225..243f618 100644
--- a/cache.h
+++ b/cache.h
@@ -1295,7 +1295,7 @@ extern int git_config_from_buf(config_fn_t fn, const char 
*name,
   const char *buf, size_t len, void *data);
 extern void git_config_push_parameter(const char *text);
 extern int git_config_from_parameters(config_fn_t fn, void *data);
-extern int git_config(config_fn_t fn, void *);
+extern void git_config(config_fn_t fn, void *);
 extern int git_config_with_options(config_fn_t fn, void *,
   struct git_config_source *config_source,
   int respect_includes);
diff --git a/config.c b/config.c
index f9bf60a..15fcd91 100644
--- a/config.c
+++ b/config.c
@@ -1229,12 +1229,24 @@ struct key_value_info {
int linenr;
 };
 
-static int git_config_raw(config_fn_t fn, void *data)
+static void git_config_raw(config_fn_t fn, void *data)
 {
-   return git_config_with_options(fn, data, NULL, 1);
+   if (git_config_with_options(fn, data, NULL, 1)  0)
+   /*
+* git_config_with_options() normally returns only
+* positive values, as most errors are fatal, and
+* non-fatal potential errors are guarded by if
+* statements that are entered only when no error is
+* possible.
+*
+* If we ever encounter a non-fatal error, it means
+* something went really wrong and we should stop
+* immediately.
+*/
+   die(_(unknown error occured while reading the configuration 
files));
 }
 
-static int configset_iter(struct config_set *cs, config_fn_t fn, void *data)
+static void configset_iter(struct config_set *cs, config_fn_t fn, void *data)
 {
int i, value_index;
struct string_list *values;
@@ -1249,23 +1261,22 @@ static int configset_iter(struct config_set *cs, 
config_fn_t fn, void *data)
if (fn(entry-key, values-items[value_index].string, data)  
0) {
kv_info = values-items[value_index].util;
if (!kv_info-linenr)
-   die(unable to parse '%s' from command-line 
config, 

[PATCH v6 5/7] add a test for semantic errors in config files

2014-07-31 Thread Tanay Abhra
Semantic errors (for example, for alias.* variables NULL values are
not allowed) in configuration files cause a die printing the line
number and file name of the offending value.

Add a test documenting that such errors cause a die printing the
accurate line number and file name.

Signed-off-by: Tanay Abhra tanay...@gmail.com
---
 t/t1308-config-set.sh | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index 7fdf840..e2f9d0b 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -197,4 +197,15 @@ test_expect_success 'proper error on error in custom 
config files' '
test_cmp expect actual
 '
 
+test_expect_success 'check line errors for malformed values' '
+   mv .git/config .git/config.old 
+   test_when_finished mv .git/config.old .git/config 
+   cat .git/config -\EOF 
+   [alias]
+   br
+   EOF
+   test_expect_code 128 git br 2result 
+   grep fatal: bad config variable '\''alias.br'\'' at file line 2 in 
.git/config result
+'
+
 test_done
-- 
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 v6 2/7] add line number and file name info to `config_set`

2014-07-31 Thread Tanay Abhra
Store file name and line number for each key-value pair in the cache
during parsing of the configuration files.

Signed-off-by: Tanay Abhra tanay...@gmail.com
---
 config.c | 21 +++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/config.c b/config.c
index ed5fc8e..4a15383 100644
--- a/config.c
+++ b/config.c
@@ -1230,6 +1230,11 @@ int git_config_with_options(config_fn_t fn, void *data,
return ret;
 }
 
+struct key_value_info {
+   const char *filename;
+   int linenr;
+};
+
 int git_config(config_fn_t fn, void *data)
 {
return git_config_with_options(fn, data, NULL, 1);
@@ -1260,6 +1265,9 @@ static struct config_set_element 
*configset_find_element(struct config_set *cs,
 static int configset_add_value(struct config_set *cs, const char *key, const 
char *value)
 {
struct config_set_element *e;
+   struct string_list_item *si;
+   struct key_value_info *kv_info = xmalloc(sizeof(*kv_info));
+
e = configset_find_element(cs, key);
/*
 * Since the keys are being fed by git_config*() callback mechanism, 
they
@@ -1272,7 +1280,16 @@ static int configset_add_value(struct config_set *cs, 
const char *key, const cha
string_list_init(e-value_list, 1);
hashmap_add(cs-config_hash, e);
}
-   string_list_append_nodup(e-value_list, value ? xstrdup(value) : NULL);
+   si = string_list_append_nodup(e-value_list, value ? xstrdup(value) : 
NULL);
+   if (cf) {
+   kv_info-filename = strintern(cf-name);
+   kv_info-linenr = cf-linenr;
+   } else {
+   /* for values read from `git_config_from_parameters()` */
+   kv_info-filename = strintern(parameter);
+   kv_info-linenr = 0;
+   }
+   si-util = kv_info;
 
return 0;
 }
@@ -1299,7 +1316,7 @@ void git_configset_clear(struct config_set *cs)
hashmap_iter_init(cs-config_hash, iter);
while ((entry = hashmap_iter_next(iter))) {
free(entry-key);
-   string_list_clear(entry-value_list, 0);
+   string_list_clear(entry-value_list, 1);
}
hashmap_free(cs-config_hash, 1);
cs-hash_initialized = 0;
-- 
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 v6 7/7] add tests for `git_config_get_string_const()`

2014-07-31 Thread Tanay Abhra
Add tests for `git_config_get_string_const()`, check whether it
dies printing the line number and the file name if a NULL
value is retrieved for the given key.

Signed-off-by: Tanay Abhra tanay...@gmail.com
---
 t/t1308-config-set.sh | 10 ++
 test-config.c | 10 ++
 2 files changed, 20 insertions(+)

diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index e2f9d0b..f012dd6 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -119,6 +119,16 @@ test_expect_success 'find integer value for a key' '
check_config get_int lamb.chop 65
 '
 
+test_expect_success 'find string value for a key' '
+   check_config get_string case.baz hask 
+   check_config expect_code 1 get_string case.ba Value not found for 
\case.ba\
+'
+
+test_expect_success 'check line error when NULL string is queried' '
+   test_expect_code 128 test-config get_string case.foo 2result 
+   grep fatal: bad config variable '\''case.foo'\'' at file line 7 in 
.git/config result
+'
+
 test_expect_success 'find integer if value is non parse-able' '
check_config expect_code 128 get_int lamb.head
 '
diff --git a/test-config.c b/test-config.c
index 9dd1b22..6a77552 100644
--- a/test-config.c
+++ b/test-config.c
@@ -16,6 +16,8 @@
  *
  * get_bool - print bool value for the entered key or die
  *
+ * get_string - print string value for the entered key or die
+ *
  * configset_get_value - returns value with the highest priority for the 
entered key
  * from a config_set constructed from files entered as 
arguments.
  *
@@ -84,6 +86,14 @@ int main(int argc, char **argv)
printf(Value not found for \%s\\n, argv[2]);
goto exit1;
}
+   } else if (argc == 3  !strcmp(argv[1], get_string)) {
+   if (!git_config_get_string_const(argv[2], v)) {
+   printf(%s\n, v);
+   goto exit0;
+   } else {
+   printf(Value not found for \%s\\n, argv[2]);
+   goto exit1;
+   }
} else if (!strcmp(argv[1], configset_get_value)) {
for (i = 3; i  argc; i++) {
int err;
-- 
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 v6 6/7] config: add `git_die_config()` to the config-set API

2014-07-31 Thread Tanay Abhra
Add `git_die_config` that dies printing the line number and the file name
of the highest priority value for the configuration variable `key`.

It has usage in non-callback based config value retrieval where we can
raise an error and die if there is a semantic error.
For example,

if (!git_config_get_value(key, value)) {
/* NULL values not allowed */
if (!value)
git_config_die(key);
else
/* do work */
}

Signed-off-by: Tanay Abhra tanay...@gmail.com
---
 Documentation/technical/api-config.txt |  5 +
 cache.h|  1 +
 config.c   | 27 +--
 3 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/Documentation/technical/api-config.txt 
b/Documentation/technical/api-config.txt
index 815c1ee..e7ec7cc 100644
--- a/Documentation/technical/api-config.txt
+++ b/Documentation/technical/api-config.txt
@@ -155,6 +155,11 @@ as well as retrieval for the queried variable, including:
Similar to `git_config_get_string`, but expands `~` or `~user` into
the user's home directory when found at the beginning of the path.
 
+`void git_die_config(const char *key)`::
+
+   Dies printing the line number and the file name of the highest
+   priority value for the configuration variable `key`.
+
 See test-config.c for usage examples.
 
 Value Parsing Helpers
diff --git a/cache.h b/cache.h
index 4d3c6bd..243f618 100644
--- a/cache.h
+++ b/cache.h
@@ -1406,6 +1406,7 @@ extern int git_config_get_bool(const char *key, int 
*dest);
 extern int git_config_get_bool_or_int(const char *key, int *is_bool, int 
*dest);
 extern int git_config_get_maybe_bool(const char *key, int *dest);
 extern int git_config_get_pathname(const char *key, const char **dest);
+extern void git_die_config(const char *key);
 
 extern int committer_ident_sufficiently_given(void);
 extern int author_ident_sufficiently_given(void);
diff --git a/config.c b/config.c
index 6b4dd65..15fcd91 100644
--- a/config.c
+++ b/config.c
@@ -1515,8 +1515,12 @@ const struct string_list 
*git_config_get_value_multi(const char *key)
 
 int git_config_get_string_const(const char *key, const char **dest)
 {
+   int ret;
git_config_check_init();
-   return git_configset_get_string_const(the_config_set, key, dest);
+   ret = git_configset_get_string_const(the_config_set, key, dest);
+   if (ret  0)
+   git_die_config(key);
+   return ret;
 }
 
 int git_config_get_string(const char *key, char **dest)
@@ -1557,10 +1561,29 @@ int git_config_get_maybe_bool(const char *key, int 
*dest)
 
 int git_config_get_pathname(const char *key, const char **dest)
 {
+   int ret;
git_config_check_init();
-   return git_configset_get_pathname(the_config_set, key, dest);
+   ret = git_configset_get_pathname(the_config_set, key, dest);
+   if (ret  0)
+   git_die_config(key);
+   return ret;
 }
 
+void git_die_config(const char *key)
+{
+   const struct string_list *values;
+   struct key_value_info *kv_info;
+   values = git_config_get_value_multi(key);
+   kv_info = values-items[values-nr - 1].util;
+   if (!kv_info-linenr)
+   die(_(unable to parse '%s' from command-line config), key);
+   else
+   die(_(bad config variable '%s' at file line %d in %s),
+   key,
+   kv_info-linenr,
+   kv_info-filename);
+ }
+
 /*
  * Find all the stuff for git_config_set() below.
  */
-- 
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 v6 4/7] rewrite git_config() to use the config-set API

2014-07-31 Thread Tanay Abhra
Of all the functions in `git_config*()` family, `git_config()` has the
most invocations in the whole code base. Each `git_config()` invocation
causes config file rereads which can be avoided using the config-set API.

Use the config-set API to rewrite `git_config()` to use the config caching
layer to avoid config file rereads on each invocation during a git process
lifetime. First invocation constructs the cache, and after that for each
successive invocation, `git_config()` feeds values from the config cache
instead of rereading the configuration files.

Signed-off-by: Tanay Abhra tanay...@gmail.com
---
 cache.h | 24 +
 config.c| 57 ++---
 t/t4055-diff-context.sh |  2 +-
 3 files changed, 74 insertions(+), 9 deletions(-)

diff --git a/cache.h b/cache.h
index c61919d..4d3c6bd 100644
--- a/cache.h
+++ b/cache.h
@@ -8,6 +8,7 @@
 #include gettext.h
 #include convert.h
 #include trace.h
+#include string-list.h
 
 #include SHA1_HEADER
 #ifndef git_SHA_CTX
@@ -1351,9 +1352,32 @@ extern int parse_config_key(const char *var,
const char **subsection, int *subsection_len,
const char **key);
 
+struct config_set_element {
+   struct hashmap_entry ent;
+   char *key;
+   struct string_list value_list;
+};
+
+struct configset_list_item {
+   struct config_set_element *e;
+   int value_index;
+};
+
+/*
+ * the contents of the list are ordered according to their
+ * position in the config files and order of parsing the files.
+ * (i.e. key-value pair at the last position of .git/config will
+ * be at the last item of the list)
+ */
+struct configset_list {
+   struct configset_list_item *items;
+   unsigned int nr, alloc;
+};
+
 struct config_set {
struct hashmap config_hash;
int hash_initialized;
+   struct configset_list list;
 };
 
 extern void git_configset_init(struct config_set *cs);
diff --git a/config.c b/config.c
index ecbe14f..6b4dd65 100644
--- a/config.c
+++ b/config.c
@@ -35,12 +35,6 @@ struct config_source {
long (*do_ftell)(struct config_source *c);
 };
 
-struct config_set_element {
-   struct hashmap_entry ent;
-   char *key;
-   struct string_list value_list;
-};
-
 static struct config_source *cf;
 
 static int zlib_compression_seen;
@@ -1235,7 +1229,7 @@ struct key_value_info {
int linenr;
 };
 
-void git_config(config_fn_t fn, void *data)
+static void git_config_raw(config_fn_t fn, void *data)
 {
if (git_config_with_options(fn, data, NULL, 1)  0)
/*
@@ -1252,6 +1246,39 @@ void git_config(config_fn_t fn, void *data)
die(_(unknown error occured while reading the configuration 
files));
 }
 
+static void configset_iter(struct config_set *cs, config_fn_t fn, void *data)
+{
+   int i, value_index;
+   struct string_list *values;
+   struct config_set_element *entry;
+   struct configset_list *list = cs-list;
+   struct key_value_info *kv_info;
+
+   for (i = 0; i  list-nr; i++) {
+   entry = list-items[i].e;
+   value_index = list-items[i].value_index;
+   values = entry-value_list;
+   if (fn(entry-key, values-items[value_index].string, data)  
0) {
+   kv_info = values-items[value_index].util;
+   if (!kv_info-linenr)
+   die(_(unable to parse '%s' from command-line 
config), entry-key);
+   else
+   die(_(bad config variable '%s' at file line %d 
in %s),
+   entry-key,
+   kv_info-linenr,
+   kv_info-filename);
+   }
+   }
+}
+
+static void git_config_check_init(void);
+
+void git_config(config_fn_t fn, void *data)
+{
+   git_config_check_init();
+   configset_iter(the_config_set, fn, data);
+}
+
 static struct config_set_element *configset_find_element(struct config_set 
*cs, const char *key)
 {
struct config_set_element k;
@@ -1278,6 +1305,7 @@ static int configset_add_value(struct config_set *cs, 
const char *key, const cha
 {
struct config_set_element *e;
struct string_list_item *si;
+   struct configset_list_item *l_item;
struct key_value_info *kv_info = xmalloc(sizeof(*kv_info));
 
e = configset_find_element(cs, key);
@@ -1293,6 +1321,12 @@ static int configset_add_value(struct config_set *cs, 
const char *key, const cha
hashmap_add(cs-config_hash, e);
}
si = string_list_append_nodup(e-value_list, value ? xstrdup(value) : 
NULL);
+
+   ALLOC_GROW(cs-list.items, cs-list.nr + 1, cs-list.alloc);
+   l_item = cs-list.items[cs-list.nr++];
+   l_item-e = e;
+   l_item-value_index = e-value_list.nr - 1;
+
if (cf) {
  

[PATCH v6 3/7] change `git_config()` return value to void

2014-07-31 Thread Tanay Abhra
Currently `git_config()` returns an integer signifying an error code.
During rewrites of the function most of the code was shifted to
`git_config_with_options()`. `git_config_with_options()` normally
returns positive values if its `config_source` parameter is set as NULL,
as most errors are fatal, and non-fatal potential errors are guarded
by if statements that are entered only when no error is possible.

Still a negative value can be returned in case of race condition between
`access_or_die()`  `git_config_from_file()`. Also, all callers of
`git_config()` ignore the return value except for one case in branch.c.

Change `git_config()` return value to void and make it die if it receives
a negative value from `git_config_with_options()`.

Original-patch-by: Matthieu Moy matthieu@imag.fr
Signed-off-by: Tanay Abhra tanay...@gmail.com
---
 branch.c |  5 +
 cache.h  |  2 +-
 config.c | 16 ++--
 3 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/branch.c b/branch.c
index 46e8aa8..735767d 100644
--- a/branch.c
+++ b/branch.c
@@ -161,10 +161,7 @@ int read_branch_desc(struct strbuf *buf, const char 
*branch_name)
strbuf_addf(name, branch.%s.description, branch_name);
cb.config_name = name.buf;
cb.value = NULL;
-   if (git_config(read_branch_desc_cb, cb)  0) {
-   strbuf_release(name);
-   return -1;
-   }
+   git_config(read_branch_desc_cb, cb);
if (cb.value)
strbuf_addstr(buf, cb.value);
strbuf_release(name);
diff --git a/cache.h b/cache.h
index 7292aef..c61919d 100644
--- a/cache.h
+++ b/cache.h
@@ -1294,7 +1294,7 @@ extern int git_config_from_buf(config_fn_t fn, const char 
*name,
   const char *buf, size_t len, void *data);
 extern void git_config_push_parameter(const char *text);
 extern int git_config_from_parameters(config_fn_t fn, void *data);
-extern int git_config(config_fn_t fn, void *);
+extern void git_config(config_fn_t fn, void *);
 extern int git_config_with_options(config_fn_t fn, void *,
   struct git_config_source *config_source,
   int respect_includes);
diff --git a/config.c b/config.c
index 4a15383..ecbe14f 100644
--- a/config.c
+++ b/config.c
@@ -1235,9 +1235,21 @@ struct key_value_info {
int linenr;
 };
 
-int git_config(config_fn_t fn, void *data)
+void git_config(config_fn_t fn, void *data)
 {
-   return git_config_with_options(fn, data, NULL, 1);
+   if (git_config_with_options(fn, data, NULL, 1)  0)
+   /*
+* git_config_with_options() normally returns only
+* positive values, as most errors are fatal, and
+* non-fatal potential errors are guarded by if
+* statements that are entered only when no error is
+* possible.
+*
+* If we ever encounter a non-fatal error, it means
+* something went really wrong and we should stop
+* immediately.
+*/
+   die(_(unknown error occured while reading the configuration 
files));
 }
 
 static struct config_set_element *configset_find_element(struct config_set 
*cs, const char *key)
-- 
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


Re: [PATCH v6 6/7] config: add `git_die_config()` to the config-set API

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

 +void git_die_config(const char *key)
 +{
 + const struct string_list *values;
 + struct key_value_info *kv_info;
 + values = git_config_get_value_multi(key);
 + kv_info = values-items[values-nr - 1].util;
 + if (!kv_info-linenr)
 + die(_(unable to parse '%s' from command-line config), key);
 + else
 + die(_(bad config variable '%s' at file line %d in %s),
 + key,
 + kv_info-linenr,
 + kv_info-filename);
 + }

Extra whitespace before }.

Also, didn't we agree that it was a good thing to factor this
if/then/else into a helper function?

-- 
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 v6 0/7] Rewrite `git_config()` using config-set API

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

 [Patch v6]: Added _() to error messages.
   Diff between v6 and v4 at the bottom.

Except for the tiny style issue in PATCH 6, the series is now

Reviewed-by: Matthieu Moy matthieu@imag.fr

-- 
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 v6 6/7] config: add `git_die_config()` to the config-set API

2014-07-31 Thread Tanay Abhra


On 7/31/2014 9:25 PM, Matthieu Moy wrote:
 Tanay Abhra tanay...@gmail.com writes:
 
 +void git_die_config(const char *key)
 +{
 +const struct string_list *values;
 +struct key_value_info *kv_info;
 +values = git_config_get_value_multi(key);
 +kv_info = values-items[values-nr - 1].util;
 +if (!kv_info-linenr)
 +die(_(unable to parse '%s' from command-line config), key);
 +else
 +die(_(bad config variable '%s' at file line %d in %s),
 +key,
 +kv_info-linenr,
 +kv_info-filename);
 + }
 
 Extra whitespace before }.
 
 Also, didn't we agree that it was a good thing to factor this
 if/then/else into a helper function?
 

I have been thinking about it, wouldn't it be better to give users
a function like,

git_config_die_exact(key, value);

where user supplies key  value both and it would print the correct message 
based
on that. git_die_config() will be a wrapper over it, supplying the last value.
It will also replace the redundant code in git_config_raw() and help in the
multi value case. If the idea sounds okay, I will send a reroll.
--
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 v6 6/7] config: add `git_die_config()` to the config-set API

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

 On 7/31/2014 9:25 PM, Matthieu Moy wrote:
 Tanay Abhra tanay...@gmail.com writes:
 
 +void git_die_config(const char *key)
 +{
 +   const struct string_list *values;
 +   struct key_value_info *kv_info;
 +   values = git_config_get_value_multi(key);
 +   kv_info = values-items[values-nr - 1].util;
 +   if (!kv_info-linenr)
 +   die(_(unable to parse '%s' from command-line config), key);
 +   else
 +   die(_(bad config variable '%s' at file line %d in %s),
 +   key,
 +   kv_info-linenr,
 +   kv_info-filename);
 + }
 
 Extra whitespace before }.
 
 Also, didn't we agree that it was a good thing to factor this
 if/then/else into a helper function?
 

 I have been thinking about it, wouldn't it be better to give users
 a function like,

 git_config_die_exact(key, value);

 where user supplies key  value both and it would print the correct message 
 based
 on that.

I suggested git_config_die_linenr(key, linenr), and I now realize it
should take the value too.

You're suggesting git_config_die_exact(key, value). Is it a typo that
you forgot the line number, or is it intentional? If intentional, I
don't think it solves your issue:

[section]
   key
   key

There are two errors in this file, and you need to provide a line
number. key and value alone do not allow you to know which line the
error is. You can use a convention like complain on the first value
equal to the argument, but I'm not sure that would always work. And
that seems backward to me to reconstruct the line number since the
function can be called from places where the line number is already
known (while iterating over the string_list for example).

-- 
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: stash-p broken?

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

 Hmph. To be honest, I am starting to wonder if implying --first-parent
 is a more sensible option for stash list. It matches stash show, at
 least, and it is not unreasonable to simply present the changes in the
 working tree by default, and ignore the index. People who are more
 clueful can pick apart the commits using git log themselves.

Yup, I tend to agree.

After thinking about this a lot, I really wish that we did not have
stash apply and stash pop, but just stash save and a single
stash restore that either checks out the original branch (if its
head have not moved) or detaches the HEAD at the original commit
(otherwise), and then restores the state of the index and the
working tree (with or without untracked) and nothing else, but the
details are too long to fit in this topic ;-)

--
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 0/5] nd/multiple-work-trees follow-ups

2014-07-31 Thread Junio C Hamano
Duy Nguyen pclo...@gmail.com writes:

 On Thu, Jul 31, 2014 at 12:51 AM, Junio C Hamano gits...@pobox.com wrote:
 Nguyễn Thái Ngọc Duy pclo...@gmail.com writes:

 The series has entered 'next' so I can't replace patches any more.
 Besides the brown paper bag fixes, checkout now rejects if a branch is
 already checked out elsewhere.

 I do not think we would want to rush the entire series to 'master'
 before the upcoming release, so we could squash these fixes into the
 original when we rewind 'next' post release, if you wanted to.

 Great. Please remove it from next at the next rewind.

I'd likely forget so please remind me when the time comes ;-)  In
the meantime, I made a note in the What's cooking report to hold
the topic in 'next' and not advance it to 'master'.
--
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 v3 1/6] alias.c: replace `git_config()` with `git_config_get_string()`

2014-07-31 Thread Samuel Bronson
Ramsay Jones ram...@ramsay1.demon.co.uk writes:
 On 21/07/14 12:12, Tanay Abhra wrote:
 -char *alias_lookup(const char *alias)
 +char *alias_lookup(const char* alias)

 No, this is not C++. :-D

Why would C++ make a difference?  Shouldn't you *never* do that?

-- 
Hi! I'm a .signature virus! Copy me into your ~/.signature to help me spread!
--
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 v6 6/7] config: add `git_die_config()` to the config-set API

2014-07-31 Thread Tanay Abhra


On 7/31/2014 10:22 PM, Matthieu Moy wrote:
 Tanay Abhra tanay...@gmail.com writes:
 
 On 7/31/2014 9:25 PM, Matthieu Moy wrote:
 Tanay Abhra tanay...@gmail.com writes:

 +void git_die_config(const char *key)
 +{
 +  const struct string_list *values;
 +  struct key_value_info *kv_info;
 +  values = git_config_get_value_multi(key);
 +  kv_info = values-items[values-nr - 1].util;
 +  if (!kv_info-linenr)
 +  die(_(unable to parse '%s' from command-line config), key);
 +  else
 +  die(_(bad config variable '%s' at file line %d in %s),
 +  key,
 +  kv_info-linenr,
 +  kv_info-filename);
 + }

 Extra whitespace before }.

 Also, didn't we agree that it was a good thing to factor this
 if/then/else into a helper function?


 I have been thinking about it, wouldn't it be better to give users
 a function like,

 git_config_die_exact(key, value);

 where user supplies key  value both and it would print the correct message 
 based
 on that.
 
 I suggested git_config_die_linenr(key, linenr), and I now realize it
 should take the value too.
 
 You're suggesting git_config_die_exact(key, value). Is it a typo that
 you forgot the line number, or is it intentional? If intentional, I
 don't think it solves your issue:
 
 [section]
key
key

 There are two errors in this file, and you need to provide a line
 number. key and value alone do not allow you to know which line the
 error is. You can use a convention like complain on the first value
 equal to the argument, but I'm not sure that would always work. And
 that seems backward to me to reconstruct the line number since the
 function can be called from places where the line number is already
 known (while iterating over the string_list for example).

Still the user would have to know that the linenr info is there.
First hear my argument, then we can go either way.

Let's first see the previous code behavior, git_config() would die on the
first corrupt value, we wouldn't live to see the future value.

for example,

[section]
key // error(old git_config() would die here)
key = good_value

[section]
key //again error

Now for the new behavior,

single valued callers use git_config_get_value() which will directly
supply the last value, so we don't see the first error value.
For such cases, git_die_config(key) is enough.

The new git_config() works exactly as the old code, it would die
on the first case of erroneous value. Here, git_die_config_exact(key, value)
would be enough.

The last case is git_config_get_value_multi(), here we iterate over the keys,
and then call git_die_config_exact(key, value) for the erroneous value.
(pros and cons: abstracts the error message implementation from the user
but there is an extra call to git_config_get_value_multi(), but its cheap and
we are dying anyway)

+   if (load_config_refs) {
+   values = git_config_get_value_multi(notes.displayref);
+   if (values) {
+   for (i = 0; i  values-nr; i++) {
+   if (!values-items[i].string) {
+   
config_error_nonbool(notes.displayref);
+   
git_die_config_exact(notes.displayref, values-items[i].string);
+   }
+   else
+   
string_list_add_refs_by_glob(display_notes_refs,
+
values-items[i].string);
+   }
+   }
+   }

What do you 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


Re: [PATCH v6 6/7] config: add `git_die_config()` to the config-set API

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

 On 7/31/2014 10:22 PM, Matthieu Moy wrote:
 Tanay Abhra tanay...@gmail.com writes:
 
 On 7/31/2014 9:25 PM, Matthieu Moy wrote:
 Tanay Abhra tanay...@gmail.com writes:

 +void git_die_config(const char *key)
 +{
 + const struct string_list *values;
 + struct key_value_info *kv_info;
 + values = git_config_get_value_multi(key);
 + kv_info = values-items[values-nr - 1].util;
 + if (!kv_info-linenr)
 + die(_(unable to parse '%s' from command-line config), key);
 + else
 + die(_(bad config variable '%s' at file line %d in %s),
 + key,
 + kv_info-linenr,
 + kv_info-filename);
 + }

 Extra whitespace before }.

 Also, didn't we agree that it was a good thing to factor this
 if/then/else into a helper function?


 I have been thinking about it, wouldn't it be better to give users
 a function like,

 git_config_die_exact(key, value);

 where user supplies key  value both and it would print the correct message 
 based
 on that.
 
 I suggested git_config_die_linenr(key, linenr), and I now realize it
 should take the value too.
 
 You're suggesting git_config_die_exact(key, value). Is it a typo that
 you forgot the line number, or is it intentional? If intentional, I
 don't think it solves your issue:
 
 [section]
key
key

 There are two errors in this file, and you need to provide a line
 number. key and value alone do not allow you to know which line the
 error is. You can use a convention like complain on the first value
 equal to the argument, but I'm not sure that would always work. And
 that seems backward to me to reconstruct the line number since the
 function can be called from places where the line number is already
 known (while iterating over the string_list for example).

 Still the user would have to know that the linenr info is there.
 First hear my argument, then we can go either way.

 Let's first see the previous code behavior, git_config() would die on the
 first corrupt value, we wouldn't live to see the future value.

 for example,

 [section]
   key // error(old git_config() would die here)
   key = good_value

 [section]
   key //again error

 Now for the new behavior,

 single valued callers use git_config_get_value() which will directly
 supply the last value, so we don't see the first error value.
 For such cases, git_die_config(key) is enough.

Yes. And it is better than the old behavior which was dying on the
erroneous value without giving a chance to the user to override the
boggus value in a more specific config file (e.g. if your sysadmin
messed-up /etc/gitconfig).

But since git_die_config(key) is simpler to use for the caller, it's
independant from git_die_config_exact()'s parameters.

 The new git_config() works exactly as the old code, it would die
 on the first case of erroneous value. Here, git_die_config_exact(key, value)
 would be enough.

Yes. But this callsite has the line number information, so it could use
it.

 The last case is git_config_get_value_multi(), here we iterate over the keys,
 and then call git_die_config_exact(key, value) for the erroneous value.
 (pros and cons: abstracts the error message implementation from the user
 but there is an extra call to git_config_get_value_multi(), but its cheap and
 we are dying anyway)

This is the part I find weird. You're calling git_die_config_exact() on
the first boggus value, and git_die_config_exact() will notify an error
at the line of the last boggus value.

I agree it works (if we give only one error message, it can be the first
or the last, the user doesn't really care), but I find the
implementation backwards. You have the line number already, as you are
iterating over the string_list which contain it. So why forget the line
number, and recompute one, possibly different, right after?

So, I see only cases where you already have the line number, hence no
reason to recompute it.

-- 
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 v6 6/7] config: add `git_die_config()` to the config-set API

2014-07-31 Thread Tanay Abhra


On 7/31/2014 11:39 PM, Matthieu Moy wrote:
 Tanay Abhra tanay...@gmail.com writes:
 
 On 7/31/2014 10:22 PM, Matthieu Moy wrote:
 Tanay Abhra tanay...@gmail.com writes:

 On 7/31/2014 9:25 PM, Matthieu Moy wrote:
 Tanay Abhra tanay...@gmail.com writes:

 +void git_die_config(const char *key)
 +{
 +const struct string_list *values;
 +struct key_value_info *kv_info;
 +values = git_config_get_value_multi(key);
 +kv_info = values-items[values-nr - 1].util;
 +if (!kv_info-linenr)
 +die(_(unable to parse '%s' from command-line config), 
 key);
 +else
 +die(_(bad config variable '%s' at file line %d in %s),
 +key,
 +kv_info-linenr,
 +kv_info-filename);
 + }

 Extra whitespace before }.

 Also, didn't we agree that it was a good thing to factor this
 if/then/else into a helper function?


 I have been thinking about it, wouldn't it be better to give users
 a function like,

 git_config_die_exact(key, value);

 where user supplies key  value both and it would print the correct 
 message based
 on that.

 I suggested git_config_die_linenr(key, linenr), and I now realize it
 should take the value too.

 You're suggesting git_config_die_exact(key, value). Is it a typo that
 you forgot the line number, or is it intentional? If intentional, I
 don't think it solves your issue:

 [section]
key
key

 There are two errors in this file, and you need to provide a line
 number. key and value alone do not allow you to know which line the
 error is. You can use a convention like complain on the first value
 equal to the argument, but I'm not sure that would always work. And
 that seems backward to me to reconstruct the line number since the
 function can be called from places where the line number is already
 known (while iterating over the string_list for example).

 Still the user would have to know that the linenr info is there.
 First hear my argument, then we can go either way.

 Let's first see the previous code behavior, git_config() would die on the
 first corrupt value, we wouldn't live to see the future value.

 for example,

 [section]
  key // error(old git_config() would die here)
  key = good_value

 [section]
  key //again error

 Now for the new behavior,

 single valued callers use git_config_get_value() which will directly
 supply the last value, so we don't see the first error value.
 For such cases, git_die_config(key) is enough.
 
 Yes. And it is better than the old behavior which was dying on the
 erroneous value without giving a chance to the user to override the
 boggus value in a more specific config file (e.g. if your sysadmin
 messed-up /etc/gitconfig).
 
 But since git_die_config(key) is simpler to use for the caller, it's
 independant from git_die_config_exact()'s parameters.
 
 The new git_config() works exactly as the old code, it would die
 on the first case of erroneous value. Here, git_die_config_exact(key, value)
 would be enough.
 
 Yes. But this callsite has the line number information, so it could use
 it.
 
 The last case is git_config_get_value_multi(), here we iterate over the keys,
 and then call git_die_config_exact(key, value) for the erroneous value.
 (pros and cons: abstracts the error message implementation from the user
 but there is an extra call to git_config_get_value_multi(), but its cheap and
 we are dying anyway)
 
 This is the part I find weird. You're calling git_die_config_exact() on
 the first boggus value, and git_die_config_exact() will notify an error
 at the line of the last boggus value.


Hmn, we may have some confusion here. I meant the implementation of
git_config_exact() to look like this,

void git_die_config_exact(const char *key, const char *value)
{
int i;
const struct string_list *values;
struct key_value_info *kv_info;
values = git_config_get_value_multi(key);
for (i = 0; i  values.nr; i++) {
kv_info = values-items[i].util;
/* A null check will be here also */
if (!strcmp(value, values-items[i].string)) {
if (!kv_info-linenr)
die(_(unable to parse '%s' from command-line 
config), key);
else
die(_(bad config variable '%s' at file line %d 
in %s),
key,
kv_info-linenr,
kv_info-filename);
}
}
}

The above code would print the info on first bogus value.
I am only rooting for it because the caller has to think very little to use it.
It's your call, I am open to both ideas.

 I agree it works (if we give only one error message, it can be the first
 or the last, the user doesn't really care), but I find the
 implementation backwards. You have the 

Re: [PATCH v6 6/7] config: add `git_die_config()` to the config-set API

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

 On 7/31/2014 11:39 PM, Matthieu Moy wrote:

 This is the part I find weird. You're calling git_die_config_exact() on
 the first boggus value, and git_die_config_exact() will notify an error
 at the line of the last boggus value.

 Hmn, we may have some confusion here. I meant the implementation of
 git_config_exact() to look like this,

 void git_die_config_exact(const char *key, const char *value)
 {
   int i;
   const struct string_list *values;
   struct key_value_info *kv_info;
   values = git_config_get_value_multi(key);
   for (i = 0; i  values.nr; i++) {
   kv_info = values-items[i].util;
   /* A null check will be here also */
   if (!strcmp(value, values-items[i].string)) {
   if (!kv_info-linenr)
   die(_(unable to parse '%s' from command-line 
 config), key);
   else
   die(_(bad config variable '%s' at file line %d 
 in %s),
   key,
   kv_info-linenr,
   kv_info-filename);
   }
   }
 }

 The above code would print the info on first bogus value.

OK, I got confused because git_die_config() errors out at the first
error. So, your version works, but I do not see any added value in this
extra complexity.

To be cleary, my version would be

NORETURN static /* not sure about the static */
void git_die_config_linenr(const char *key,
   const char *filename, int linenr)
{
if (!linenr)
die(_(unable to parse '%s' from command-line config), key);
else
die(_(bad config variable '%s' at file line %d in %s),
key,
linenr,
filename);
}

(hmm, I actually do not need the value, it's not printed)

NORETURN
void git_die_config(const char *key)
{
const struct string_list *values;
struct key_value_info *kv_info;
values = git_config_get_value_multi(key);
kv_info = values-items[values-nr - 1].util;
git_die_config_linenr(key, kv_info-linenr, kv_info-filename);
}

(we forgot the NORETURN in previous version BTW. It should be there in
both functions here and in the .h file)

In my version, git_die_config uses git_die_config_linenr, and there's no
issue with first/last boggus value. Callers of git_die_config_linenr
have all the information to call it directly.

There are 3 code path that leads to the final die() calls, and having
this little helper allows making sure the messages are the same for
every callers, by construction (as opposed to cut-and-pasting).

Really, I don't see any reason to do anything more complex.

-- 
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 2/2] imap-send: create target mailbox if it is missing

2014-07-31 Thread Junio C Hamano
Tony Finch d...@dotat.at writes:

 Some MUAs delete their drafts folder when it is empty, so
 git imap-send should be able to create it if necessary.

 This change checks that the folder exists immediately after
 login and tries to create it if it is missing.

 There was some vestigial code to handle a [TRYCREATE] response
 from the server when an APPEND target is missing. However this
 code never ran (the create and trycreate flags were never set)
 and when I tried to make it run I found that the code had already
 thrown away the contents of the message it was trying to append.

 Signed-off-by: Tony Finch d...@dotat.at
 ---

The basic idea looks good, but I have doubts on one point.

 diff --git a/imap-send.c b/imap-send.c
 index 524fbab..5e4a24e 100644
 --- a/imap-send.c
 +++ b/imap-send.c
 @@ -1156,6 +1133,25 @@ static struct imap_store *imap_open_store(struct 
 imap_server_conf *srvc)
   credential_approve(cred);
   credential_clear(cred);

 + /* check the target mailbox exists */
 + ctx-name = folder;
 + switch (imap_exec(ctx, NULL, EXAMINE \%s\, ctx-name)) {
 + case RESP_OK:
 + /* ok */
 + break;
 + case RESP_BAD:
 + fprintf(stderr, IMAP error: could not check mailbox\n);
 + goto bail;
 + case RESP_NO:
 + if (imap_exec(ctx, NULL, CREATE \%s\, ctx-name) == 
 RESP_OK) {
 + imap_info(Created missing mailbox\n);
 + } else {
 + fprintf(stderr, IMAP error: could not create missing 
 mailbox\n);
 + goto bail;
 + }
 + break;
 + }

At any and all the existing places that goto bail in the function,
we know we failed to authenticate.  I think they are all sensible
places to call credential_reject().

On the other hand, at this point before you try to check the target
mailbox exists, we have authenticated sucessfully, we know the
credential used was good, and called credential_approve() to mark it
as such.  I do agree that you would want to signal an error to the
caller upon these two failures, but I do not think you want to goto
bail and reject the credential.  The error you observed in the new
codepath is caused by something else, not authentication failure,
and in such a case you do not want to cause the credential helper to
evict the user/pass pair from the keyring, no?

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 2/2] imap-send: create target mailbox if it is missing

2014-07-31 Thread Tony Finch
Junio C Hamano gits...@pobox.com wrote:

 The basic idea looks good, but I have doubts on one point.

Thanks for spotting the mistake in the error handling. I'll send an update
with a fix.

Tony.
-- 
f.anthony.n.finch  d...@dotat.at  http://dotat.at/
South Utsire: Southwesterly 4 or 5, occasionally 6 at first in south, backing
southeasterly later. Moderate. Thundery showers. Good.
--
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


Bug report about symlinks

2014-07-31 Thread Nikolay Avdeev
Greetings from Russia, comrads!

I've noticed something strange with git status when replacing a folder with
symlink to another folder.
There is a git repo with script with demo in the attachment.

Yours sincerely,
NickKolok aka Nikolay Avdeev.

Доброго времени суток, товарищи!

При замене папки на симлинк на другую папку с похожими, но не одинаковыми
файлами git status ведёт себя странно.
Прилагаю архив с репозиторием. В скрипте - пример и пояснения.

С уважением,
Николай Авдеев aka NickKolok.


git-bug-demo.tar.bz2
Description: application/bzip


Re: [PATCH v6 6/7] config: add `git_die_config()` to the config-set API

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

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

 On 7/31/2014 11:39 PM, Matthieu Moy wrote:

 This is the part I find weird. You're calling git_die_config_exact() on
 the first boggus value, and git_die_config_exact() will notify an error
 at the line of the last boggus value.

 Hmn, we may have some confusion here. I meant the implementation of
 git_config_exact() to look like this,

 void git_die_config_exact(const char *key, const char *value)
 {
  int i;
  const struct string_list *values;
  struct key_value_info *kv_info;
  values = git_config_get_value_multi(key);
  for (i = 0; i  values.nr; i++) {
  kv_info = values-items[i].util;
  /* A null check will be here also */
  if (!strcmp(value, values-items[i].string)) {
  if (!kv_info-linenr)
  die(_(unable to parse '%s' from command-line 
 config), key);
  else
  die(_(bad config variable '%s' at file line %d 
 in %s),
  key,
  kv_info-linenr,
  kv_info-filename);
  }
  }
 }

 The above code would print the info on first bogus value.

 OK, I got confused because git_die_config() errors out at the first
 error. So, your version works, but I do not see any added value in this
 extra complexity.

Hmm, I am still confused ;-)

Can there be more than one 'i' whose value-items[i].string is the
same as the given value?  IOW, if you have [user] nameEOL in
both .git/config and ~/.gitconfig, don't we want to make sure that
we complain on the one in .git/config, which would have taken
precedence if it were spelled correctly?

Your version below makes it very clear that you only complain on the
last one, no matter how many identical copies of the value for the
given key are defined incorrectly the same way, which is easier to
understand what is going on.

 To be cleary, my version would be

 NORETURN static /* not sure about the static */
 void git_die_config_linenr(const char *key,
const char *filename, int linenr)
 {
   if (!linenr)
   die(_(unable to parse '%s' from command-line config), key);
   else
   die(_(bad config variable '%s' at file line %d in %s),
   key,
   linenr,
   filename);
 }

 (hmm, I actually do not need the value, it's not printed)

 NORETURN
 void git_die_config(const char *key)
 {
   const struct string_list *values;
   struct key_value_info *kv_info;
   values = git_config_get_value_multi(key);
   kv_info = values-items[values-nr - 1].util;
   git_die_config_linenr(key, kv_info-linenr, kv_info-filename);
 }

 (we forgot the NORETURN in previous version BTW. It should be there in
 both functions here and in the .h file)

 In my version, git_die_config uses git_die_config_linenr, and there's no
 issue with first/last boggus value. Callers of git_die_config_linenr
 have all the information to call it directly.

 There are 3 code path that leads to the final die() calls, and having
 this little helper allows making sure the messages are the same for
 every callers, by construction (as opposed to cut-and-pasting).

 Really, I don't see any reason to do anything more complex.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/5] refs.c: replace the onerr argument in update_ref with a strbuf err

2014-07-31 Thread Ronnie Sahlberg
Signed-off-by: Ronnie Sahlberg sahlb...@google.com
---
 builtin/checkout.c   |  7 +--
 builtin/clone.c  | 23 +++
 builtin/merge.c  | 20 +---
 builtin/notes.c  | 24 ++--
 builtin/reset.c  | 12 
 builtin/update-ref.c |  7 +--
 notes-cache.c|  2 +-
 notes-utils.c|  5 +++--
 refs.c   | 14 +++---
 refs.h   | 10 ++
 transport-helper.c   |  7 ++-
 transport.c  |  9 ++---
 12 files changed, 81 insertions(+), 59 deletions(-)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index 808c58f..a9ec5be 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -580,6 +580,8 @@ static void update_refs_for_switch(const struct 
checkout_opts *opts,
 {
struct strbuf msg = STRBUF_INIT;
const char *old_desc, *reflog_msg;
+   struct strbuf err = STRBUF_INIT;
+
if (opts-new_branch) {
if (opts-new_orphan_branch) {
if (opts-new_branch_log  !log_all_ref_updates) {
@@ -617,8 +619,9 @@ static void update_refs_for_switch(const struct 
checkout_opts *opts,
if (!strcmp(new-name, HEAD)  !new-path  !opts-force_detach) {
/* Nothing to do. */
} else if (opts-force_detach || !new-path) {  /* No longer on any 
branch. */
-   update_ref(msg.buf, HEAD, new-commit-object.sha1, NULL,
-  REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);
+   if (update_ref(msg.buf, HEAD, new-commit-object.sha1, NULL,
+  REF_NODEREF, err))
+   die(%s, err.buf);
if (!opts-quiet) {
if (old-path  advice_detached_head)
detach_advice(new-name);
diff --git a/builtin/clone.c b/builtin/clone.c
index 7737e12..99e23cf 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -521,6 +521,7 @@ static void write_remote_refs(const struct ref *local_refs)
 static void write_followtags(const struct ref *refs, const char *msg)
 {
const struct ref *ref;
+   struct strbuf err = STRBUF_INIT;
for (ref = refs; ref; ref = ref-next) {
if (!starts_with(ref-name, refs/tags/))
continue;
@@ -528,8 +529,9 @@ static void write_followtags(const struct ref *refs, const 
char *msg)
continue;
if (!has_sha1_file(ref-old_sha1))
continue;
-   update_ref(msg, ref-name, ref-old_sha1,
-  NULL, 0, UPDATE_REFS_DIE_ON_ERR);
+   if (update_ref(msg, ref-name, ref-old_sha1,
+  NULL, 0, err))
+   die(%s, err.buf);
}
 }
 
@@ -592,28 +594,33 @@ static void update_remote_refs(const struct ref *refs,
 static void update_head(const struct ref *our, const struct ref *remote,
const char *msg)
 {
+   struct strbuf err = STRBUF_INIT;
+
if (our  starts_with(our-name, refs/heads/)) {
/* Local default branch link */
create_symref(HEAD, our-name, NULL);
if (!option_bare) {
const char *head = skip_prefix(our-name, 
refs/heads/);
-   update_ref(msg, HEAD, our-old_sha1, NULL, 0,
-  UPDATE_REFS_DIE_ON_ERR);
+   if (update_ref(msg, HEAD, our-old_sha1, NULL, 0,
+  err))
+   die(%s, err.buf);
install_branch_config(0, head, option_origin, 
our-name);
}
} else if (our) {
struct commit *c = lookup_commit_reference(our-old_sha1);
/* --branch specifies a non-branch (i.e. tags), detach HEAD */
-   update_ref(msg, HEAD, c-object.sha1,
-  NULL, REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);
+   if (update_ref(msg, HEAD, c-object.sha1,
+  NULL, REF_NODEREF, err))
+   die(%s, err.buf);
} else if (remote) {
/*
 * We know remote HEAD points to a non-branch, or
 * HEAD points to a branch but we don't know which one.
 * Detach HEAD in all these cases.
 */
-   update_ref(msg, HEAD, remote-old_sha1,
-  NULL, REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);
+ if (update_ref(msg, HEAD, remote-old_sha1,
+NULL, REF_NODEREF, err))
+   die(%s, err.buf);
}
 }
 
diff --git a/builtin/merge.c b/builtin/merge.c
index 428ca24..17dda64 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -396,9 +396,11 @@ static void finish(struct commit *head_commit,
printf(_(No merge message -- not updating HEAD\n));
else {
 

[PATCH 0/5] ref-transactions-req-strbuf-err

2014-07-31 Thread Ronnie Sahlberg
List,

This is the next patch series in the ref transaction work.
This patch series is called ref-transactions-req-strbuf-err and builds ontop
of the series called ref-transactions-req-packed-refs which is origin/pu


This patch series mainly adds some nice strbuf arguments to some functions to
pass errors back to callers.
The only thing noteworthy is that we finally get to remove
-enum action_on_err {
-   UPDATE_REFS_MSG_ON_ERR,
-   UPDATE_REFS_DIE_ON_ERR,
-   UPDATE_REFS_QUIET_ON_ERR
-};

aside from that there is little/nothing much interesting in there.


Ronnie Sahlberg (5):
  refs.c: replace the onerr argument in update_ref with a strbuf err
  refs.c: make add_packed_ref return an error instead of calling die
  refs.c: make lock_packed_refs take an err argument
  refs.c: add an err argument to commit_packed_refs
  refs.c: add an err argument to pack_refs

 builtin/checkout.c   |   7 ++-
 builtin/clone.c  |  23 +---
 builtin/merge.c  |  20 ---
 builtin/notes.c  |  24 +
 builtin/pack-refs.c  |   8 ++-
 builtin/reset.c  |  12 +++--
 builtin/update-ref.c |   7 ++-
 notes-cache.c|   2 +-
 notes-utils.c|   5 +-
 refs.c   | 148 +--
 refs.h   |  13 ++---
 transport-helper.c   |   7 ++-
 transport.c  |   9 ++--
 13 files changed, 170 insertions(+), 115 deletions(-)

-- 
2.0.1.523.g70700c9

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


[PATCH 5/5] refs.c: add an err argument to pack_refs

2014-07-31 Thread Ronnie Sahlberg
Signed-off-by: Ronnie Sahlberg sahlb...@google.com
---
 builtin/pack-refs.c |  8 +++-
 refs.c  | 13 ++---
 refs.h  |  3 ++-
 3 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/builtin/pack-refs.c b/builtin/pack-refs.c
index b20b1ec..da5d46a 100644
--- a/builtin/pack-refs.c
+++ b/builtin/pack-refs.c
@@ -10,6 +10,7 @@ static char const * const pack_refs_usage[] = {
 int cmd_pack_refs(int argc, const char **argv, const char *prefix)
 {
unsigned int flags = PACK_REFS_PRUNE;
+   struct strbuf err = STRBUF_INIT;
struct option opts[] = {
OPT_BIT(0, all,   flags, N_(pack everything), 
PACK_REFS_ALL),
OPT_BIT(0, prune, flags, N_(prune loose refs (default)), 
PACK_REFS_PRUNE),
@@ -17,5 +18,10 @@ int cmd_pack_refs(int argc, const char **argv, const char 
*prefix)
};
if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0))
usage_with_options(pack_refs_usage, opts);
-   return pack_refs(flags);
+   if (pack_refs(flags, err)) {
+   error(%s, err.buf);
+   strbuf_release(err);
+   return 1;
+   }
+   return 0;
 }
diff --git a/refs.c b/refs.c
index 19e73f3..5875c29 100644
--- a/refs.c
+++ b/refs.c
@@ -2328,7 +2328,7 @@ static int commit_packed_refs(struct strbuf *err)
strbuf_addf(err, error writing packed-refs. %s,
strerror(errno));
return -1;
-   }
+   }
 
data.fd = packed_ref_cache-lock-fd;
data.err = err;
@@ -2482,24 +2482,23 @@ static void prune_refs(struct ref_to_prune *r)
}
 }
 
-int pack_refs(unsigned int flags)
+int pack_refs(unsigned int flags, struct strbuf *err)
 {
struct pack_refs_cb_data cbdata;
-   struct strbuf err = STRBUF_INIT;
 
memset(cbdata, 0, sizeof(cbdata));
cbdata.flags = flags;
 
-   if (lock_packed_refs(err))
-   die(%s, err.buf);
+   if (lock_packed_refs(err))
+   return -1;
 
cbdata.packed_refs = get_packed_refs(ref_cache);
 
do_for_each_entry_in_dir(get_loose_refs(ref_cache), 0,
 pack_if_possible_fn, cbdata);
 
-   if (commit_packed_refs(err))
-   die(%s, err.buf);
+   if (commit_packed_refs(err))
+   return -1;
 
prune_refs(cbdata.ref_to_prune);
return 0;
diff --git a/refs.h b/refs.h
index dee9a98..1a98e27 100644
--- a/refs.h
+++ b/refs.h
@@ -122,8 +122,9 @@ extern void warn_dangling_symrefs(FILE *fp, const char 
*msg_fmt, const struct st
 /*
  * Write a packed-refs file for the current repository.
  * flags: Combination of the above PACK_REFS_* flags.
+ * Returns 0 on success and fills in err on failure.
  */
-int pack_refs(unsigned int flags);
+int pack_refs(unsigned int flags, struct strbuf *err);
 
 extern int ref_exists(const char *);
 
-- 
2.0.1.523.g70700c9

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


[PATCH 2/5] refs.c: make add_packed_ref return an error instead of calling die

2014-07-31 Thread Ronnie Sahlberg
Change add_packed_ref to return an error instead of calling die().
Update all callers to check the return value of add_packed_ref.

We can also skip checking the refname format since this function is now
static and only called from the transaction code.
If we are updating a ref and the refname is bad then we fail the transaction
already in transaction_update_sha1().
For the ref deletion case the only caveat is that we would not want
to move the badly named ref into the packed refs file during transaction
commit. This again is not a problem since if the name is bad, then
resolve_ref_unsafe() will fail which protects us from calling add_packed_ref()
with the bad name.

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

diff --git a/refs.c b/refs.c
index 65eee72..0aad8c8 100644
--- a/refs.c
+++ b/refs.c
@@ -1135,17 +1135,16 @@ static struct ref_dir *get_packed_refs(struct ref_cache 
*refs)
return get_packed_ref_dir(get_packed_ref_cache(refs));
 }
 
-static void add_packed_ref(const char *refname, const unsigned char *sha1)
+static int add_packed_ref(const char *refname, const unsigned char *sha1)
 {
struct packed_ref_cache *packed_ref_cache =
get_packed_ref_cache(ref_cache);
 
if (!packed_ref_cache-lock)
-   die(internal error: packed refs not locked);
-   if (check_refname_format(refname, 
REFNAME_ALLOW_ONELEVEL|REFNAME_DOT_COMPONENT))
-   die(Reference has invalid format: '%s', refname);
+   return -1;
add_ref(get_packed_ref_dir(packed_ref_cache),
create_ref_entry(refname, sha1, REF_ISPACKED));
+   return 0;
 }
 
 /*
@@ -3666,7 +3665,13 @@ int transaction_commit(struct ref_transaction 
*transaction,
RESOLVE_REF_READING, NULL))
continue;
 
-   add_packed_ref(update-refname, sha1);
+   if (add_packed_ref(update-refname, sha1)) {
+   if (err)
+   strbuf_addf(err, Failed to add %s to packed 
+   refs, update-refname);
+   ret = -1;
+   goto cleanup;
+   }
need_repack = 1;
}
if (need_repack) {
@@ -3778,7 +3783,13 @@ int transaction_commit(struct ref_transaction 
*transaction,
 
packed = get_packed_refs(ref_cache);
remove_entry(packed, update-refname);
-   add_packed_ref(update-refname, update-new_sha1);
+   if (add_packed_ref(update-refname, update-new_sha1)) {
+   if (err)
+   strbuf_addf(err, Failed to add %s to packed 
+   refs, update-refname);
+   ret = -1;
+   goto cleanup;
+   }
need_repack = 1;
 
try_remove_empty_parents((char *)update-refname);
-- 
2.0.1.523.g70700c9

--
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 3/5] refs.c: make lock_packed_refs take an err argument

2014-07-31 Thread Ronnie Sahlberg
Signed-off-by: Ronnie Sahlberg sahlb...@google.com
---
 refs.c | 25 +
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/refs.c b/refs.c
index 0aad8c8..cfe1292 100644
--- a/refs.c
+++ b/refs.c
@@ -2270,13 +2270,17 @@ static int write_packed_entry_fn(struct ref_entry 
*entry, void *cb_data)
return 0;
 }
 
-/* This should return a meaningful errno on failure */
-static int lock_packed_refs(int flags)
+static int lock_packed_refs(struct strbuf *err)
 {
struct packed_ref_cache *packed_ref_cache;
 
-   if (hold_lock_file_for_update(packlock, git_path(packed-refs), 
flags)  0)
+   if (hold_lock_file_for_update(packlock, git_path(packed-refs),
+ 0)  0) {
+   if (err)
+   unable_to_lock_message(git_path(packed-refs),
+  errno, err);
return -1;
+   }
/*
 * Get the current packed-refs while holding the lock.  If the
 * packed-refs file has been modified since we last read it,
@@ -2460,11 +2464,14 @@ static void prune_refs(struct ref_to_prune *r)
 int pack_refs(unsigned int flags)
 {
struct pack_refs_cb_data cbdata;
+   struct strbuf err = STRBUF_INIT;
 
memset(cbdata, 0, sizeof(cbdata));
cbdata.flags = flags;
 
-   lock_packed_refs(LOCK_DIE_ON_ERROR);
+   if (lock_packed_refs(err))
+   die(%s, err.buf);
+
cbdata.packed_refs = get_packed_refs(ref_cache);
 
do_for_each_entry_in_dir(get_loose_refs(ref_cache), 0,
@@ -3626,10 +3633,7 @@ int transaction_commit(struct ref_transaction 
*transaction,
}
 
/* Lock packed refs during commit */
-   if (lock_packed_refs(0)) {
-   if (err)
-   unable_to_lock_message(git_path(packed-refs),
-  errno, err);
+   if (lock_packed_refs(err)) {
ret = -1;
goto cleanup;
}
@@ -3684,10 +3688,7 @@ int transaction_commit(struct ref_transaction 
*transaction,
goto cleanup;
}
/* lock the packed refs again so no one can change it */
-   if (lock_packed_refs(0)) {
-   if (err)
-   unable_to_lock_message(git_path(packed-refs),
-  errno, err);
+   if (lock_packed_refs(err)) {
ret = -1;
goto cleanup;
}
-- 
2.0.1.523.g70700c9

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


[PATCH 4/5] refs.c: add an err argument to commit_packed_refs

2014-07-31 Thread Ronnie Sahlberg
Signed-off-by: Ronnie Sahlberg sahlb...@google.com
---
 refs.c | 85 +++---
 1 file changed, 50 insertions(+), 35 deletions(-)

diff --git a/refs.c b/refs.c
index cfe1292..19e73f3 100644
--- a/refs.c
+++ b/refs.c
@@ -2232,8 +2232,8 @@ static struct ref_lock *lock_ref_sha1_basic(const char 
*refname,
  * Write an entry to the packed-refs file for the specified refname.
  * If peeled is non-NULL, write it as the entry's peeled value.
  */
-static void write_packed_entry(int fd, char *refname, unsigned char *sha1,
-  unsigned char *peeled)
+static int write_packed_entry(int fd, char *refname, unsigned char *sha1,
+ unsigned char *peeled, struct strbuf *err)
 {
char line[PATH_MAX + 100];
int len;
@@ -2241,33 +2241,50 @@ static void write_packed_entry(int fd, char *refname, 
unsigned char *sha1,
len = snprintf(line, sizeof(line), %s %s\n,
   sha1_to_hex(sha1), refname);
/* this should not happen but just being defensive */
-   if (len  sizeof(line))
-   die(too long a refname '%s', refname);
-   write_or_die(fd, line, len);
-
+   if (len  sizeof(line)) {
+   strbuf_addf(err, too long a refname '%s', refname);
+   return -1;
+   }
+   if (write_in_full(fd, line, len) != len) {
+   strbuf_addf(err, error writing to packed-refs. %s,
+   strerror(errno));
+   return -1;
+   }
if (peeled) {
if (snprintf(line, sizeof(line), ^%s\n,
 sha1_to_hex(peeled)) != PEELED_LINE_LENGTH)
die(internal error);
-   write_or_die(fd, line, PEELED_LINE_LENGTH);
+   len = PEELED_LINE_LENGTH;
+   if (write_in_full(fd, line, len) != len) {
+   strbuf_addf(err, error writing to packed-refs. %s,
+   strerror(errno));
+   return -1;
+   }
}
+   return 0;
 }
 
+struct write_packed_data {
+   int fd;
+   struct strbuf *err;
+};
+
 /*
  * An each_ref_entry_fn that writes the entry to a packed-refs file.
  */
 static int write_packed_entry_fn(struct ref_entry *entry, void *cb_data)
 {
-   int *fd = cb_data;
+   struct write_packed_data *data = cb_data;
enum peel_status peel_status = peel_entry(entry, 0);
 
-   if (peel_status != PEEL_PEELED  peel_status != PEEL_NON_TAG)
-   error(internal error: %s is not a valid packed reference!,
- entry-name);
-   write_packed_entry(*fd, entry-name, entry-u.value.sha1,
-  peel_status == PEEL_PEELED ?
-  entry-u.value.peeled : NULL);
-   return 0;
+   if (peel_status != PEEL_PEELED  peel_status != PEEL_NON_TAG) {
+   strbuf_addf(data-err, internal error: %s is not a 
+   valid packed reference!, entry-name);
+   return -1;
+   }
+   return write_packed_entry(data-fd, entry-name, entry-u.value.sha1,
+ peel_status == PEEL_PEELED ?
+ entry-u.value.peeled : NULL, data-err);
 }
 
 static int lock_packed_refs(struct strbuf *err)
@@ -2296,30 +2313,34 @@ static int lock_packed_refs(struct strbuf *err)
 
 /*
  * Commit the packed refs changes.
- * On error we must make sure that errno contains a meaningful value.
  */
-static int commit_packed_refs(void)
+static int commit_packed_refs(struct strbuf *err)
 {
struct packed_ref_cache *packed_ref_cache =
get_packed_ref_cache(ref_cache);
int error = 0;
-   int save_errno = 0;
+   struct write_packed_data data;
 
if (!packed_ref_cache-lock)
die(internal error: packed-refs not locked);
-   write_or_die(packed_ref_cache-lock-fd,
-PACKED_REFS_HEADER, strlen(PACKED_REFS_HEADER));
+   if (write_in_full(packed_ref_cache-lock-fd,
+ PACKED_REFS_HEADER, strlen(PACKED_REFS_HEADER))  0) {
+   strbuf_addf(err, error writing packed-refs. %s,
+   strerror(errno));
+   return -1;
+   }
 
+   data.fd = packed_ref_cache-lock-fd;
+   data.err = err;
do_for_each_entry_in_dir(get_packed_ref_dir(packed_ref_cache),
-0, write_packed_entry_fn,
-packed_ref_cache-lock-fd);
+0, write_packed_entry_fn, data);
if (commit_lock_file(packed_ref_cache-lock)) {
-   save_errno = errno;
+   strbuf_addf(err, unable to overwrite old ref-pack 
+   file. %s, strerror(errno));
error = -1;
}
packed_ref_cache-lock = NULL;

[PATCH 1/5] receive-pack.c: add protocol support to negotiate atomic-push

2014-07-31 Thread Ronnie Sahlberg
Signed-off-by: Ronnie Sahlberg sahlb...@google.com
---
 builtin/receive-pack.c |  6 +-
 send-pack.c| 12 +---
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 0565b94..f6b20cb 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -36,6 +36,7 @@ static int transfer_unpack_limit = -1;
 static int unpack_limit = 100;
 static int report_status;
 static int use_sideband;
+static int use_atomic_push;
 static int quiet;
 static int prefer_ofs_delta = 1;
 static int auto_update_server_info;
@@ -142,7 +143,8 @@ static void show_ref(const char *path, const unsigned char 
*sha1)
else
packet_write(1, %s %s%c%s%s agent=%s\n,
 sha1_to_hex(sha1), path, 0,
- report-status delete-refs side-band-64k quiet,
+ report-status delete-refs side-band-64k quiet
+ atomic-push,
 prefer_ofs_delta ?  ofs-delta : ,
 git_user_agent_sanitized());
sent_capabilities = 1;
@@ -892,6 +894,8 @@ static struct command *read_head_info(struct sha1_array 
*shallow)
use_sideband = LARGE_PACKET_MAX;
if (parse_feature_request(feature_list, quiet))
quiet = 1;
+   if (parse_feature_request(feature_list, atomic-push))
+   use_atomic_push = 1;
}
cmd = xcalloc(1, sizeof(struct command) + len - 80);
hashcpy(cmd-old_sha1, old_sha1);
diff --git a/send-pack.c b/send-pack.c
index 6129b0f..f91b8d9 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -205,6 +205,7 @@ int send_pack(struct send_pack_args *args,
int use_sideband = 0;
int quiet_supported = 0;
int agent_supported = 0;
+   int atomic_push_supported = 0;
unsigned cmds_sent = 0;
int ret;
struct async demux;
@@ -224,6 +225,8 @@ int send_pack(struct send_pack_args *args,
agent_supported = 1;
if (server_supports(no-thin))
args-use_thin_pack = 0;
+   if (server_supports(atomic-push))
+   atomic_push_supported = 1;
 
if (!remote_refs) {
fprintf(stderr, No refs in common and none specified; doing 
nothing.\n
@@ -269,17 +272,20 @@ int send_pack(struct send_pack_args *args,
char *old_hex = sha1_to_hex(ref-old_sha1);
char *new_hex = sha1_to_hex(ref-new_sha1);
int quiet = quiet_supported  (args-quiet || 
!args-progress);
+   int atomic_push = atomic_push_supported;
 
if (!cmds_sent  (status_report || use_sideband ||
-  quiet || agent_supported)) {
+  quiet || agent_supported ||
+  atomic_push)) {
packet_buf_write(req_buf,
-%s %s %s%c%s%s%s%s%s,
+%s %s %s%c%s%s%s%s%s%s,
 old_hex, new_hex, ref-name, 0,
 status_report ?  
report-status : ,
 use_sideband ?  
side-band-64k : ,
 quiet ?  quiet : ,
 agent_supported ?  agent= : 
,
-agent_supported ? 
git_user_agent_sanitized() : 
+agent_supported ? 
git_user_agent_sanitized() : ,
+atomic_push ?  atomic-push : 

);
}
else
-- 
2.0.1.528.gd0e7a84

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


[PATCH 0/5] ref-transactions-send-pack

2014-07-31 Thread Ronnie Sahlberg
List,

This small patch series adds atomic-push support to for pushes.
By default git will use the old style non-atomic updates for pushes,
as not to cause disruption in client scripts that may depend on that
behaviour.

Command line arguments are introduced to allow the client side to request/
negotiate atomic pushes if the remote repo supports it.
There is also a new configuration variable where a repo can set that it
wants all pushes to become atomic whether the client requests it or not.

This patch series is called ref-transactions-send-pack and depends on/is built
ontop of the series called ref-transactions-req-strbuf-err


Ronnie Sahlberg (5):
  receive-pack.c: add protocol support to negotiate atomic-push
  send-pack.c: add an --atomic-push command line argument
  receive-pack.c: use a single transaction when atomic-push is
negotiated
  receive-pack.c: add receive.atomicpush configuration option
  push.c: add an --atomic-push argument

 Documentation/config.txt|  5 
 Documentation/git-push.txt  |  7 -
 Documentation/git-send-pack.txt |  7 -
 builtin/push.c  |  2 ++
 builtin/receive-pack.c  | 66 +
 builtin/send-pack.c |  6 +++-
 send-pack.c | 18 +--
 send-pack.h |  1 +
 transport.c |  1 +
 transport.h |  1 +
 10 files changed, 96 insertions(+), 18 deletions(-)

-- 
2.0.1.528.gd0e7a84

--
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 3/5] receive-pack.c: use a single transaction when atomic-push is negotiated

2014-07-31 Thread Ronnie Sahlberg
Update receive-pack to use an atomic transaction IFF the client negotiated
that it wanted atomic-push.
This leaves the default behaviour to be the old non-atomic one ref at a
time update. This is to cause as little disruption as possible to existing
clients. It is unknown if there are client scripts that depend on the old
non-atomic behaviour so we make it opt-in for now.

Later patch in this series also adds a configuration variable where you can
override the atomic push behaviour on the receiving repo and force it
to use atomic updates always.

If it turns out over time that there are no client scripts that depend on the
old behaviour we can change git to default to use atomic pushes by default
and instead offer an opt-out argument for people that do not want atomic
updates at all.

Signed-off-by: Ronnie Sahlberg sahlb...@google.com
---
 builtin/receive-pack.c | 55 --
 1 file changed, 44 insertions(+), 11 deletions(-)

diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index f6b20cb..47f778d 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -47,6 +47,8 @@ static void *head_name_to_free;
 static int sent_capabilities;
 static int shallow_update;
 static const char *alt_shallow_file;
+struct strbuf err = STRBUF_INIT;
+struct ref_transaction *transaction;
 
 static enum deny_action parse_deny_action(const char *var, const char *value)
 {
@@ -577,26 +579,38 @@ static char *update(struct command *cmd, struct 
shallow_info *si)
return NULL; /* good */
}
else {
-   struct strbuf err = STRBUF_INIT;
-   struct ref_transaction *transaction;
-
if (shallow_update  si-shallow_ref[cmd-index] 
update_shallow_ref(cmd, si))
return xstrdup(shallow error);
-
-   transaction = transaction_begin(err);
-   if (!transaction ||
-   transaction_update_sha1(transaction, namespaced_name,
+   if (!use_atomic_push) {
+   transaction = transaction_begin(err);
+   if (!transaction) {
+   char *str = xstrdup(err.buf);
+
+   strbuf_release(err);
+   transaction_free(transaction);
+   rp_error(%s, str);
+   return str;
+   }
+   }
+   if (transaction_update_sha1(transaction, namespaced_name,
new_sha1, old_sha1, 0, 1, push,
-   err) ||
-   transaction_commit(transaction, err)) {
-   char *str = strbuf_detach(err, NULL);
-   transaction_free(transaction);
+   err)) {
+   char *str = xstrdup(err.buf);
 
+   strbuf_release(err);
+   transaction_free(transaction);
rp_error(%s, str);
return str;
}
+   if (!use_atomic_push  transaction_commit(transaction, err)) {
+   char *str = xstrdup(err.buf);
 
+   strbuf_release(err);
+   transaction_free(transaction);
+   rp_error(%s, str);
+   return str;
+   }
transaction_free(transaction);
strbuf_release(err);
return NULL; /* good */
@@ -810,6 +824,16 @@ static void execute_commands(struct command *commands,
return;
}
 
+   if (use_atomic_push) {
+   transaction = transaction_begin(err);
+   if (!transaction) {
+   error(%s, err.buf);
+   strbuf_release(err);
+   for (cmd = commands; cmd; cmd = cmd-next)
+   cmd-error_string = transaction error;
+   return;
+   }
+   }
data.cmds = commands;
data.si = si;
if (check_everything_connected(iterate_receive_command_list, 0, data))
@@ -848,6 +872,14 @@ static void execute_commands(struct command *commands,
}
}
 
+   if (use_atomic_push) {
+   if (transaction_commit(transaction, err)) {
+   rp_error(%s, err.buf);
+   for (cmd = commands; cmd; cmd = cmd-next)
+   cmd-error_string = err.buf;
+   }
+   transaction_free(transaction);
+   }
if (shallow_update  !checked_connectivity)
error(BUG: run 'git fsck' for safety.\n
  If there are errors, try to remove 
@@ -1250,5 +1282,6 @@ int cmd_receive_pack(int argc, const char **argv, const 
char *prefix)

[PATCH 5/5] push.c: add an --atomic-push argument

2014-07-31 Thread Ronnie Sahlberg
Signed-off-by: Ronnie Sahlberg sahlb...@google.com
---
 Documentation/git-push.txt | 7 ++-
 builtin/push.c | 2 ++
 transport.c| 1 +
 transport.h| 1 +
 4 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 21cd455..b80b0ac 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -9,7 +9,7 @@ git-push - Update remote refs along with associated objects
 SYNOPSIS
 
 [verse]
-'git push' [--all | --mirror | --tags] [--follow-tags] [-n | --dry-run] 
[--receive-pack=git-receive-pack]
+'git push' [--all | --mirror | --tags] [--follow-tags] [--atomic-push] [-n | 
--dry-run] [--receive-pack=git-receive-pack]
   [--repo=repository] [-f | --force] [--prune] [-v | --verbose] [-u 
| --set-upstream]
   [--force-with-lease[=refname[:expect]]]
   [--no-verify] [repository [refspec...]]
@@ -129,6 +129,11 @@ already exists on the remote side.
from the remote but are pointing at commit-ish that are
reachable from the refs being pushed.
 
+--atomic-push::
+   Try using atomic push. If atomic push is negotiated with the server
+   then any push covering multiple refs will be atomic. Either all
+   refs are updated, or on error, no refs are updated.
+
 --receive-pack=git-receive-pack::
 --exec=git-receive-pack::
Path to the 'git-receive-pack' program on the remote
diff --git a/builtin/push.c b/builtin/push.c
index f8dfea4..f37390c 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -507,6 +507,8 @@ int cmd_push(int argc, const char **argv, const char 
*prefix)
OPT_BIT(0, no-verify, flags, N_(bypass pre-push hook), 
TRANSPORT_PUSH_NO_HOOK),
OPT_BIT(0, follow-tags, flags, N_(push missing but relevant 
tags),
TRANSPORT_PUSH_FOLLOW_TAGS),
+   OPT_BIT(0, atomic-push, flags, N_(use atomic push, if 
available),
+   TRANSPORT_ATOMIC_PUSH),
OPT_END()
};
 
diff --git a/transport.c b/transport.c
index a3b7f48..ab5f553 100644
--- a/transport.c
+++ b/transport.c
@@ -837,6 +837,7 @@ static int git_transport_push(struct transport *transport, 
struct ref *remote_re
args.progress = transport-progress;
args.dry_run = !!(flags  TRANSPORT_PUSH_DRY_RUN);
args.porcelain = !!(flags  TRANSPORT_PUSH_PORCELAIN);
+   args.use_atomic_push = !!(flags  TRANSPORT_ATOMIC_PUSH);
 
ret = send_pack(args, data-fd, data-conn, remote_refs,
data-extra_have);
diff --git a/transport.h b/transport.h
index 02ea248..407d641 100644
--- a/transport.h
+++ b/transport.h
@@ -123,6 +123,7 @@ struct transport {
 #define TRANSPORT_RECURSE_SUBMODULES_ON_DEMAND 256
 #define TRANSPORT_PUSH_NO_HOOK 512
 #define TRANSPORT_PUSH_FOLLOW_TAGS 1024
+#define TRANSPORT_ATOMIC_PUSH 2048
 
 #define TRANSPORT_SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3)
 #define TRANSPORT_SUMMARY(x) (int)(TRANSPORT_SUMMARY_WIDTH + strlen(x) - 
gettext_width(x)), (x)
-- 
2.0.1.528.gd0e7a84

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


[PATCH 2/5] send-pack.c: add an --atomic-push command line argument

2014-07-31 Thread Ronnie Sahlberg
Signed-off-by: Ronnie Sahlberg sahlb...@google.com
---
 Documentation/git-send-pack.txt | 7 ++-
 builtin/send-pack.c | 6 +-
 send-pack.c | 8 +++-
 send-pack.h | 1 +
 4 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/Documentation/git-send-pack.txt b/Documentation/git-send-pack.txt
index dc3a568..4ee2ca1 100644
--- a/Documentation/git-send-pack.txt
+++ b/Documentation/git-send-pack.txt
@@ -9,7 +9,7 @@ git-send-pack - Push objects over Git protocol to another 
repository
 SYNOPSIS
 
 [verse]
-'git send-pack' [--all] [--dry-run] [--force] 
[--receive-pack=git-receive-pack] [--verbose] [--thin] [host:]directory 
[ref...]
+'git send-pack' [--all] [--dry-run] [--force] 
[--receive-pack=git-receive-pack] [--verbose] [--thin] [--atomic-push] 
[host:]directory [ref...]
 
 DESCRIPTION
 ---
@@ -52,6 +52,11 @@ OPTIONS
Send a thin pack, which records objects in deltified form based
on objects not included in the pack to reduce network traffic.
 
+--atomic-push::
+   With atomic-push all refs are updated in one single atomic transaction.
+   This means that if any of the refs fails then the entire push will
+   fail without changing any refs.
+
 host::
A remote host to house the repository.  When this
part is specified, 'git-receive-pack' is invoked via
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index f420b74..78e7d8f 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -13,7 +13,7 @@
 #include sha1-array.h
 
 static const char send_pack_usage[] =
-git send-pack [--all | --mirror] [--dry-run] [--force] 
[--receive-pack=git-receive-pack] [--verbose] [--thin] [host:]directory 
[ref...]\n
+git send-pack [--all | --mirror] [--dry-run] [--force] 
[--receive-pack=git-receive-pack] [--verbose] [--thin] [--atomic-push] 
[host:]directory [ref...]\n
   --all and explicit ref specification are mutually exclusive.;
 
 static struct send_pack_args args;
@@ -165,6 +165,10 @@ int cmd_send_pack(int argc, const char **argv, const char 
*prefix)
args.use_thin_pack = 1;
continue;
}
+   if (!strcmp(arg, --atomic-push)) {
+   args.use_atomic_push = 1;
+   continue;
+   }
if (!strcmp(arg, --stateless-rpc)) {
args.stateless_rpc = 1;
continue;
diff --git a/send-pack.c b/send-pack.c
index f91b8d9..66f3724 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -228,6 +228,11 @@ int send_pack(struct send_pack_args *args,
if (server_supports(atomic-push))
atomic_push_supported = 1;
 
+   if (args-use_atomic_push  !atomic_push_supported) {
+   fprintf(stderr, Server does not support atomic-push.);
+   return -1;
+   }
+
if (!remote_refs) {
fprintf(stderr, No refs in common and none specified; doing 
nothing.\n
Perhaps you should specify a branch such as 
'master'.\n);
@@ -272,7 +277,8 @@ int send_pack(struct send_pack_args *args,
char *old_hex = sha1_to_hex(ref-old_sha1);
char *new_hex = sha1_to_hex(ref-new_sha1);
int quiet = quiet_supported  (args-quiet || 
!args-progress);
-   int atomic_push = atomic_push_supported;
+   int atomic_push = atomic_push_supported 
+   args-use_atomic_push;
 
if (!cmds_sent  (status_report || use_sideband ||
   quiet || agent_supported ||
diff --git a/send-pack.h b/send-pack.h
index 8e84392..0374ed8 100644
--- a/send-pack.h
+++ b/send-pack.h
@@ -10,6 +10,7 @@ struct send_pack_args {
force_update:1,
use_thin_pack:1,
use_ofs_delta:1,
+   use_atomic_push:1,
dry_run:1,
stateless_rpc:1;
 };
-- 
2.0.1.528.gd0e7a84

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


[PATCH 4/5] receive-pack.c: add receive.atomicpush configuration option

2014-07-31 Thread Ronnie Sahlberg
Signed-off-by: Ronnie Sahlberg sahlb...@google.com
---
 Documentation/config.txt | 5 +
 builtin/receive-pack.c   | 5 +
 2 files changed, 10 insertions(+)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 1d718bd..75ce157 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -2038,6 +2038,11 @@ rebase.autostash::
successful rebase might result in non-trivial conflicts.
Defaults to false.
 
+receive.atomicpush::
+   By default, git-receive-pack will only use atomic ref transactions
+   if the client negotiates it. When set to true, git-receive-pack
+   will force atomic ref updates for all client pushes.
+
 receive.autogc::
By default, git-receive-pack will run git-gc --auto after
receiving data from git-push and updating refs.  You can stop
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 47f778d..9fa637a 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -132,6 +132,11 @@ static int receive_pack_config(const char *var, const char 
*value, void *cb)
return 0;
}
 
+   if (strcmp(var, receive.atomicpush) == 0) {
+   use_atomic_push = git_config_bool(var, value);
+   return 0;
+   }
+
return git_default_config(var, value, cb);
 }
 
-- 
2.0.1.528.gd0e7a84

--
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: Transaction patch series overview

2014-07-31 Thread Ronnie Sahlberg
List, please see here an overview and ordering of the ref transaction
patch series.
These series build on each other and needs to be applied in the order
listed below.

This is an update.



rs/ref-transaction-0
---
Early part of the ref transaction topic.

* rs/ref-transaction-0:
  refs.c: change ref_transaction_update() to do error checking and
return status
  refs.c: remove the onerr argument to ref_transaction_commit
  update-ref: use err argument to get error from ref_transaction_commit
  refs.c: make update_ref_write update a strbuf on failure
  refs.c: make ref_update_reject_duplicates take a strbuf argument
for errors
  refs.c: log_ref_write should try to return meaningful errno
  refs.c: make resolve_ref_unsafe set errno to something meaningful on error
  refs.c: commit_packed_refs to return a meaningful errno on failure
  refs.c: make remove_empty_directories always set errno to something sane
  refs.c: verify_lock should set errno to something meaningful
  refs.c: make sure log_ref_setup returns a meaningful errno
  refs.c: add an err argument to repack_without_refs
  lockfile.c: make lock_file return a meaningful errno on failurei
  lockfile.c: add a new public function unable_to_lock_message
  refs.c: add a strbuf argument to ref_transaction_commit for error logging
  refs.c: allow passing NULL to ref_transaction_free
  refs.c: constify the sha arguments for
ref_transaction_create|delete|update
  refs.c: ref_transaction_commit should not free the transaction
  refs.c: remove ref_transaction_rollback

Has been merged into next.



ref-transaction-1 (2014-07-16) 20 commits
-
Second batch of ref transactions

 - refs.c: make delete_ref use a transaction
 - refs.c: make prune_ref use a transaction to delete the ref
 - refs.c: remove lock_ref_sha1
 - refs.c: remove the update_ref_write function
 - refs.c: remove the update_ref_lock function
 - refs.c: make lock_ref_sha1 static
 - walker.c: use ref transaction for ref updates
 - fast-import.c: use a ref transaction when dumping tags
 - receive-pack.c: use a reference transaction for updating the refs
 - refs.c: change update_ref to use a transaction
 - branch.c: use ref transaction for all ref updates
 - fast-import.c: change update_branch to use ref transactions
 - sequencer.c: use ref transactions for all ref updates
 - commit.c: use ref transactions for updates
 - replace.c: use the ref transaction functions for updates
 - tag.c: use ref transactions when doing updates
 - refs.c: add transaction.status and track OPEN/CLOSED/ERROR
 - refs.c: make ref_transaction_begin take an err argument
 - refs.c: update ref_transaction_delete to check for error and return status
 - refs.c: change ref_transaction_create to do error checking and return status
 (this branch is used by rs/ref-transaction, rs/ref-transaction-multi,
rs/ref-transaction-reflog and rs/ref-transaction-rename.)

 The second batch of the transactional ref update series.

Has been merged into pu



rs/ref-transaction (2014-07-17) 12 commits
-
 - refs.c: fix handling of badly named refs
 - refs.c: make write_ref_sha1 static
 - fetch.c: change s_update_ref to use a ref transaction
 - refs.c: propagate any errno==ENOTDIR from _commit back to the callers
 - refs.c: pass a skip list to name_conflict_fn
 - refs.c: call lock_ref_sha1_basic directly from commit
 - refs.c: move the check for valid refname to lock_ref_sha1_basic
 - refs.c: pass NULL as *flags to read_ref_full
 - refs.c: pass the ref log message to _create/delete/update instead of _commit
 - refs.c: add an err argument to delete_ref_loose
 - wrapper.c: add a new function unlink_or_msg
 - wrapper.c: simplify warn_if_unremovable
 (this branch is used by rs/ref-transaction-multi,
rs/ref-transaction-reflog and rs/ref-transaction-rename; uses
rs/ref-transaction-1.)

The third and final part of the basic ref-transaction work.

Has been merged into pu.




rs/ref-transaction-reflog (2014-07-23) 15 commits
---
 - refs.c: allow deleting refs with a broken sha1
 - refs.c: remove lock_any_ref_for_update
 - refs.c: make unlock_ref/close_ref/commit_ref static
 - refs.c: rename log_ref_setup to create_reflog
 - reflog.c: use a reflog transaction when writing during expire
 - refs.c: allow multiple reflog updates during a single transaction
 - refs.c: only write reflog update if msg is non-NULL
 - refs.c: add a flag to allow reflog updates to truncate the log
 - refs.c: add a transaction function to append a reflog entry
 - lockfile.c: make hold_lock_file_for_append preserve meaningful errno
 - refs.c: add a function to append a reflog entry to a fd
 - refs.c: add a new update_type field to ref_update
 - refs.c: rename the transaction functions
 - 

Re: Bug report about symlinks

2014-07-31 Thread René Scharfe

Am 31.07.2014 um 21:50 schrieb Nikolay Avdeev:

I've noticed something strange with git status when replacing a folder with
symlink to another folder.
There is a git repo with script with demo in the attachment.


Let's try and make this a bit easier for folks to follow along.

# Create test repo with two directories with two files each.
$ git init
Initialized empty Git repository in /tmp/.git/
$ mkdir a b
$ echo x a/equal
$ echo x b/equal
$ echo y a/different
$ echo z b/different
$ git add a b
$ git commit -minitial
[master (root-commit) 6d36895] initial
 4 files changed, 4 insertions(+)
 create mode 100644 a/different
 create mode 100644 a/equal
 create mode 100644 b/different
 create mode 100644 b/equal

# Replace one directory with a symlink to the other.
$ rm -rf b
$ ln -s a b

# First git status call.
$ git status
On branch master
Changes not staged for commit:
  (use git add/rm file... to update what will be committed)
  (use git checkout -- file... to discard changes in working directory)

deleted:b/different

Untracked files:
  (use git add file... to include in what will be committed)

b

no changes added to commit (use git add and/or git commit -a)

# Stage the changes.
$ git add b

# Second git status call.
$ git status
On branch master
Changes to be committed:
  (use git reset HEAD file... to unstage)

new file:   b
deleted:b/different
deleted:b/equal

# Commit the staged changes.
$ git commit -msymlinked
[master 4498f28] symlinked
 3 files changed, 1 insertion(+), 2 deletions(-)
 create mode 12 b
 delete mode 100644 b/different
 delete mode 100644 b/equal


That the first and second status call report different results is a 
feature; staging changes using git add alters the status.  A commit 
after the first status call would be empty.


It could be debated if the first git status call should also report 
b/equal as deleted.


René

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


article: Using a rolling hash to break up binary files

2014-07-31 Thread Philip Oakley
I thought it worth bring to the list's attention a  recent article on 
CodeProject that may be of interest to those looking at splitting binary 
files into deterministic hunks.


http://www.codeproject.com/Articles/801608/Using-a-rolling-hash-to-break-up-binary-files

It's based on Rabin and Karp's algorithm 
http://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm.


--
Philip 


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


cherry picking and merge

2014-07-31 Thread Mike Stump
Cherry picking doesn’t work as well as it should.  I was testing on git version 
1.7.9.5.

Put in a line in a file, call it:

first version

then cherry pick this into your branch. Then update on master and transform 
that into:

second version

then, merge that branch back to master.  Death in the form of conflicts.

In gcc land, I do this sort of thing all the time, and I need a merging 
subsystem to actually keep track of things.  I can manage this will diff and 
patch and it works flawlessly.  The point of using something better than diff 
and patch is for it to be better than diff and patch.

I’d like for merge to merge in the work that has yet to be merged.  Not that, 
plus blindly try and apply or reapply cherry picked items.--
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: cherry picking and merge

2014-07-31 Thread brian m. carlson
On Thu, Jul 31, 2014 at 05:58:17PM -0700, Mike Stump wrote:
 Cherry picking doesn’t work as well as it should.  I was testing on
 git version 1.7.9.5.
 
 Put in a line in a file, call it:
 
 first version
 
 then cherry pick this into your branch. Then update on master and transform 
 that into:
 
 second version
 
 then, merge that branch back to master.  Death in the form of conflicts.
 
 In gcc land, I do this sort of thing all the time, and I need a
 merging subsystem to actually keep track of things.  I can manage this
 will diff and patch and it works flawlessly.  The point of using
 something better than diff and patch is for it to be better than diff
 and patch.
 
 I’d like for merge to merge in the work that has yet to be merged.
 Not that, plus blindly try and apply or reapply cherry picked items.

You're not the first person to be surprised by the way merge works.
From the git-merge manpage:

  [This behavior] occurs because only the heads and the merge base are
  considered when performing a merge, not the individual commits.

(That was added after 1.7.9.5.)

If you want the behavior of applying multiple patches in a row, you want
to use git rebase, not git merge.  Since rebase re-applies the patches
of each of your commits on top of another branch, the identical change
won't cause conflicts.

-- 
brian m. carlson / brian with sandals: Houston, Texas, US
+1 832 623 2791 | http://www.crustytoothpaste.net/~bmc | My opinion only
OpenPGP: RSA v4 4096b: 88AC E9B2 9196 305B A994 7552 F1BA 225C 0223 B187


signature.asc
Description: Digital signature


Re: article: Using a rolling hash to break up binary files

2014-07-31 Thread Shawn Pearce
On Thu, Jul 31, 2014 at 3:31 PM, Philip Oakley philipoak...@iee.org wrote:
 I thought it worth bring to the list's attention a  recent article on
 CodeProject that may be of interest to those looking at splitting binary
 files into deterministic hunks.

 http://www.codeproject.com/Articles/801608/Using-a-rolling-hash-to-break-up-binary-files

 It's based on Rabin and Karp's algorithm
 http://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm.

If I remember right, this is how bup[1] works. Its certainly what we
do for delta compressing files.

[1] https://github.com/bup/bup
--
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